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