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_avc_g11.cpp
24 //! \brief     This modules implements Render interface layer for AVC decoding to be used on all operating systems/DDIs, across CODECHAL components.
25 //!
26 
27 #include "codechal_decoder.h"
28 #include "codechal_decode_avc_g11.h"
29 #include "codechal_secure_decode_interface.h"
30 #include "mhw_vdbox_mfx_g11_X.h"
31 #include "hal_oca_interface.h"
32 
AllocateStandard(CodechalSetting * settings)33 MOS_STATUS CodechalDecodeAvcG11::AllocateStandard(
34     CodechalSetting *          settings)
35 {
36     CODECHAL_DECODE_FUNCTION_ENTER;
37 
38     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
39 
40     CODECHAL_DECODE_CHK_NULL_RETURN(settings);
41 
42     CODECHAL_DECODE_CHK_STATUS_RETURN(CodechalDecodeAvc::AllocateStandard(settings));
43 
44     if ( MOS_VE_SUPPORTED(m_osInterface))
45     {
46         static_cast<MhwVdboxMfxInterfaceG11*>(m_mfxInterface)->DisableScalabilitySupport();
47 
48         //single pipe VE initialize
49         m_veState = (PCODECHAL_DECODE_SINGLEPIPE_VIRTUALENGINE_STATE)MOS_AllocAndZeroMemory(sizeof(CODECHAL_DECODE_SINGLEPIPE_VIRTUALENGINE_STATE));
50         CODECHAL_DECODE_CHK_NULL_RETURN(m_veState);
51         CODECHAL_DECODE_CHK_STATUS_RETURN(CodecHalDecodeSinglePipeVE_InitInterface(m_osInterface, m_veState));
52     }
53 
54     return eStatus;
55 }
56 
~CodechalDecodeAvcG11()57 CodechalDecodeAvcG11::~CodechalDecodeAvcG11()
58 {
59     CODECHAL_DECODE_FUNCTION_ENTER;
60 
61     if (m_veState)
62     {
63         MOS_FreeMemAndSetNull(m_veState);
64         m_veState = nullptr;
65     }
66 
67     return;
68 }
69 
SetGpuCtxCreatOption(CodechalSetting * codecHalSetting)70 MOS_STATUS CodechalDecodeAvcG11::SetGpuCtxCreatOption(
71     CodechalSetting *          codecHalSetting)
72 {
73     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
74 
75     CODECHAL_DECODE_FUNCTION_ENTER;
76 
77     if (!MOS_VE_CTXBASEDSCHEDULING_SUPPORTED(m_osInterface))
78     {
79         CodechalDecode::SetGpuCtxCreatOption(codecHalSetting);
80     }
81     else
82     {
83         m_gpuCtxCreatOpt = MOS_New(MOS_GPUCTX_CREATOPTIONS_ENHANCED);
84 
85         bool sfcInUse = IsSfcInUse(codecHalSetting);
86 
87         CODECHAL_DECODE_CHK_STATUS_RETURN(CodecHalDecodeSinglePipeVE_ConstructParmsForGpuCtxCreation(
88             m_veState,
89             (PMOS_GPUCTX_CREATOPTIONS_ENHANCED)m_gpuCtxCreatOpt,
90             sfcInUse));
91 
92         if (sfcInUse)
93         {
94             m_videoContext = MOS_GPU_CONTEXT_VIDEO4;
95 
96             CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnCreateGpuContext(
97                 m_osInterface,
98                 m_videoContext,
99                 MOS_GPU_NODE_VIDEO,
100                 m_gpuCtxCreatOpt));
101 
102             MOS_GPUCTX_CREATOPTIONS createOption;
103             CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnCreateGpuContext(
104                 m_osInterface,
105                 MOS_GPU_CONTEXT_VIDEO,
106                 MOS_GPU_NODE_VIDEO,
107                 &createOption));
108         }
109         else
110         {
111             m_videoContext = MOS_GPU_CONTEXT_VIDEO;
112         }
113     }
114 
115     return eStatus;
116 }
117 
SetFrameStates()118 MOS_STATUS CodechalDecodeAvcG11::SetFrameStates()
119 {
120     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
121 
122     CODECHAL_DECODE_FUNCTION_ENTER;
123 
124     CODECHAL_DECODE_CHK_STATUS_RETURN(CodechalDecodeAvc::SetFrameStates());
125 
126     if ( MOS_VE_SUPPORTED(m_osInterface))
127     {
128         if (!MOS_VE_CTXBASEDSCHEDULING_SUPPORTED(m_osInterface))
129         {
130             MOS_VIRTUALENGINE_SET_PARAMS vesetParams;
131 
132             MOS_ZeroMemory(&vesetParams, sizeof(vesetParams));
133 #ifdef _DECODE_PROCESSING_SUPPORTED
134             vesetParams.bSFCInUse = m_sfcState->m_sfcPipeOut;
135 #else
136             vesetParams.bSFCInUse                   = false;
137 #endif
138             vesetParams.bNeedSyncWithPrevious       = true;
139             vesetParams.bSameEngineAsLastSubmission = false;
140             CODECHAL_DECODE_CHK_STATUS_RETURN(CodecHalDecodeSinglePipeVE_SetHintParams(m_veState, &vesetParams));
141         }
142     }
143 
144     return eStatus;
145 }
146 
DecodeStateLevel()147 MOS_STATUS CodechalDecodeAvcG11::DecodeStateLevel()
148 {
149     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
150 
151     CODECHAL_DECODE_FUNCTION_ENTER;
152 
153     if (m_secureDecoder)
154     {
155         CODECHAL_DECODE_CHK_STATUS_RETURN(m_secureDecoder->Execute(this));
156     }
157 
158     MOS_COMMAND_BUFFER cmdBuffer;
159     CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(m_osInterface, &cmdBuffer, 0));
160 
161     CODECHAL_DECODE_CHK_STATUS_RETURN(SendPrologWithFrameTracking(
162         &cmdBuffer, true));
163 
164     PIC_MHW_PARAMS picMhwParams;
165     CODECHAL_DECODE_CHK_STATUS_RETURN(InitPicMhwParams(&picMhwParams));
166 
167     auto mmioRegisters = m_hwInterface->GetMfxInterface()->GetMmioRegisters(m_vdboxIndex);
168     HalOcaInterface::On1stLevelBBStart(cmdBuffer, *m_osInterface->pOsContext, m_osInterface->CurrentGpuContextHandle, *m_miInterface, *mmioRegisters);
169 
170     if (m_cencBuf && m_cencBuf->checkStatusRequired)
171     {
172         CODECHAL_DECODE_COND_ASSERTMESSAGE((m_vdboxIndex > m_hwInterface->GetMfxInterface()->GetMaxVdboxIndex()), "ERROR - vdbox index exceed the maximum");
173 
174         CODECHAL_DECODE_CHK_STATUS_RETURN(m_hwInterface->GetCpInterface()->CheckStatusReportNum(
175             mmioRegisters,
176             m_cencBuf->bufIdx,
177             m_cencBuf->resStatus,
178             &cmdBuffer));
179     }
180 
181     if (m_statusQueryReportingEnabled)
182     {
183         CODECHAL_DECODE_CHK_STATUS_RETURN(StartStatusReport(&cmdBuffer));
184     }
185 
186     CODECHAL_DECODE_CHK_STATUS_RETURN(AddPictureCmds(&cmdBuffer, &picMhwParams));
187 
188     m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0);
189 
190     return eStatus;
191 }
192 
DecodePrimitiveLevel()193 MOS_STATUS CodechalDecodeAvcG11::DecodePrimitiveLevel()
194 {
195     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
196 
197     CODECHAL_DECODE_FUNCTION_ENTER;
198 
199     CODECHAL_DECODE_CHK_NULL_RETURN(m_avcPicParams);
200 
201     MOS_COMMAND_BUFFER cmdBuffer;
202     CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(m_osInterface, &cmdBuffer, 0));
203 
204     if (m_cencBuf)
205     {
206         CODECHAL_DECODE_CHK_STATUS_RETURN(SetCencBatchBuffer(&cmdBuffer));
207     }
208     else
209     {
210         CODECHAL_DECODE_CHK_STATUS_RETURN(ParseSlice(&cmdBuffer));
211     }
212 
213     // Check if destination surface needs to be synchronized
214     MOS_SYNC_PARAMS syncParams;
215     syncParams = g_cInitSyncParams;
216     syncParams.GpuContext = m_videoContext;
217     syncParams.presSyncResource         = &m_destSurface.OsResource;
218     syncParams.bReadOnly = false;
219     syncParams.bDisableDecodeSyncLock = m_disableDecodeSyncLock;
220     syncParams.bDisableLockForTranscode = m_disableLockForTranscode;
221 
222     if (!CodecHal_PictureIsField(m_avcPicParams->CurrPic) ||
223         !m_isSecondField)
224     {
225         CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnPerformOverlaySync(m_osInterface, &syncParams));
226         CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnResourceWait(m_osInterface, &syncParams));
227 
228         // Update the resource tag (s/w tag) for On-Demand Sync
229         m_osInterface->pfnSetResourceSyncTag(m_osInterface, &syncParams);
230     }
231 
232 #ifdef _DECODE_PROCESSING_SUPPORTED
233     DecodeProcessingParams *decProcessingParams = (DecodeProcessingParams *)m_decodeParams.m_procParams;
234     if (decProcessingParams != nullptr && decProcessingParams->m_isReferenceOnlyPattern)
235     {
236         CODECHAL_DECODE_CHK_STATUS_RETURN(HucCopy(&cmdBuffer,
237                                             &m_destSurface.OsResource,
238                                             &decProcessingParams->m_outputSurface->OsResource,
239                                             decProcessingParams->m_outputSurface->dwSize,
240                                             m_destSurface.dwOffset,
241                                             decProcessingParams->m_outputSurface->dwOffset
242         ));
243     }
244 #endif
245 
246     MHW_MI_FLUSH_DW_PARAMS flushDwParams;
247     MOS_ZeroMemory(&flushDwParams, sizeof(flushDwParams));
248 
249     CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd(
250         &cmdBuffer,
251         &flushDwParams));
252 
253     // Update the tag in GPU Sync eStatus buffer (H/W Tag) to match the current S/W tag
254     if (m_osInterface->bTagResourceSync &&
255         (!CodecHal_PictureIsField(m_avcPicParams->CurrPic) || m_isSecondField))
256     {
257         CODECHAL_DECODE_CHK_STATUS_RETURN(m_hwInterface->WriteSyncTagToResource(&cmdBuffer, &syncParams));
258     }
259 
260     if (m_statusQueryReportingEnabled)
261     {
262         CodechalDecodeStatusReport decodeStatusReport;
263 
264         decodeStatusReport.m_statusReportNumber = m_statusReportFeedbackNumber;
265         decodeStatusReport.m_currDecodedPic     = m_avcPicParams->CurrPic;
266         decodeStatusReport.m_currDeblockedPic   = m_avcPicParams->CurrPic;
267         decodeStatusReport.m_codecStatus = CODECHAL_STATUS_UNAVAILABLE;
268         decodeStatusReport.m_currDecodedPicRes  = m_avcRefList[m_avcPicParams->CurrPic.FrameIdx]->resRefPic;
269 
270         CODECHAL_DEBUG_TOOL(
271             if (m_streamOutEnabled) {
272                 // add current streamout buffer to the report and move onto the next one
273                 decodeStatusReport.m_streamOutBuf = &(m_streamOutBuffer[m_streamOutCurrBufIdx]);
274                 decodeStatusReport.m_streamoutIdx = m_streamOutCurrBufIdx;
275                 if (++m_streamOutCurrBufIdx >= CODECHAL_DECODE_NUM_STREAM_OUT_BUFFERS)
276                 {
277                     m_streamOutCurrBufIdx = 0;
278                 }
279                 // check next buffer in the list is free.
280                 if (m_streamOutCurrStatusIdx[m_streamOutCurrBufIdx] != CODECHAL_DECODE_STATUS_NUM)
281                 {
282                     // We've run out of buffers. Temporarily lock the next one down to force a wait. Then mark it as free.
283                     CodechalResLock ResourceLock(m_osInterface, &(m_streamOutBuffer[m_streamOutCurrBufIdx]));
284                     ResourceLock.Lock(CodechalResLock::readOnly);
285 
286                     m_streamOutCurrStatusIdx[m_streamOutCurrBufIdx] = CODECHAL_DECODE_STATUS_NUM;
287                 }
288             }
289 
290             decodeStatusReport.m_secondField = CodecHal_PictureIsBottomField(m_avcPicParams->CurrPic);
291             decodeStatusReport.m_frameType   = m_perfType;)
292 
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     bool syncCompleteFrame = (m_avcPicParams->seq_fields.chroma_format_idc == avcChromaFormatMono && !m_hwInterface->m_noHuC);
301     if (syncCompleteFrame)
302     {
303         syncParams = g_cInitSyncParams;
304         syncParams.GpuContext = m_videoContextForWa;
305         syncParams.presSyncResource = &m_resSyncObjectWaContextInUse;
306 
307         CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineSignal(m_osInterface, &syncParams));
308 
309         syncParams = g_cInitSyncParams;
310         syncParams.GpuContext = m_videoContext;
311         syncParams.presSyncResource = &m_resSyncObjectWaContextInUse;
312 
313         CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineWait(m_osInterface, &syncParams));
314     }
315 
316     CODECHAL_DEBUG_TOOL(
317         CODECHAL_DECODE_CHK_STATUS_RETURN(m_debugInterface->DumpCmdBuffer(
318             &cmdBuffer,
319             CODECHAL_NUM_MEDIA_STATES,
320             "_DEC"));
321 
322     //CODECHAL_DECODE_CHK_STATUS_RETURN(CodecHal_DbgReplaceAllCommands(
323     //    m_debugInterface,
324     //    &cmdBuffer));
325     )
326 
327     if ( MOS_VE_SUPPORTED(m_osInterface))
328     {
329         CodecHalDecodeSinglePipeVE_PopulateHintParams(m_veState, &cmdBuffer, true);
330     }
331 
332     HalOcaInterface::DumpCodechalParam(cmdBuffer, (MOS_CONTEXT_HANDLE)m_osInterface->pOsContext, m_pCodechalOcaDumper, CODECHAL_AVC);
333     HalOcaInterface::On1stLevelBBEnd(cmdBuffer, *m_osInterface);
334 
335     CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnSubmitCommandBuffer(m_osInterface, &cmdBuffer, m_videoContextUsesNullHw));
336 
337     CODECHAL_DEBUG_TOOL(
338         m_mmc->UpdateUserFeatureKey(&m_destSurface);)
339 #ifdef _DECODE_PROCESSING_SUPPORTED
340     decProcessingParams = (DecodeProcessingParams *)m_decodeParams.m_procParams;
341     if (decProcessingParams != nullptr && !m_sfcState->m_sfcPipeOut && (m_isSecondField || m_avcPicParams->seq_fields.mb_adaptive_frame_field_flag))
342     {
343         CODECHAL_DECODE_CHK_STATUS_RETURN(m_fieldScalingInterface->DoFieldScaling(
344             decProcessingParams,
345             m_renderContext,
346             m_disableDecodeSyncLock,
347             m_disableLockForTranscode));
348     }
349     else
350 #endif
351     {
352         if (m_statusQueryReportingEnabled)
353         {
354             CODECHAL_DECODE_CHK_STATUS_RETURN(ResetStatusReport(m_videoContextUsesNullHw));
355         }
356     }
357 
358     // Needs to be re-set for Linux buffer re-use scenarios
359     m_avcRefList[m_avcPicParams->CurrPic.FrameIdx]->resRefPic =
360         m_destSurface.OsResource;
361 
362     // Send the signal to indicate decode completion, in case On-Demand Sync is not present
363     if (!CodecHal_PictureIsField(m_avcPicParams->CurrPic) || m_isSecondField)
364     {
365         syncParams = g_cInitSyncParams;
366         syncParams.GpuContext = m_videoContext;
367         syncParams.presSyncResource = &m_destSurface.OsResource;
368 
369         CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnResourceSignal(m_osInterface, &syncParams));
370 #ifdef _DECODE_PROCESSING_SUPPORTED
371         if (decProcessingParams && !m_sfcState->m_sfcPipeOut)
372         {
373             syncParams = g_cInitSyncParams;
374             syncParams.GpuContext = m_renderContext;
375             syncParams.presSyncResource = &decProcessingParams->m_outputSurface->OsResource;
376 
377             CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnResourceSignal(m_osInterface, &syncParams));
378         }
379 #endif
380     }
381 
382 #ifdef _DECODE_PROCESSING_SUPPORTED
383     CODECHAL_DEBUG_TOOL(
384         // Dump out downsampling result
385         if (decProcessingParams && decProcessingParams->m_outputSurface)
386         {
387             MOS_SURFACE dstSurface;
388             MOS_ZeroMemory(&dstSurface, sizeof(dstSurface));
389             dstSurface.Format = Format_NV12;
390             dstSurface.OsResource = decProcessingParams->m_outputSurface->OsResource;
391 
392             CODECHAL_DECODE_CHK_STATUS_RETURN(CodecHalGetResourceInfo(
393                 m_osInterface,
394                 &dstSurface));
395 
396             CODECHAL_DECODE_CHK_STATUS_RETURN(m_debugInterface->DumpYUVSurface(
397                 &dstSurface,
398                 CodechalDbgAttr::attrSfcOutputSurface,
399                 "SfcDstSurf"));
400         }
401     )
402 #endif
403         return eStatus;
404 }
405 
CodechalDecodeAvcG11(CodechalHwInterface * hwInterface,CodechalDebugInterface * debugInterface,PCODECHAL_STANDARD_INFO standardInfo)406 CodechalDecodeAvcG11::CodechalDecodeAvcG11(
407     CodechalHwInterface *   hwInterface,
408     CodechalDebugInterface *debugInterface,
409     PCODECHAL_STANDARD_INFO standardInfo) : CodechalDecodeAvc(hwInterface, debugInterface, standardInfo),
410                                             m_veState(nullptr)
411 {
412     CODECHAL_DECODE_FUNCTION_ENTER;
413 
414     CODECHAL_DECODE_CHK_NULL_NO_STATUS_RETURN(m_osInterface);
415 
416     m_osInterface->pfnVirtualEngineSupported(m_osInterface, true, true);
417 };
418 
419