xref: /aosp_15_r20/external/intel-media-driver/media_driver/linux/common/codec/ddi/media_ddi_decode_vp8.cpp (revision ba62d9d3abf0e404f2022b4cd7a85e107f48596f)
1 /*
2 * Copyright (c) 2015-2017, 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_vp8.cpp
24 //! \brief    The class implementation of DdiDecodeVP8  for VP8 decode
25 //!
26 
27 #include "media_libva_decoder.h"
28 #include "media_libva_util.h"
29 
30 #include "media_ddi_decode_vp8.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 
36 #define DDI_DECODE_VP8_QINDEX_RANGE 128
37 
38 // Tables from the VP8 reference decoder
39 static const int32_t Vp8DcQlookup[DDI_DECODE_VP8_QINDEX_RANGE] =
40 {
41 4, 5, 6, 7, 8, 9, 10, 10, 11, 12, 13, 14, 15,
42 16, 17, 17, 18, 19, 20, 20, 21, 21, 22, 22, 23, 23,
43 24, 25, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
44 36, 37, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 46,
45 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
46 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72,
47 73, 74, 75, 76, 76, 77, 78, 79, 80, 81, 82, 83, 84,
48 85, 86, 87, 88, 89, 91, 93, 95, 96, 98, 100, 101, 102,
49 104, 106, 108, 110, 112, 114, 116, 118, 122, 124, 126, 128, 130,
50 132, 134, 136, 138, 140, 143, 145, 148, 151, 154, 157,
51 };
52 
53 static const int32_t Vp8AcQlookup[DDI_DECODE_VP8_QINDEX_RANGE] =
54 {
55 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
56 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
57 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
58 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
59 56, 57, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78,
60 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104,
61 106, 108, 110, 112, 114, 116, 119, 122, 125, 128, 131, 134, 137,
62 140, 143, 146, 149, 152, 155, 158, 161, 164, 167, 170, 173, 177,
63 181, 185, 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229,
64 234, 239, 245, 249, 254, 259, 264, 269, 274, 279, 284,
65 };
66 
67 // Load VP8 Slice Parameters from the libva buffer into the Codec Hal Picture Parameters buffer.
68 // 2 libva buffers (VASliceParameterBufferVP8 & VAPictureParameterBufferVP8) get merged into one CodecHal buffer (CODEC_VP8_PIC_PARAMS)
69 // Only one sliceParameterBuffer is enough for VP8.
ParseSliceParams(DDI_MEDIA_CONTEXT * mediaCtx,VASliceParameterBufferVP8 * slcParam)70 VAStatus DdiDecodeVP8::ParseSliceParams(
71     DDI_MEDIA_CONTEXT         *mediaCtx,
72     VASliceParameterBufferVP8 *slcParam)
73 {
74     PCODEC_VP8_PIC_PARAMS picParams = (PCODEC_VP8_PIC_PARAMS)(m_ddiDecodeCtx->DecodeParams.m_picParams);
75 
76     if ((slcParam == nullptr) || (picParams == nullptr))
77     {
78         DDI_ASSERTMESSAGE("Invalid Parameter for Parsing VP8 Slice parameter\n");
79         return VA_STATUS_ERROR_INVALID_PARAMETER;
80     }
81     // num_of_partitions = (1 << CodedCoeffTokenPartition)+1, count both control partition(frame header) and token partition.
82     uint8_t num_token_partitions;
83     num_token_partitions                = slcParam->num_of_partitions - 1;
84     picParams->CodedCoeffTokenPartition = (num_token_partitions != 8) ? (num_token_partitions >> 1) : 3;
85     //macroblock_offset is in unit of bit.it should be always the next byte, the byte is divided to two parts
86     //used bits and remaining bits, if used bits == 8, uiFirstMbByteOffset should add 1, so use 8 to do the ceil operator
87     picParams->uiFirstMbByteOffset = slcParam->slice_data_offset + ((slcParam->macroblock_offset + 8) >> 3);
88 
89     MOS_SecureMemcpy(picParams->uiPartitionSize, sizeof(picParams->uiPartitionSize), slcParam->partition_size, sizeof(picParams->uiPartitionSize));
90     //partition 0 size in command buffer includes the one byte in bool decoder if remaining bits of bool decoder is zero.
91     picParams->uiPartitionSize[0] -= (slcParam->macroblock_offset & 0x7) ? 0 : 1;
92 
93     return VA_STATUS_SUCCESS;
94 }
95 
Vp8QuantIdx(int16_t index)96 static uint16_t Vp8QuantIdx(int16_t index)
97 {
98     if (index > 127)
99         index = 127;
100     if (index < 0)
101         index = 0;
102 
103     return index;
104 }
105 
Vp8AcQuant(uint16_t index)106 static uint16_t Vp8AcQuant(uint16_t index)
107 {
108     return Vp8AcQlookup[Vp8QuantIdx(index)];
109 }
110 
Vp8DcQuant(uint16_t index)111 static uint16_t Vp8DcQuant(uint16_t index)
112 {
113     return Vp8DcQlookup[Vp8QuantIdx(index)];
114 }
115 
116 // Copy VP8 IQ Matrix from the libva buffer into the Codec Hal buffer. A memcpy can be used, as the buffers have the same structure.
ParseIQMatrix(DDI_MEDIA_CONTEXT * mediaCtx,VAIQMatrixBufferVP8 * matrix)117 VAStatus DdiDecodeVP8::ParseIQMatrix(
118     DDI_MEDIA_CONTEXT *  mediaCtx,
119     VAIQMatrixBufferVP8 *matrix)
120 {
121     CODEC_VP8_IQ_MATRIX_PARAMS *iqParams = (CODEC_VP8_IQ_MATRIX_PARAMS *)(m_ddiDecodeCtx->DecodeParams.m_iqMatrixBuffer);
122 
123     if ((matrix == nullptr) || (iqParams == nullptr))
124     {
125         DDI_ASSERTMESSAGE("Invalid Parameter for Parsing VP8 IQMatrix parameter\n");
126         return VA_STATUS_ERROR_INVALID_PARAMETER;
127     }
128     uint32_t i;
129     for (i = 0; i < 4; i++)
130     {
131         iqParams->quantization_values[i][0] = Vp8DcQuant(matrix->quantization_index[i][1]);
132         iqParams->quantization_values[i][1] = Vp8AcQuant(matrix->quantization_index[i][0]);
133         iqParams->quantization_values[i][2] = Vp8DcQuant(matrix->quantization_index[i][4]);
134         iqParams->quantization_values[i][3] = Vp8AcQuant(matrix->quantization_index[i][5]);
135         iqParams->quantization_values[i][4] = 2 * Vp8DcQuant(matrix->quantization_index[i][2]);
136         iqParams->quantization_values[i][5] = 155 * Vp8AcQuant(matrix->quantization_index[i][3]) / 100;
137 
138         if (iqParams->quantization_values[i][5] < 8)
139             iqParams->quantization_values[i][5] = 8;
140         if (iqParams->quantization_values[i][2] > 132)
141             iqParams->quantization_values[i][2] = 132;
142     }
143 
144     return VA_STATUS_SUCCESS;
145 }
146 
147 // Load VP8 Picture Parameters from the libva buffer into the Codec Hal buffer.
ParsePicParams(DDI_MEDIA_CONTEXT * mediaCtx,VAPictureParameterBufferVP8 * picParam)148 VAStatus DdiDecodeVP8::ParsePicParams(
149     DDI_MEDIA_CONTEXT           *mediaCtx,
150     VAPictureParameterBufferVP8 *picParam)
151 {
152     PDDI_MEDIA_SURFACE lastRefSurface   = nullptr;
153     PDDI_MEDIA_SURFACE goldenRefSurface = nullptr;
154     PDDI_MEDIA_SURFACE altRefSurface    = nullptr;
155 
156     PCODEC_VP8_PIC_PARAMS codecPicParams = (PCODEC_VP8_PIC_PARAMS)(m_ddiDecodeCtx->DecodeParams.m_picParams);
157 
158     PDDI_MEDIA_SURFACE *vp8Surfaces = m_ddiDecodeCtx->BufMgr.Codec_Param.Codec_Param_VP8.pReferenceFrames;
159 
160     PDDI_MEDIA_SURFACE currentSurface = m_ddiDecodeCtx->RTtbl.pCurrentRT;
161 
162     // only no-keyframe have last/gold/alt reference frame
163     if (picParam->pic_fields.bits.key_frame)
164     {
165         lastRefSurface   = DdiMedia_GetSurfaceFromVASurfaceID(mediaCtx, picParam->last_ref_frame);
166         if(lastRefSurface)
167         {
168             DdiMedia_MediaSurfaceToMosResource(lastRefSurface, &m_resNoneRegLastRefFrame);
169             m_ddiDecodeCtx->DecodeParams.m_presNoneRegLastRefFrame = &m_resNoneRegLastRefFrame;
170         }
171         goldenRefSurface = DdiMedia_GetSurfaceFromVASurfaceID(mediaCtx, picParam->golden_ref_frame);
172         if(goldenRefSurface)
173         {
174             DdiMedia_MediaSurfaceToMosResource(goldenRefSurface, &m_resNoneRegGoldenRefFrame);
175             m_ddiDecodeCtx->DecodeParams.m_presNoneRegGoldenRefFrame = &m_resNoneRegGoldenRefFrame;
176         }
177         altRefSurface    = DdiMedia_GetSurfaceFromVASurfaceID(mediaCtx, picParam->alt_ref_frame);
178         if(altRefSurface)
179         {
180             DdiMedia_MediaSurfaceToMosResource(altRefSurface, &m_resNoneRegAltRefFrame);
181             m_ddiDecodeCtx->DecodeParams.m_presNoneRegAltRefFrame = &m_resNoneRegAltRefFrame;
182         }
183     }
184 
185     int32_t frameIdx;
186     frameIdx = GetRenderTargetID(&m_ddiDecodeCtx->RTtbl, currentSurface);
187     if (frameIdx == (int32_t)DDI_CODEC_INVALID_FRAME_INDEX)
188     {
189         return VA_STATUS_ERROR_INVALID_PARAMETER;
190     }
191     codecPicParams->ucCurrPicIndex = frameIdx;
192 
193     frameIdx                          = GetRenderTargetID(&m_ddiDecodeCtx->RTtbl, lastRefSurface);
194     codecPicParams->ucLastRefPicIndex = ((uint32_t)frameIdx >= CODECHAL_NUM_UNCOMPRESSED_SURFACE_VP8) ? (CODECHAL_NUM_UNCOMPRESSED_SURFACE_VP8 - 1) : frameIdx;
195 
196     frameIdx                            = GetRenderTargetID(&m_ddiDecodeCtx->RTtbl, goldenRefSurface);
197     codecPicParams->ucGoldenRefPicIndex = ((uint32_t)frameIdx >= CODECHAL_NUM_UNCOMPRESSED_SURFACE_VP8) ? (CODECHAL_NUM_UNCOMPRESSED_SURFACE_VP8 - 1) : frameIdx;
198 
199     frameIdx                         = GetRenderTargetID(&m_ddiDecodeCtx->RTtbl, altRefSurface);
200     codecPicParams->ucAltRefPicIndex = ((uint32_t)frameIdx >= CODECHAL_NUM_UNCOMPRESSED_SURFACE_VP8) ? (CODECHAL_NUM_UNCOMPRESSED_SURFACE_VP8 - 1) : frameIdx;
201 
202     codecPicParams->CurrPic.FrameIdx            = codecPicParams->ucCurrPicIndex;
203     codecPicParams->wFrameWidthInMbsMinus1      = ((picParam->frame_width + 15) / 16) - 1;
204     codecPicParams->wFrameHeightInMbsMinus1     = ((picParam->frame_height + 15) / 16) - 1;
205     codecPicParams->ucDeblockedPicIndex         = codecPicParams->ucCurrPicIndex;
206     codecPicParams->ucReserved8Bits             = 0;
207     codecPicParams->key_frame                   = (picParam->pic_fields.bits.key_frame == 0);  // Yes, really.
208     codecPicParams->version                     = picParam->pic_fields.bits.version;
209     codecPicParams->segmentation_enabled        = picParam->pic_fields.bits.segmentation_enabled;
210     codecPicParams->update_mb_segmentation_map  = picParam->pic_fields.bits.update_mb_segmentation_map;
211     codecPicParams->update_segment_feature_data = picParam->pic_fields.bits.update_segment_feature_data;
212     codecPicParams->filter_type                 = picParam->pic_fields.bits.filter_type;
213     codecPicParams->sign_bias_golden            = picParam->pic_fields.bits.sign_bias_golden;
214     codecPicParams->sign_bias_alternate         = picParam->pic_fields.bits.sign_bias_alternate;
215     codecPicParams->mb_no_coeff_skip            = picParam->pic_fields.bits.mb_no_coeff_skip;
216     codecPicParams->mode_ref_lf_delta_update    = picParam->pic_fields.bits.mode_ref_lf_delta_update;
217 
218     // Loop filter settings
219     codecPicParams->LoopFilterDisable                = picParam->pic_fields.bits.loop_filter_disable;
220     codecPicParams->loop_filter_adj_enable           = picParam->pic_fields.bits.loop_filter_adj_enable;
221     *((uint32_t *)codecPicParams->ucLoopFilterLevel) = *((uint32_t *)picParam->loop_filter_level);
222     *((uint32_t *)codecPicParams->cRefLfDelta)       = *((uint32_t *)picParam->loop_filter_deltas_ref_frame);
223     *((uint32_t *)codecPicParams->cModeLfDelta)      = *((uint32_t *)picParam->loop_filter_deltas_mode);
224     codecPicParams->ucSharpnessLevel                 = picParam->pic_fields.bits.sharpness_level;
225 
226     // Probability settings
227     codecPicParams->cMbSegmentTreeProbs[0]      = picParam->mb_segment_tree_probs[0];
228     codecPicParams->cMbSegmentTreeProbs[1]      = picParam->mb_segment_tree_probs[1];
229     codecPicParams->cMbSegmentTreeProbs[2]      = picParam->mb_segment_tree_probs[2];
230     codecPicParams->ucProbSkipFalse             = picParam->prob_skip_false;
231     codecPicParams->ucProbIntra                 = picParam->prob_intra;
232     codecPicParams->ucProbLast                  = picParam->prob_last;
233     codecPicParams->ucProbGolden                = picParam->prob_gf;
234     *((uint32_t *)codecPicParams->ucYModeProbs) = *((uint32_t *)picParam->y_mode_probs);
235     codecPicParams->ucUvModeProbs[0]            = picParam->uv_mode_probs[0];
236     codecPicParams->ucUvModeProbs[1]            = picParam->uv_mode_probs[1];
237     codecPicParams->ucUvModeProbs[2]            = picParam->uv_mode_probs[2];
238 
239     MOS_SecureMemcpy(codecPicParams->ucMvUpdateProb[0],
240         sizeof(codecPicParams->ucMvUpdateProb[0]),
241         picParam->mv_probs[0],
242         sizeof(codecPicParams->ucMvUpdateProb[0]));
243 
244     MOS_SecureMemcpy(codecPicParams->ucMvUpdateProb[1],
245         sizeof(codecPicParams->ucMvUpdateProb[1]),
246         picParam->mv_probs[1],
247         sizeof(codecPicParams->ucMvUpdateProb[1]));
248 
249     codecPicParams->ucP0EntropyCount = (8 - picParam->bool_coder_ctx.count) & 0x7;  //hardware needs used bits not remaining bits in bool decoder
250     codecPicParams->ucP0EntropyValue = picParam->bool_coder_ctx.value;
251     codecPicParams->uiP0EntropyRange = picParam->bool_coder_ctx.range;
252 
253     codecPicParams->uiStatusReportFeedbackNumber = 0;
254     return VA_STATUS_SUCCESS;
255 }
256 
257 // Copy VP8ProbabilityData from the libva buffer (pBuf) into the Codec Hal buffer. A memcpy can be used, as the buffers have the same structure.
ParseProbabilityData(struct _DDI_MEDIA_BUFFER * vp8ProbDataBuff,VAProbabilityDataBufferVP8 * probInputBuf)258 VAStatus DdiDecodeVP8::ParseProbabilityData(
259     struct _DDI_MEDIA_BUFFER *  vp8ProbDataBuff,
260     VAProbabilityDataBufferVP8 *probInputBuf)
261 {
262     if (vp8ProbDataBuff->pData && probInputBuf)
263     {
264         mos_bo_wait_rendering(vp8ProbDataBuff->bo);
265         MOS_SecureMemcpy(vp8ProbDataBuff->pData,
266                          sizeof(CODECHAL_VP8_COEFFPROB_DATA),
267                          probInputBuf,
268                          sizeof(CODECHAL_VP8_COEFFPROB_DATA));
269         return VA_STATUS_SUCCESS;
270     }
271     else
272     {
273         return VA_STATUS_ERROR_INVALID_PARAMETER;
274     }
275 }
276 
RenderPicture(VADriverContextP ctx,VAContextID context,VABufferID * buffers,int32_t numBuffers)277 VAStatus DdiDecodeVP8::RenderPicture(
278     VADriverContextP ctx,
279     VAContextID      context,
280     VABufferID       *buffers,
281     int32_t          numBuffers)
282 {
283     VAStatus           va = VA_STATUS_SUCCESS;
284     PDDI_MEDIA_CONTEXT mediaCtx = DdiMedia_GetMediaContext(ctx);
285 
286     DDI_FUNCTION_ENTER();
287     void *            data = nullptr;
288     for (int32_t i = 0; i < numBuffers; i++)
289     {
290         if (!buffers || (buffers[i] == VA_INVALID_ID))
291         {
292             return VA_STATUS_ERROR_INVALID_BUFFER;
293         }
294 
295         DDI_MEDIA_BUFFER *buf = DdiMedia_GetBufferFromVABufferID(mediaCtx, buffers[i]);
296         if (nullptr == buf)
297         {
298             return VA_STATUS_ERROR_INVALID_BUFFER;
299         }
300 
301         uint32_t dataSize = buf->iSize;
302         DdiMedia_MapBuffer(ctx, buffers[i], &data);
303 
304         if (data == nullptr)
305         {
306             return VA_STATUS_ERROR_INVALID_BUFFER;
307         }
308 
309         switch ((int32_t)buf->uiType)
310         {
311         case VASliceDataBufferType:
312         {
313             int32_t index = GetBitstreamBufIndexFromBuffer(&m_ddiDecodeCtx->BufMgr, buf);
314             if (index == DDI_CODEC_INVALID_BUFFER_INDEX)
315             {
316                 return VA_STATUS_ERROR_INVALID_BUFFER;
317             }
318 
319             DdiMedia_MediaBufferToMosResource(m_ddiDecodeCtx->BufMgr.pBitStreamBuffObject[index], &m_ddiDecodeCtx->BufMgr.resBitstreamBuffer);
320             m_ddiDecodeCtx->DecodeParams.m_dataSize += dataSize;
321             break;
322         }
323         case VASliceParameterBufferType:
324         {
325             if (m_ddiDecodeCtx->DecodeParams.m_numSlices)
326             {
327                 // VP8 only supports only one slice. If it is passed, another slice_param
328                 // buffer will be ignored.
329                 DDI_NORMALMESSAGE("SliceParamBufferVP8 is already rendered\n");
330                 break;
331             }
332             if (buf->uiNumElements == 0)
333             {
334                 return VA_STATUS_ERROR_INVALID_BUFFER;
335             }
336             uint32_t numSlices = buf->uiNumElements;
337 
338             VASliceParameterBufferVP8 *slcInfoVP8 = (VASliceParameterBufferVP8 *)data;
339             for(uint32_t j = 0; j < numSlices; j++)
340             {
341                 slcInfoVP8[j].slice_data_offset += GetBsBufOffset(m_groupIndex);
342             }
343 
344             DDI_CHK_RET(ParseSliceParams(mediaCtx, slcInfoVP8),"ParseSliceParams failed!");
345             m_ddiDecodeCtx->DecodeParams.m_numSlices += numSlices;
346             m_groupIndex++;
347             break;
348         }
349         case VAPictureParameterBufferType:
350         {
351             VAPictureParameterBufferVP8 *picParam = (VAPictureParameterBufferVP8 *)data;
352             DDI_CHK_RET(ParsePicParams(mediaCtx, picParam),"ParsePicParams failed!");
353             break;
354         }
355         case VAProbabilityBufferType:
356         {
357             VAProbabilityDataBufferVP8 *probInput = (VAProbabilityDataBufferVP8 *)data;
358         DDI_CHK_RET(ParseProbabilityData(m_ddiDecodeCtx->BufMgr.Codec_Param.Codec_Param_VP8.pVP8ProbabilityDataBuffObject, probInput),"ParseProbabilityData failed!");
359             DdiMedia_MediaBufferToMosResource(m_ddiDecodeCtx->BufMgr.Codec_Param.Codec_Param_VP8.pVP8ProbabilityDataBuffObject,
360                 &m_ddiDecodeCtx->BufMgr.Codec_Param.Codec_Param_VP8.resProbabilityDataBuffer);
361             m_ddiDecodeCtx->DecodeParams.m_coefProbSize = dataSize;
362             break;
363         }
364         case VAIQMatrixBufferType:
365         {
366             VAIQMatrixBufferVP8 *imxBuf = (VAIQMatrixBufferVP8 *)data;
367             DDI_CHK_RET(ParseIQMatrix(mediaCtx, imxBuf),"ParseIQMatrix failed!");
368             break;
369         }
370 
371         case VADecodeStreamoutBufferType:
372         {
373             DdiMedia_MediaBufferToMosResource(buf, &m_ddiDecodeCtx->BufMgr.resExternalStreamOutBuffer);
374             m_streamOutEnabled = true;
375             break;
376         }
377         default:
378             va = VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE;
379             break;
380         }
381         DdiMedia_UnmapBuffer(ctx, buffers[i]);
382     }
383 
384     DDI_FUNCTION_EXIT(va);
385     return va;
386 }
387 
InitResourceBuffer(DDI_MEDIA_CONTEXT * mediaCtx)388 VAStatus DdiDecodeVP8::InitResourceBuffer(DDI_MEDIA_CONTEXT *mediaCtx)
389 {
390     VAStatus vaStatus = VA_STATUS_SUCCESS;
391 
392     DDI_CODEC_COM_BUFFER_MGR *bufMgr = &(m_ddiDecodeCtx->BufMgr);
393     bufMgr->pSliceData               = nullptr;
394 
395     bufMgr->ui64BitstreamOrder = 0;
396     bufMgr->dwMaxBsSize        = m_width *
397                           m_height * 3 / 2;
398     // minimal 10k bytes for some special case. Will refractor this later
399     if (bufMgr->dwMaxBsSize < DDI_CODEC_MIN_VALUE_OF_MAX_BS_SIZE)
400     {
401         bufMgr->dwMaxBsSize = DDI_CODEC_MIN_VALUE_OF_MAX_BS_SIZE;
402     }
403 
404     int32_t i;
405     // init decode bitstream buffer object
406     for (i = 0; i < DDI_CODEC_MAX_BITSTREAM_BUFFER; i++)
407     {
408         bufMgr->pBitStreamBuffObject[i] = (DDI_MEDIA_BUFFER *)MOS_AllocAndZeroMemory(sizeof(DDI_MEDIA_BUFFER));
409         if (bufMgr->pBitStreamBuffObject[i] == nullptr)
410         {
411             vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
412             goto finish;
413         }
414         bufMgr->pBitStreamBuffObject[i]->iSize    = bufMgr->dwMaxBsSize;
415         bufMgr->pBitStreamBuffObject[i]->uiType   = VASliceDataBufferType;
416         bufMgr->pBitStreamBuffObject[i]->format   = Media_Format_Buffer;
417         bufMgr->pBitStreamBuffObject[i]->uiOffset = 0;
418         bufMgr->pBitStreamBuffObject[i]->bo       = nullptr;
419         bufMgr->pBitStreamBase[i]                 = nullptr;
420     }
421 
422     // VP8 can support up to eight token partitions. So the max number of sliceData is 8 + 1.
423     // 10 is allocated for the safety.
424     bufMgr->m_maxNumSliceData = 10;
425     bufMgr->pSliceData        = (DDI_CODEC_BITSTREAM_BUFFER_INFO *)MOS_AllocAndZeroMemory(sizeof(bufMgr->pSliceData[0]) * 10);
426 
427     if (bufMgr->pSliceData == nullptr)
428     {
429         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
430         goto finish;
431     }
432 
433     bufMgr->Codec_Param.Codec_Param_VP8.pVP8ProbabilityDataBuffObject = (DDI_MEDIA_BUFFER *)MOS_AllocAndZeroMemory(sizeof(DDI_MEDIA_BUFFER));
434     if (bufMgr->Codec_Param.Codec_Param_VP8.pVP8ProbabilityDataBuffObject == nullptr)
435     {
436         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
437         goto finish;
438     }
439     bufMgr->Codec_Param.Codec_Param_VP8.pVP8ProbabilityDataBuffObject->iSize     = sizeof(CODECHAL_VP8_COEFFPROB_DATA);
440     bufMgr->Codec_Param.Codec_Param_VP8.pVP8ProbabilityDataBuffObject->uiType    = VAProbabilityBufferType;
441     bufMgr->Codec_Param.Codec_Param_VP8.pVP8ProbabilityDataBuffObject->format    = Media_Format_Buffer;
442     bufMgr->Codec_Param.Codec_Param_VP8.pVP8ProbabilityDataBuffObject->uiOffset  = 0;
443     bufMgr->Codec_Param.Codec_Param_VP8.pVP8ProbabilityDataBuffObject->pMediaCtx = mediaCtx;
444 
445     // Create a buffer of size iSize
446     vaStatus = DdiMediaUtil_CreateBuffer(bufMgr->Codec_Param.Codec_Param_VP8.pVP8ProbabilityDataBuffObject, mediaCtx->pDrmBufMgr);
447     if (vaStatus != VA_STATUS_SUCCESS)
448     {
449         goto finish;
450     }
451 
452     bufMgr->Codec_Param.Codec_Param_VP8.pProbabilityDataBase = (uint8_t *)DdiMediaUtil_LockBuffer(bufMgr->Codec_Param.Codec_Param_VP8.pVP8ProbabilityDataBuffObject, MOS_LOCKFLAG_WRITEONLY);
453     if (bufMgr->Codec_Param.Codec_Param_VP8.pProbabilityDataBase == nullptr)
454     {
455         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
456         goto finish;
457     }
458 
459     bufMgr->dwNumSliceData    = 0;
460     bufMgr->dwNumSliceControl = 0;
461 
462     // Max 4 slices/segments in VP8
463     bufMgr->Codec_Param.Codec_Param_VP8.pVASliceParaBufVP8 = (VASliceParameterBufferVP8 *)MOS_AllocAndZeroMemory(sizeof(VASliceParameterBufferVP8) * 4);
464     if (bufMgr->Codec_Param.Codec_Param_VP8.pVASliceParaBufVP8 == nullptr)
465     {
466         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
467         goto finish;
468     }
469 
470     return VA_STATUS_SUCCESS;
471 
472 finish:
473     FreeResourceBuffer();
474     return vaStatus;
475 }
476 
FreeResourceBuffer()477 void DdiDecodeVP8::FreeResourceBuffer()
478 {
479     DDI_CODEC_COM_BUFFER_MGR *bufMgr = &(m_ddiDecodeCtx->BufMgr);
480 
481     int32_t i;
482     for (i = 0; i < DDI_CODEC_MAX_BITSTREAM_BUFFER; i++)
483     {
484         if (bufMgr->pBitStreamBase[i])
485         {
486             DdiMediaUtil_UnlockBuffer(bufMgr->pBitStreamBuffObject[i]);
487             bufMgr->pBitStreamBase[i] = nullptr;
488         }
489         if (bufMgr->pBitStreamBuffObject[i])
490         {
491             DdiMediaUtil_FreeBuffer(bufMgr->pBitStreamBuffObject[i]);
492             MOS_FreeMemory(bufMgr->pBitStreamBuffObject[i]);
493             bufMgr->pBitStreamBuffObject[i] = nullptr;
494         }
495     }
496 
497     if (bufMgr->Codec_Param.Codec_Param_VP8.pVASliceParaBufVP8)
498     {
499         MOS_FreeMemory(bufMgr->Codec_Param.Codec_Param_VP8.pVASliceParaBufVP8);
500         bufMgr->Codec_Param.Codec_Param_VP8.pVASliceParaBufVP8 = nullptr;
501     }
502 
503     if (bufMgr->Codec_Param.Codec_Param_VP8.pVP8ProbabilityDataBuffObject)
504     {
505         DdiMediaUtil_UnlockBuffer(bufMgr->Codec_Param.Codec_Param_VP8.pVP8ProbabilityDataBuffObject);
506         DdiMediaUtil_FreeBuffer(bufMgr->Codec_Param.Codec_Param_VP8.pVP8ProbabilityDataBuffObject);
507         MOS_FreeMemory(bufMgr->Codec_Param.Codec_Param_VP8.pVP8ProbabilityDataBuffObject);
508         bufMgr->Codec_Param.Codec_Param_VP8.pVP8ProbabilityDataBuffObject = nullptr;
509     }
510 
511     // free decode bitstream buffer object
512     MOS_FreeMemory(bufMgr->pSliceData);
513     bufMgr->pSliceData = nullptr;
514 }
515 
GetPicParamBuf(DDI_CODEC_COM_BUFFER_MGR * bufMgr)516 uint8_t* DdiDecodeVP8::GetPicParamBuf(
517     DDI_CODEC_COM_BUFFER_MGR    *bufMgr)
518 {
519     return (uint8_t*)(&(bufMgr->Codec_Param.Codec_Param_VP8.PicParamVP8));
520 }
521 
AllocSliceControlBuffer(DDI_MEDIA_BUFFER * buf)522 VAStatus DdiDecodeVP8::AllocSliceControlBuffer(
523     DDI_MEDIA_BUFFER       *buf)
524 {
525     DDI_CODEC_COM_BUFFER_MGR   *bufMgr;
526 
527     bufMgr     = &(m_ddiDecodeCtx->BufMgr);
528 
529     if(bufMgr->Codec_Param.Codec_Param_VP8.pVASliceParaBufVP8 == nullptr)
530     {
531         return VA_STATUS_ERROR_ALLOCATION_FAILED;
532     }
533     buf->pData      = (uint8_t*)bufMgr->Codec_Param.Codec_Param_VP8.pVASliceParaBufVP8;
534     buf->uiOffset   = bufMgr->dwNumSliceControl * sizeof(VASliceParameterBufferVP8);
535 
536     bufMgr->dwNumSliceControl += buf->uiNumElements;
537 
538     return VA_STATUS_SUCCESS;
539 }
540 
CodecHalInit(DDI_MEDIA_CONTEXT * mediaCtx,void * ptr)541 VAStatus DdiDecodeVP8::CodecHalInit(
542     DDI_MEDIA_CONTEXT *mediaCtx,
543     void              *ptr)
544 {
545     VAStatus     vaStatus = VA_STATUS_SUCCESS;
546     MOS_CONTEXT *mosCtx   = (MOS_CONTEXT *)ptr;
547 
548     CODECHAL_FUNCTION codecFunction = CODECHAL_FUNCTION_DECODE;
549     m_ddiDecodeCtx->pCpDdiInterface->SetCpParams(m_ddiDecodeAttr->uiEncryptionType, m_codechalSettings);
550 
551     CODECHAL_STANDARD_INFO standardInfo;
552     memset(&standardInfo, 0, sizeof(standardInfo));
553 
554     standardInfo.CodecFunction = codecFunction;
555     standardInfo.Mode          = (CODECHAL_MODE)m_ddiDecodeCtx->wMode;
556 
557     m_codechalSettings->codecFunction                = codecFunction;
558     m_codechalSettings->width                      = m_width;
559     m_codechalSettings->height                     = m_height;
560     m_codechalSettings->intelEntrypointInUse        = false;
561 
562     m_codechalSettings->lumaChromaDepth = CODECHAL_LUMA_CHROMA_DEPTH_8_BITS;
563 
564     m_codechalSettings->shortFormatInUse = m_ddiDecodeCtx->bShortFormatInUse;
565 
566     m_codechalSettings->mode     = CODECHAL_DECODE_MODE_VP8VLD;
567     m_codechalSettings->standard = CODECHAL_VP8;
568 
569     m_ddiDecodeCtx->DecodeParams.m_iqMatrixBuffer = MOS_AllocAndZeroMemory(sizeof(CODEC_VP8_IQ_MATRIX_PARAMS));
570     if (m_ddiDecodeCtx->DecodeParams.m_iqMatrixBuffer == nullptr)
571     {
572         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
573         goto CleanUpandReturn;
574     }
575     m_ddiDecodeCtx->DecodeParams.m_picParams = MOS_AllocAndZeroMemory(sizeof(CODEC_VP8_PIC_PARAMS));
576     if (m_ddiDecodeCtx->DecodeParams.m_picParams == nullptr)
577     {
578         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
579         goto CleanUpandReturn;
580     }
581 
582     vaStatus = CreateCodecHal(mediaCtx,
583         ptr,
584         &standardInfo);
585 
586     if (vaStatus != VA_STATUS_SUCCESS)
587     {
588         goto CleanUpandReturn;
589     }
590 
591     if (InitResourceBuffer(mediaCtx) != VA_STATUS_SUCCESS)
592     {
593         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
594         goto CleanUpandReturn;
595     }
596 
597     return vaStatus;
598 
599 CleanUpandReturn:
600     FreeResourceBuffer();
601 
602     if (m_ddiDecodeCtx->pCodecHal)
603     {
604         m_ddiDecodeCtx->pCodecHal->Destroy();
605         MOS_Delete(m_ddiDecodeCtx->pCodecHal);
606         m_ddiDecodeCtx->pCodecHal = nullptr;
607     }
608 
609     MOS_FreeMemory(m_ddiDecodeCtx->DecodeParams.m_iqMatrixBuffer);
610     m_ddiDecodeCtx->DecodeParams.m_iqMatrixBuffer = nullptr;
611     MOS_FreeMemory(m_ddiDecodeCtx->DecodeParams.m_picParams);
612     m_ddiDecodeCtx->DecodeParams.m_picParams = nullptr;
613     MOS_FreeMemory(m_ddiDecodeCtx->DecodeParams.m_sliceParams);
614     m_ddiDecodeCtx->DecodeParams.m_sliceParams = nullptr;
615 
616     return vaStatus;
617 }
618 
SetDecodeParams()619 VAStatus DdiDecodeVP8::SetDecodeParams()
620 {
621     DDI_CHK_RET(DdiMediaDecode::SetDecodeParams(),"SetDecodeParams failed!");
622     DDI_CODEC_COM_BUFFER_MGR *bufMgr = &(m_ddiDecodeCtx->BufMgr);
623     (&m_ddiDecodeCtx->DecodeParams)->m_coefProbBuffer = &(bufMgr->Codec_Param.Codec_Param_VP8.resProbabilityDataBuffer);
624     return  VA_STATUS_SUCCESS;
625 }
626 
DestroyContext(VADriverContextP ctx)627 void DdiDecodeVP8::DestroyContext(
628     VADriverContextP ctx)
629 {
630     FreeResourceBuffer();
631     // explicitly call the base function to do the further clean-up
632     DdiMediaDecode::DestroyContext(ctx);
633 }
634 
ContextInit(int32_t picWidth,int32_t picHeight)635 void DdiDecodeVP8::ContextInit(
636     int32_t picWidth,
637     int32_t picHeight)
638 {
639     // call the function in base class to initialize it.
640     DdiMediaDecode::ContextInit(picWidth, picHeight);
641 
642     m_ddiDecodeCtx->wMode    = CODECHAL_DECODE_MODE_VP8VLD;
643 }
644 
645 extern template class MediaDdiFactory<DdiMediaDecode, DDI_DECODE_CONFIG_ATTR>;
646 
647 static bool vp8Registered =
648     MediaDdiFactory<DdiMediaDecode, DDI_DECODE_CONFIG_ATTR>::RegisterCodec<DdiDecodeVP8>(DECODE_ID_VP8);
649