1 /*
2 * Copyright (c) 2018-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_avc_packet.cpp
24 //! \brief Defines the interface for avc decode packet.
25 //!
26
27 #include "decode_avc_packet.h"
28 #include "decode_utils.h"
29 #include "decode_marker_packet.h"
30 #include "decode_status_report_defs.h"
31 #include "decode_predication_packet.h"
32 #include "codechal_debug.h"
33
34 namespace decode
35 {
Init()36 MOS_STATUS AvcDecodePkt::Init()
37 {
38 DECODE_FUNC_CALL();
39 DECODE_CHK_NULL(m_miItf);
40 DECODE_CHK_NULL(m_statusReport);
41 DECODE_CHK_NULL(m_featureManager);
42 DECODE_CHK_NULL(m_avcPipeline);
43 DECODE_CHK_NULL(m_osInterface);
44
45 DECODE_CHK_STATUS(CmdPacket::Init());
46
47 m_avcBasicFeature = dynamic_cast<AvcBasicFeature *>(m_featureManager->GetFeature(FeatureIDs::basicFeature));
48 DECODE_CHK_NULL(m_avcBasicFeature);
49
50 m_allocator = m_avcPipeline->GetDecodeAllocator();
51 DECODE_CHK_NULL(m_allocator);
52
53 DECODE_CHK_STATUS(m_statusReport->RegistObserver(this));
54
55 DecodeSubPacket *subPacket = m_avcPipeline->GetSubPacket(DecodePacketId(m_avcPipeline, avcPictureSubPacketId));
56
57 m_picturePkt = dynamic_cast<AvcDecodePicPkt *>(subPacket);
58 DECODE_CHK_NULL(m_picturePkt);
59 DECODE_CHK_STATUS(m_picturePkt->CalculateCommandSize(m_pictureStatesSize, m_picturePatchListSize));
60
61 subPacket = m_avcPipeline->GetSubPacket(DecodePacketId(m_avcPipeline, avcSliceSubPacketId));
62 m_slicePkt = dynamic_cast<AvcDecodeSlcPkt *>(subPacket);
63 DECODE_CHK_NULL(m_slicePkt);
64 DECODE_CHK_STATUS(m_slicePkt->CalculateCommandSize(m_sliceStatesSize, m_slicePatchListSize));
65
66 return MOS_STATUS_SUCCESS;
67 }
68
Prepare()69 MOS_STATUS AvcDecodePkt::Prepare()
70 {
71 DECODE_FUNC_CALL();
72
73 DECODE_CHK_NULL(m_avcBasicFeature->m_avcPicParams);
74 m_avcPicParams = m_avcBasicFeature->m_avcPicParams;
75
76 return MOS_STATUS_SUCCESS;
77 }
78
Destroy()79 MOS_STATUS AvcDecodePkt::Destroy()
80 {
81 m_statusReport->UnregistObserver(this);
82 return MOS_STATUS_SUCCESS;
83 }
84
SetPerfTag(CODECHAL_MODE mode,uint16_t picCodingType)85 void AvcDecodePkt::SetPerfTag(CODECHAL_MODE mode, uint16_t picCodingType)
86 {
87 DECODE_FUNC_CALL();
88 uint16_t perfTag = ((mode << 4) & 0xF0) | (picCodingType & 0xF);
89
90 m_osInterface->pfnIncPerfFrameID(m_osInterface);
91 m_osInterface->pfnSetPerfTag(m_osInterface, perfTag);
92 m_osInterface->pfnResetPerfBufferID(m_osInterface);
93 }
94
IsPrologRequired()95 bool AvcDecodePkt::IsPrologRequired()
96 {
97 return true;
98 }
99
AddForceWakeup(MOS_COMMAND_BUFFER & cmdBuffer)100 MOS_STATUS AvcDecodePkt::AddForceWakeup(MOS_COMMAND_BUFFER &cmdBuffer)
101 {
102 DECODE_FUNC_CALL();
103
104 auto &par = m_miItf->GETPAR_MI_FORCE_WAKEUP();
105 MOS_ZeroMemory(&par, sizeof(mhw::mi::MI_FORCE_WAKEUP_PAR));
106 par.bMFXPowerWellControl = true;
107 par.bMFXPowerWellControlMask = true;
108 par.bHEVCPowerWellControl = false;
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 AvcDecodePkt::SendPrologWithFrameTracking(MOS_COMMAND_BUFFER &cmdBuffer, bool frameTrackingRequested)
117 {
118 DecodeSubPacket *subPacket = m_avcPipeline->GetSubPacket(DecodePacketId(m_avcPipeline, 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 m_mmcState = m_avcPipeline->GetMmcState();
125 bool isMmcEnabled = (m_mmcState != nullptr && m_mmcState->IsMmcEnabled());
126 if (isMmcEnabled)
127 {
128 DECODE_CHK_STATUS(m_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
137 #ifdef _MMC_SUPPORTED
138 genericPrologParams.bMmcEnabled = isMmcEnabled;
139 #endif
140
141 DECODE_CHK_STATUS(Mhw_SendGenericPrologCmdNext(&cmdBuffer, &genericPrologParams, m_miItf));
142
143 subPacket = m_avcPipeline->GetSubPacket(DecodePacketId(m_avcPipeline, predicationSubPacketId));
144 DecodePredicationPkt *predicationPacket = dynamic_cast<DecodePredicationPkt *>(subPacket);
145 DECODE_CHK_NULL(predicationPacket);
146 DECODE_CHK_STATUS(predicationPacket->Execute(cmdBuffer));
147
148 return MOS_STATUS_SUCCESS;
149 }
150
MiFlush(MOS_COMMAND_BUFFER & cmdBuffer)151 MOS_STATUS AvcDecodePkt::MiFlush(MOS_COMMAND_BUFFER &cmdBuffer)
152 {
153 DECODE_FUNC_CALL();
154
155 auto &par = m_miItf->GETPAR_MI_FLUSH_DW();
156 MOS_ZeroMemory(&par, sizeof(mhw::mi::MI_FLUSH_DW_PAR));
157 DECODE_CHK_STATUS(m_miItf->ADDCMD_MI_FLUSH_DW(&cmdBuffer));
158
159 return MOS_STATUS_SUCCESS;
160 }
161
Completed(void * mfxStatus,void * rcsStatus,void * statusReport)162 MOS_STATUS AvcDecodePkt::Completed(void *mfxStatus, void *rcsStatus, void *statusReport)
163 {
164 DECODE_FUNC_CALL();
165
166 DECODE_CHK_NULL(mfxStatus);
167 DECODE_CHK_NULL(statusReport);
168 DECODE_CHK_NULL(m_avcBasicFeature);
169
170 DecodeStatusMfx * decodeStatusMfx = (DecodeStatusMfx *)mfxStatus;
171 DecodeStatusReportData *statusReportData = (DecodeStatusReportData *)statusReport;
172 auto mfxItf = std::static_pointer_cast<mhw::vdbox::mfx::Itf>(m_hwInterface->GetMfxInterfaceNext());
173
174 if (mfxItf)
175 {
176 if ((decodeStatusMfx->m_mmioErrorStatusReg & mfxItf->GetMfxErrorFlagsMask()) != 0)
177 {
178 statusReportData->codecStatus = CODECHAL_STATUS_ERROR;
179 statusReportData->numMbsAffected = decodeStatusMfx->m_mmioMBCountReg & 0xFFFF;
180 }
181 statusReportData->frameCrc = decodeStatusMfx->m_mmioFrameCrcReg;
182 }
183
184 DECODE_VERBOSEMESSAGE("Current Frame Index = %d", statusReportData->currDecodedPic.FrameIdx);
185 DECODE_VERBOSEMESSAGE("FrameCrc = 0x%x", statusReportData->frameCrc);
186
187 return MOS_STATUS_SUCCESS;
188 }
189
CalculateCommandSize(uint32_t & commandBufferSize,uint32_t & requestedPatchListSize)190 MOS_STATUS AvcDecodePkt::CalculateCommandSize(uint32_t &commandBufferSize, uint32_t &requestedPatchListSize)
191 {
192 commandBufferSize = CalculateCommandBufferSize();
193 requestedPatchListSize = CalculatePatchListSize();
194
195 return MOS_STATUS_SUCCESS;
196 }
197
CalculateCommandBufferSize()198 uint32_t AvcDecodePkt::CalculateCommandBufferSize()
199 {
200 uint32_t commandBufferSize = 0;
201
202 // plus 1 is for phantom slice command
203 commandBufferSize = m_pictureStatesSize + m_sliceStatesSize * (m_avcBasicFeature->m_numSlices + 1);
204
205 return (commandBufferSize + COMMAND_BUFFER_RESERVED_SPACE);
206 }
207
CalculatePatchListSize()208 uint32_t AvcDecodePkt::CalculatePatchListSize()
209 {
210 if (!m_osInterface->bUsesPatchList)
211 {
212 return 0;
213 }
214
215 uint32_t requestedPatchListSize = 0;
216 requestedPatchListSize = m_picturePatchListSize + m_slicePatchListSize * (m_avcBasicFeature->m_numSlices + 1);
217
218 return requestedPatchListSize;
219 }
220
ReadMfxStatus(MediaStatusReport * statusReport,MOS_COMMAND_BUFFER & cmdBuffer)221 MOS_STATUS AvcDecodePkt::ReadMfxStatus(MediaStatusReport *statusReport, MOS_COMMAND_BUFFER &cmdBuffer)
222 {
223 DECODE_FUNC_CALL();
224
225 DECODE_CHK_NULL(statusReport);
226
227 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
228 MOS_RESOURCE *osResource = nullptr;
229 uint32_t offset = 0;
230
231 auto &par = m_miItf->GETPAR_MI_STORE_REGISTER_MEM();
232 par = {};
233
234 DECODE_CHK_NULL(m_hwInterface->GetVdencInterfaceNext());
235 auto mmioRegisters = m_hwInterface->GetVdencInterfaceNext()->GetMmioRegisters(MHW_VDBOX_NODE_1);
236
237 DECODE_CHK_STATUS(statusReport->GetAddress(decode::DecodeStatusReportType::DecErrorStatusOffset, osResource, offset));
238 par.presStoreBuffer = osResource;
239 par.dwOffset = offset;
240 par.dwRegister = mmioRegisters->mfxErrorFlagsRegOffset;
241
242 DECODE_CHK_STATUS(m_miItf->ADDCMD_MI_STORE_REGISTER_MEM(&cmdBuffer));
243
244 DECODE_CHK_STATUS(statusReport->GetAddress(decode::DecodeStatusReportType::DecFrameCrcOffset, osResource, offset));
245 par.presStoreBuffer = osResource;
246 par.dwOffset = offset;
247 par.dwRegister = mmioRegisters->mfxFrameCrcRegOffset;
248
249 DECODE_CHK_STATUS(m_miItf->ADDCMD_MI_STORE_REGISTER_MEM(&cmdBuffer));
250
251 DECODE_CHK_STATUS(statusReport->GetAddress(decode::DecodeStatusReportType::DecMBCountOffset, osResource, offset));
252 par.presStoreBuffer = osResource;
253 par.dwOffset = offset;
254 par.dwRegister = mmioRegisters->mfxMBCountRegOffset;
255
256 DECODE_CHK_STATUS(m_miItf->ADDCMD_MI_STORE_REGISTER_MEM(&cmdBuffer));
257
258 return eStatus;
259 }
260
StartStatusReport(uint32_t srType,MOS_COMMAND_BUFFER * cmdBuffer)261 MOS_STATUS AvcDecodePkt::StartStatusReport(uint32_t srType, MOS_COMMAND_BUFFER *cmdBuffer)
262 {
263 DECODE_FUNC_CALL();
264
265 DECODE_CHK_STATUS(MediaPacket::StartStatusReportNext(srType, cmdBuffer));
266
267 SetPerfTag(CODECHAL_DECODE_MODE_AVCVLD, m_avcBasicFeature->m_pictureCodingType);
268
269 MediaPerfProfiler *perfProfiler = MediaPerfProfiler::Instance();
270 DECODE_CHK_NULL(perfProfiler);
271 DECODE_CHK_STATUS(perfProfiler->AddPerfCollectStartCmd(
272 (void *)m_avcPipeline, m_osInterface, m_miItf, cmdBuffer));
273
274 return MOS_STATUS_SUCCESS;
275 }
276
EndStatusReport(uint32_t srType,MOS_COMMAND_BUFFER * cmdBuffer)277 MOS_STATUS AvcDecodePkt::EndStatusReport(uint32_t srType, MOS_COMMAND_BUFFER *cmdBuffer)
278 {
279 DECODE_FUNC_CALL();
280 DECODE_CHK_NULL(cmdBuffer);
281 DECODE_CHK_STATUS(ReadMfxStatus(m_statusReport, *cmdBuffer));
282 DECODE_CHK_STATUS(MediaPacket::EndStatusReportNext(srType, cmdBuffer));
283
284 MediaPerfProfiler *perfProfiler = MediaPerfProfiler::Instance();
285 DECODE_CHK_NULL(perfProfiler);
286 DECODE_CHK_STATUS(perfProfiler->AddPerfCollectEndCmd(
287 (void *)m_avcPipeline, m_osInterface, m_miItf, cmdBuffer));
288
289 // Add Mi flush here to ensure end status tag flushed to memory earlier than completed count
290 DECODE_CHK_STATUS(MiFlush(*cmdBuffer));
291
292 return MOS_STATUS_SUCCESS;
293 }
294
SetCencBatchBuffer(PMOS_COMMAND_BUFFER cmdBuffer)295 MOS_STATUS AvcDecodePkt::SetCencBatchBuffer(
296 PMOS_COMMAND_BUFFER cmdBuffer)
297 {
298 DECODE_FUNC_CALL();
299 DECODE_CHK_NULL(cmdBuffer);
300
301 auto cencBuf = m_avcBasicFeature->m_cencBuf;
302 DECODE_CHK_NULL(cencBuf);
303 MHW_BATCH_BUFFER batchBuffer;
304 MOS_ZeroMemory(&batchBuffer, sizeof(MHW_BATCH_BUFFER));
305 MOS_RESOURCE *resHeap = nullptr;
306 DECODE_CHK_NULL(resHeap = cencBuf->secondLvlBbBlock->GetResource());
307 batchBuffer.OsResource = *resHeap;
308 batchBuffer.dwOffset = cencBuf->secondLvlBbBlock->GetOffset();
309 batchBuffer.iSize = cencBuf->secondLvlBbBlock->GetSize();
310 batchBuffer.bSecondLevel = true;
311 #if (_DEBUG || _RELEASE_INTERNAL)
312 batchBuffer.iLastCurrent = batchBuffer.iSize;
313 #endif // (_DEBUG || _RELEASE_INTERNAL)
314
315 DECODE_CHK_STATUS(m_miItf->ADDCMD_MI_BATCH_BUFFER_START(cmdBuffer, &batchBuffer));
316
317 #if USE_CODECHAL_DEBUG_TOOL
318 CODECHAL_DEBUG_TOOL(
319 CodechalDebugInterface *debugInterface = m_avcPipeline->GetDebugInterface();
320 DECODE_CHK_STATUS(debugInterface->Dump2ndLvlBatch(
321 &batchBuffer,
322 CODECHAL_NUM_MEDIA_STATES,
323 "_2ndLvlBatch"));)
324 #endif
325 // Update GlobalCmdBufId
326 auto &par = m_miItf->GETPAR_MI_STORE_DATA_IMM();
327 par = {};
328 par.pOsResource = cencBuf->resTracker;
329 par.dwValue = cencBuf->trackerId;
330 DECODE_NORMALMESSAGE("dwCmdBufId = %d", par.dwValue);
331 DECODE_CHK_STATUS(m_miItf->ADDCMD_MI_STORE_DATA_IMM(cmdBuffer));
332
333 return MOS_STATUS_SUCCESS;
334 }
335
336 } // namespace decode