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