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