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