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