1 /*
2 * Copyright (c) 2021, Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22 //!
23 //! \file     decode_vp8_packet.cpp
24 //! \brief    Defines the interface for vp8 decode packet
25 //!
26 #include "decode_vp8_packet.h"
27 #include "decode_status_report_defs.h"
28 #include "decode_predication_packet.h"
29 #include "decode_marker_packet.h"
30 
31 namespace decode
32 {
Vp8DecodePkt(MediaPipeline * pipeline,MediaTask * task,CodechalHwInterfaceNext * hwInterface)33 Vp8DecodePkt::Vp8DecodePkt(MediaPipeline *pipeline, MediaTask *task, CodechalHwInterfaceNext *hwInterface)
34     : CmdPacket(task)
35 {
36     if (pipeline != nullptr)
37     {
38         m_statusReport   = pipeline->GetStatusReportInstance();
39         m_featureManager = pipeline->GetFeatureManager();
40         m_vp8Pipeline    = dynamic_cast<Vp8Pipeline *>(pipeline);
41     }
42     if (hwInterface != nullptr)
43     {
44         m_hwInterface    = hwInterface;
45         m_miItf          = std::static_pointer_cast<mhw::mi::Itf>(hwInterface->GetMiInterfaceNext());
46         m_osInterface    = hwInterface->GetOsInterface();
47     }
48 }
49 
Init()50 MOS_STATUS Vp8DecodePkt::Init()
51 {
52     DECODE_FUNC_CALL();
53     DECODE_CHK_NULL(m_statusReport);
54     DECODE_CHK_NULL(m_featureManager);
55     DECODE_CHK_NULL(m_vp8Pipeline);
56     DECODE_CHK_NULL(m_osInterface);
57     DECODE_CHK_NULL(m_miItf);
58 
59     DECODE_CHK_STATUS(CmdPacket::Init());
60 
61     DecodeSubPacket *subPacket = m_vp8Pipeline->GetSubPacket(DecodePacketId(m_vp8Pipeline, vp8PictureSubPacketId));
62     m_picturePkt               = dynamic_cast<Vp8DecodePicPkt *>(subPacket);
63     DECODE_CHK_NULL(m_picturePkt);
64 
65     subPacket  = m_vp8Pipeline->GetSubPacket(DecodePacketId(m_vp8Pipeline, vp8SliceSubPacketId));
66     m_slicePkt = dynamic_cast<Vp8DecodeSlcPkt *>(subPacket);
67     DECODE_CHK_NULL(m_slicePkt);
68 
69     m_vp8BasicFeature = dynamic_cast<Vp8BasicFeature *>(m_featureManager->GetFeature(FeatureIDs::basicFeature));
70     DECODE_CHK_NULL(m_vp8BasicFeature);
71 
72     m_allocator = m_vp8Pipeline->GetDecodeAllocator();
73     DECODE_CHK_NULL(m_allocator);
74 
75     DECODE_CHK_STATUS(m_statusReport->RegistObserver(this));
76 
77     return MOS_STATUS_SUCCESS;
78 }
79 
Prepare()80 MOS_STATUS Vp8DecodePkt::Prepare()
81 {
82     DECODE_FUNC_CALL();
83 
84     DECODE_CHK_NULL(m_vp8BasicFeature);
85     DECODE_CHK_NULL(m_vp8BasicFeature->m_vp8PicParams);
86     m_vp8PicParams = m_vp8BasicFeature->m_vp8PicParams;
87 
88     return MOS_STATUS_SUCCESS;
89 }
90 
Destroy()91 MOS_STATUS Vp8DecodePkt::Destroy()
92 {
93     m_statusReport->UnregistObserver(this);
94     return MOS_STATUS_SUCCESS;
95 }
96 
SetPerfTag(CODECHAL_MODE mode,uint16_t picCodingType)97 void Vp8DecodePkt::SetPerfTag(CODECHAL_MODE mode, uint16_t picCodingType)
98 {
99     DECODE_FUNC_CALL();
100 
101     uint16_t perfTag = ((mode << 4) & 0xF0) | (picCodingType & 0xF);
102     m_osInterface->pfnIncPerfFrameID(m_osInterface);
103     m_osInterface->pfnSetPerfTag(m_osInterface, perfTag);
104     m_osInterface->pfnResetPerfBufferID(m_osInterface);
105 }
106 
IsPrologRequired()107 bool Vp8DecodePkt::IsPrologRequired()
108 {
109     return true;
110 }
111 
AddForceWakeup(MOS_COMMAND_BUFFER & cmdBuffer)112 MOS_STATUS Vp8DecodePkt::AddForceWakeup(MOS_COMMAND_BUFFER &cmdBuffer)
113 {
114     DECODE_FUNC_CALL();
115 
116     auto &par = m_miItf->GETPAR_MI_FORCE_WAKEUP();
117     MOS_ZeroMemory(&par, sizeof(par));
118     par.bMFXPowerWellControl                    = true;
119     par.bMFXPowerWellControlMask                = true;
120     par.bHEVCPowerWellControl                   = false;
121     par.bHEVCPowerWellControlMask               = true;
122 
123     DECODE_CHK_STATUS(m_miItf->ADDCMD_MI_FORCE_WAKEUP(&cmdBuffer));
124     return MOS_STATUS_SUCCESS;
125 }
126 
SendPrologWithFrameTracking(MOS_COMMAND_BUFFER & cmdBuffer,bool frameTrackingRequested)127 MOS_STATUS Vp8DecodePkt::SendPrologWithFrameTracking(MOS_COMMAND_BUFFER &cmdBuffer, bool frameTrackingRequested)
128 {
129     DecodeSubPacket *subPacket   = m_vp8Pipeline->GetSubPacket(DecodePacketId(m_vp8Pipeline, markerSubPacketId));
130     DecodeMarkerPkt *makerPacket = dynamic_cast<DecodeMarkerPkt *>(subPacket);
131     DECODE_CHK_NULL(makerPacket);
132     DECODE_CHK_STATUS(makerPacket->Execute(cmdBuffer));
133 
134 #ifdef _MMC_SUPPORTED
135     m_mmcState        = m_vp8Pipeline->GetMmcState();
136     bool isMmcEnabled = (m_mmcState != nullptr && m_mmcState->IsMmcEnabled());
137     if (isMmcEnabled)
138     {
139         DECODE_CHK_STATUS(m_mmcState->SendPrologCmd(&cmdBuffer, false));
140     }
141 #endif
142 
143     MHW_GENERIC_PROLOG_PARAMS genericPrologParams;
144     MOS_ZeroMemory(&genericPrologParams, sizeof(genericPrologParams));
145     genericPrologParams.pOsInterface  = m_osInterface;
146     genericPrologParams.pvMiInterface = nullptr;
147 #ifdef _MMC_SUPPORTED
148     genericPrologParams.bMmcEnabled = isMmcEnabled;
149 #endif
150 
151     DECODE_CHK_STATUS(Mhw_SendGenericPrologCmdNext(&cmdBuffer, &genericPrologParams, m_miItf));
152 
153     subPacket                               = m_vp8Pipeline->GetSubPacket(DecodePacketId(m_vp8Pipeline, predicationSubPacketId));
154     DecodePredicationPkt *predicationPacket = dynamic_cast<DecodePredicationPkt *>(subPacket);
155     DECODE_CHK_NULL(predicationPacket);
156     DECODE_CHK_STATUS(predicationPacket->Execute(cmdBuffer));
157 
158     return MOS_STATUS_SUCCESS;
159 }
160 
MiFlush(MOS_COMMAND_BUFFER & cmdBuffer)161 MOS_STATUS Vp8DecodePkt::MiFlush(MOS_COMMAND_BUFFER &cmdBuffer)
162 {
163     DECODE_FUNC_CALL();
164 
165     auto &par = m_miItf->GETPAR_MI_FLUSH_DW();
166     MOS_ZeroMemory(&par, sizeof(par));
167     DECODE_CHK_STATUS(m_miItf->ADDCMD_MI_FLUSH_DW(&cmdBuffer));
168 
169     return MOS_STATUS_SUCCESS;
170 }
171 
Completed(void * mfxStatus,void * rcsStatus,void * statusReport)172 MOS_STATUS Vp8DecodePkt::Completed(void *mfxStatus, void *rcsStatus, void *statusReport)
173 {
174     DECODE_FUNC_CALL();
175 
176     DECODE_CHK_NULL(mfxStatus);
177     DECODE_CHK_NULL(statusReport);
178 
179     DecodeStatusMfx *       decodeStatusMfx  = (DecodeStatusMfx *)mfxStatus;
180     DecodeStatusReportData *statusReportData = (DecodeStatusReportData *)statusReport;
181 
182     auto hcpInterface = m_hwInterface->GetHcpInterfaceNext();
183     if (hcpInterface != nullptr)
184     {
185         if ((decodeStatusMfx->m_mmioErrorStatusReg & hcpInterface->GetHcpCabacErrorFlagsMask()) != 0)
186         {
187             statusReportData->codecStatus    = CODECHAL_STATUS_ERROR;
188             statusReportData->numMbsAffected = (decodeStatusMfx->m_mmioMBCountReg & 0xFFFC0000) >> 18;
189         }
190 
191         statusReportData->frameCrc = decodeStatusMfx->m_mmioFrameCrcReg;
192     }
193 
194     DECODE_VERBOSEMESSAGE("Index = %d", statusReportData->currDecodedPic.FrameIdx);
195     DECODE_VERBOSEMESSAGE("FrameCrc = 0x%x", statusReportData->frameCrc);
196 
197     return MOS_STATUS_SUCCESS;
198 }
199 
ReadMfxStatus(MediaStatusReport * statusReport,MOS_COMMAND_BUFFER & cmdBuffer)200 MOS_STATUS Vp8DecodePkt::ReadMfxStatus(MediaStatusReport* statusReport, MOS_COMMAND_BUFFER& cmdBuffer)
201 {
202     DECODE_FUNC_CALL();
203 
204     DECODE_CHK_NULL(statusReport);
205 
206     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
207     MOS_RESOURCE* osResource = nullptr;
208     uint32_t     offset = 0;
209 
210     auto &par = m_miItf->GETPAR_MI_STORE_REGISTER_MEM();
211     MOS_ZeroMemory(&par, sizeof(par));
212 
213     DECODE_CHK_NULL(m_hwInterface->GetVdencInterfaceNext());
214     auto mmioRegisters = m_hwInterface->GetVdencInterfaceNext()->GetMmioRegisters(MHW_VDBOX_NODE_1);
215 
216     DECODE_CHK_STATUS(statusReport->GetAddress(decode::DecodeStatusReportType::DecErrorStatusOffset, osResource, offset));
217 
218     par.presStoreBuffer = osResource;
219     par.dwOffset        = offset;
220     par.dwRegister      = mmioRegisters->mfxErrorFlagsRegOffset;
221     DECODE_CHK_STATUS(m_miItf->ADDCMD_MI_STORE_REGISTER_MEM(&cmdBuffer));
222 
223 
224     DECODE_CHK_STATUS(statusReport->GetAddress(decode::DecodeStatusReportType::DecMBCountOffset, osResource, offset));
225 
226     par.presStoreBuffer = osResource;
227     par.dwOffset        = offset;
228     par.dwRegister      = mmioRegisters->mfxMBCountRegOffset;
229     DECODE_CHK_STATUS(m_miItf->ADDCMD_MI_STORE_REGISTER_MEM(&cmdBuffer));
230 
231     return MOS_STATUS_SUCCESS;
232 }
233 
StartStatusReport(uint32_t srType,MOS_COMMAND_BUFFER * cmdBuffer)234 MOS_STATUS Vp8DecodePkt::StartStatusReport(uint32_t srType, MOS_COMMAND_BUFFER *cmdBuffer)
235 {
236     DECODE_FUNC_CALL();
237     DECODE_CHK_NULL(cmdBuffer);
238     DECODE_CHK_STATUS(MediaPacket::StartStatusReportNext(srType, cmdBuffer));
239 
240     SetPerfTag(CODECHAL_DECODE_MODE_VP8VLD, m_vp8BasicFeature->m_pictureCodingType);
241     MediaPerfProfiler *perfProfiler = MediaPerfProfiler::Instance();
242     DECODE_CHK_NULL(perfProfiler);
243     DECODE_CHK_STATUS(perfProfiler->AddPerfCollectStartCmd(
244         (void *)m_vp8Pipeline, m_osInterface, m_miItf, cmdBuffer));
245 
246     return MOS_STATUS_SUCCESS;
247 }
248 
EndStatusReport(uint32_t srType,MOS_COMMAND_BUFFER * cmdBuffer)249 MOS_STATUS Vp8DecodePkt::EndStatusReport(uint32_t srType, MOS_COMMAND_BUFFER *cmdBuffer)
250 {
251     DECODE_FUNC_CALL();
252     DECODE_CHK_NULL(cmdBuffer);
253     DECODE_CHK_STATUS(ReadMfxStatus(m_statusReport, *cmdBuffer));
254     DECODE_CHK_STATUS(MediaPacket::EndStatusReportNext(srType, cmdBuffer));
255 
256     MediaPerfProfiler *perfProfiler = MediaPerfProfiler::Instance();
257     DECODE_CHK_NULL(perfProfiler);
258     DECODE_CHK_STATUS(perfProfiler->AddPerfCollectEndCmd(
259         (void *)m_vp8Pipeline, m_osInterface, m_miItf, cmdBuffer));
260 
261     // Add Mi flush here to ensure end status tag flushed to memory earlier than completed count
262     DECODE_CHK_STATUS(MiFlush(*cmdBuffer));
263 
264     return MOS_STATUS_SUCCESS;
265 }
266 
267 }  // namespace decode