1 /*
2 * Copyright (c) 2022-2023, 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_vp9_packet.cpp
24 //! \brief    Defines the interface for vp9 decode packet
25 //!
26 #include "decode_vp9_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 
Vp9DecodePkt(MediaPipeline * pipeline,MediaTask * task,CodechalHwInterfaceNext * hwInterface)33 Vp9DecodePkt::Vp9DecodePkt(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_vp9Pipeline    = dynamic_cast<Vp9Pipeline *>(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 Vp9DecodePkt::Init()
51 {
52     DECODE_FUNC_CALL();
53     DECODE_CHK_NULL(m_miItf);
54     DECODE_CHK_NULL(m_statusReport);
55     DECODE_CHK_NULL(m_featureManager);
56     DECODE_CHK_NULL(m_vp9Pipeline);
57     DECODE_CHK_NULL(m_osInterface);
58 
59     DECODE_CHK_STATUS(CmdPacket::Init());
60 
61     m_vp9BasicFeature = dynamic_cast<Vp9BasicFeature*>(m_featureManager->GetFeature(FeatureIDs::basicFeature));
62     DECODE_CHK_NULL(m_vp9BasicFeature);
63 
64     m_allocator = m_vp9Pipeline->GetDecodeAllocator();
65     DECODE_CHK_NULL(m_allocator);
66 
67     return MOS_STATUS_SUCCESS;
68 }
69 
Prepare()70 MOS_STATUS Vp9DecodePkt::Prepare()
71 {
72     DECODE_FUNC_CALL();
73 
74     m_phase = static_cast<DecodePhase *>(m_vp9Pipeline->GetComponentState());
75     DECODE_CHK_NULL(m_phase);
76 
77     DECODE_CHK_NULL(m_vp9BasicFeature);
78     DECODE_CHK_NULL(m_vp9BasicFeature->m_vp9PicParams);
79     m_vp9PicParams = m_vp9BasicFeature->m_vp9PicParams;
80 
81     return MOS_STATUS_SUCCESS;
82 }
83 
Destroy()84 MOS_STATUS Vp9DecodePkt::Destroy()
85 {
86     m_statusReport->UnregistObserver(this);
87     return MOS_STATUS_SUCCESS;
88 }
89 
SetPerfTag(CODECHAL_MODE mode,uint16_t picCodingType)90 void Vp9DecodePkt::SetPerfTag(CODECHAL_MODE mode, uint16_t picCodingType)
91 {
92     DECODE_FUNC_CALL();
93 
94     uint16_t perfTag = ((mode << 4) & 0xF0) | (picCodingType & 0xF);
95     m_osInterface->pfnIncPerfFrameID(m_osInterface);
96     m_osInterface->pfnSetPerfTag(m_osInterface, perfTag);
97     m_osInterface->pfnResetPerfBufferID(m_osInterface);
98 }
99 
AddForceWakeup(MOS_COMMAND_BUFFER & cmdBuffer)100 MOS_STATUS Vp9DecodePkt::AddForceWakeup(MOS_COMMAND_BUFFER& cmdBuffer)
101 {
102     DECODE_FUNC_CALL();
103 
104     auto &par = m_miItf->GETPAR_MI_FORCE_WAKEUP();
105     par                                         = {};
106     par.bMFXPowerWellControl                    = false;
107     par.bMFXPowerWellControlMask                = true;
108     par.bHEVCPowerWellControl                   = true;
109     par.bHEVCPowerWellControlMask               = true;
110 
111     DECODE_CHK_STATUS(m_miItf->ADDCMD_MI_FORCE_WAKEUP(&cmdBuffer));
112 
113     return MOS_STATUS_SUCCESS;
114 }
115 
SendPrologWithFrameTracking(MOS_COMMAND_BUFFER & cmdBuffer,bool frameTrackingRequested)116 MOS_STATUS Vp9DecodePkt::SendPrologWithFrameTracking(MOS_COMMAND_BUFFER& cmdBuffer, bool frameTrackingRequested)
117 {
118     DecodeSubPacket* subPacket = m_vp9Pipeline->GetSubPacket(DecodePacketId(m_vp9Pipeline, markerSubPacketId));
119     DecodeMarkerPkt *makerPacket = dynamic_cast<DecodeMarkerPkt*>(subPacket);
120     DECODE_CHK_NULL(makerPacket);
121     DECODE_CHK_STATUS(makerPacket->Execute(cmdBuffer));
122 
123 #ifdef _MMC_SUPPORTED
124     DecodeMemComp *mmcState = m_vp9Pipeline->GetMmcState();
125     bool isMmcEnabled = (mmcState != nullptr && mmcState->IsMmcEnabled());
126     if (isMmcEnabled)
127     {
128         DECODE_CHK_STATUS(mmcState->SendPrologCmd(&cmdBuffer, false));
129     }
130 #endif
131 
132     MHW_GENERIC_PROLOG_PARAMS  genericPrologParams;
133     MOS_ZeroMemory(&genericPrologParams, sizeof(genericPrologParams));
134     genericPrologParams.pOsInterface = m_osInterface;
135     genericPrologParams.pvMiInterface = nullptr;
136 #ifdef _MMC_SUPPORTED
137     genericPrologParams.bMmcEnabled = isMmcEnabled;
138 #endif
139 
140     DECODE_CHK_STATUS(Mhw_SendGenericPrologCmdNext(&cmdBuffer, &genericPrologParams, m_miItf));
141 
142     subPacket = m_vp9Pipeline->GetSubPacket(DecodePacketId(m_vp9Pipeline, predicationSubPacketId));
143     DecodePredicationPkt *predicationPacket = dynamic_cast<DecodePredicationPkt*>(subPacket);
144     DECODE_CHK_NULL(predicationPacket);
145     DECODE_CHK_STATUS(predicationPacket->Execute(cmdBuffer));
146 
147     return MOS_STATUS_SUCCESS;
148 }
149 
MiFlush(MOS_COMMAND_BUFFER & cmdBuffer)150 MOS_STATUS Vp9DecodePkt::MiFlush(MOS_COMMAND_BUFFER &cmdBuffer)
151 {
152     DECODE_FUNC_CALL();
153 
154     auto &par = m_miItf->GETPAR_MI_FLUSH_DW();
155     par       = {};
156     DECODE_CHK_STATUS(m_miItf->ADDCMD_MI_FLUSH_DW(&cmdBuffer));
157 
158     return MOS_STATUS_SUCCESS;
159 }
160 
Completed(void * mfxStatus,void * rcsStatus,void * statusReport)161 MOS_STATUS Vp9DecodePkt::Completed(void *mfxStatus, void *rcsStatus, void *statusReport)
162 {
163     DECODE_FUNC_CALL();
164 
165     DECODE_CHK_NULL(mfxStatus);
166     DECODE_CHK_NULL(statusReport);
167 
168     DecodeStatusMfx *       decodeStatusMfx  = (DecodeStatusMfx *)mfxStatus;
169     DecodeStatusReportData *statusReportData = (DecodeStatusReportData *)statusReport;
170 
171     std::shared_ptr<mhw::vdbox::hcp::Itf> hcpItf = std::static_pointer_cast<mhw::vdbox::hcp::Itf>(m_hwInterface->GetHcpInterfaceNext());
172     if (hcpItf != nullptr)
173     {
174         if ((decodeStatusMfx->m_mmioErrorStatusReg & hcpItf->GetHcpCabacErrorFlagsMask()) != 0)
175         {
176             statusReportData->codecStatus    = CODECHAL_STATUS_ERROR;
177             statusReportData->numMbsAffected = (decodeStatusMfx->m_mmioMBCountReg & 0xFFFC0000) >> 18;
178         }
179 
180         statusReportData->frameCrc = decodeStatusMfx->m_mmioFrameCrcReg;
181     }
182 
183     DECODE_VERBOSEMESSAGE("Index = %d", statusReportData->currDecodedPic.FrameIdx);
184     DECODE_VERBOSEMESSAGE("FrameCrc = 0x%x", statusReportData->frameCrc);
185 
186     return MOS_STATUS_SUCCESS;
187 }
188 
ReadVdboxId(MOS_COMMAND_BUFFER & cmdBuffer)189 MOS_STATUS Vp9DecodePkt::ReadVdboxId(MOS_COMMAND_BUFFER &cmdBuffer)
190 {
191     DECODE_FUNC_CALL();
192     DECODE_CHK_NULL(m_phase);
193     DECODE_CHK_NULL(m_statusReport);
194 
195     uint8_t curPipe = m_phase->GetPipe();
196     DECODE_CHK_COND(curPipe >= csInstanceIdMax, "Invalid pipe index.");
197     uint32_t csEngineIdOffsetIdx = decode::DecodeStatusReportType::CsEngineIdOffset_0 + curPipe;
198 
199     auto &par = m_miItf->GETPAR_MI_STORE_REGISTER_MEM();
200     par       = {};
201 
202     auto mmioRegistersHcp = m_hwInterface->GetHcpInterfaceNext()->GetMmioRegisters(MHW_VDBOX_NODE_1);
203 
204     MOS_RESOURCE* osResource = nullptr;
205     uint32_t      offset     = 0;
206     DECODE_CHK_STATUS(m_statusReport->GetAddress(csEngineIdOffsetIdx, osResource, offset));
207     par.presStoreBuffer      = osResource;
208     par.dwOffset             = offset;
209     par.dwRegister           = mmioRegistersHcp->csEngineIdOffset;
210 
211     DECODE_CHK_STATUS(m_miItf->ADDCMD_MI_STORE_REGISTER_MEM(&cmdBuffer));
212 
213     return MOS_STATUS_SUCCESS;
214 }
215 
ReadHcpStatus(MediaStatusReport * statusReport,MOS_COMMAND_BUFFER & cmdBuffer)216 MOS_STATUS Vp9DecodePkt::ReadHcpStatus(MediaStatusReport *statusReport, MOS_COMMAND_BUFFER &cmdBuffer)
217 {
218     DECODE_FUNC_CALL();
219 
220     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
221 
222     DECODE_CHK_NULL(statusReport);
223 
224     MOS_RESOURCE *osResource;
225     uint32_t      offset;
226 
227     auto &par = m_miItf->GETPAR_MI_STORE_REGISTER_MEM();
228     par       = {};
229 
230     auto mmioRegistersHcp = m_hwInterface->GetHcpInterfaceNext()->GetMmioRegisters(MHW_VDBOX_NODE_1);
231 
232     DECODE_CHK_STATUS(statusReport->GetAddress(decode::DecodeStatusReportType::DecErrorStatusOffset, osResource, offset));
233     par.presStoreBuffer    = osResource;
234     par.dwOffset           = offset;
235     par.dwRegister         = mmioRegistersHcp->hcpCabacStatusRegOffset;
236 
237     DECODE_CHK_STATUS(m_miItf->ADDCMD_MI_STORE_REGISTER_MEM(&cmdBuffer));
238 
239     DECODE_CHK_STATUS(statusReport->GetAddress(decode::DecodeStatusReportType::DecFrameCrcOffset, osResource, offset));
240     par.presStoreBuffer    = osResource;
241     par.dwOffset           = offset;
242     par.dwRegister         = mmioRegistersHcp->hcpFrameCrcRegOffset;
243 
244     DECODE_CHK_STATUS(m_miItf->ADDCMD_MI_STORE_REGISTER_MEM(&cmdBuffer));
245 
246     DECODE_CHK_STATUS(statusReport->GetAddress(decode::DecodeStatusReportType::DecMBCountOffset, osResource, offset));
247     par.presStoreBuffer    = osResource;
248     par.dwOffset           = offset;
249     par.dwRegister         = mmioRegistersHcp->hcpDecStatusRegOffset;
250 
251     DECODE_CHK_STATUS(m_miItf->ADDCMD_MI_STORE_REGISTER_MEM(&cmdBuffer));
252 
253     return MOS_STATUS_SUCCESS;
254 }
255 
StartStatusReport(uint32_t srType,MOS_COMMAND_BUFFER * cmdBuffer)256 MOS_STATUS Vp9DecodePkt::StartStatusReport(uint32_t srType, MOS_COMMAND_BUFFER* cmdBuffer)
257 {
258     DECODE_FUNC_CALL();
259     DECODE_CHK_NULL(cmdBuffer);
260     DECODE_CHK_STATUS(MediaPacket::StartStatusReportNext(srType, cmdBuffer));
261 
262     SetPerfTag(CODECHAL_DECODE_MODE_VP9VLD, m_vp9BasicFeature->m_pictureCodingType);
263 
264     MediaPerfProfiler *perfProfiler = MediaPerfProfiler::Instance();
265     DECODE_CHK_NULL(perfProfiler);
266     DECODE_CHK_STATUS(perfProfiler->AddPerfCollectStartCmd(
267         (void*)m_vp9Pipeline, m_osInterface, m_miItf, cmdBuffer));
268 
269     return MOS_STATUS_SUCCESS;
270 }
271 
EndStatusReport(uint32_t srType,MOS_COMMAND_BUFFER * cmdBuffer)272 MOS_STATUS Vp9DecodePkt::EndStatusReport(uint32_t srType, MOS_COMMAND_BUFFER* cmdBuffer)
273 {
274     DECODE_FUNC_CALL();
275     DECODE_CHK_NULL(cmdBuffer);
276     DECODE_CHK_STATUS(ReadHcpStatus(m_statusReport, *cmdBuffer));
277     DECODE_CHK_STATUS(MediaPacket::EndStatusReportNext(srType, cmdBuffer));
278 
279     MediaPerfProfiler *perfProfiler = MediaPerfProfiler::Instance();
280     DECODE_CHK_NULL(perfProfiler);
281     DECODE_CHK_STATUS(perfProfiler->AddPerfCollectEndCmd(
282         (void*)m_vp9Pipeline, m_osInterface, m_miItf, cmdBuffer));
283 
284     // Add Mi flush here to ensure end status tag flushed to memory earlier than completed count
285     DECODE_CHK_STATUS(MiFlush(*cmdBuffer));
286 
287     return MOS_STATUS_SUCCESS;
288 }
289 
EnsureAllCommandsExecuted(MOS_COMMAND_BUFFER & cmdBuffer)290 MOS_STATUS Vp9DecodePkt::EnsureAllCommandsExecuted(MOS_COMMAND_BUFFER &cmdBuffer)
291 {
292     DECODE_FUNC_CALL();
293 
294     // Send MI_FLUSH command
295     auto &par = m_miItf->GETPAR_MI_FLUSH_DW();
296     par       = {};
297     auto *skuTable = m_vp9Pipeline->GetSkuTable();
298     if (skuTable && MEDIA_IS_SKU(skuTable, FtrEnablePPCFlush))
299     {
300         // Add PPC fulsh
301         par.bEnablePPCFlush = true;
302     }
303     DECODE_CHK_STATUS(m_miItf->ADDCMD_MI_FLUSH_DW(&cmdBuffer));
304 
305     return MOS_STATUS_SUCCESS;
306 }
307 
308 #if USE_CODECHAL_DEBUG_TOOL
DumpSecondaryCommandBuffer(MOS_COMMAND_BUFFER & cmdBuffer)309 MOS_STATUS Vp9DecodePkt::DumpSecondaryCommandBuffer(MOS_COMMAND_BUFFER &cmdBuffer)
310 {
311     DECODE_ASSERT(m_phase != nullptr);
312     CodechalDebugInterface *debugInterface = m_vp9Pipeline->GetDebugInterface();
313     DECODE_CHK_NULL(debugInterface);
314     std::string cmdName = "DEC_secondary_" + std::to_string(m_phase->GetCmdBufIndex());
315     DECODE_CHK_STATUS(debugInterface->DumpCmdBuffer(
316         &cmdBuffer, CODECHAL_NUM_MEDIA_STATES, cmdName.c_str()));
317 
318     return MOS_STATUS_SUCCESS;
319 }
320 #endif
321 
322 }
323