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