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