1 /*
2 * Copyright (c) 2021-2022, 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_mpeg2_packet.cpp
24 //! \brief Defines the interface for mpeg2 decode packet.
25 //!
26
27 #include "decode_mpeg2_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 Mpeg2DecodePkt::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_mpeg2Pipeline);
43 DECODE_CHK_NULL(m_osInterface);
44
45 DECODE_CHK_STATUS(CmdPacket::Init());
46
47 m_mpeg2BasicFeature = dynamic_cast<Mpeg2BasicFeature*>(m_featureManager->GetFeature(FeatureIDs::basicFeature));
48 DECODE_CHK_NULL(m_mpeg2BasicFeature);
49
50 m_allocator = m_mpeg2Pipeline->GetDecodeAllocator();
51 DECODE_CHK_NULL(m_allocator);
52
53 DECODE_CHK_STATUS(m_statusReport->RegistObserver(this));
54
55 DecodeSubPacket* subPacket = m_mpeg2Pipeline->GetSubPacket(DecodePacketId(m_mpeg2Pipeline, mpeg2PictureSubPacketId));
56 m_picturePkt = dynamic_cast<Mpeg2DecodePicPkt*>(subPacket);
57 DECODE_CHK_NULL(m_picturePkt);
58 DECODE_CHK_STATUS(m_picturePkt->CalculateCommandSize(m_pictureStatesSize, m_picturePatchListSize));
59
60 uint32_t secondLevelBBSize = 0;
61 uint32_t numMacroblocks = m_mpeg2BasicFeature->m_picWidthInMb * m_mpeg2BasicFeature->m_picHeightInMb;
62
63 if (m_mpeg2BasicFeature->m_mode == CODECHAL_DECODE_MODE_MPEG2VLD)
64 {
65 subPacket = m_mpeg2Pipeline->GetSubPacket(DecodePacketId(m_mpeg2Pipeline, mpeg2SliceSubPacketId));
66 m_slicePkt = dynamic_cast<Mpeg2DecodeSlcPkt*>(subPacket);
67 DECODE_CHK_NULL(m_slicePkt);
68 DECODE_CHK_STATUS(m_slicePkt->CalculateCommandSize(m_sliceStatesSize, m_slicePatchListSize));
69 secondLevelBBSize = (m_sliceStatesSize * numMacroblocks) + m_hwInterface->m_sizeOfCmdBatchBufferEnd;
70 }
71 else
72 {
73 subPacket = m_mpeg2Pipeline->GetSubPacket(DecodePacketId(m_mpeg2Pipeline, mpeg2MbSubPacketId));
74 m_mbPkt = dynamic_cast<Mpeg2DecodeMbPkt*>(subPacket);
75 DECODE_CHK_NULL(m_mbPkt);
76 DECODE_CHK_STATUS(m_mbPkt->CalculateCommandSize(m_mbStatesSize, m_mbPatchListSize));
77 secondLevelBBSize = (m_mbStatesSize * numMacroblocks) + m_hwInterface->m_sizeOfCmdBatchBufferEnd;
78 }
79
80 m_secondLevelBBArray = m_allocator->AllocateBatchBufferArray(
81 secondLevelBBSize, 1, CODEC_MPEG2_BATCH_BUFFERS_NUM, true, lockableVideoMem);
82 DECODE_CHK_NULL(m_secondLevelBBArray);
83
84 return MOS_STATUS_SUCCESS;
85 }
86
Prepare()87 MOS_STATUS Mpeg2DecodePkt::Prepare()
88 {
89 DECODE_FUNC_CALL();
90
91 DECODE_CHK_NULL(m_mpeg2BasicFeature->m_mpeg2PicParams);
92 m_mpeg2PicParams = m_mpeg2BasicFeature->m_mpeg2PicParams;
93
94 return MOS_STATUS_SUCCESS;
95 }
96
Destroy()97 MOS_STATUS Mpeg2DecodePkt::Destroy()
98 {
99 m_statusReport->UnregistObserver(this);
100 if (m_allocator != nullptr)
101 {
102 DECODE_CHK_STATUS(m_allocator->Destroy(m_secondLevelBBArray));
103 }
104
105 return MOS_STATUS_SUCCESS;
106 }
107
SetPerfTag(CODECHAL_MODE mode,uint16_t picCodingType)108 void Mpeg2DecodePkt::SetPerfTag(CODECHAL_MODE mode, uint16_t picCodingType)
109 {
110 DECODE_FUNC_CALL();
111
112 uint16_t perfTag = ((mode << 4) & 0xF0) | (picCodingType & 0xF);
113 m_osInterface->pfnIncPerfFrameID(m_osInterface);
114 m_osInterface->pfnSetPerfTag(m_osInterface, perfTag);
115 m_osInterface->pfnResetPerfBufferID(m_osInterface);
116 }
117
IsPrologRequired()118 bool Mpeg2DecodePkt::IsPrologRequired()
119 {
120 return true;
121 }
122
AddForceWakeup(MOS_COMMAND_BUFFER & cmdBuffer)123 MOS_STATUS Mpeg2DecodePkt::AddForceWakeup(MOS_COMMAND_BUFFER& cmdBuffer)
124 {
125 DECODE_FUNC_CALL();
126
127 auto &par = m_miItf->GETPAR_MI_FORCE_WAKEUP();
128 par = {};
129 par.bMFXPowerWellControl = true;
130 par.bMFXPowerWellControlMask = true;
131 par.bHEVCPowerWellControl = false;
132 par.bHEVCPowerWellControlMask = true;
133
134 DECODE_CHK_STATUS(m_miItf->ADDCMD_MI_FORCE_WAKEUP(&cmdBuffer));
135
136 return MOS_STATUS_SUCCESS;
137 }
138
SendPrologWithFrameTracking(MOS_COMMAND_BUFFER & cmdBuffer,bool frameTrackingRequested)139 MOS_STATUS Mpeg2DecodePkt::SendPrologWithFrameTracking(MOS_COMMAND_BUFFER& cmdBuffer, bool frameTrackingRequested)
140 {
141 DECODE_FUNC_CALL();
142
143 DecodeSubPacket* subPacket = m_mpeg2Pipeline->GetSubPacket(DecodePacketId(m_mpeg2Pipeline, markerSubPacketId));
144 DecodeMarkerPkt *makerPacket = dynamic_cast<DecodeMarkerPkt*>(subPacket);
145 DECODE_CHK_NULL(makerPacket);
146 DECODE_CHK_STATUS(makerPacket->Execute(cmdBuffer));
147
148 #ifdef _MMC_SUPPORTED
149 m_mmcState = m_mpeg2Pipeline->GetMmcState();
150 bool isMmcEnabled = (m_mmcState != nullptr && m_mmcState->IsMmcEnabled());
151 if (isMmcEnabled)
152 {
153 DECODE_CHK_STATUS(m_mmcState->SendPrologCmd(&cmdBuffer, false));
154 }
155 #endif
156
157 MHW_GENERIC_PROLOG_PARAMS genericPrologParams;
158 MOS_ZeroMemory(&genericPrologParams, sizeof(genericPrologParams));
159 genericPrologParams.pOsInterface = m_osInterface;
160 genericPrologParams.pvMiInterface = nullptr;
161
162 #ifdef _MMC_SUPPORTED
163 genericPrologParams.bMmcEnabled = isMmcEnabled;
164 #endif
165
166 DECODE_CHK_STATUS(Mhw_SendGenericPrologCmdNext(&cmdBuffer, &genericPrologParams, m_miItf));
167
168 subPacket = m_mpeg2Pipeline->GetSubPacket(DecodePacketId(m_mpeg2Pipeline, predicationSubPacketId));
169 DecodePredicationPkt *predicationPacket = dynamic_cast<DecodePredicationPkt*>(subPacket);
170 DECODE_CHK_NULL(predicationPacket);
171 DECODE_CHK_STATUS(predicationPacket->Execute(cmdBuffer));
172
173 return MOS_STATUS_SUCCESS;
174 }
175
MiFlush(MOS_COMMAND_BUFFER & cmdBuffer)176 MOS_STATUS Mpeg2DecodePkt::MiFlush(MOS_COMMAND_BUFFER & cmdBuffer)
177 {
178 DECODE_FUNC_CALL();
179
180 auto &par = m_miItf->GETPAR_MI_FLUSH_DW();
181 par = {};
182 DECODE_CHK_STATUS(m_miItf->ADDCMD_MI_FLUSH_DW(&cmdBuffer));
183
184 return MOS_STATUS_SUCCESS;
185 }
186
Completed(void * mfxStatus,void * rcsStatus,void * statusReport)187 MOS_STATUS Mpeg2DecodePkt::Completed(void *mfxStatus, void *rcsStatus, void *statusReport)
188 {
189 DECODE_FUNC_CALL();
190
191 DecodeStatusMfx *decodeStatusMfx = (DecodeStatusMfx *)mfxStatus;
192 DecodeStatusReportData *statusReportData = (DecodeStatusReportData *)statusReport;
193 auto mfxItf = std::static_pointer_cast<mhw::vdbox::mfx::Itf>(m_hwInterface->GetMfxInterfaceNext());
194
195 if (mfxItf && decodeStatusMfx && statusReportData)
196 {
197 if ((decodeStatusMfx->m_mmioErrorStatusReg & mfxItf->GetMfxErrorFlagsMask()) != 0)
198 {
199 statusReportData->codecStatus = CODECHAL_STATUS_ERROR;
200 statusReportData->numMbsAffected = decodeStatusMfx->m_mmioMBCountReg & 0xFFFF;
201 }
202 DECODE_VERBOSEMESSAGE("Current Frame Index = %d", statusReportData->currDecodedPic.FrameIdx);
203 }
204
205 return MOS_STATUS_SUCCESS;
206 }
207
CalculateCommandSize(uint32_t & commandBufferSize,uint32_t & requestedPatchListSize)208 MOS_STATUS Mpeg2DecodePkt::CalculateCommandSize(uint32_t &commandBufferSize, uint32_t &requestedPatchListSize)
209 {
210 commandBufferSize = CalculateCommandBufferSize();
211 requestedPatchListSize = CalculatePatchListSize();
212
213 return MOS_STATUS_SUCCESS;
214 }
215
CalculateCommandBufferSize()216 uint32_t Mpeg2DecodePkt::CalculateCommandBufferSize()
217 {
218 // slice/macroblock level commands are put into 2nd level BB.
219 return (m_pictureStatesSize + COMMAND_BUFFER_RESERVED_SPACE);
220 }
221
CalculatePatchListSize()222 uint32_t Mpeg2DecodePkt::CalculatePatchListSize()
223 {
224 if (!m_osInterface->bUsesPatchList)
225 {
226 return 0;
227 }
228
229 return m_picturePatchListSize;
230 }
231
ReadMfxStatus(MediaStatusReport * statusReport,MOS_COMMAND_BUFFER & cmdBuffer)232 MOS_STATUS Mpeg2DecodePkt::ReadMfxStatus(MediaStatusReport* statusReport, MOS_COMMAND_BUFFER& cmdBuffer)
233 {
234 DECODE_FUNC_CALL();
235
236 DECODE_CHK_NULL(statusReport);
237
238 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
239 MOS_RESOURCE* osResource = nullptr;
240 uint32_t offset = 0;
241
242 auto &par = m_miItf->GETPAR_MI_STORE_REGISTER_MEM();
243 par = {};
244
245 DECODE_CHK_NULL(m_hwInterface->GetVdencInterfaceNext());
246 auto mmioRegisters = m_hwInterface->GetVdencInterfaceNext()->GetMmioRegisters(MHW_VDBOX_NODE_1);
247
248 DECODE_CHK_STATUS(statusReport->GetAddress(decode::DecodeStatusReportType::DecErrorStatusOffset, osResource, offset));
249 par.presStoreBuffer = osResource;
250 par.dwOffset = offset;
251 par.dwRegister = mmioRegisters->mfxErrorFlagsRegOffset;
252
253 DECODE_CHK_STATUS(m_miItf->ADDCMD_MI_STORE_REGISTER_MEM(&cmdBuffer));
254
255 DECODE_CHK_STATUS(statusReport->GetAddress(decode::DecodeStatusReportType::DecMBCountOffset, osResource, offset));
256 par.presStoreBuffer = osResource;
257 par.dwOffset = offset;
258 par.dwRegister = mmioRegisters->mfxMBCountRegOffset;
259
260 DECODE_CHK_STATUS(m_miItf->ADDCMD_MI_STORE_REGISTER_MEM(&cmdBuffer));
261
262 return MOS_STATUS_SUCCESS;
263 }
264
StartStatusReport(uint32_t srType,MOS_COMMAND_BUFFER * cmdBuffer)265 MOS_STATUS Mpeg2DecodePkt::StartStatusReport(uint32_t srType, MOS_COMMAND_BUFFER* cmdBuffer)
266 {
267 DECODE_FUNC_CALL();
268
269 DECODE_CHK_STATUS(MediaPacket::StartStatusReportNext(srType, cmdBuffer));
270
271 SetPerfTag(m_mpeg2BasicFeature->m_mode, m_mpeg2BasicFeature->m_pictureCodingType);
272
273 MediaPerfProfiler *perfProfiler = MediaPerfProfiler::Instance();
274 DECODE_CHK_NULL(perfProfiler);
275 DECODE_CHK_STATUS(perfProfiler->AddPerfCollectStartCmd(
276 (void*)m_mpeg2Pipeline, m_osInterface, m_miItf, cmdBuffer));
277
278 return MOS_STATUS_SUCCESS;
279 }
280
EndStatusReport(uint32_t srType,MOS_COMMAND_BUFFER * cmdBuffer)281 MOS_STATUS Mpeg2DecodePkt::EndStatusReport(uint32_t srType, MOS_COMMAND_BUFFER* cmdBuffer)
282 {
283 DECODE_FUNC_CALL();
284
285 DECODE_CHK_NULL(cmdBuffer);
286 DECODE_CHK_STATUS(ReadMfxStatus(m_statusReport, *cmdBuffer));
287 DECODE_CHK_STATUS(MediaPacket::EndStatusReportNext(srType, cmdBuffer));
288
289 MediaPerfProfiler *perfProfiler = MediaPerfProfiler::Instance();
290 DECODE_CHK_NULL(perfProfiler);
291 DECODE_CHK_STATUS(perfProfiler->AddPerfCollectEndCmd(
292 (void*)m_mpeg2Pipeline, m_osInterface, m_miItf, cmdBuffer));
293
294 DECODE_CHK_STATUS(MiFlush(*cmdBuffer));
295
296 return MOS_STATUS_SUCCESS;
297 }
298
299 }
300