xref: /aosp_15_r20/external/intel-media-driver/media_driver/linux/common/codec/ddi/media_ddi_decode_vp9.cpp (revision ba62d9d3abf0e404f2022b4cd7a85e107f48596f)
1 /*
2 * Copyright (c) 2015-2020, Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22 //!
23 //! \file     media_ddi_decode_vp9.cpp
24 //! \brief    The class implementation of DdiDecodeVP9  for VP9 decode
25 //!
26 
27 #include "media_libva_decoder.h"
28 #include "media_libva_util.h"
29 
30 #include "media_ddi_decode_vp9.h"
31 #include "mos_solo_generic.h"
32 #include "codechal_memdecomp.h"
33 #include "media_ddi_decode_const.h"
34 #include "media_ddi_factory.h"
35 
ParseSliceParams(DDI_MEDIA_CONTEXT * mediaCtx,VASliceParameterBufferVP9 * slcParam)36 VAStatus DdiDecodeVP9::ParseSliceParams(
37     DDI_MEDIA_CONTEXT         *mediaCtx,
38     VASliceParameterBufferVP9 *slcParam)
39 {
40     PCODEC_VP9_PIC_PARAMS     picParam  = (PCODEC_VP9_PIC_PARAMS)(m_ddiDecodeCtx->DecodeParams.m_picParams);
41     PCODEC_VP9_SEGMENT_PARAMS segParams = (PCODEC_VP9_SEGMENT_PARAMS)(m_ddiDecodeCtx->DecodeParams.m_iqMatrixBuffer);
42 
43     if ((slcParam == nullptr) ||
44         (picParam == nullptr) ||
45         (segParams == nullptr))
46     {
47         DDI_ASSERTMESSAGE("Invalid Parameter for Parsing VP9 Slice parameter\n");
48         return VA_STATUS_ERROR_INVALID_PARAMETER;
49     }
50 
51     picParam->BSBytesInBuffer = slcParam->slice_data_size;
52 
53     int32_t i, j, k;
54     for (i = 0; i < 8; i++)
55     {
56         segParams->SegData[i].SegmentFlags.fields.SegmentReferenceEnabled = slcParam->seg_param[i].segment_flags.fields.segment_reference_enabled;
57         segParams->SegData[i].SegmentFlags.fields.SegmentReference        = slcParam->seg_param[i].segment_flags.fields.segment_reference;
58         segParams->SegData[i].SegmentFlags.fields.SegmentReferenceSkipped = slcParam->seg_param[i].segment_flags.fields.segment_reference_skipped;
59 
60         for (j = 0; j < 4; j++)
61         {
62             for (k = 0; k < 2; k++)
63             {
64                 segParams->SegData[i].FilterLevel[j][k] = slcParam->seg_param[i].filter_level[j][k];
65             }
66         }
67 
68         segParams->SegData[i].LumaACQuantScale   = slcParam->seg_param[i].luma_ac_quant_scale;
69         segParams->SegData[i].LumaDCQuantScale   = slcParam->seg_param[i].luma_dc_quant_scale;
70         segParams->SegData[i].ChromaACQuantScale = slcParam->seg_param[i].chroma_ac_quant_scale;
71         segParams->SegData[i].ChromaDCQuantScale = slcParam->seg_param[i].chroma_dc_quant_scale;
72     }
73 
74     return VA_STATUS_SUCCESS;
75 }
76 
ParsePicParams(DDI_MEDIA_CONTEXT * mediaCtx,VADecPictureParameterBufferVP9 * picParam)77 VAStatus DdiDecodeVP9::ParsePicParams(
78     DDI_MEDIA_CONTEXT              *mediaCtx,
79     VADecPictureParameterBufferVP9 *picParam)
80 {
81     PCODEC_VP9_PIC_PARAMS picVp9Params = (PCODEC_VP9_PIC_PARAMS)(m_ddiDecodeCtx->DecodeParams.m_picParams);
82 
83     if ((picParam == nullptr) || (picVp9Params == nullptr))
84     {
85         DDI_ASSERTMESSAGE("Invalid Parameter for Parsing VP9 Picture parameter\n");
86         return VA_STATUS_ERROR_INVALID_PARAMETER;
87     }
88 
89     picVp9Params->FrameHeightMinus1 = picParam->frame_height - 1;
90     picVp9Params->FrameWidthMinus1  = picParam->frame_width - 1;
91 
92     picVp9Params->PicFlags.fields.frame_type                   = picParam->pic_fields.bits.frame_type;
93     picVp9Params->PicFlags.fields.show_frame                   = picParam->pic_fields.bits.show_frame;
94     picVp9Params->PicFlags.fields.error_resilient_mode         = picParam->pic_fields.bits.error_resilient_mode;
95     picVp9Params->PicFlags.fields.intra_only                   = picParam->pic_fields.bits.intra_only;
96     picVp9Params->PicFlags.fields.LastRefIdx                   = picParam->pic_fields.bits.last_ref_frame;
97     picVp9Params->PicFlags.fields.LastRefSignBias              = picParam->pic_fields.bits.last_ref_frame_sign_bias;
98     picVp9Params->PicFlags.fields.GoldenRefIdx                 = picParam->pic_fields.bits.golden_ref_frame;
99     picVp9Params->PicFlags.fields.GoldenRefSignBias            = picParam->pic_fields.bits.golden_ref_frame_sign_bias;
100     picVp9Params->PicFlags.fields.AltRefIdx                    = picParam->pic_fields.bits.alt_ref_frame;
101     picVp9Params->PicFlags.fields.AltRefSignBias               = picParam->pic_fields.bits.alt_ref_frame_sign_bias;
102     picVp9Params->PicFlags.fields.allow_high_precision_mv      = picParam->pic_fields.bits.allow_high_precision_mv;
103     picVp9Params->PicFlags.fields.mcomp_filter_type            = picParam->pic_fields.bits.mcomp_filter_type;
104     picVp9Params->PicFlags.fields.frame_parallel_decoding_mode = picParam->pic_fields.bits.frame_parallel_decoding_mode;
105     picVp9Params->PicFlags.fields.segmentation_enabled         = picParam->pic_fields.bits.segmentation_enabled;
106     picVp9Params->PicFlags.fields.segmentation_temporal_update = picParam->pic_fields.bits.segmentation_temporal_update;
107     picVp9Params->PicFlags.fields.segmentation_update_map      = picParam->pic_fields.bits.segmentation_update_map;
108     picVp9Params->PicFlags.fields.reset_frame_context          = picParam->pic_fields.bits.reset_frame_context;
109     picVp9Params->PicFlags.fields.refresh_frame_context        = picParam->pic_fields.bits.refresh_frame_context;
110     picVp9Params->PicFlags.fields.frame_context_idx            = picParam->pic_fields.bits.frame_context_idx;
111     picVp9Params->PicFlags.fields.LosslessFlag                 = picParam->pic_fields.bits.lossless_flag;
112 
113     int32_t frameIdx;
114     frameIdx = GetRenderTargetID(&m_ddiDecodeCtx->RTtbl, m_ddiDecodeCtx->RTtbl.pCurrentRT);
115     if (frameIdx == (int32_t)DDI_CODEC_INVALID_FRAME_INDEX)
116     {
117         return VA_STATUS_ERROR_INVALID_PARAMETER;
118     }
119     picVp9Params->CurrPic.FrameIdx = frameIdx;
120 
121     int32_t i;
122     for (i = 0; i < 8; i++)
123     {
124         if (picParam->reference_frames[i] < mediaCtx->uiNumSurfaces)
125         {
126             PDDI_MEDIA_SURFACE refSurface          = DdiMedia_GetSurfaceFromVASurfaceID(mediaCtx, picParam->reference_frames[i]);
127             frameIdx                               = GetRenderTargetID(&m_ddiDecodeCtx->RTtbl, refSurface);
128             picVp9Params->RefFrameList[i].FrameIdx = ((uint32_t)frameIdx >= CODECHAL_NUM_UNCOMPRESSED_SURFACE_VP9) ? (CODECHAL_NUM_UNCOMPRESSED_SURFACE_VP9 - 1) : frameIdx;
129         }
130         else
131         {
132             PDDI_MEDIA_SURFACE refSurface          = DdiMedia_GetSurfaceFromVASurfaceID(mediaCtx, picParam->reference_frames[i]);
133             if (refSurface != nullptr)
134             {
135                 frameIdx = GetRenderTargetID(&m_ddiDecodeCtx->RTtbl, refSurface);
136                 if (frameIdx != DDI_CODEC_INVALID_FRAME_INDEX)
137                 {
138                     picVp9Params->RefFrameList[i].FrameIdx = ((uint32_t)frameIdx >= CODECHAL_NUM_UNCOMPRESSED_SURFACE_VP9) ? (CODECHAL_NUM_UNCOMPRESSED_SURFACE_VP9 - 1) : frameIdx;
139                 }
140                 else
141                 {
142                     picVp9Params->RefFrameList[i].FrameIdx = CODECHAL_NUM_UNCOMPRESSED_SURFACE_VP9 - 1;
143                 }
144             }
145             else
146             {
147                 picVp9Params->RefFrameList[i].FrameIdx = CODECHAL_NUM_UNCOMPRESSED_SURFACE_VP9 - 1;
148             }
149         }
150     }
151 
152     picVp9Params->filter_level                    = picParam->filter_level;
153     picVp9Params->sharpness_level                 = picParam->sharpness_level;
154     picVp9Params->log2_tile_rows                  = picParam->log2_tile_rows;
155     picVp9Params->log2_tile_columns               = picParam->log2_tile_columns;
156     picVp9Params->UncompressedHeaderLengthInBytes = picParam->frame_header_length_in_bytes;
157     picVp9Params->FirstPartitionSize              = picParam->first_partition_size;
158     picVp9Params->profile                         = picParam->profile;
159 
160     /* Only 8bit depth is supported on picParam->profile=0.
161      * If picParam->profile=2,3, it is possible to support the 10/12 bit-depth.
162      * otherwise the bit_depth is 8.
163      */
164     if (((picParam->profile == CODEC_PROFILE_VP9_PROFILE2) ||
165             (picParam->profile == CODEC_PROFILE_VP9_PROFILE3)) &&
166         (picParam->bit_depth >= 8))
167     {
168         picVp9Params->BitDepthMinus8 = picParam->bit_depth - 8;
169     }
170     else
171     {
172         picVp9Params->BitDepthMinus8 = 0;
173     }
174 
175     picVp9Params->subsampling_x = picParam->pic_fields.bits.subsampling_x;
176     picVp9Params->subsampling_y = picParam->pic_fields.bits.subsampling_y;
177 
178     MOS_SecureMemcpy(picVp9Params->SegTreeProbs, 7, picParam->mb_segment_tree_probs, 7);
179     MOS_SecureMemcpy(picVp9Params->SegPredProbs, 3, picParam->segment_pred_probs, 3);
180 
181 #if MOS_EVENT_TRACE_DUMP_SUPPORTED
182     // Picture Info
183     uint32_t subSamplingSum = picVp9Params->subsampling_x + picVp9Params->subsampling_y;
184     DECODE_EVENTDATA_INFO_PICTUREVA eventData = {0};
185     eventData.CodecFormat                   = m_ddiDecodeCtx->wMode;
186     eventData.FrameType                     = picVp9Params->PicFlags.fields.frame_type == 0 ? I_TYPE : MIXED_TYPE;
187     eventData.PicStruct                     = FRAME_PICTURE;
188     eventData.Width                         = picVp9Params->FrameWidthMinus1 + 1;
189     eventData.Height                        = picVp9Params->FrameHeightMinus1 + 1;
190     eventData.Bitdepth                      = picVp9Params->BitDepthMinus8 + 8;
191     eventData.ChromaFormat                  = (subSamplingSum == 2) ? 1 : (subSamplingSum == 1 ? 2 : 3);  // 1-4:2:0; 2-4:2:2; 3-4:4:4
192     eventData.EnabledSegment                = picVp9Params->PicFlags.fields.segmentation_enabled;
193     MOS_TraceEvent(EVENT_DECODE_INFO_PICTUREVA, EVENT_TYPE_INFO, &eventData, sizeof(eventData), NULL, 0);
194 #endif
195 
196     return VA_STATUS_SUCCESS;
197 }
198 
SetDecodeParams()199 VAStatus DdiDecodeVP9::SetDecodeParams()
200 {
201      DDI_CHK_RET(DdiMediaDecode::SetDecodeParams(),"SetDecodeParams failed!");
202 #ifdef _DECODE_PROCESSING_SUPPORTED
203     // Bridge the SFC input with vdbox output
204     if (m_decProcessingType == VA_DEC_PROCESSING)
205     {
206         auto procParams =
207             (DecodeProcessingParams *)m_ddiDecodeCtx->DecodeParams.m_procParams;
208         procParams->m_inputSurface = (&m_ddiDecodeCtx->DecodeParams)->m_destSurface;
209         // codechal_decode_sfc.c expects Input Width/Height information.
210         procParams->m_inputSurface->dwWidth  = procParams->m_inputSurface->OsResource.iWidth;
211         procParams->m_inputSurface->dwHeight = procParams->m_inputSurface->OsResource.iHeight;
212         procParams->m_inputSurface->dwPitch  = procParams->m_inputSurface->OsResource.iPitch;
213         procParams->m_inputSurface->Format   = procParams->m_inputSurface->OsResource.Format;
214 
215         if(m_requireInputRegion)
216         {
217             procParams->m_inputSurfaceRegion.m_x = 0;
218             procParams->m_inputSurfaceRegion.m_y = 0;
219             procParams->m_inputSurfaceRegion.m_width = procParams->m_inputSurface->dwWidth;
220             procParams->m_inputSurfaceRegion.m_height = procParams->m_inputSurface->dwHeight;
221         }
222     }
223 #endif
224      return VA_STATUS_SUCCESS;
225 }
226 
RenderPicture(VADriverContextP ctx,VAContextID context,VABufferID * buffers,int32_t numBuffers)227 VAStatus DdiDecodeVP9::RenderPicture(
228     VADriverContextP ctx,
229     VAContextID      context,
230     VABufferID       *buffers,
231     int32_t          numBuffers)
232 {
233     VAStatus           va = VA_STATUS_SUCCESS;
234     PDDI_MEDIA_CONTEXT mediaCtx = DdiMedia_GetMediaContext(ctx);
235 
236     DDI_FUNCTION_ENTER();
237 
238     void             *data = nullptr;
239     for (int32_t i = 0; i < numBuffers; i++)
240     {
241         if (!buffers || (buffers[i] == VA_INVALID_ID))
242         {
243             return VA_STATUS_ERROR_INVALID_BUFFER;
244         }
245         DDI_MEDIA_BUFFER *buf = DdiMedia_GetBufferFromVABufferID(mediaCtx, buffers[i]);
246         if (nullptr == buf)
247         {
248             return VA_STATUS_ERROR_INVALID_BUFFER;
249         }
250 
251         uint32_t dataSize = buf->iSize;
252         DdiMedia_MapBuffer(ctx, buffers[i], &data);
253 
254         if (data == nullptr)
255         {
256             return VA_STATUS_ERROR_INVALID_BUFFER;
257         }
258 
259         switch ((int32_t)buf->uiType)
260         {
261         case VASliceDataBufferType:
262         {
263             if (slcFlag)
264             {
265                 // VP9 only supports only one slice_data. If it is passed, another slice_data
266                 // buffer will be ignored.
267                 DDI_NORMALMESSAGE("Slice data is already rendered\n");
268                 break;
269             }
270             int32_t index = GetBitstreamBufIndexFromBuffer(&m_ddiDecodeCtx->BufMgr, buf);
271             if (index == DDI_CODEC_INVALID_BUFFER_INDEX)
272             {
273                 return VA_STATUS_ERROR_INVALID_BUFFER;
274             }
275 
276             DdiMedia_MediaBufferToMosResource(m_ddiDecodeCtx->BufMgr.pBitStreamBuffObject[index], &m_ddiDecodeCtx->BufMgr.resBitstreamBuffer);
277             m_ddiDecodeCtx->DecodeParams.m_dataSize += dataSize;
278             slcFlag = true;
279 
280             break;
281         }
282         case VASliceParameterBufferType:
283         {
284             if (m_ddiDecodeCtx->DecodeParams.m_numSlices)
285             {
286                 // VP9 only supports only one slice. If it is passed, another slice_param
287                 // buffer will be ignored.
288                 DDI_NORMALMESSAGE("SliceParamBufferVP9 is already rendered\n");
289                 break;
290             }
291             if (buf->uiNumElements == 0)
292             {
293                 return VA_STATUS_ERROR_INVALID_BUFFER;
294             }
295 
296             VASliceParameterBufferVP9 *slcInfoVP9 = (VASliceParameterBufferVP9 *)data;
297             DDI_CHK_RET(ParseSliceParams(mediaCtx, slcInfoVP9),"ParseSliceParams failed!");
298             m_ddiDecodeCtx->DecodeParams.m_numSlices++;
299             m_groupIndex++;
300             break;
301         }
302         case VAPictureParameterBufferType:
303         {
304             VADecPictureParameterBufferVP9 *picParam;
305 
306             picParam = (VADecPictureParameterBufferVP9 *)data;
307             DDI_CHK_RET(ParsePicParams(mediaCtx, picParam),"ParsePicParams failed!");
308             break;
309         }
310 
311         case VAProcPipelineParameterBufferType:
312         {
313             DDI_CHK_RET(ParseProcessingBuffer(mediaCtx, data),"ParseProcessingBuffer failed!");
314             break;
315         }
316         case VADecodeStreamoutBufferType:
317         {
318             DdiMedia_MediaBufferToMosResource(buf, &m_ddiDecodeCtx->BufMgr.resExternalStreamOutBuffer);
319             m_streamOutEnabled = true;
320             break;
321         }
322 
323         default:
324             va = m_ddiDecodeCtx->pCpDdiInterface->RenderCencPicture(ctx, context, buf, data);
325             break;
326         }
327         DdiMedia_UnmapBuffer(ctx, buffers[i]);
328     }
329 
330     DDI_FUNCTION_EXIT(va);
331     return va;
332 }
333 
InitResourceBuffer()334 VAStatus DdiDecodeVP9::InitResourceBuffer()
335 {
336     VAStatus                  vaStatus = VA_STATUS_SUCCESS;
337     DDI_CODEC_COM_BUFFER_MGR *bufMgr   = &(m_ddiDecodeCtx->BufMgr);
338 
339     bufMgr->pSliceData = nullptr;
340 
341     bufMgr->ui64BitstreamOrder = 0;
342     bufMgr->dwMaxBsSize        = m_width *
343                           m_height * 3 / 2;
344     // minimal 10k bytes for some special case. Will refractor this later
345     if (bufMgr->dwMaxBsSize < DDI_CODEC_MIN_VALUE_OF_MAX_BS_SIZE)
346     {
347         bufMgr->dwMaxBsSize = DDI_CODEC_MIN_VALUE_OF_MAX_BS_SIZE;
348     }
349 
350     int32_t i;
351     // init decode bitstream buffer object
352     for (i = 0; i < DDI_CODEC_MAX_BITSTREAM_BUFFER; i++)
353     {
354         bufMgr->pBitStreamBuffObject[i] = (DDI_MEDIA_BUFFER *)MOS_AllocAndZeroMemory(sizeof(DDI_MEDIA_BUFFER));
355         if (bufMgr->pBitStreamBuffObject[i] == nullptr)
356         {
357             vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
358             goto finish;
359         }
360         bufMgr->pBitStreamBuffObject[i]->iSize    = bufMgr->dwMaxBsSize;
361         bufMgr->pBitStreamBuffObject[i]->uiType   = VASliceDataBufferType;
362         bufMgr->pBitStreamBuffObject[i]->format   = Media_Format_Buffer;
363         bufMgr->pBitStreamBuffObject[i]->uiOffset = 0;
364         bufMgr->pBitStreamBuffObject[i]->bo       = nullptr;
365         bufMgr->pBitStreamBase[i]                 = nullptr;
366     }
367 
368     // VP9 can support only one SliceDataBuffer. In such case only one is enough.
369     // 2 is allocated for the safety.
370     bufMgr->m_maxNumSliceData = 2;
371     bufMgr->pSliceData        = (DDI_CODEC_BITSTREAM_BUFFER_INFO *)MOS_AllocAndZeroMemory(sizeof(bufMgr->pSliceData[0]) * 2);
372 
373     if (bufMgr->pSliceData == nullptr)
374     {
375         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
376         goto finish;
377     }
378 
379     bufMgr->dwNumSliceData    = 0;
380     bufMgr->dwNumSliceControl = 0;
381 
382     bufMgr->Codec_Param.Codec_Param_VP9.pVASliceParaBufVP9 = (VASliceParameterBufferVP9 *)MOS_AllocAndZeroMemory(sizeof(VASliceParameterBufferVP9));
383     if (bufMgr->Codec_Param.Codec_Param_VP9.pVASliceParaBufVP9 == nullptr)
384     {
385         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
386         goto finish;
387     }
388 
389     return VA_STATUS_SUCCESS;
390 
391 finish:
392     FreeResourceBuffer();
393     return vaStatus;
394 }
395 
FreeResourceBuffer()396 void DdiDecodeVP9::FreeResourceBuffer()
397 {
398     DDI_CODEC_COM_BUFFER_MGR *bufMgr = &(m_ddiDecodeCtx->BufMgr);
399 
400     int32_t i;
401     for (i = 0; i < DDI_CODEC_MAX_BITSTREAM_BUFFER; i++)
402     {
403         if (bufMgr->pBitStreamBase[i])
404         {
405             DdiMediaUtil_UnlockBuffer(bufMgr->pBitStreamBuffObject[i]);
406             bufMgr->pBitStreamBase[i] = nullptr;
407         }
408         if (bufMgr->pBitStreamBuffObject[i])
409         {
410             DdiMediaUtil_FreeBuffer(bufMgr->pBitStreamBuffObject[i]);
411             MOS_FreeMemory(bufMgr->pBitStreamBuffObject[i]);
412             bufMgr->pBitStreamBuffObject[i] = nullptr;
413         }
414     }
415 
416     if (bufMgr->Codec_Param.Codec_Param_VP9.pVASliceParaBufVP9)
417     {
418         MOS_FreeMemory(bufMgr->Codec_Param.Codec_Param_VP9.pVASliceParaBufVP9);
419         bufMgr->Codec_Param.Codec_Param_VP9.pVASliceParaBufVP9 = nullptr;
420     }
421 
422     // free decode bitstream buffer object
423     MOS_FreeMemory(bufMgr->pSliceData);
424     bufMgr->pSliceData = nullptr;
425 }
426 
GetPicParamBuf(DDI_CODEC_COM_BUFFER_MGR * bufMgr)427 uint8_t* DdiDecodeVP9::GetPicParamBuf(
428     DDI_CODEC_COM_BUFFER_MGR    *bufMgr)
429 {
430     return (uint8_t*)(&(bufMgr->Codec_Param.Codec_Param_VP9.PicParamVP9));
431 }
432 
AllocSliceControlBuffer(DDI_MEDIA_BUFFER * buf)433 VAStatus DdiDecodeVP9::AllocSliceControlBuffer(
434     DDI_MEDIA_BUFFER       *buf)
435 {
436     DDI_CODEC_COM_BUFFER_MGR   *bufMgr;
437 
438     bufMgr     = &(m_ddiDecodeCtx->BufMgr);
439     if(bufMgr->Codec_Param.Codec_Param_VP9.pVASliceParaBufVP9 == nullptr)
440     {
441         return VA_STATUS_ERROR_ALLOCATION_FAILED;
442     }
443     buf->pData    = (uint8_t*)bufMgr->Codec_Param.Codec_Param_VP9.pVASliceParaBufVP9;
444     buf->uiOffset = bufMgr->dwNumSliceControl * sizeof(VASliceParameterBufferVP9);
445 
446     bufMgr->dwNumSliceControl += buf->uiNumElements;
447 
448     return VA_STATUS_SUCCESS;
449 }
450 
CodecHalInit(DDI_MEDIA_CONTEXT * mediaCtx,void * ptr)451 VAStatus DdiDecodeVP9::CodecHalInit(
452     DDI_MEDIA_CONTEXT *mediaCtx,
453     void              *ptr)
454 {
455     VAStatus     vaStatus = VA_STATUS_SUCCESS;
456     MOS_CONTEXT *mosCtx   = (MOS_CONTEXT *)ptr;
457 
458     CODECHAL_FUNCTION codecFunction = CODECHAL_FUNCTION_DECODE;
459     m_ddiDecodeCtx->pCpDdiInterface->SetCpParams(m_ddiDecodeAttr->uiEncryptionType, m_codechalSettings);
460 
461     CODECHAL_STANDARD_INFO standardInfo;
462     memset(&standardInfo, 0, sizeof(standardInfo));
463 
464     standardInfo.CodecFunction = codecFunction;
465     standardInfo.Mode          = (CODECHAL_MODE)m_ddiDecodeCtx->wMode;
466 
467     m_codechalSettings->codecFunction = codecFunction;
468     m_codechalSettings->width       = m_width;
469     m_codechalSettings->height      = m_height;
470     m_codechalSettings->intelEntrypointInUse = false;
471 
472     m_codechalSettings->lumaChromaDepth = CODECHAL_LUMA_CHROMA_DEPTH_8_BITS;
473     if ((m_ddiDecodeAttr->profile == VAProfileVP9Profile2) ||
474         (m_ddiDecodeAttr->profile == VAProfileVP9Profile3))
475     {
476         m_codechalSettings->lumaChromaDepth |= CODECHAL_LUMA_CHROMA_DEPTH_10_BITS;
477     }
478 
479     m_codechalSettings->shortFormatInUse = m_ddiDecodeCtx->bShortFormatInUse;
480 
481     m_codechalSettings->mode           = CODECHAL_DECODE_MODE_VP9VLD;
482     m_codechalSettings->standard       = CODECHAL_VP9;
483     m_codechalSettings->chromaFormat = HCP_CHROMA_FORMAT_YUV420;
484 
485     if(m_ddiDecodeAttr->profile == VAProfileVP9Profile1 ||
486        m_ddiDecodeAttr->profile == VAProfileVP9Profile3)
487     {
488         m_codechalSettings->chromaFormat = HCP_CHROMA_FORMAT_YUV444;
489     }
490 
491     m_ddiDecodeCtx->DecodeParams.m_iqMatrixBuffer = MOS_AllocAndZeroMemory(sizeof(CODEC_VP9_SEGMENT_PARAMS));
492     if (m_ddiDecodeCtx->DecodeParams.m_iqMatrixBuffer == nullptr)
493     {
494         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
495         goto CleanUpandReturn;
496     }
497     m_ddiDecodeCtx->DecodeParams.m_picParams = MOS_AllocAndZeroMemory(sizeof(CODEC_VP9_PIC_PARAMS));
498     if (m_ddiDecodeCtx->DecodeParams.m_picParams == nullptr)
499     {
500         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
501         goto CleanUpandReturn;
502     }
503 #ifdef _DECODE_PROCESSING_SUPPORTED
504     if (m_decProcessingType == VA_DEC_PROCESSING)
505     {
506         DecodeProcessingParams *procParams = nullptr;
507 
508         m_codechalSettings->downsamplingHinted = true;
509 
510         procParams = (DecodeProcessingParams *)MOS_AllocAndZeroMemory(sizeof(DecodeProcessingParams));
511         if (procParams == nullptr)
512         {
513             vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
514             goto CleanUpandReturn;
515         }
516 
517         m_ddiDecodeCtx->DecodeParams.m_procParams = procParams;
518         procParams->m_outputSurface = (PMOS_SURFACE)MOS_AllocAndZeroMemory(sizeof(MOS_SURFACE));
519         if (procParams->m_outputSurface == nullptr)
520         {
521             vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
522             goto CleanUpandReturn;
523         }
524     }
525 #endif
526     vaStatus = CreateCodecHal(mediaCtx,
527         ptr,
528         &standardInfo);
529 
530     if (vaStatus != VA_STATUS_SUCCESS)
531     {
532         goto CleanUpandReturn;
533     }
534 
535     if (InitResourceBuffer() != VA_STATUS_SUCCESS)
536     {
537         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
538         goto CleanUpandReturn;
539     }
540 
541     return vaStatus;
542 
543 CleanUpandReturn:
544     FreeResourceBuffer();
545 
546     if (m_ddiDecodeCtx->pCodecHal)
547     {
548         m_ddiDecodeCtx->pCodecHal->Destroy();
549         MOS_Delete(m_ddiDecodeCtx->pCodecHal);
550         m_ddiDecodeCtx->pCodecHal = nullptr;
551     }
552 
553     MOS_FreeMemory(m_ddiDecodeCtx->DecodeParams.m_iqMatrixBuffer);
554     m_ddiDecodeCtx->DecodeParams.m_iqMatrixBuffer = nullptr;
555     MOS_FreeMemory(m_ddiDecodeCtx->DecodeParams.m_picParams);
556     m_ddiDecodeCtx->DecodeParams.m_picParams = nullptr;
557     MOS_FreeMemory(m_ddiDecodeCtx->DecodeParams.m_sliceParams);
558     m_ddiDecodeCtx->DecodeParams.m_sliceParams = nullptr;
559 #ifdef _DECODE_PROCESSING_SUPPORTED
560         if (m_ddiDecodeCtx->DecodeParams.m_procParams)
561         {
562             auto procParams =
563                 (DecodeProcessingParams *)m_ddiDecodeCtx->DecodeParams.m_procParams;
564             MOS_FreeMemory(procParams->m_outputSurface);
565 
566             MOS_FreeMemory(m_ddiDecodeCtx->DecodeParams.m_procParams);
567             m_ddiDecodeCtx->DecodeParams.m_procParams = nullptr;
568         }
569 #endif
570 
571     return vaStatus;
572 }
573 
InitDecodeParams(VADriverContextP ctx,VAContextID context)574 VAStatus DdiDecodeVP9::InitDecodeParams(
575     VADriverContextP ctx,
576     VAContextID      context)
577 {
578     slcFlag = false;
579     /* skip the mediaCtx check as it is checked in caller */
580     PDDI_MEDIA_CONTEXT mediaCtx = DdiMedia_GetMediaContext(ctx);
581     DDI_CHK_RET(DecodeCombineBitstream(mediaCtx),"DecodeCombineBitstream failed!");
582     DDI_CODEC_COM_BUFFER_MGR *bufMgr = &(m_ddiDecodeCtx->BufMgr);
583     bufMgr->dwNumSliceData    = 0;
584     bufMgr->dwNumSliceControl = 0;
585 
586     DDI_CODEC_RENDER_TARGET_TABLE *rtTbl = &(m_ddiDecodeCtx->RTtbl);
587 
588     if ((rtTbl == nullptr) || (rtTbl->pCurrentRT == nullptr))
589     {
590         return VA_STATUS_ERROR_INVALID_PARAMETER;
591     }
592     return VA_STATUS_SUCCESS;
593 }
594 
GetFormat()595 MOS_FORMAT DdiDecodeVP9::GetFormat()
596 {
597     slcFlag = false;
598     MOS_FORMAT Format = Format_NV12;
599     DDI_CODEC_RENDER_TARGET_TABLE *rtTbl = &(m_ddiDecodeCtx->RTtbl);
600     CodechalDecodeParams *decodeParams = &m_ddiDecodeCtx->DecodeParams;
601 
602     CODEC_VP9_PIC_PARAMS *picParams = (CODEC_VP9_PIC_PARAMS *)decodeParams->m_picParams;
603     if((picParams->profile == CODEC_PROFILE_VP9_PROFILE1) &&
604         (picParams->BitDepthMinus8 == 0))
605     {
606         Format = Format_AYUV;
607     }
608     if (((picParams->profile == CODEC_PROFILE_VP9_PROFILE2) ||
609         (picParams->profile == CODEC_PROFILE_VP9_PROFILE3)) &&
610         (picParams->BitDepthMinus8 > 0))
611     {
612         Format = Format_P010;
613         if((picParams->BitDepthMinus8 > 2) || (rtTbl->pCurrentRT->format == Media_Format_P016 || rtTbl->pCurrentRT->format == Media_Format_P012))
614         {
615             Format = Format_P016;
616         }
617         if ((picParams->subsampling_x == 1) && (picParams->subsampling_y == 0))
618         {
619             Format = Format_Y210;
620         }
621         else if ((picParams->subsampling_x == 0) && (picParams->subsampling_y == 0))
622         {
623             if(picParams->BitDepthMinus8 == 2)
624             {
625                 Format = Format_Y410;
626 
627                 //10bit decode in 12bit
628 #if VA_CHECK_VERSION(1, 9, 0)
629                 if(rtTbl->pCurrentRT->format == Media_Format_Y416 || rtTbl->pCurrentRT->format == Media_Format_Y412)
630 #else
631                 if(rtTbl->pCurrentRT->format == Media_Format_Y416)
632 #endif
633                 {
634                     Format = Format_Y416;
635                 }
636             }
637             else if(picParams->BitDepthMinus8 > 2)
638             {
639                 Format = Format_Y416;
640             }
641         }
642     }
643     return Format;
644 }
645 
DestroyContext(VADriverContextP ctx)646 void DdiDecodeVP9::DestroyContext(
647     VADriverContextP ctx)
648 {
649     FreeResourceBuffer();
650     // explicitly call the base function to do the further clean-up
651     DdiMediaDecode::DestroyContext(ctx);
652 }
653 
ContextInit(int32_t picWidth,int32_t picHeight)654 void DdiDecodeVP9::ContextInit(
655     int32_t picWidth,
656     int32_t picHeight)
657 {
658     // call the function in base class to initialize it.
659     DdiMediaDecode::ContextInit(picWidth, picHeight);
660 
661     m_ddiDecodeCtx->wMode    = CODECHAL_DECODE_MODE_VP9VLD;
662 }
663 
664 extern template class MediaDdiFactory<DdiMediaDecode, DDI_DECODE_CONFIG_ATTR>;
665 
666 static bool vp9Registered =
667     MediaDdiFactory<DdiMediaDecode, DDI_DECODE_CONFIG_ATTR>::RegisterCodec<DdiDecodeVP9>(DECODE_ID_VP9);
668