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     media_ddi_decode_base_specific.cpp
24 //! \brief    The class implementation of DdiDecodeBase for all decoders
25 //!
26 
27 #include "ddi_vp_functions.h"
28 #include "media_libva_util_next.h"
29 #include "media_interfaces_codechal.h"
30 #include "media_interfaces_mmd_next.h"
31 #include "mos_solo_generic.h"
32 #include "ddi_decode_base_specific.h"
33 #include "media_libva_common_next.h"
34 #include "media_interfaces_codechal_next.h"
35 #include "ddi_decode_trace_specific.h"
36 #include "media_libva_caps_next.h"
37 
38 namespace decode
39 {
40 
DdiDecodeBase()41 DdiDecodeBase::DdiDecodeBase()
42     : DdiCodecBase()
43 {
44     DDI_CODEC_FUNC_ENTER;
45 
46     m_decodeCtx = nullptr;
47     MOS_ZeroMemory(&m_destSurface, sizeof(m_destSurface));
48     m_groupIndex    = 0;
49     m_picWidthInMB  = 0;
50     m_picHeightInMB = 0;
51     m_decProcessingType = 0;
52     m_width  = 0;
53     m_height = 0;
54     m_streamOutEnabled = false;
55     m_sliceParamBufNum = 0;
56     m_sliceCtrlBufNum  = 0;
57     m_codechalSettings = CodechalSetting::CreateCodechalSetting();
58 }
59 
BasicInit(ConfigLinux * configItem)60 VAStatus DdiDecodeBase::BasicInit(
61     ConfigLinux *configItem)
62 {
63     DDI_CODEC_FUNC_ENTER;
64 
65     if (configItem == nullptr)
66     {
67         return VA_STATUS_ERROR_ALLOCATION_FAILED;
68     }
69 
70     m_ddiDecodeAttr = (ConfigLinux *)MOS_AllocAndZeroMemory(sizeof(ConfigLinux));
71     if (m_ddiDecodeAttr && configItem)
72     {
73         MOS_SecureMemcpy(m_ddiDecodeAttr, sizeof(ConfigLinux), configItem, sizeof(ConfigLinux));
74     }
75 
76     m_decodeCtx = (DDI_DECODE_CONTEXT *)MOS_AllocAndZeroMemory(sizeof(DDI_DECODE_CONTEXT));
77 
78     if ((m_ddiDecodeAttr == nullptr) ||
79         (m_decodeCtx == nullptr))
80     {
81         MOS_FreeMemory(m_ddiDecodeAttr);
82         m_ddiDecodeAttr = nullptr;
83         MOS_FreeMemory(m_decodeCtx);
84         m_decodeCtx  = nullptr;
85         return VA_STATUS_ERROR_ALLOCATION_FAILED;
86     }
87 
88     return VA_STATUS_SUCCESS;
89 }
90 
GetBsBufOffset(int32_t sliceGroup)91 uint32_t DdiDecodeBase::GetBsBufOffset(int32_t sliceGroup)
92 {
93     DDI_CODEC_FUNC_ENTER;
94 
95     return m_decodeCtx->BufMgr.pSliceData[sliceGroup].uiOffset;
96 }
97 
ParseProcessingBuffer(DDI_MEDIA_CONTEXT * mediaCtx,void * bufAddr)98 VAStatus DdiDecodeBase::ParseProcessingBuffer(
99     DDI_MEDIA_CONTEXT *mediaCtx,
100     void              *bufAddr)
101 {
102     DDI_CODEC_FUNC_ENTER;
103 
104 #ifdef _DECODE_PROCESSING_SUPPORTED
105     VAProcPipelineParameterBuffer *procBuf =
106         (VAProcPipelineParameterBuffer *)bufAddr;
107 
108     DDI_CODEC_CHK_NULL(procBuf, "nullptr Processing buffer", VA_STATUS_ERROR_INVALID_PARAMETER)
109 
110     if (m_decProcessingType == VA_DEC_PROCESSING)
111     {
112         if (m_procBuf == nullptr)
113         {
114             m_procBuf = (VAProcPipelineParameterBuffer*)MOS_AllocAndZeroMemory(sizeof(VAProcPipelineParameterBuffer));
115             DDI_CODEC_CHK_NULL(m_procBuf, "nullptr m_procBuf", VA_STATUS_ERROR_ALLOCATION_FAILED);
116             MOS_SecureMemcpy(m_procBuf, sizeof(VAProcPipelineParameterBuffer), procBuf, sizeof(VAProcPipelineParameterBuffer));
117         }
118         auto decProcessingParams =
119             (DecodeProcessingParams *)m_decodeCtx->DecodeParams.m_procParams;
120 
121         auto decProcessingSurface = decProcessingParams->m_outputSurface;
122 
123         memset(decProcessingSurface, 0, sizeof(MOS_SURFACE));
124 
125         PDDI_MEDIA_SURFACE surface =
126             MediaLibvaCommonNext::GetSurfaceFromVASurfaceID(mediaCtx, procBuf->additional_outputs[0]);
127 
128         DDI_CODEC_CHK_NULL(surface, "Null surface in Processing buffer", VA_STATUS_ERROR_INVALID_PARAMETER)
129 
130         MediaLibvaCommonNext::MediaSurfaceToMosResource(surface, &(decProcessingSurface->OsResource));
131 
132         decProcessingSurface->dwWidth  = decProcessingSurface->OsResource.iWidth;
133         decProcessingSurface->dwHeight = decProcessingSurface->OsResource.iHeight;
134         decProcessingSurface->dwPitch  = decProcessingSurface->OsResource.iPitch;
135         decProcessingSurface->TileType = decProcessingSurface->OsResource.TileType;
136         decProcessingSurface->Format   = decProcessingSurface->OsResource.Format;
137 
138         if (procBuf->surface_region != nullptr)
139         {
140             m_requireInputRegion                               = false;
141             decProcessingParams->m_inputSurfaceRegion.m_x      = procBuf->surface_region->x;
142             decProcessingParams->m_inputSurfaceRegion.m_y      = procBuf->surface_region->y;
143             decProcessingParams->m_inputSurfaceRegion.m_width  = procBuf->surface_region->width;
144             decProcessingParams->m_inputSurfaceRegion.m_height = procBuf->surface_region->height;
145         }
146         else
147         {
148             m_requireInputRegion = true;
149         }
150 
151         decProcessingParams->m_outputSurface                = decProcessingSurface;
152         if (procBuf->output_region != nullptr)
153         {
154             decProcessingParams->m_outputSurfaceRegion.m_x      = procBuf->output_region->x;
155             decProcessingParams->m_outputSurfaceRegion.m_y      = procBuf->output_region->y;
156             decProcessingParams->m_outputSurfaceRegion.m_width  = procBuf->output_region->width;
157             decProcessingParams->m_outputSurfaceRegion.m_height = procBuf->output_region->height;
158         }
159         else
160         {
161             decProcessingParams->m_outputSurfaceRegion.m_x      = 0;
162             decProcessingParams->m_outputSurfaceRegion.m_y      = 0;
163             decProcessingParams->m_outputSurfaceRegion.m_width  = decProcessingSurface->dwWidth;
164             decProcessingParams->m_outputSurfaceRegion.m_height = decProcessingSurface->dwHeight;
165         }
166 
167         // Interpolation flags
168         // Set the vdbox scaling mode
169         uint32_t uInterpolationflags = 0;
170 #if VA_CHECK_VERSION(1, 9, 0)
171         uInterpolationflags = procBuf->filter_flags & VA_FILTER_INTERPOLATION_MASK;
172 #endif
173 
174         switch (uInterpolationflags)
175         {
176 #if VA_CHECK_VERSION(1, 9, 0)
177         case VA_FILTER_INTERPOLATION_NEAREST_NEIGHBOR:
178             decProcessingParams->m_scalingMode = CODECHAL_SCALING_NEAREST;
179             break;
180         case VA_FILTER_INTERPOLATION_BILINEAR:
181             decProcessingParams->m_scalingMode = CODECHAL_SCALING_BILINEAR;
182             break;
183         case VA_FILTER_INTERPOLATION_ADVANCED:
184         case VA_FILTER_INTERPOLATION_DEFAULT:
185 #endif
186         default:
187             decProcessingParams->m_scalingMode = CODECHAL_SCALING_AVS;
188            break;
189         }
190 
191         // Chroma siting
192         // Set the vertical chroma siting info
193         uint32_t chromaSitingFlags = 0;
194         chromaSitingFlags                       = procBuf->input_color_properties.chroma_sample_location & 0x3;
195         decProcessingParams->m_chromaSitingType = CODECHAL_CHROMA_SITING_NONE;
196         decProcessingParams->m_rotationState    = 0;
197         decProcessingParams->m_blendState       = 0;
198         decProcessingParams->m_mirrorState      = 0;
199 
200         switch (chromaSitingFlags)
201         {
202         case VA_CHROMA_SITING_VERTICAL_TOP:
203             decProcessingParams->m_chromaSitingType = CODECHAL_CHROMA_SITING_VERT_TOP;
204             break;
205         case VA_CHROMA_SITING_VERTICAL_CENTER:
206             decProcessingParams->m_chromaSitingType = CODECHAL_CHROMA_SITING_VERT_CENTER;
207             break;
208         case VA_CHROMA_SITING_VERTICAL_BOTTOM:
209             decProcessingParams->m_chromaSitingType = CODECHAL_CHROMA_SITING_VERT_BOTTOM;
210             break;
211         default:
212             decProcessingParams->m_chromaSitingType = CODECHAL_CHROMA_SITING_NONE;
213             break;
214         }
215 
216         if (decProcessingParams->m_chromaSitingType != CODECHAL_CHROMA_SITING_NONE)
217         {
218             // Set the horizontal chroma siting info
219             chromaSitingFlags = procBuf->input_color_properties.chroma_sample_location & 0xc;
220 
221             switch (chromaSitingFlags)
222             {
223             case VA_CHROMA_SITING_HORIZONTAL_LEFT:
224                 decProcessingParams->m_chromaSitingType |= CODECHAL_CHROMA_SITING_HORZ_LEFT;
225                 break;
226             case VA_CHROMA_SITING_HORIZONTAL_CENTER:
227                 decProcessingParams->m_chromaSitingType |= CODECHAL_CHROMA_SITING_HORZ_CENTER;
228                 break;
229             default:
230                 decProcessingParams->m_chromaSitingType = CODECHAL_CHROMA_SITING_NONE;
231                 break;
232             }
233         }
234     }
235 
236     return VA_STATUS_SUCCESS;
237 #else
238     return VA_STATUS_ERROR_INVALID_PARAMETER;
239 #endif
240 }
241 
BeginPicture(VADriverContextP ctx,VAContextID context,VASurfaceID renderTarget)242 VAStatus DdiDecodeBase::BeginPicture(
243     VADriverContextP ctx,
244     VAContextID      context,
245     VASurfaceID      renderTarget)
246 {
247     DDI_CODEC_FUNC_ENTER;
248 
249     PDDI_MEDIA_CONTEXT mediaCtx;
250 
251     /* As it is already checked in the upper caller, skip the check */
252     mediaCtx = GetMediaContext(ctx);
253 
254 #ifdef _DECODE_PROCESSING_SUPPORTED
255     // renderTarget is decode output surface; set renderTarget as vp sfc input surface m_procBuf->surface = rederTarget
256     if (m_procBuf)
257     {
258         m_procBuf->surface = renderTarget;
259     }
260 #endif
261 
262     DDI_MEDIA_SURFACE *curRT = nullptr;
263     curRT = (DDI_MEDIA_SURFACE *)MediaLibvaCommonNext::GetSurfaceFromVASurfaceID(mediaCtx, renderTarget);
264     DDI_CODEC_CHK_NULL(curRT, "nullptr pCurRT", VA_STATUS_ERROR_INVALID_SURFACE);
265     curRT->pDecCtx = m_decodeCtx;
266 
267     DDI_CODEC_RENDER_TARGET_TABLE *RTtbl;
268     RTtbl             = &(m_decodeCtx->RTtbl);
269     RTtbl->pCurrentRT = curRT;
270 
271     m_streamOutEnabled                           = false;
272     m_decodeCtx->DecodeParams.m_numSlices        = 0;
273     m_decodeCtx->DecodeParams.m_dataSize         = 0;
274     m_decodeCtx->DecodeParams.m_dataOffset       = 0;
275     m_decodeCtx->DecodeParams.m_deblockDataSize  = 0;
276     m_decodeCtx->DecodeParams.m_executeCallIndex = 0;
277     m_decodeCtx->DecodeParams.m_cencBuf          = nullptr;
278     m_groupIndex                                 = 0;
279 
280     // register render targets
281     DDI_CHK_RET(RegisterRTSurfaces(&m_decodeCtx->RTtbl, curRT),"RegisterRTSurfaces failed!");
282 
283     if (nullptr == m_decodeCtx->pCodecHal)
284     {
285         return VA_STATUS_ERROR_ALLOCATION_FAILED;
286     }
287 
288     MOS_STATUS eStatus = m_decodeCtx->pCodecHal->BeginFrame();
289     if (eStatus != MOS_STATUS_SUCCESS)
290     {
291         return VA_STATUS_ERROR_DECODING_ERROR;
292     }
293 
294     return VA_STATUS_SUCCESS;
295 }
296 
DecodeCombineBitstream(DDI_MEDIA_CONTEXT * mediaCtx)297 VAStatus DdiDecodeBase::DecodeCombineBitstream(DDI_MEDIA_CONTEXT *mediaCtx)
298 {
299     DDI_CODEC_FUNC_ENTER;
300 
301     DDI_CODEC_COM_BUFFER_MGR *bufMgr = nullptr;
302     /* As it is checked in previous caller, it is skipped. */
303     bufMgr = &(m_decodeCtx->BufMgr);
304 
305     if (bufMgr && (bufMgr->bIsSliceOverSize == false))
306     {
307         return VA_STATUS_SUCCESS;
308     }
309 
310     PDDI_MEDIA_BUFFER newBitstreamBuffer;
311     // allocate a new bit stream buffer
312     newBitstreamBuffer = (DDI_MEDIA_BUFFER *)MOS_AllocAndZeroMemory(sizeof(DDI_MEDIA_BUFFER));
313     if (newBitstreamBuffer == nullptr)
314     {
315         DDI_CODEC_ASSERTMESSAGE("DDI:AllocAndZeroMem return failure.");
316         return VA_STATUS_ERROR_DECODING_ERROR;
317     }
318 
319     newBitstreamBuffer->iSize     = m_decodeCtx->DecodeParams.m_dataSize;
320     newBitstreamBuffer->uiType    = VASliceDataBufferType;
321     newBitstreamBuffer->format    = Media_Format_Buffer;
322     newBitstreamBuffer->uiOffset  = 0;
323     newBitstreamBuffer->pMediaCtx = mediaCtx;
324 
325     VAStatus vaStatus;
326     vaStatus = MediaLibvaUtilNext::CreateBuffer(newBitstreamBuffer,
327         mediaCtx->pDrmBufMgr);
328     if (vaStatus != VA_STATUS_SUCCESS)
329     {
330         MOS_FreeMemory(newBitstreamBuffer);
331         newBitstreamBuffer = nullptr;
332         return VA_STATUS_ERROR_ALLOCATION_FAILED;
333     }
334 
335     uint8_t *newBitStreamBase = nullptr;
336     newBitStreamBase = (uint8_t *)MediaLibvaUtilNext::LockBuffer(newBitstreamBuffer, MOS_LOCKFLAG_WRITEONLY);
337 
338     if (newBitStreamBase == nullptr)
339     {
340         MediaLibvaUtilNext::FreeBuffer(newBitstreamBuffer);
341         MOS_FreeMemory(newBitstreamBuffer);
342         newBitstreamBuffer = nullptr;
343         return VA_STATUS_ERROR_ALLOCATION_FAILED;
344     }
345 
346     uint32_t slcInd = 0;
347     // copy data to new bit stream
348     for (slcInd = 0; slcInd < bufMgr->dwNumSliceData; slcInd++)
349     {
350         if (bufMgr->pSliceData[slcInd].bIsUseExtBuf == true)
351         {
352             if (bufMgr->pSliceData[slcInd].pSliceBuf)
353             {
354                 MOS_SecureMemcpy(newBitStreamBase + bufMgr->pSliceData[slcInd].uiOffset,
355                     bufMgr->pSliceData[slcInd].uiLength,
356                     bufMgr->pSliceData[slcInd].pSliceBuf,
357                     bufMgr->pSliceData[slcInd].uiLength);
358                 MOS_FreeMemory(bufMgr->pSliceData[slcInd].pSliceBuf);
359                 bufMgr->pSliceData[slcInd].pSliceBuf    = nullptr;
360                 bufMgr->pSliceData[slcInd].bIsUseExtBuf = false;
361             }
362         }
363         else
364         {
365             MOS_SecureMemcpy(newBitStreamBase + bufMgr->pSliceData[slcInd].uiOffset,
366                 bufMgr->pSliceData[slcInd].uiLength,
367                 bufMgr->pBitStreamBase[bufMgr->dwBitstreamIndex] + bufMgr->pSliceData[slcInd].uiOffset,
368                 bufMgr->pSliceData[slcInd].uiLength);
369         }
370     }
371 
372     // free original buffers
373     if (bufMgr->pBitStreamBase[bufMgr->dwBitstreamIndex])
374     {
375         MediaLibvaUtilNext::UnlockBuffer(bufMgr->pBitStreamBuffObject[bufMgr->dwBitstreamIndex]);
376         bufMgr->pBitStreamBase[bufMgr->dwBitstreamIndex] = nullptr;
377     }
378 
379     if (bufMgr->pBitStreamBuffObject[bufMgr->dwBitstreamIndex])
380     {
381         MediaLibvaUtilNext::FreeBuffer(bufMgr->pBitStreamBuffObject[bufMgr->dwBitstreamIndex]);
382         MOS_FreeMemory(bufMgr->pBitStreamBuffObject[bufMgr->dwBitstreamIndex]);
383         bufMgr->pBitStreamBuffObject[bufMgr->dwBitstreamIndex] = nullptr;
384     }
385 
386     // set new bitstream buffer
387     bufMgr->pBitStreamBuffObject[bufMgr->dwBitstreamIndex] = newBitstreamBuffer;
388     bufMgr->pBitStreamBase[bufMgr->dwBitstreamIndex]       = newBitStreamBase;
389     MediaLibvaCommonNext::MediaBufferToMosResource(m_decodeCtx->BufMgr.pBitStreamBuffObject[bufMgr->dwBitstreamIndex], &m_decodeCtx->BufMgr.resBitstreamBuffer);
390 
391     return VA_STATUS_SUCCESS;
392 }
393 
CheckDecodeResolution(ConfigLinux * configItem,uint32_t width,uint32_t height)394 VAStatus DdiDecodeBase::CheckDecodeResolution(
395     ConfigLinux       *configItem,
396     uint32_t          width,
397     uint32_t          height)
398 {
399     DDI_CODEC_FUNC_ENTER;
400     uint32_t maxWidth  = 0;
401     uint32_t maxHeight = 0;
402 
403     DDI_CODEC_CHK_NULL(configItem, "nullptr configItem", VA_STATUS_ERROR_INVALID_CONFIG);
404     VAConfigAttrib  *supportedAttribList = configItem->attribList;
405     DDI_CODEC_CHK_NULL(supportedAttribList, "nullptr supportedAttribList", VA_STATUS_ERROR_INVALID_CONFIG);
406 
407     // parse supported width and height from capstable attributes
408     for (uint32_t i = 0; i < configItem->numAttribs; i++)
409     {
410         if (supportedAttribList[i].type == VAConfigAttribMaxPictureWidth)
411         {
412             maxWidth = supportedAttribList[i].value;
413         }
414         else if (supportedAttribList[i].type == VAConfigAttribMaxPictureHeight)
415         {
416             maxHeight = supportedAttribList[i].value;
417         }
418         else
419         {
420             continue;
421         }
422     }
423 
424     if (width > maxWidth || height > maxHeight)
425     {
426         return VA_STATUS_ERROR_RESOLUTION_NOT_SUPPORTED;
427     }
428     else
429     {
430         return VA_STATUS_SUCCESS;
431     }
432 
433 }
434 
DestroyContext(VADriverContextP ctx)435 void DdiDecodeBase::DestroyContext(VADriverContextP ctx)
436 {
437     DDI_CODEC_FUNC_ENTER;
438 
439     Codechal *codecHal = nullptr;
440     /* as they are already checked in caller, this is skipped */
441     codecHal = m_decodeCtx->pCodecHal;
442 
443     if (codecHal != nullptr)
444     {
445         if (codecHal->GetOsInterface() && codecHal->GetOsInterface()->pOsContext)
446         {
447             MOS_FreeMemory(codecHal->GetOsInterface()->pOsContext->pPerfData);
448             codecHal->GetOsInterface()->pOsContext->pPerfData = nullptr;
449         }
450 
451         // destroy codechal
452         codecHal->Destroy();
453         MOS_Delete(codecHal);
454 
455         m_decodeCtx->pCodecHal = nullptr;
456     }
457 
458     int32_t i = 0;
459     for (i = 0; i < DDI_MEDIA_MAX_SURFACE_NUMBER_CONTEXT; i++)
460     {
461         if ((m_decodeCtx->RTtbl.pRT[i] != nullptr) &&
462             (m_decodeCtx->RTtbl.pRT[i]->pDecCtx == m_decodeCtx))
463         {
464             m_decodeCtx->RTtbl.pRT[i]->pDecCtx = nullptr;
465         }
466     }
467 
468     if (m_decodeCtx->pCpDdiInterfaceNext)
469     {
470         MOS_Delete(m_decodeCtx->pCpDdiInterfaceNext);
471     }
472 
473     MOS_FreeMemory(m_decodeCtx->DecodeParams.m_iqMatrixBuffer);
474     m_decodeCtx->DecodeParams.m_iqMatrixBuffer = nullptr;
475 
476     MOS_FreeMemory(m_decodeCtx->DecodeParams.m_huffmanTable);
477     m_decodeCtx->DecodeParams.m_huffmanTable = nullptr;
478 
479     MOS_FreeMemory(m_decodeCtx->DecodeParams.m_picParams);
480     m_decodeCtx->DecodeParams.m_picParams = nullptr;
481 
482     MOS_FreeMemory(m_decodeCtx->DecodeParams.m_sliceParams);
483     m_decodeCtx->DecodeParams.m_sliceParams = nullptr;
484 
485     MOS_FreeMemory(m_decodeCtx->DecodeParams.m_extPicParams);
486     m_decodeCtx->DecodeParams.m_sliceParams = nullptr;
487 
488     MOS_FreeMemory(m_decodeCtx->DecodeParams.m_advPicParams);
489     m_decodeCtx->DecodeParams.m_sliceParams = nullptr;
490 
491     MOS_FreeMemory(m_decodeCtx->DecodeParams.m_extSliceParams);
492     m_decodeCtx->DecodeParams.m_sliceParams = nullptr;
493 
494     MOS_FreeMemory(m_decodeCtx->DecodeParams.m_subsetParams);
495     m_decodeCtx->DecodeParams.m_sliceParams = nullptr;
496 
497 #ifdef _DECODE_PROCESSING_SUPPORTED
498     if (m_decodeCtx->DecodeParams.m_procParams != nullptr)
499     {
500         auto procParams =
501             (DecodeProcessingParams *)m_decodeCtx->DecodeParams.m_procParams;
502         MOS_FreeMemory(procParams->m_outputSurface);
503         procParams->m_outputSurface = nullptr;
504 
505         MOS_FreeMemory(m_decodeCtx->DecodeParams.m_procParams);
506         m_decodeCtx->DecodeParams.m_procParams = nullptr;
507     }
508 #endif
509 
510     return;
511 }
512 
GetBitstreamBufIndexFromBuffer(DDI_CODEC_COM_BUFFER_MGR * bufMgr,DDI_MEDIA_BUFFER * buf)513 int32_t DdiDecodeBase::GetBitstreamBufIndexFromBuffer(DDI_CODEC_COM_BUFFER_MGR *bufMgr, DDI_MEDIA_BUFFER *buf)
514 {
515     DDI_CODEC_FUNC_ENTER;
516 
517     int32_t i = 0;
518     for(i = 0; i < DDI_CODEC_MAX_BITSTREAM_BUFFER; i++)
519     {
520         if (bufMgr->pBitStreamBuffObject[i]->bo == buf->bo)
521         {
522             return i;
523         }
524     }
525 
526     return DDI_CODEC_INVALID_BUFFER_INDEX;
527 }
528 
AllocBsBuffer(DDI_CODEC_COM_BUFFER_MGR * bufMgr,DDI_MEDIA_BUFFER * buf)529 VAStatus DdiDecodeBase::AllocBsBuffer(
530     DDI_CODEC_COM_BUFFER_MGR *bufMgr,
531     DDI_MEDIA_BUFFER         *buf)
532 {
533     DDI_CODEC_FUNC_ENTER;
534 
535     uint32_t         index = 0, i = 0;
536     VAStatus         vaStatus  = VA_STATUS_SUCCESS;
537     uint8_t          *sliceBuf = nullptr;
538     DDI_MEDIA_BUFFER *bsBufObj = nullptr;
539     uint8_t          *bsBufBaseAddr = nullptr;
540     bool             createBsBuffer = false;
541 
542     if (nullptr == bufMgr || nullptr == buf || nullptr == (m_decodeCtx->pMediaCtx))
543     {
544         DDI_CODEC_ASSERTMESSAGE("invalidate input parameters.");
545         return VA_STATUS_ERROR_ALLOCATION_FAILED;
546     }
547 
548     index = bufMgr->dwNumSliceData;
549 
550     /* the pSliceData needs to be reallocated in order to contain more SliceDataBuf */
551     if (index >= bufMgr->m_maxNumSliceData)
552     {
553         /* In theroy it can resize the m_maxNumSliceData one by one. But in order to
554          * avoid calling realloc frequently, it will try to allocate 10 to  hold more
555          * SliceDataBuf. This is only for the optimized purpose.
556          */
557         int32_t reallocSize = bufMgr->m_maxNumSliceData + 10;
558 
559         bufMgr->pSliceData  = (DDI_CODEC_BITSTREAM_BUFFER_INFO *)realloc(bufMgr->pSliceData, sizeof(bufMgr->pSliceData[0]) * reallocSize);
560 
561         if (bufMgr->pSliceData == nullptr)
562         {
563             DDI_CODEC_ASSERTMESSAGE("fail to reallocate pSliceData\n.");
564             return VA_STATUS_ERROR_ALLOCATION_FAILED;
565         }
566         memset(bufMgr->pSliceData + bufMgr->m_maxNumSliceData, 0,
567                sizeof(bufMgr->pSliceData[0]) * 10);
568 
569         bufMgr->m_maxNumSliceData += 10;
570     }
571 
572     if (index >= 1)
573     {
574         buf->uiOffset = bufMgr->pSliceData[index-1].uiOffset + bufMgr->pSliceData[index-1].uiLength;
575         if ((buf->uiOffset + buf->iSize) > bufMgr->pBitStreamBuffObject[bufMgr->dwBitstreamIndex]->iSize)
576         {
577             sliceBuf = (uint8_t*)MOS_AllocAndZeroMemory(buf->iSize);
578             if (sliceBuf == nullptr)
579             {
580                 DDI_CODEC_ASSERTMESSAGE("DDI:AllocAndZeroMem return failure.")
581                 return VA_STATUS_ERROR_ALLOCATION_FAILED;
582             }
583             bufMgr->bIsSliceOverSize = true;
584         }
585         else
586         {
587             bufMgr->bIsSliceOverSize = false;
588         }
589     }
590     else
591     {
592         bufMgr->bIsSliceOverSize = false;
593         for (i = 0; i < DDI_CODEC_MAX_BITSTREAM_BUFFER; i++)
594         {
595             if (bufMgr->pBitStreamBuffObject[i]->bo != nullptr)
596             {
597                 if (!mos_bo_busy(bufMgr->pBitStreamBuffObject[i]->bo))
598                 {
599                     // find a bitstream buffer whoes graphic memory is allocated but not used by HW now.
600                     break;
601                 }
602             }
603             else
604             {
605                 // find a new bitstream buffer whoes graphic memory is not allocated yet
606                 break;
607             }
608         }
609 
610         if (i == DDI_CODEC_MAX_BITSTREAM_BUFFER)
611         {
612             // find the oldest bistream buffer which is the most possible one to become free in the shortest time.
613             bufMgr->dwBitstreamIndex = (bufMgr->ui64BitstreamOrder >> (DDI_CODEC_BITSTREAM_BUFFER_INDEX_BITS * DDI_CODEC_MAX_BITSTREAM_BUFFER_MINUS1)) & DDI_CODEC_MAX_BITSTREAM_BUFFER_INDEX;
614             // wait until decode complete
615             mos_bo_wait_rendering(bufMgr->pBitStreamBuffObject[bufMgr->dwBitstreamIndex]->bo);
616         }
617         else
618         {
619             bufMgr->dwBitstreamIndex = i;
620         }
621         bufMgr->ui64BitstreamOrder = (bufMgr->ui64BitstreamOrder << 4) + bufMgr->dwBitstreamIndex;
622 
623         bsBufObj            = bufMgr->pBitStreamBuffObject[bufMgr->dwBitstreamIndex];
624         bsBufObj->pMediaCtx = m_decodeCtx->pMediaCtx;
625         bsBufBaseAddr       = bufMgr->pBitStreamBase[bufMgr->dwBitstreamIndex];
626 
627         if (bsBufBaseAddr == nullptr)
628         {
629             createBsBuffer = true;
630             if (buf->iSize > bsBufObj->iSize)
631             {
632                 bsBufObj->iSize = buf->iSize;
633             }
634         }
635         else if (buf->iSize > bsBufObj->iSize)
636         {
637            // free bo
638             MediaLibvaUtilNext::UnlockBuffer(bsBufObj);
639             MediaLibvaUtilNext::FreeBuffer(bsBufObj);
640             bsBufBaseAddr = nullptr;
641 
642             createBsBuffer  = true;
643             bsBufObj->iSize = buf->iSize;
644         }
645 
646         if (createBsBuffer)
647         {
648             if (VA_STATUS_SUCCESS != MediaLibvaUtilNext::CreateBuffer(bsBufObj, m_decodeCtx->pMediaCtx->pDrmBufMgr))
649             {
650                return VA_STATUS_ERROR_ALLOCATION_FAILED;
651             }
652 
653             bsBufBaseAddr = (uint8_t*)MediaLibvaUtilNext::LockBuffer(bsBufObj, MOS_LOCKFLAG_WRITEONLY);
654             if (bsBufBaseAddr == nullptr)
655             {
656                 MediaLibvaUtilNext::FreeBuffer(bsBufObj);
657                 return VA_STATUS_ERROR_ALLOCATION_FAILED;
658             }
659             bufMgr->pBitStreamBase[bufMgr->dwBitstreamIndex] = bsBufBaseAddr;
660         }
661     }
662 
663     if (bufMgr->pBitStreamBase[bufMgr->dwBitstreamIndex] == nullptr)
664     {
665         return VA_STATUS_ERROR_ALLOCATION_FAILED;
666     }
667 
668     bufMgr->pSliceData[index].uiLength = buf->iSize;
669     bufMgr->pSliceData[index].uiOffset = buf->uiOffset;
670 
671     if (bufMgr->bIsSliceOverSize == true)
672     {
673         buf->pData                              = sliceBuf;
674         buf->uiOffset                           = 0;
675         bufMgr->pSliceData[index].bIsUseExtBuf  = true;
676         bufMgr->pSliceData[index].pSliceBuf     = sliceBuf;
677         buf->bCFlushReq                         = false;
678     }
679     else
680     {
681         buf->pData                              = (uint8_t*)(bufMgr->pBitStreamBase[bufMgr->dwBitstreamIndex]);
682         bufMgr->pSliceData[index].bIsUseExtBuf  = false;
683         bufMgr->pSliceData[index].pSliceBuf     = nullptr;
684         buf->bCFlushReq                         = true;
685     }
686 
687     bufMgr->dwNumSliceData ++;
688     buf->bo = bufMgr->pBitStreamBuffObject[bufMgr->dwBitstreamIndex]->bo;
689 
690     return VA_STATUS_SUCCESS;
691 }
692 
GetFormat()693 MOS_FORMAT DdiDecodeBase::GetFormat()
694 {
695     DDI_CODEC_FUNC_ENTER;
696 
697     return  Format_NV12;
698 }
699 
InitDecodeParams(VADriverContextP ctx,VAContextID context)700 VAStatus DdiDecodeBase::InitDecodeParams(
701     VADriverContextP ctx,
702     VAContextID      context)
703 {
704     DDI_CODEC_FUNC_ENTER;
705 
706     /* skip the mediaCtx check as it is checked in caller */
707     PDDI_MEDIA_CONTEXT mediaCtx;
708     mediaCtx = GetMediaContext(ctx);
709     DDI_CHK_RET(DecodeCombineBitstream(mediaCtx),"DecodeCombineBitstream failed!");
710     DDI_CODEC_COM_BUFFER_MGR *bufMgr = &(m_decodeCtx->BufMgr);
711     bufMgr->dwNumSliceData    = 0;
712     bufMgr->dwNumSliceControl = 0;
713     memset(&m_destSurface, 0, sizeof(MOS_SURFACE));
714     m_destSurface.dwOffset = 0;
715 
716     DDI_CODEC_RENDER_TARGET_TABLE *rtTbl = &(m_decodeCtx->RTtbl);
717 
718     if ((rtTbl == nullptr) || (rtTbl->pCurrentRT == nullptr))
719     {
720         return VA_STATUS_ERROR_INVALID_PARAMETER;
721     }
722     return VA_STATUS_SUCCESS;
723 
724 }
725 
SetDecodeParams()726 VAStatus DdiDecodeBase::SetDecodeParams()
727 {
728     DDI_CODEC_FUNC_ENTER;
729 
730     DDI_CODEC_COM_BUFFER_MGR *bufMgr = &(m_decodeCtx->BufMgr);
731     if ((&m_decodeCtx->DecodeParams)->m_numSlices == 0)
732     {
733         return VA_STATUS_ERROR_INVALID_PARAMETER;
734     }
735 
736     MOS_FORMAT expectedFormat = GetFormat();
737     m_destSurface.Format      = expectedFormat;
738     MediaLibvaCommonNext::MediaSurfaceToMosResource((&(m_decodeCtx->RTtbl))->pCurrentRT, &(m_destSurface.OsResource));
739 
740     if (m_destSurface.OsResource.Format != expectedFormat)
741     {
742         DDI_CODEC_NORMALMESSAGE("Surface fomrat of decoded surface is inconsistent with Codec bitstream\n");
743         return VA_STATUS_ERROR_INVALID_PARAMETER;
744     }
745 
746     m_decodeCtx->DecodeParams.m_destSurface    = &m_destSurface;
747     m_decodeCtx->DecodeParams.m_deblockSurface = nullptr;
748 
749     m_decodeCtx->DecodeParams.m_dataBuffer       = &bufMgr->resBitstreamBuffer;
750     m_decodeCtx->DecodeParams.m_bitStreamBufData = bufMgr->pBitstreamBuffer;
751 
752     m_decodeCtx->DecodeParams.m_bitplaneBuffer = nullptr;
753 
754     if (m_streamOutEnabled)
755     {
756         m_decodeCtx->DecodeParams.m_streamOutEnabled        = true;
757         m_decodeCtx->DecodeParams.m_externalStreamOutBuffer = &bufMgr->resExternalStreamOutBuffer;
758     }
759     else
760     {
761         m_decodeCtx->DecodeParams.m_streamOutEnabled        = false;
762         m_decodeCtx->DecodeParams.m_externalStreamOutBuffer = nullptr;
763     }
764 
765     if (m_decodeCtx->pCpDdiInterfaceNext)
766     {
767         DDI_CHK_RET(m_decodeCtx->pCpDdiInterfaceNext->SetDecodeParams(m_decodeCtx, m_codechalSettings), "SetDecodeParams failed!");
768     }
769 
770     Mos_Solo_OverrideBufferSize(m_decodeCtx->DecodeParams.m_dataSize, m_decodeCtx->DecodeParams.m_dataBuffer);
771 
772     return VA_STATUS_SUCCESS;
773 }
774 
ExtraDownScaling(VADriverContextP ctx,VAContextID context)775 VAStatus DdiDecodeBase::ExtraDownScaling(
776     VADriverContextP ctx,
777     VAContextID      context)
778 {
779     DDI_CODEC_FUNC_ENTER;
780 
781 #ifdef _DECODE_PROCESSING_SUPPORTED
782     DDI_CODEC_CHK_NULL(ctx, "nullptr ctx", VA_STATUS_ERROR_INVALID_CONTEXT);
783     VAStatus vaStatus = MOS_STATUS_SUCCESS;
784     PDDI_MEDIA_CONTEXT mediaCtx = GetMediaContext(ctx);
785     DDI_CODEC_CHK_NULL(mediaCtx, "nullptr ctx", VA_STATUS_ERROR_INVALID_CONTEXT);
786     DDI_CODEC_CHK_NULL(m_decodeCtx, "nullptr ctx", VA_STATUS_ERROR_INVALID_CONTEXT);
787 
788     bool isDecodeDownScalingSupported = false;
789     DecodePipelineAdapter *decoder = dynamic_cast<DecodePipelineAdapter *>(m_decodeCtx->pCodecHal);
790     DDI_CODEC_CHK_NULL(decoder, "nullptr decoder", VA_STATUS_ERROR_INVALID_PARAMETER);
791     isDecodeDownScalingSupported = decoder->IsDownSamplingSupported();
792 
793     if (m_decodeCtx->DecodeParams.m_procParams != nullptr &&
794        m_procBuf &&
795        !isDecodeDownScalingSupported)
796     {
797         // check vp context
798         VAContextID vpCtxID = VA_INVALID_ID;
799         if (mediaCtx->pVpCtxHeap != nullptr && mediaCtx->pVpCtxHeap->pHeapBase != nullptr)
800         {
801             // Get VP Context from heap.
802             vpCtxID = (VAContextID)(0 + DDI_MEDIA_SOFTLET_VACONTEXTID_VP_OFFSET);
803         }
804         else
805         {
806             // Create VP Context.
807             vaStatus = mediaCtx->m_compList[CompVp]->CreateContext(ctx, 0, 0, 0, 0, 0, 0, &vpCtxID);
808             DDI_CHK_RET(vaStatus, "Create VP Context failed.");
809         }
810 
811         uint32_t ctxType;
812         PDDI_VP_CONTEXT pVpCtx = (PDDI_VP_CONTEXT)MediaLibvaCommonNext::GetContextFromContextID(ctx, vpCtxID, &ctxType);
813         DDI_CODEC_CHK_NULL(pVpCtx, "nullptr pVpCtx", VA_STATUS_ERROR_INVALID_CONTEXT);
814 
815         // Set parameters
816         VAProcPipelineParameterBuffer* pInputPipelineParam = m_procBuf;
817         DDI_CODEC_CHK_NULL(pInputPipelineParam, "nullptr pInputPipelineParam", VA_STATUS_ERROR_ALLOCATION_FAILED);
818 
819         vaStatus = mediaCtx->m_compList[CompVp]->BeginPicture(ctx, vpCtxID, pInputPipelineParam->additional_outputs[0]);
820         DDI_CHK_RET(vaStatus, "VP BeginPicture failed");
821 
822         vaStatus = m_decodeCtx->pVpDdiInterface->DdiSetProcPipelineParams(ctx, pVpCtx, pInputPipelineParam);
823         DDI_CHK_RET(vaStatus, "VP SetProcPipelineParams failed.");
824 
825         vaStatus = mediaCtx->m_compList[CompVp]->EndPicture(ctx, vpCtxID);
826         DDI_CHK_RET(vaStatus, "VP EndPicture failed.");
827     }
828 #endif
829     return MOS_STATUS_SUCCESS;
830 }
831 
InitDummyReference(CodechalDecode & decoder)832 VAStatus DdiDecodeBase::InitDummyReference(CodechalDecode& decoder)
833 {
834     DDI_CODEC_FUNC_ENTER;
835 
836     PMOS_SURFACE dummyReference = decoder.GetDummyReference();
837 
838     // If dummy reference is from decode output surface, need to update frame by frame
839     if (decoder.GetDummyReferenceStatus() == CODECHAL_DUMMY_REFERENCE_DEST_SURFACE)
840     {
841         MOS_ZeroMemory(dummyReference, sizeof(MOS_SURFACE));
842         decoder.SetDummyReferenceStatus(CODECHAL_DUMMY_REFERENCE_INVALID);
843     }
844 
845     if (!Mos_ResourceIsNull(&dummyReference->OsResource))
846     {
847         Mos_Specific_GetResourceInfo(decoder.GetOsInterface(), &dummyReference->OsResource, dummyReference);
848 
849         // Check if need to re-get dummy reference from DPB or re-allocated
850         if (dummyReference->dwWidth  < m_decodeCtx->DecodeParams.m_destSurface->dwWidth ||
851             dummyReference->dwHeight < m_decodeCtx->DecodeParams.m_destSurface->dwHeight)
852         {
853             // Check if the dummy reference needs to be re-allocated
854             if (decoder.GetDummyReferenceStatus() == CODECHAL_DUMMY_REFERENCE_ALLOCATED)
855             {
856                 decoder.GetOsInterface()->pfnFreeResource(decoder.GetOsInterface(), &dummyReference->OsResource);
857             }
858 
859             // Reset dummy reference
860             MOS_ZeroMemory(dummyReference, sizeof(MOS_SURFACE));
861             decoder.SetDummyReferenceStatus(CODECHAL_DUMMY_REFERENCE_INVALID);
862 
863             // Considering potential risk, disable the dummy reference from DPB path temporarily
864             //GetDummyReferenceFromDPB(m_decodeCtx);
865 
866             //if (!Mos_ResourceIsNull(&dummyReference->OsResource))
867             //{
868             //    decoder->SetDummyReferenceStatus(CODECHAL_DUMMY_REFERENCE_DPB);
869             //}
870         }
871     }
872     else
873     {
874         // Init dummy reference
875         MOS_ZeroMemory(dummyReference, sizeof(MOS_SURFACE));
876         decoder.SetDummyReferenceStatus(CODECHAL_DUMMY_REFERENCE_INVALID);
877 
878         // Considering potential risk, disable the dummy reference from DPB path temporarily
879         //GetDummyReferenceFromDPB(m_decodeCtx);
880         //if (!Mos_ResourceIsNull(&dummyReference->OsResource))
881         //{
882         //    decoder->SetDummyReferenceStatus(CODECHAL_DUMMY_REFERENCE_DPB);
883         //}
884     }
885 
886     return VA_STATUS_SUCCESS;
887 }
888 
InitDummyReference(DecodePipelineAdapter & decoder)889 VAStatus DdiDecodeBase::InitDummyReference(DecodePipelineAdapter &decoder)
890 {
891     DDI_CODEC_FUNC_ENTER;
892 
893     PMOS_SURFACE dummyReference = decoder.GetDummyReference();
894 
895     // If dummy reference is from decode output surface, need to update frame by frame
896     if (decoder.GetDummyReferenceStatus() == CODECHAL_DUMMY_REFERENCE_DEST_SURFACE)
897     {
898         MOS_ZeroMemory(dummyReference, sizeof(MOS_SURFACE));
899         decoder.SetDummyReferenceStatus(CODECHAL_DUMMY_REFERENCE_INVALID);
900     }
901 
902     if (!Mos_ResourceIsNull(&dummyReference->OsResource))
903     {
904         Mos_Specific_GetResourceInfo(decoder.GetOsInterface(), &dummyReference->OsResource, dummyReference);
905 
906         // Check if need to re-get dummy reference from DPB or re-allocated
907         if (dummyReference->dwWidth  < m_decodeCtx->DecodeParams.m_destSurface->dwWidth ||
908             dummyReference->dwHeight < m_decodeCtx->DecodeParams.m_destSurface->dwHeight)
909         {
910             // Check if the dummy reference needs to be re-allocated
911             if (decoder.GetDummyReferenceStatus() == CODECHAL_DUMMY_REFERENCE_ALLOCATED)
912             {
913                 decoder.GetOsInterface()->pfnFreeResource(decoder.GetOsInterface(), &dummyReference->OsResource);
914             }
915 
916             // Reset dummy reference
917             MOS_ZeroMemory(dummyReference, sizeof(MOS_SURFACE));
918             decoder.SetDummyReferenceStatus(CODECHAL_DUMMY_REFERENCE_INVALID);
919 
920             // Considering potential risk, disable the dummy reference from DPB path temporarily
921             //GetDummyReferenceFromDPB(m_decodeCtx);
922 
923             //if (!Mos_ResourceIsNull(&dummyReference->OsResource))
924             //{
925             //    decoder->SetDummyReferenceStatus(CODECHAL_DUMMY_REFERENCE_DPB);
926             //}
927         }
928     }
929     else
930     {
931         // Init dummy reference
932         MOS_ZeroMemory(dummyReference, sizeof(MOS_SURFACE));
933         decoder.SetDummyReferenceStatus(CODECHAL_DUMMY_REFERENCE_INVALID);
934 
935         // Considering potential risk, disable the dummy reference from DPB path temporarily
936         //GetDummyReferenceFromDPB(m_decodeCtx);
937         //if (!Mos_ResourceIsNull(&dummyReference->OsResource))
938         //{
939         //    decoder->SetDummyReferenceStatus(CODECHAL_DUMMY_REFERENCE_DPB);
940         //}
941     }
942 
943     return VA_STATUS_SUCCESS;
944 }
945 
EndPicture(VADriverContextP ctx,VAContextID context)946 VAStatus DdiDecodeBase::EndPicture(
947     VADriverContextP ctx,
948     VAContextID      context)
949 {
950     DDI_CODEC_FUNC_ENTER;
951 
952     if (m_decodeCtx->bDecodeModeReported == false)
953     {
954         ReportDecodeMode(m_decodeCtx->wMode);
955         m_decodeCtx->bDecodeModeReported = true;
956     }
957 
958     DDI_CHK_RET(InitDecodeParams(ctx,context),"InitDecodeParams failed!");
959 
960     DDI_CHK_RET(SetDecodeParams(), "SetDecodeParams failed!");
961     DDI_CHK_RET(ClearRefList(&(m_decodeCtx->RTtbl), m_withDpb), "ClearRefList failed!");
962     if (m_decodeCtx->pCodecHal == nullptr)
963     {
964         return VA_STATUS_ERROR_ALLOCATION_FAILED;
965     }
966 
967     if (MEDIA_IS_WA(&m_decodeCtx->pMediaCtx->WaTable, WaDummyReference))
968     {
969         Mos_Specific_GetResourceInfo(
970             m_decodeCtx->pCodecHal->GetOsInterface(),
971             &m_decodeCtx->DecodeParams.m_destSurface->OsResource,
972             m_decodeCtx->DecodeParams.m_destSurface);
973 
974         DecodePipelineAdapter *decoder = dynamic_cast<DecodePipelineAdapter *>(m_decodeCtx->pCodecHal);
975         DDI_CODEC_CHK_NULL(decoder, "Null decoder", VA_STATUS_ERROR_INVALID_PARAMETER);
976         DDI_CHK_RET(InitDummyReference(*decoder), "InitDummyReference failed!");
977     }
978 
979     MOS_STATUS status = m_decodeCtx->pCodecHal->Execute((void *)(&m_decodeCtx->DecodeParams));
980     if (status != MOS_STATUS_SUCCESS)
981     {
982         DDI_CODEC_ASSERTMESSAGE("DDI:DdiDecode_DecodeInCodecHal return failure.");
983         return VA_STATUS_ERROR_DECODING_ERROR;
984     }
985 
986     m_decodeCtx->DecodeParams.m_executeCallIndex++;
987 
988     (&(m_decodeCtx->RTtbl))->pCurrentRT = nullptr;
989 
990     status = m_decodeCtx->pCodecHal->EndFrame();
991     if (status != MOS_STATUS_SUCCESS)
992     {
993         return VA_STATUS_ERROR_DECODING_ERROR;
994     }
995 
996 #ifdef _DECODE_PROCESSING_SUPPORTED
997     if (ExtraDownScaling(ctx,context) != VA_STATUS_SUCCESS)
998     {
999         return VA_STATUS_ERROR_DECODING_ERROR;
1000     }
1001 #endif
1002 
1003     return VA_STATUS_SUCCESS;
1004 }
1005 
CreateBuffer(VABufferType type,uint32_t size,uint32_t numElements,void * data,VABufferID * bufId)1006 VAStatus DdiDecodeBase::CreateBuffer(
1007     VABufferType type,
1008     uint32_t     size,
1009     uint32_t     numElements,
1010     void         *data,
1011     VABufferID   *bufId)
1012 {
1013     DDI_CODEC_FUNC_ENTER;
1014 
1015     DDI_MEDIA_BUFFER                *buf = nullptr;
1016     PDDI_MEDIA_BUFFER_HEAP_ELEMENT  bufferHeapElement;
1017     uint16_t                        segMapWidth  = m_picWidthInMB;
1018     uint16_t                        segMapHeight = m_picHeightInMB;
1019     MOS_STATUS                      status = MOS_STATUS_SUCCESS;
1020     VAStatus                        va = VA_STATUS_SUCCESS;
1021 
1022     // only for VASliceParameterBufferType of buffer, the number of elements can be greater than 1
1023     if (type != VASliceParameterBufferType && numElements > 1)
1024     {
1025         return VA_STATUS_ERROR_INVALID_PARAMETER;
1026     }
1027 
1028     buf = (DDI_MEDIA_BUFFER *)MOS_AllocAndZeroMemory(sizeof(DDI_MEDIA_BUFFER));
1029     if (buf == nullptr)
1030     {
1031         return VA_STATUS_ERROR_ALLOCATION_FAILED;
1032     }
1033     buf->iSize         = size * numElements;
1034     buf->uiNumElements = numElements;
1035     buf->uiType        = type;
1036     buf->format        = Media_Format_Buffer;
1037     buf->uiOffset      = 0;
1038     buf->bCFlushReq    = false;
1039     buf->pMediaCtx     = m_decodeCtx->pMediaCtx;
1040 
1041     switch ((int32_t)type)
1042     {
1043         case VABitPlaneBufferType:
1044             buf->pData = (uint8_t*)((m_decodeCtx->BufMgr.Codec_Param.Codec_Param_VC1.pBitPlaneBuffer));
1045             break;
1046         case VASliceDataBufferType:
1047         case VAProtectedSliceDataBufferType:
1048             va = AllocBsBuffer(&(m_decodeCtx->BufMgr), buf);
1049             if (va != VA_STATUS_SUCCESS)
1050             {
1051                 MOS_FreeMemory(buf);
1052                 return va;
1053             }
1054             break;
1055         case VASliceParameterBufferType:
1056             va = AllocSliceControlBuffer(buf);
1057             if (va != VA_STATUS_SUCCESS)
1058             {
1059                 MOS_FreeMemory(buf);
1060                 return va;
1061             }
1062             buf->format = Media_Format_CPU;
1063             break;
1064         case VAPictureParameterBufferType:
1065             buf->pData  = GetPicParamBuf(&(m_decodeCtx->BufMgr));
1066             buf->format = Media_Format_CPU;
1067             break;
1068         case VASubsetsParameterBufferType:
1069             buf->pData  = (uint8_t*)MOS_AllocAndZeroMemory(size * numElements);
1070             buf->format = Media_Format_CPU;
1071             break;
1072         case VAIQMatrixBufferType:
1073             buf->pData  = (uint8_t*)MOS_AllocAndZeroMemory(size * numElements);
1074             buf->format = Media_Format_CPU;
1075             break;
1076         case VAProbabilityBufferType:
1077             buf->pData  = (uint8_t*)(&(m_decodeCtx->BufMgr.Codec_Param.Codec_Param_VP8.ProbabilityDataVP8));
1078             break;
1079         case VAProcFilterParameterBufferType:
1080             buf->pData  = (uint8_t*)MOS_AllocAndZeroMemory(sizeof(VAProcPipelineCaps));
1081             buf->format = Media_Format_CPU;
1082             break;
1083         case VAProcPipelineParameterBufferType:
1084             buf->pData  = (uint8_t*)MOS_AllocAndZeroMemory(sizeof(VAProcPipelineParameterBuffer));
1085             buf->format = Media_Format_CPU;
1086             break;
1087         case VADecodeStreamoutBufferType:
1088         {
1089             segMapHeight = ((segMapHeight + 1) >> 1);   // uiSize must be equal and bigger than size for interlaced case
1090 
1091             if (size < MOS_ALIGN_CEIL(segMapHeight * segMapWidth * CODEC_SIZE_MFX_STREAMOUT_DATA, 64))
1092             {
1093                 va = VA_STATUS_ERROR_INVALID_PARAMETER;
1094                 MOS_FreeMemory(buf);
1095                 return va;
1096             }
1097             buf->iSize  = size * numElements;
1098             buf->format = Media_Format_Buffer;
1099             va = MediaLibvaUtilNext::CreateBuffer(buf, m_decodeCtx->pMediaCtx->pDrmBufMgr);
1100             if (va != VA_STATUS_SUCCESS)
1101             {
1102                 MOS_FreeMemory(buf);
1103                 return va;
1104             }
1105             break;
1106         }
1107         case VAHuffmanTableBufferType:
1108             buf->pData  = (uint8_t*)MOS_AllocAndZeroMemory(size * numElements);
1109             buf->format = Media_Format_CPU;
1110             break;
1111 #if VA_CHECK_VERSION(1, 10, 0)
1112         case VAContextParameterUpdateBufferType:
1113         {
1114             buf->pData  = (uint8_t*)MOS_AllocAndZeroMemory(size * numElements);
1115             buf->format = Media_Format_CPU;
1116             break;
1117         }
1118 #endif
1119         default:
1120             va = m_decodeCtx->pCpDdiInterfaceNext->CreateBuffer(type, buf, size, numElements);
1121             if (va == VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE)
1122             {
1123                 DDI_CODEC_ASSERTMESSAGE("DDI:Decode CreateBuffer unsuppoted buffer type.");
1124                 buf->pData  = (uint8_t*)MOS_AllocAndZeroMemory(size * numElements);
1125                 buf->format = Media_Format_CPU;
1126                 if (buf->pData != NULL)
1127                 {
1128                     va = VA_STATUS_SUCCESS;
1129                 }
1130             }
1131             break;
1132     }
1133 
1134     bufferHeapElement = MediaLibvaUtilNext::AllocPMediaBufferFromHeap(m_decodeCtx->pMediaCtx->pBufferHeap);
1135     if (nullptr == bufferHeapElement)
1136     {
1137         va = VA_STATUS_ERROR_MAX_NUM_EXCEEDED;
1138         MOS_FreeMemory(buf);
1139         return va;
1140     }
1141     bufferHeapElement->pBuffer   = buf;
1142     bufferHeapElement->pCtx      = (void*)m_decodeCtx;
1143     bufferHeapElement->uiCtxType = DDI_MEDIA_CONTEXT_TYPE_DECODER;
1144     *bufId                       = bufferHeapElement->uiVaBufferID;
1145 
1146     // Keep record the VaBufferID of JPEG slice data buffer we allocated, in order to do buffer mapping when render this buffer. otherwise we
1147     // can not get correct buffer address when application create them disordered.
1148     if (type == VASliceDataBufferType && m_decodeCtx->wMode == CODECHAL_DECODE_MODE_JPEG)
1149     {
1150         // since the dwNumSliceData already +1 when allocate buffer, but here we need to track the VaBufferID before dwSliceData increased.
1151         m_decodeCtx->BufMgr.pSliceData[m_decodeCtx->BufMgr.dwNumSliceData - 1].vaBufferId = *bufId;
1152     }
1153     m_decodeCtx->pMediaCtx->uiNumBufs++;
1154 
1155     if (data == nullptr)
1156     {
1157         return va;
1158     }
1159 
1160     if (true == buf->bCFlushReq)
1161     {
1162         mos_bo_wait_rendering(buf->bo);
1163     }
1164     status = MOS_SecureMemcpy((void *)(buf->pData + buf->uiOffset), size * numElements, data, size * numElements);
1165     DDI_CHK_CONDITION((status != MOS_STATUS_SUCCESS), "DDI:Failed to copy buffer data!", VA_STATUS_ERROR_OPERATION_FAILED);
1166 
1167     return va;
1168 }
1169 
ContextInit(int32_t picWidth,int32_t picHeight)1170 void DdiDecodeBase::ContextInit(
1171     int32_t picWidth,
1172     int32_t picHeight)
1173 {
1174     DDI_CODEC_FUNC_ENTER;
1175 
1176     m_width         = picWidth;
1177     m_height        = picHeight;
1178     m_picWidthInMB  = (int16_t)(DDI_CODEC_NUM_MACROBLOCKS_WIDTH(picWidth));
1179     m_picHeightInMB = (int16_t)(DDI_CODEC_NUM_MACROBLOCKS_HEIGHT(picHeight));
1180     m_decodeCtx->wMode = CODECHAL_DECODE_MODE_AVCVLD;
1181     m_decodeCtx->bShortFormatInUse = false;
1182 #ifdef _DECODE_PROCESSING_SUPPORTED
1183     if (m_ddiDecodeAttr->componentData.data.processType == VA_DEC_PROCESSING)
1184     {
1185         DDI_CODEC_NORMALMESSAGE("Decoding context has scaling/format conversion capabilities");
1186         m_decProcessingType = VA_DEC_PROCESSING;
1187     }
1188     else
1189 #endif
1190     {
1191         DDI_CODEC_NORMALMESSAGE("Decoding context DOESN'T have scaling/format conversion capabilities");
1192         m_decProcessingType = VA_DEC_PROCESSING_NONE;
1193     }
1194     m_streamOutEnabled = false;
1195     m_decodeCtx->DecodeParams.m_picIdRemappingInUse = true;
1196     return;
1197 }
1198 
CreateCodecHal(DDI_MEDIA_CONTEXT * mediaCtx,void * ptr,_CODECHAL_STANDARD_INFO * standardInfo)1199 VAStatus DdiDecodeBase::CreateCodecHal(
1200     DDI_MEDIA_CONTEXT       *mediaCtx,
1201     void                    *ptr,
1202     _CODECHAL_STANDARD_INFO *standardInfo)
1203 {
1204     DDI_CODEC_FUNC_ENTER;
1205 
1206     if ((mediaCtx == nullptr) ||
1207         (ptr == nullptr) ||
1208         (m_codechalSettings == nullptr) ||
1209         (standardInfo == nullptr))
1210     {
1211         DDI_CODEC_ASSERTMESSAGE("NULL pointer is passed for CreateCodecHal.\n");
1212         return VA_STATUS_ERROR_INVALID_PARAMETER;
1213 
1214     }
1215     MOS_CONTEXT *mosCtx  = (MOS_CONTEXT *)ptr;
1216     VAStatus    vaStatus = VA_STATUS_SUCCESS;
1217 
1218     Codechal *codecHal = CodechalDeviceNext::CreateFactory(
1219         nullptr,
1220         mosCtx,
1221         standardInfo,
1222         m_codechalSettings);
1223 
1224     if (nullptr == codecHal)
1225     {
1226         DDI_CODEC_ASSERTMESSAGE("Failure in CodecHal create.\n");
1227         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
1228         return vaStatus;
1229     }
1230 
1231     DecodePipelineAdapter *decoder = dynamic_cast<DecodePipelineAdapter *>(codecHal);
1232     if (nullptr == decoder)
1233     {
1234         DDI_CODEC_ASSERTMESSAGE("Failure in CodecHal create.\n");
1235         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
1236         return vaStatus;
1237     }
1238 
1239     m_decodeCtx->pCodecHal = codecHal;
1240 
1241     m_codechalSettings->sfcInUseHinted = true;
1242 
1243     if (m_ddiDecodeAttr && m_ddiDecodeAttr->componentData.data.encryptType)
1244     {
1245         m_codechalSettings->secureMode = true;
1246     }
1247 
1248     if (codecHal->Allocate(m_codechalSettings) != MOS_STATUS_SUCCESS)
1249     {
1250         DDI_CODEC_ASSERTMESSAGE("Failure in decode allocate.\n");
1251         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
1252         return vaStatus;
1253     }
1254 
1255     PMOS_INTERFACE osInterface = codecHal->GetOsInterface();
1256     if (osInterface == nullptr)
1257     {
1258         DDI_CODEC_ASSERTMESSAGE("Failure in decode allocate.\n");
1259         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
1260         return vaStatus;
1261     }
1262 
1263     m_decodeCtx->pCpDdiInterfaceNext->CreateCencDecode(codecHal->GetDebugInterface(), mosCtx, m_codechalSettings);
1264 
1265     return vaStatus;
1266 }
1267 
GetDummyReferenceFromDPB(DDI_DECODE_CONTEXT * decodeCtx)1268 void DdiDecodeBase::GetDummyReferenceFromDPB(
1269     DDI_DECODE_CONTEXT *decodeCtx)
1270 {
1271     DDI_CODEC_FUNC_ENTER;
1272 
1273     MOS_SURFACE *destSurface = decodeCtx->DecodeParams.m_destSurface;
1274     MOS_SURFACE dummyReference;
1275     MOS_STATUS  eStatus = MOS_STATUS_SUCCESS;
1276     uint32_t    i = 0;
1277 
1278     if (destSurface == nullptr)
1279     {
1280         DDI_CODEC_ASSERTMESSAGE("Decode output surface is NULL.\n");
1281         return;
1282     }
1283 
1284     for (i = 0; i < DDI_MEDIA_MAX_SURFACE_NUMBER_CONTEXT; i++)
1285     {
1286         if (decodeCtx->RTtbl.pRT[i] != nullptr &&
1287             decodeCtx->RTtbl.pRT[i] != decodeCtx->RTtbl.pCurrentRT)
1288         {
1289             MOS_ZeroMemory(&dummyReference, sizeof(MOS_SURFACE));
1290             MediaLibvaCommonNext::MediaSurfaceToMosResource(decodeCtx->RTtbl.pRT[i], &(dummyReference.OsResource));
1291 
1292             if (!Mos_ResourceIsNull(&dummyReference.OsResource))
1293             {
1294                 eStatus = MOS_STATUS_SUCCESS;
1295                 dummyReference.Format = Format_Invalid;
1296                 eStatus = Mos_Specific_GetResourceInfo(decodeCtx->pCodecHal->GetOsInterface(), &dummyReference.OsResource, &dummyReference);
1297                 if (eStatus != MOS_STATUS_SUCCESS)
1298                 {
1299                     continue;
1300                 }
1301 
1302                 if (dummyReference.Type   == destSurface->Type   &&
1303                     dummyReference.Format == destSurface->Format &&
1304                     dummyReference.bIsCompressed   == destSurface->bIsCompressed   &&
1305                     dummyReference.CompressionMode == destSurface->CompressionMode &&
1306                     dummyReference.TileType == destSurface->TileType &&
1307                     dummyReference.dwPitch  >= destSurface->dwPitch  &&
1308                     dummyReference.dwWidth  >= destSurface->dwWidth  &&
1309                     dummyReference.dwHeight >= destSurface->dwHeight)
1310                 {
1311                     break;
1312                 }
1313             }
1314         }
1315     }
1316 
1317     if (i < DDI_MEDIA_MAX_SURFACE_NUMBER_CONTEXT)
1318     {
1319         DecodePipelineAdapter *decoder = dynamic_cast<DecodePipelineAdapter *>(decodeCtx->pCodecHal);
1320         if (decoder == nullptr)
1321         {
1322             DDI_CODEC_ASSERTMESSAGE("Codechal decode context is NULL.\n");
1323             return;
1324         }
1325         decoder->GetDummyReference()->OsResource = dummyReference.OsResource;
1326     }
1327 
1328     return;
1329 }
1330 
ReportDecodeMode(uint16_t wMode)1331 void DdiDecodeBase::ReportDecodeMode(
1332     uint16_t wMode)
1333 {
1334     DDI_CODEC_FUNC_ENTER;
1335 
1336     PMOS_INTERFACE     osInterface = m_decodeCtx->pCodecHal ? m_decodeCtx->pCodecHal->GetOsInterface() : nullptr;
1337     MOS_CONTEXT_HANDLE ctxHandle   = osInterface ? (MOS_CONTEXT_HANDLE)osInterface->pOsContext : nullptr;
1338 
1339     MOS_USER_FEATURE_VALUE_WRITE_DATA userFeatureWriteData;
1340     MOS_ZeroMemory(&userFeatureWriteData, sizeof(userFeatureWriteData));
1341     userFeatureWriteData.Value.i32Data = wMode;
1342     switch (wMode)
1343     {
1344     case CODECHAL_DECODE_MODE_MPEG2IDCT:
1345     case CODECHAL_DECODE_MODE_MPEG2VLD:
1346         userFeatureWriteData.ValueID = __MEDIA_USER_FEATURE_VALUE_DECODE_MPEG2_MODE_ID;
1347         MOS_UserFeature_WriteValues_ID(nullptr, &userFeatureWriteData, 1, ctxHandle);
1348         break;
1349     case CODECHAL_DECODE_MODE_AVCVLD:
1350         userFeatureWriteData.ValueID = __MEDIA_USER_FEATURE_VALUE_DECODE_AVC_MODE_ID;
1351         MOS_UserFeature_WriteValues_ID(nullptr, &userFeatureWriteData, 1, ctxHandle);
1352         break;
1353     case CODECHAL_DECODE_MODE_JPEG:
1354         userFeatureWriteData.ValueID = __MEDIA_USER_FEATURE_VALUE_DECODE_JPEG_MODE_ID;
1355         MOS_UserFeature_WriteValues_ID(nullptr, &userFeatureWriteData, 1, ctxHandle);
1356         break;
1357     case CODECHAL_DECODE_MODE_VP8VLD:
1358         userFeatureWriteData.ValueID = __MEDIA_USER_FEATURE_VALUE_DECODE_VP8_MODE_ID;
1359         MOS_UserFeature_WriteValues_ID(nullptr, &userFeatureWriteData, 1, ctxHandle);
1360         break;
1361     case CODECHAL_DECODE_MODE_HEVCVLD:
1362         userFeatureWriteData.ValueID = __MEDIA_USER_FEATURE_VALUE_DECODE_HEVC_MODE_ID;
1363         MOS_UserFeature_WriteValues_ID(nullptr, &userFeatureWriteData, 1, ctxHandle);
1364         break;
1365     case CODECHAL_DECODE_MODE_VP9VLD:
1366         userFeatureWriteData.ValueID = __MEDIA_USER_FEATURE_VALUE_DECODE_VP9_MODE_ID;
1367         MOS_UserFeature_WriteValues_ID(nullptr, &userFeatureWriteData, 1, ctxHandle);
1368         break;
1369     case CODECHAL_DECODE_MODE_AV1VLD:
1370         userFeatureWriteData.ValueID = __MEDIA_USER_FEATURE_VALUE_DECODE_AV1_MODE_ID;
1371         MOS_UserFeature_WriteValues_ID(nullptr, &userFeatureWriteData, 1, ctxHandle);
1372         break;
1373     default:
1374         break;
1375     }
1376 #if MOS_EVENT_TRACE_DUMP_SUPPORTED
1377     {
1378         DECODE_EVENTDATA_VA_FEATURE_REPORTMODE eventData;
1379         eventData.wMode = (uint32_t)wMode;
1380         eventData.ValueID = userFeatureWriteData.ValueID;
1381         MOS_TraceEvent(EVENT_DECODE_FEATURE_DECODEMODE_REPORTVA, EVENT_TYPE_INFO, &eventData, sizeof(eventData), NULL, 0);
1382     }
1383 #endif
1384     return;
1385 }
1386 } // namespace decode
1387