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