1 /*
2 * Copyright (c) 2011-2020, 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     codechal_decode_vp8_g11.cpp
24 //! \brief    Implements the decode interface extension for VP8.
25 //! \details  Implements all functions and constants required by CodecHal for VP8 decoding.
26 //!
27 
28 #include "codechal_decoder.h"
29 #include "codechal_decode_vp8_g11.h"
30 #include "mhw_vdbox_mfx_g11_X.h"
31 #include "hal_oca_interface.h"
32 
~CodechalDecodeVp8G11()33 CodechalDecodeVp8G11::~CodechalDecodeVp8G11()
34 {
35     CODECHAL_DECODE_FUNCTION_ENTER;
36 
37     if (m_veState != nullptr)
38     {
39         MOS_FreeMemAndSetNull(m_veState);
40         m_veState = nullptr;
41     }
42 }
43 
SetGpuCtxCreatOption(CodechalSetting * codecHalSetting)44 MOS_STATUS CodechalDecodeVp8G11::SetGpuCtxCreatOption(
45     CodechalSetting *          codecHalSetting)
46 {
47     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
48 
49     CODECHAL_DECODE_FUNCTION_ENTER;
50 
51     if (!MOS_VE_CTXBASEDSCHEDULING_SUPPORTED(m_osInterface))
52     {
53         CodechalDecode::SetGpuCtxCreatOption(codecHalSetting);
54     }
55     else
56     {
57         m_gpuCtxCreatOpt = MOS_New(MOS_GPUCTX_CREATOPTIONS_ENHANCED);
58 
59         CODECHAL_DECODE_CHK_STATUS_RETURN(CodecHalDecodeSinglePipeVE_ConstructParmsForGpuCtxCreation(
60             m_veState,
61             (PMOS_GPUCTX_CREATOPTIONS_ENHANCED)m_gpuCtxCreatOpt,
62             false));
63         m_videoContext = MOS_GPU_CONTEXT_VIDEO; // Move functionality to CodecHalDecodeMapGpuNodeToGpuContex
64     }
65     return eStatus;
66 }
67 
SetFrameStates()68 MOS_STATUS CodechalDecodeVp8G11::SetFrameStates()
69 {
70     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
71 
72     CODECHAL_DECODE_FUNCTION_ENTER;
73 
74     CODECHAL_DECODE_CHK_STATUS_RETURN(CodechalDecodeVp8::SetFrameStates());
75 
76     if ( MOS_VE_SUPPORTED(m_osInterface))
77     {
78         if (!MOS_VE_CTXBASEDSCHEDULING_SUPPORTED(m_osInterface))
79         {
80             MOS_VIRTUALENGINE_SET_PARAMS  vesetParams;
81 
82             MOS_ZeroMemory(&vesetParams, sizeof(vesetParams));
83             vesetParams.bSFCInUse = false;
84             vesetParams.bNeedSyncWithPrevious = true;
85             vesetParams.bSameEngineAsLastSubmission = false;
86             CODECHAL_DECODE_CHK_STATUS_RETURN(CodecHalDecodeSinglePipeVE_SetHintParams(m_veState, &vesetParams));
87         }
88     }
89 
90     return eStatus;
91 }
92 
DecodeStateLevel()93 MOS_STATUS CodechalDecodeVp8G11::DecodeStateLevel()
94 {
95     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
96 
97     CODECHAL_DECODE_FUNCTION_ENTER;
98 
99     PCODEC_REF_LIST *vp8RefList = m_vp8RefList;
100 
101     uint8_t lastRefPicIndex   = m_vp8PicParams->ucLastRefPicIndex;
102     uint8_t goldenRefPicIndex = m_vp8PicParams->ucGoldenRefPicIndex;
103     uint8_t altRefPicIndex    = m_vp8PicParams->ucAltRefPicIndex;
104 
105     PMOS_SURFACE destSurface = &m_destSurface;
106     if (m_vp8PicParams->key_frame)  // reference surface should be nullptr when key_frame == true
107     {
108         m_presLastRefSurface   = nullptr;
109         m_presGoldenRefSurface = nullptr;
110         m_presAltRefSurface    = nullptr;
111     }
112     else
113     {
114         if((Mos_ResourceIsNull(&vp8RefList[m_vp8PicParams->ucLastRefPicIndex]->resRefPic)) && (m_presLastRefSurface))
115         {
116             vp8RefList[m_vp8PicParams->ucLastRefPicIndex]->resRefPic = *m_presLastRefSurface;
117         }
118         else
119         {
120             m_presLastRefSurface   = &(vp8RefList[lastRefPicIndex]->resRefPic);
121         }
122         if((Mos_ResourceIsNull(&vp8RefList[m_vp8PicParams->ucGoldenRefPicIndex]->resRefPic)) && (m_presGoldenRefSurface))
123         {
124             vp8RefList[m_vp8PicParams->ucGoldenRefPicIndex]->resRefPic = *m_presGoldenRefSurface;
125         }
126         else
127         {
128             m_presGoldenRefSurface = &(vp8RefList[goldenRefPicIndex]->resRefPic);
129         }
130         if((Mos_ResourceIsNull(&vp8RefList[m_vp8PicParams->ucAltRefPicIndex]->resRefPic)) && (m_presAltRefSurface))
131         {
132             vp8RefList[m_vp8PicParams->ucAltRefPicIndex]->resRefPic = *m_presAltRefSurface;
133         }
134         else
135         {
136             m_presAltRefSurface    = &(vp8RefList[altRefPicIndex]->resRefPic);
137         }
138     }
139 
140     MOS_COMMAND_BUFFER cmdBuffer;
141     CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(m_osInterface, &cmdBuffer, 0));
142 
143     auto mmioRegisters = m_hwInterface->GetMfxInterface()->GetMmioRegisters(m_vdboxIndex);
144     HalOcaInterface::On1stLevelBBStart(cmdBuffer, *m_osInterface->pOsContext, m_osInterface->CurrentGpuContextHandle, *m_miInterface, *mmioRegisters);
145 
146     MHW_VDBOX_PIPE_MODE_SELECT_PARAMS pipeModeSelectParams;
147     pipeModeSelectParams.Mode               = m_mode;
148     pipeModeSelectParams.bStreamOutEnabled  = m_streamOutEnabled;
149     pipeModeSelectParams.bPostDeblockOutEnable = m_deblockingEnabled;
150     pipeModeSelectParams.bPreDeblockOutEnable  = !m_deblockingEnabled;
151     pipeModeSelectParams.bShortFormatInUse     = m_shortFormatInUse;
152 
153     MHW_VDBOX_SURFACE_PARAMS surfaceParams;
154     MOS_ZeroMemory(&surfaceParams, sizeof(surfaceParams));
155     surfaceParams.Mode = m_mode;
156     surfaceParams.psSurface = destSurface;
157 
158     MHW_VDBOX_PIPE_BUF_ADDR_PARAMS pipeBufAddrParams;
159     pipeBufAddrParams.Mode = m_mode;
160     // MMC is only enabled for frame decoding and no interlaced support in VP8
161     // So no need to check frame/field type here.
162     if (m_deblockingEnabled)
163     {
164         pipeBufAddrParams.psPostDeblockSurface = destSurface;
165     }
166     else
167     {
168         pipeBufAddrParams.psPreDeblockSurface = destSurface;
169     }
170 
171 #ifdef _MMC_SUPPORTED
172     CODECHAL_DECODE_CHK_STATUS_RETURN(m_mmc->SetPipeBufAddr(&pipeBufAddrParams));
173 #endif
174 
175     // when there is no last, golden and alternate reference,
176     // the index is set to the destination frame index
177     pipeBufAddrParams.presReferences[CodechalDecodeLastRef]      = m_presLastRefSurface;
178     pipeBufAddrParams.presReferences[CodechalDecodeGoldenRef]    = m_presGoldenRefSurface;
179     pipeBufAddrParams.presReferences[CodechalDecodeAlternateRef] = m_presAltRefSurface;
180 
181     pipeBufAddrParams.presMfdIntraRowStoreScratchBuffer            = &m_resMfdIntraRowStoreScratchBuffer;
182     pipeBufAddrParams.presMfdDeblockingFilterRowStoreScratchBuffer = &m_resMfdDeblockingFilterRowStoreScratchBuffer;
183     if (m_streamOutEnabled)
184     {
185         pipeBufAddrParams.presStreamOutBuffer =
186             &(m_streamOutBuffer[m_streamOutCurrBufIdx]);
187     }
188 
189     // set all ref pic addresses to valid addresses for error concealment purpose
190     for (uint32_t i = 0; i <= CodechalDecodeAlternateRef; i++)
191     {
192         if (pipeBufAddrParams.presReferences[i] == nullptr &&
193             MEDIA_IS_WA(m_waTable, WaDummyReference) &&
194             !Mos_ResourceIsNull(&m_dummyReference.OsResource))
195         {
196             pipeBufAddrParams.presReferences[i] = &m_dummyReference.OsResource;
197         }
198     }
199 
200 #ifdef _MMC_SUPPORTED
201     CODECHAL_DECODE_CHK_STATUS_RETURN(m_mmc->CheckReferenceList(&pipeBufAddrParams));
202 
203     CODECHAL_DECODE_CHK_STATUS_RETURN(m_mmc->SetRefrenceSync(m_disableDecodeSyncLock, m_disableLockForTranscode));
204 #endif
205 
206     MHW_VDBOX_IND_OBJ_BASE_ADDR_PARAMS indObjBaseAddrParams;
207     MOS_ZeroMemory(&indObjBaseAddrParams, sizeof(indObjBaseAddrParams));
208     indObjBaseAddrParams.Mode = m_mode;
209     indObjBaseAddrParams.dwDataSize     = m_dataSize;
210     indObjBaseAddrParams.presDataBuffer = &m_resDataBuffer;
211 
212     MHW_VDBOX_BSP_BUF_BASE_ADDR_PARAMS bspBufBaseAddrParams;
213     MOS_ZeroMemory(&bspBufBaseAddrParams, sizeof(bspBufBaseAddrParams));
214     bspBufBaseAddrParams.presBsdMpcRowStoreScratchBuffer = &m_resBsdMpcRowStoreScratchBuffer;
215     bspBufBaseAddrParams.presMprRowStoreScratchBuffer    = &m_resMprRowStoreScratchBuffer;
216 
217     MHW_VDBOX_VP8_PIC_STATE vp8PicState;
218     vp8PicState.pVp8PicParams                  = m_vp8PicParams;
219     vp8PicState.pVp8IqMatrixParams             = m_vp8IqMatrixParams;
220     vp8PicState.presSegmentationIdStreamBuffer = &m_resSegmentationIdStreamBuffer;
221     vp8PicState.dwCoefProbTableOffset = 0;
222     vp8PicState.presCoefProbBuffer             = &m_resCoefProbBuffer;
223 
224     CODECHAL_DECODE_CHK_STATUS_RETURN(SendPrologWithFrameTracking(
225         &cmdBuffer, true));
226 
227     if (m_statusQueryReportingEnabled)
228     {
229         CODECHAL_DECODE_CHK_STATUS_RETURN(StartStatusReport(&cmdBuffer));
230     }
231 
232     CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxPipeModeSelectCmd(&cmdBuffer, &pipeModeSelectParams));
233 
234     CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxSurfaceCmd(&cmdBuffer, &surfaceParams));
235 
236     CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxPipeBufAddrCmd(&cmdBuffer, &pipeBufAddrParams));
237 
238     CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxIndObjBaseAddrCmd(&cmdBuffer, &indObjBaseAddrParams));
239 
240     CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxBspBufBaseAddrCmd(&cmdBuffer, &bspBufBaseAddrParams));
241 
242     CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxVp8PicCmd(&cmdBuffer, &vp8PicState));
243 
244     m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0);
245 
246     return eStatus;
247 }
248 
DecodePrimitiveLevel()249 MOS_STATUS CodechalDecodeVp8G11::DecodePrimitiveLevel()
250 {
251     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
252 
253     CODECHAL_DECODE_FUNCTION_ENTER;
254 
255     CODECHAL_DECODE_CHK_NULL_RETURN(m_osInterface);
256 
257     MOS_COMMAND_BUFFER cmdBuffer;
258     CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(m_osInterface, &cmdBuffer, 0));
259 
260     // Fill BSD Object Commands
261     MHW_VDBOX_VP8_BSD_PARAMS vp8BsdParams;
262     vp8BsdParams.pVp8PicParams = m_vp8PicParams;
263 
264     CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfdVp8BsdObjectCmd(&cmdBuffer, &vp8BsdParams));
265 
266     // Check if destination surface needs to be synchronized
267     MOS_SYNC_PARAMS syncParams;
268     syncParams = g_cInitSyncParams;
269     syncParams.GpuContext = m_videoContext;
270     syncParams.presSyncResource         = &m_destSurface.OsResource;
271     syncParams.bReadOnly = false;
272     syncParams.bDisableDecodeSyncLock = m_disableDecodeSyncLock;
273     syncParams.bDisableLockForTranscode = m_disableLockForTranscode;
274 
275     CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnPerformOverlaySync(m_osInterface, &syncParams));
276     CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnResourceWait(m_osInterface, &syncParams));
277 
278     // Update the resource tag (s/w tag) for On-Demand Sync
279     m_osInterface->pfnSetResourceSyncTag(m_osInterface, &syncParams);
280 
281     MHW_MI_FLUSH_DW_PARAMS flushDwParams;
282     MOS_ZeroMemory(&flushDwParams, sizeof(flushDwParams));
283 
284     CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd(&cmdBuffer, &flushDwParams));
285 
286     // Update the tag in GPU Sync eStatus buffer (H/W Tag) to match the current S/W tag
287     if (m_osInterface->bTagResourceSync)
288     {
289         CODECHAL_DECODE_CHK_STATUS_RETURN(m_hwInterface->WriteSyncTagToResource(&cmdBuffer, &syncParams));
290     }
291 
292     if (m_statusQueryReportingEnabled)
293     {
294         CodechalDecodeStatusReport decodeStatusReport;
295 
296         decodeStatusReport.m_statusReportNumber = m_statusReportFeedbackNumber;
297         decodeStatusReport.m_currDecodedPic     = m_vp8PicParams->CurrPic;
298         decodeStatusReport.m_currDeblockedPic   = m_vp8PicParams->CurrPic;
299         decodeStatusReport.m_codecStatus        = CODECHAL_STATUS_UNAVAILABLE;
300         decodeStatusReport.m_currDecodedPicRes  = m_vp8RefList[m_vp8PicParams->CurrPic.FrameIdx]->resRefPic;
301         CODECHAL_DEBUG_TOOL(
302             decodeStatusReport.m_secondField = CodecHal_PictureIsBottomField(m_vp8PicParams->CurrPic);
303             decodeStatusReport.m_frameType   = m_perfType;)
304         CODECHAL_DECODE_CHK_STATUS_RETURN(EndStatusReport(decodeStatusReport, &cmdBuffer));
305     }
306 
307     CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferEnd(&cmdBuffer, nullptr));
308 
309     m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0);
310 
311     CODECHAL_DEBUG_TOOL(
312         CODECHAL_DECODE_CHK_STATUS_RETURN(m_debugInterface->DumpCmdBuffer(
313             &cmdBuffer,
314             CODECHAL_NUM_MEDIA_STATES,
315             "_DEC"));
316     )
317 
318         if ( MOS_VE_SUPPORTED(m_osInterface))
319         {
320             CodecHalDecodeSinglePipeVE_PopulateHintParams(m_veState, &cmdBuffer, true);
321         }
322 
323         if (m_huCCopyInUse)
324         {
325             syncParams                  = g_cInitSyncParams;
326             syncParams.GpuContext       = m_videoContextForWa;
327             syncParams.presSyncResource = &m_resSyncObjectWaContextInUse;
328 
329             CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineSignal(m_osInterface, &syncParams));
330 
331             syncParams                  = g_cInitSyncParams;
332             syncParams.GpuContext       = m_videoContext;
333             syncParams.presSyncResource = &m_resSyncObjectWaContextInUse;
334 
335             CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineWait(m_osInterface, &syncParams));
336 
337             m_huCCopyInUse = false;
338     }
339 
340     HalOcaInterface::On1stLevelBBEnd(cmdBuffer, *m_osInterface);
341 
342     CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnSubmitCommandBuffer(m_osInterface, &cmdBuffer, m_videoContextUsesNullHw));
343 
344     CODECHAL_DEBUG_TOOL(
345         m_mmc->UpdateUserFeatureKey(&m_destSurface);)
346 
347     if (m_statusQueryReportingEnabled)
348     {
349         CODECHAL_DECODE_CHK_STATUS_RETURN(ResetStatusReport(m_videoContextUsesNullHw));
350         }
351 
352     // Needs to be re-set for Linux buffer re-use scenarios
353         m_vp8RefList[m_vp8PicParams->ucCurrPicIndex]->resRefPic =
354             m_destSurface.OsResource;
355 
356         // Send the signal to indicate decode completion, in case On-Demand Sync is not present
357         CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnResourceSignal(m_osInterface, &syncParams));
358 
359         return eStatus;
360 }
361 
AllocateStandard(CodechalSetting * settings)362 MOS_STATUS CodechalDecodeVp8G11::AllocateStandard(
363     CodechalSetting *          settings)
364 {
365     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
366 
367     CODECHAL_DECODE_FUNCTION_ENTER;
368 
369     CODECHAL_DECODE_CHK_NULL_RETURN(settings);
370 
371     CODECHAL_DECODE_CHK_STATUS_RETURN(CodechalDecodeVp8::AllocateStandard(settings));
372 
373     if ( MOS_VE_SUPPORTED(m_osInterface))
374     {
375         static_cast<MhwVdboxMfxInterfaceG11*>(m_mfxInterface)->DisableScalabilitySupport();
376 
377         //single pipe VE initialize
378         m_veState = (PCODECHAL_DECODE_SINGLEPIPE_VIRTUALENGINE_STATE)MOS_AllocAndZeroMemory(sizeof(CODECHAL_DECODE_SINGLEPIPE_VIRTUALENGINE_STATE));
379         CODECHAL_DECODE_CHK_NULL_RETURN(m_veState);
380         CODECHAL_DECODE_CHK_STATUS_RETURN(CodecHalDecodeSinglePipeVE_InitInterface(m_osInterface, m_veState));
381     }
382 
383     return eStatus;
384 }
385 
CodechalDecodeVp8G11(CodechalHwInterface * hwInterface,CodechalDebugInterface * debugInterface,PCODECHAL_STANDARD_INFO standardInfo)386 CodechalDecodeVp8G11::CodechalDecodeVp8G11(
387     CodechalHwInterface   *hwInterface,
388     CodechalDebugInterface* debugInterface,
389     PCODECHAL_STANDARD_INFO standardInfo) :
390     CodechalDecodeVp8(hwInterface, debugInterface, standardInfo)
391 {
392     CODECHAL_DECODE_FUNCTION_ENTER;
393 
394     CODECHAL_DECODE_CHK_NULL_NO_STATUS_RETURN(m_osInterface);
395 
396     m_osInterface->pfnVirtualEngineSupported(m_osInterface, true, true);
397 }
398 
399