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