1 /*
2 * Copyright (c) 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_av1_packet.cpp
24 //! \brief    Defines the interface for av1 decode packet
25 //!
26 #include "decode_av1_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 Av1DecodePkt::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_av1Pipeline);
40     DECODE_CHK_NULL(m_osInterface);
41 
42     DECODE_CHK_STATUS(CmdPacket::Init());
43 
44     m_av1BasicFeature = dynamic_cast<Av1BasicFeature*>(m_featureManager->GetFeature(FeatureIDs::basicFeature));
45     DECODE_CHK_NULL(m_av1BasicFeature);
46 
47     m_allocator = m_av1Pipeline->GetDecodeAllocator();
48     DECODE_CHK_NULL(m_allocator);
49 
50     DECODE_CHK_STATUS(m_statusReport->RegistObserver(this));
51 
52     DecodeSubPacket* subPacket = m_av1Pipeline->GetSubPacket(DecodePacketId(m_av1Pipeline, av1PictureSubPacketId));
53 
54     m_picturePkt = dynamic_cast<Av1DecodePicPkt*>(subPacket);
55     DECODE_CHK_NULL(m_picturePkt);
56     DECODE_CHK_STATUS(m_picturePkt->CalculateCommandSize(m_pictureStatesSize, m_picturePatchListSize));
57 
58     subPacket = m_av1Pipeline->GetSubPacket(DecodePacketId(m_av1Pipeline, av1TileSubPacketId));
59     m_tilePkt = dynamic_cast<Av1DecodeTilePkt*>(subPacket);
60     DECODE_CHK_NULL(m_tilePkt);
61     DECODE_CHK_STATUS(m_tilePkt->CalculateCommandSize(m_tileStatesSize, m_tilePatchListSize));
62 
63     m_secondLevelBBArray = m_allocator->AllocateBatchBufferArray(
64         m_pictureStatesSize, 1, CODEC_NUM_AV1_SECOND_BB, true, lockableVideoMem);
65     DECODE_CHK_NULL(m_secondLevelBBArray);
66 
67     return MOS_STATUS_SUCCESS;
68 }
69 
Prepare()70 MOS_STATUS Av1DecodePkt::Prepare()
71 {
72     DECODE_FUNC_CALL();
73 
74     DECODE_CHK_NULL(m_av1BasicFeature->m_av1PicParams);
75     m_av1PicParams = m_av1BasicFeature->m_av1PicParams;
76 
77     return MOS_STATUS_SUCCESS;
78 }
79 
Destroy()80 MOS_STATUS Av1DecodePkt::Destroy()
81 {
82     m_statusReport->UnregistObserver(this);
83     if (m_allocator != nullptr)
84     {
85         DECODE_CHK_STATUS(m_allocator->Destroy(m_secondLevelBBArray));
86     }
87 
88     return MOS_STATUS_SUCCESS;
89 }
90 
SetPerfTag(CODECHAL_MODE mode,uint16_t picCodingType)91 void Av1DecodePkt::SetPerfTag(CODECHAL_MODE mode, uint16_t picCodingType)
92 {
93     DECODE_FUNC_CALL();
94 
95     uint16_t perfTag = ((mode << 4) & 0xF0) | (picCodingType & 0xF);
96     m_osInterface->pfnIncPerfFrameID(m_osInterface);
97     m_osInterface->pfnSetPerfTag(m_osInterface, perfTag);
98     m_osInterface->pfnResetPerfBufferID(m_osInterface);
99 }
100 
IsPrologRequired()101 bool Av1DecodePkt::IsPrologRequired()
102 {
103     return true; // if ScalableMode, should set to false.
104 }
105 
AddForceWakeup(MOS_COMMAND_BUFFER & cmdBuffer)106 MOS_STATUS Av1DecodePkt::AddForceWakeup(MOS_COMMAND_BUFFER& cmdBuffer)
107 {
108     DECODE_FUNC_CALL();
109 
110     auto &par = m_miItf->GETPAR_MI_FORCE_WAKEUP();
111     MOS_ZeroMemory(&par, sizeof(mhw::mi::MI_FORCE_WAKEUP_PAR));
112     par.bMFXPowerWellControl                    = false;
113     par.bMFXPowerWellControlMask                = true;
114     par.bHEVCPowerWellControl                   = true;
115     par.bHEVCPowerWellControlMask               = true;
116 
117     DECODE_CHK_STATUS(m_miItf->ADDCMD_MI_FORCE_WAKEUP(&cmdBuffer));
118 
119     return MOS_STATUS_SUCCESS;
120 }
121 
SendPrologWithFrameTracking(MOS_COMMAND_BUFFER & cmdBuffer,bool frameTrackingRequested)122 MOS_STATUS Av1DecodePkt::SendPrologWithFrameTracking(MOS_COMMAND_BUFFER& cmdBuffer, bool frameTrackingRequested)
123 {
124     DecodeSubPacket* subPacket = m_av1Pipeline->GetSubPacket(DecodePacketId(m_av1Pipeline, markerSubPacketId));
125     DecodeMarkerPkt *makerPacket = dynamic_cast<DecodeMarkerPkt*>(subPacket);
126     DECODE_CHK_NULL(makerPacket);
127     DECODE_CHK_STATUS(makerPacket->Execute(cmdBuffer));
128 
129 #ifdef _MMC_SUPPORTED
130     m_mmcState = m_av1Pipeline->GetMmcState();
131     bool isMmcEnabled = (m_mmcState != nullptr && m_mmcState->IsMmcEnabled());
132     if (isMmcEnabled)
133     {
134         DECODE_CHK_STATUS(m_mmcState->SendPrologCmd(&cmdBuffer, false));
135     }
136 #endif
137 
138     MHW_GENERIC_PROLOG_PARAMS  genericPrologParams;
139     MOS_ZeroMemory(&genericPrologParams, sizeof(genericPrologParams));
140     genericPrologParams.pOsInterface = m_osInterface;
141     genericPrologParams.pvMiInterface = nullptr;
142 
143 #ifdef _MMC_SUPPORTED
144     genericPrologParams.bMmcEnabled = isMmcEnabled;
145 #endif
146 
147     DECODE_CHK_STATUS(Mhw_SendGenericPrologCmdNext(&cmdBuffer, &genericPrologParams, m_miItf));
148 
149     subPacket = m_av1Pipeline->GetSubPacket(DecodePacketId(m_av1Pipeline, predicationSubPacketId));
150     DecodePredicationPkt *predicationPacket = dynamic_cast<DecodePredicationPkt*>(subPacket);
151     DECODE_CHK_NULL(predicationPacket);
152     DECODE_CHK_STATUS(predicationPacket->Execute(cmdBuffer));
153 
154     return MOS_STATUS_SUCCESS;
155 }
156 
VdPipelineFlush(MOS_COMMAND_BUFFER & cmdBuffer)157 MOS_STATUS Av1DecodePkt::VdPipelineFlush(MOS_COMMAND_BUFFER & cmdBuffer)
158 {
159     DECODE_FUNC_CALL();
160 
161     auto &par = m_vdencItf->GETPAR_VD_PIPELINE_FLUSH();
162     par       = {};
163     par.waitDoneAV1 = 1;
164     par.flushAV1    = 1;
165     par.waitDoneVDCmdMsgParser = 1;
166     m_vdencItf->ADDCMD_VD_PIPELINE_FLUSH(&cmdBuffer);
167 
168     return MOS_STATUS_SUCCESS;
169 }
170 
MiFlush(MOS_COMMAND_BUFFER & cmdBuffer)171 MOS_STATUS Av1DecodePkt::MiFlush(MOS_COMMAND_BUFFER & cmdBuffer)
172 {
173     DECODE_FUNC_CALL();
174 
175     auto &par = m_miItf->GETPAR_MI_FLUSH_DW();
176     MOS_ZeroMemory(&par, sizeof(mhw::mi::MI_FLUSH_DW_PAR));
177     DECODE_CHK_STATUS(m_miItf->ADDCMD_MI_FLUSH_DW(&cmdBuffer));
178 
179     return MOS_STATUS_SUCCESS;
180 }
181 
Completed(void * mfxStatus,void * rcsStatus,void * statusReport)182 MOS_STATUS Av1DecodePkt::Completed(void *mfxStatus, void *rcsStatus, void *statusReport)
183 {
184     DECODE_FUNC_CALL();
185 
186     DECODE_CHK_NULL(mfxStatus);
187     DECODE_CHK_NULL(statusReport);
188     DECODE_CHK_NULL(m_av1BasicFeature);
189 
190     DecodeStatusMfx *       decodeStatusMfx  = (DecodeStatusMfx *)mfxStatus;
191     DecodeStatusReportData *statusReportData = (DecodeStatusReportData *)statusReport;
192     DECODE_VERBOSEMESSAGE("Current Frame Index = %d", statusReportData->currDecodedPic.FrameIdx);
193 
194     return MOS_STATUS_SUCCESS;
195 }
196 
CalculateCommandSize(uint32_t & commandBufferSize,uint32_t & requestedPatchListSize)197 MOS_STATUS Av1DecodePkt::CalculateCommandSize(uint32_t &commandBufferSize, uint32_t &requestedPatchListSize)
198 {
199     commandBufferSize = CalculateCommandBufferSize();
200     requestedPatchListSize = CalculatePatchListSize();
201     return MOS_STATUS_SUCCESS;
202 }
203 
CalculateCommandBufferSize()204 uint32_t Av1DecodePkt::CalculateCommandBufferSize()
205 {
206     uint32_t commandBufferSize = 0;
207 
208     commandBufferSize = m_pictureStatesSize + m_tileStatesSize;
209 
210     return (commandBufferSize + COMMAND_BUFFER_RESERVED_SPACE);
211 }
212 
CalculatePatchListSize()213 uint32_t Av1DecodePkt::CalculatePatchListSize()
214 {
215     if (!m_osInterface->bUsesPatchList)
216     {
217         return 0;
218     }
219 
220     uint32_t requestedPatchListSize = 0;
221 
222     requestedPatchListSize = m_picturePatchListSize + m_tilePatchListSize;
223 
224     return requestedPatchListSize;
225 }
226 
ReadAvpStatus(MediaStatusReport * statusReport,MOS_COMMAND_BUFFER & cmdBuffer)227 MOS_STATUS Av1DecodePkt::ReadAvpStatus(MediaStatusReport* statusReport, MOS_COMMAND_BUFFER& cmdBuffer)
228 {
229     DECODE_FUNC_CALL();
230 
231     DECODE_CHK_NULL(statusReport);
232 
233     if (!m_osInterface->bSimIsActive)
234     {
235         MOS_RESOURCE* osResource = nullptr;
236         uint32_t offset = 0;
237 
238         auto &par = m_miItf->GETPAR_MI_STORE_REGISTER_MEM();
239         MOS_ZeroMemory(&par, sizeof(mhw::mi::MI_STORE_REGISTER_MEM_PAR));
240 
241         DECODE_CHK_NULL(m_hwInterface->GetAvpInterfaceNext());
242         auto mmioRegistersAvp = m_hwInterface->GetAvpInterfaceNext()->GetMmioRegisters(MHW_VDBOX_NODE_1);
243 
244         DECODE_CHK_STATUS(statusReport->GetAddress(decode::DecodeStatusReportType::DecErrorStatusOffset, osResource, offset));
245         par.presStoreBuffer = osResource;
246         par.dwOffset        = offset;
247         par.dwRegister      = mmioRegistersAvp->avpAv1DecErrorStatusAddrRegOffset;
248 
249         DECODE_CHK_STATUS(m_miItf->ADDCMD_MI_STORE_REGISTER_MEM(&cmdBuffer));
250     }
251 
252     return MOS_STATUS_SUCCESS;
253 }
254 
StartStatusReport(uint32_t srType,MOS_COMMAND_BUFFER * cmdBuffer)255 MOS_STATUS Av1DecodePkt::StartStatusReport(uint32_t srType, MOS_COMMAND_BUFFER* cmdBuffer)
256 {
257     DECODE_FUNC_CALL();
258 
259     DECODE_CHK_STATUS(MediaPacket::StartStatusReportNext(srType, cmdBuffer));
260 
261     SetPerfTag(CODECHAL_DECODE_MODE_AV1VLD, m_av1BasicFeature->m_pictureCodingType);
262     MediaPerfProfiler *perfProfiler = MediaPerfProfiler::Instance();
263     DECODE_CHK_NULL(perfProfiler);
264     DECODE_CHK_STATUS(perfProfiler->AddPerfCollectStartCmd(
265         (void*)m_av1Pipeline, m_osInterface, m_miItf, cmdBuffer));
266 
267     return MOS_STATUS_SUCCESS;
268 }
269 
EndStatusReport(uint32_t srType,MOS_COMMAND_BUFFER * cmdBuffer)270 MOS_STATUS Av1DecodePkt::EndStatusReport(uint32_t srType, MOS_COMMAND_BUFFER* cmdBuffer)
271 {
272     DECODE_FUNC_CALL();
273 
274     DECODE_CHK_NULL(cmdBuffer);
275     DECODE_CHK_STATUS(ReadAvpStatus( m_statusReport, *cmdBuffer));
276     DECODE_CHK_STATUS(MediaPacket::EndStatusReportNext(srType, cmdBuffer));
277 
278     MediaPerfProfiler *perfProfiler = MediaPerfProfiler::Instance();
279     DECODE_CHK_NULL(perfProfiler);
280     DECODE_CHK_STATUS(perfProfiler->AddPerfCollectEndCmd(
281         (void*)m_av1Pipeline, m_osInterface, m_miItf, cmdBuffer));
282 
283     // Add Mi flush here to ensure end status tag flushed to memory earlier than completed count
284     DECODE_CHK_STATUS(MiFlush(*cmdBuffer));
285 
286     return MOS_STATUS_SUCCESS;
287 }
288 
InitPicLevelCmdBuffer(MHW_BATCH_BUFFER & batchBuffer,uint8_t * batchBufBase)289 MOS_STATUS Av1DecodePkt::InitPicLevelCmdBuffer(MHW_BATCH_BUFFER &batchBuffer, uint8_t *batchBufBase)
290 {
291     DECODE_FUNC_CALL();
292 
293     auto &cmdBuffer = m_picCmdBuffer;
294     MOS_ZeroMemory(&cmdBuffer, sizeof(MOS_COMMAND_BUFFER));
295     cmdBuffer.pCmdBase   = (uint32_t*)batchBufBase;
296     cmdBuffer.pCmdPtr    = cmdBuffer.pCmdBase;
297     cmdBuffer.iRemaining = batchBuffer.iSize;
298     cmdBuffer.OsResource = batchBuffer.OsResource;
299 
300     return MOS_STATUS_SUCCESS;
301 }
302 
303 }
304