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