1 /*
2 * Copyright (c) 2017-2020, 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_avc.cpp
24 //! \brief The class implementation of DdiDecodeAVC for Avc decode
25 //!
26
27 #include "media_libva_decoder.h"
28 #include "media_libva_util.h"
29 #include "media_ddi_decode_avc.h"
30 #include "mos_solo_generic.h"
31 #include "codechal_memdecomp.h"
32 #include "media_ddi_decode_const.h"
33 #include "media_ddi_factory.h"
34 #include "media_factory.h"
35
ParseSliceParams(DDI_MEDIA_CONTEXT * mediaCtx,VASliceParameterBufferH264 * slcParam,uint32_t numSlices)36 VAStatus DdiDecodeAVC::ParseSliceParams(
37 DDI_MEDIA_CONTEXT *mediaCtx,
38 VASliceParameterBufferH264 *slcParam,
39 uint32_t numSlices)
40 {
41 PCODEC_AVC_SLICE_PARAMS avcSliceParams;
42 avcSliceParams = (PCODEC_AVC_SLICE_PARAMS)(m_ddiDecodeCtx->DecodeParams.m_sliceParams);
43 avcSliceParams += m_ddiDecodeCtx->DecodeParams.m_numSlices;
44
45 if ((slcParam == nullptr) || (avcSliceParams == nullptr))
46 {
47 DDI_ASSERTMESSAGE("Invalid Parameter for Parsing AVC Slice parameter\n");
48 return VA_STATUS_ERROR_INVALID_PARAMETER;
49 }
50 VASliceParameterBufferH264 *slc;
51 slc = (VASliceParameterBufferH264 *)slcParam;
52
53 VASliceParameterBufferBase *slcBase;
54 slcBase = (VASliceParameterBufferBase *)slcParam;
55
56 PCODEC_AVC_PIC_PARAMS avcPicParams;
57 avcPicParams = (PCODEC_AVC_PIC_PARAMS)(m_ddiDecodeCtx->DecodeParams.m_picParams);
58 avcPicParams->pic_fields.IntraPicFlag = (slc->slice_type == 2) ? 1 : 0;
59
60 bool useCABAC = (bool)(avcPicParams->pic_fields.entropy_coding_mode_flag);
61
62 uint32_t sliceBaseOffset;
63 sliceBaseOffset = GetBsBufOffset(m_groupIndex);
64
65 uint32_t i, slcCount, refCount;
66 for (slcCount = 0; slcCount < numSlices; slcCount++)
67 {
68 if (m_ddiDecodeCtx->bShortFormatInUse)
69 {
70 avcSliceParams->slice_data_size = slcBase->slice_data_size;
71 avcSliceParams->slice_data_offset = sliceBaseOffset +
72 slcBase->slice_data_offset;
73 if (slcBase->slice_data_flag)
74 {
75 DDI_NORMALMESSAGE("The whole slice is not in the bitstream buffer for this Execute call");
76 }
77 slcBase++;
78 }
79 else
80 {
81 if (useCABAC)
82 {
83 // add the alignment bit
84 slc->slice_data_bit_offset = MOS_ALIGN_CEIL(slc->slice_data_bit_offset, 8);
85 }
86
87 // remove 1 byte of NAL unit code
88 slc->slice_data_bit_offset = slc->slice_data_bit_offset - 8;
89
90 avcSliceParams->slice_data_size = slc->slice_data_size;
91 avcSliceParams->slice_data_offset = sliceBaseOffset +
92 slc->slice_data_offset;
93 if (slc->slice_data_flag)
94 {
95 DDI_NORMALMESSAGE("The whole slice is not in the bitstream buffer for this Execute call");
96 }
97
98 avcSliceParams->slice_data_bit_offset = slc->slice_data_bit_offset;
99 avcSliceParams->first_mb_in_slice = slc->first_mb_in_slice;
100 avcSliceParams->NumMbsForSlice = 0; // not in LibVA slc->NumMbsForSlice;
101 avcSliceParams->slice_type = slc->slice_type;
102 avcSliceParams->direct_spatial_mv_pred_flag = slc->direct_spatial_mv_pred_flag;
103 avcSliceParams->num_ref_idx_l0_active_minus1 = slc->num_ref_idx_l0_active_minus1;
104 avcSliceParams->num_ref_idx_l1_active_minus1 = slc->num_ref_idx_l1_active_minus1;
105 if(slcCount == 0)
106 {
107 avcPicParams->num_ref_idx_l0_active_minus1 = avcSliceParams->num_ref_idx_l0_active_minus1;
108 avcPicParams->num_ref_idx_l1_active_minus1 = avcSliceParams->num_ref_idx_l1_active_minus1;
109 }
110 avcSliceParams->cabac_init_idc = slc->cabac_init_idc;
111 avcSliceParams->slice_qp_delta = slc->slice_qp_delta;
112 avcSliceParams->disable_deblocking_filter_idc = slc->disable_deblocking_filter_idc;
113 avcSliceParams->slice_alpha_c0_offset_div2 = slc->slice_alpha_c0_offset_div2;
114 avcSliceParams->slice_beta_offset_div2 = slc->slice_beta_offset_div2;
115 // reference list 0
116 refCount = std::min(avcSliceParams->num_ref_idx_l0_active_minus1 + 1, CODEC_MAX_NUM_REF_FIELD);
117 for (i = 0; i < refCount; i++)
118 {
119 SetupCodecPicture(
120 mediaCtx,
121 &(m_ddiDecodeCtx->RTtbl),
122 &(avcSliceParams->RefPicList[0][i]),
123 slc->RefPicList0[i],
124 avcPicParams->pic_fields.field_pic_flag,
125 false,
126 true);
127
128 GetSlcRefIdx(&(avcPicParams->RefFrameList[0]), &(avcSliceParams->RefPicList[0][i]));
129 }
130 // reference list 1
131 refCount = std::min(avcSliceParams->num_ref_idx_l1_active_minus1 + 1, CODEC_MAX_NUM_REF_FIELD);
132 for (i = 0; i < refCount; i++)
133 {
134 SetupCodecPicture(
135 mediaCtx,
136 &(m_ddiDecodeCtx->RTtbl),
137 &(avcSliceParams->RefPicList[1][i]),
138 slc->RefPicList1[i],
139 avcPicParams->pic_fields.field_pic_flag,
140 false,
141 true);
142
143 GetSlcRefIdx(&(avcPicParams->RefFrameList[0]), &(avcSliceParams->RefPicList[1][i]));
144 }
145
146 avcSliceParams->luma_log2_weight_denom = slc->luma_log2_weight_denom;
147 avcSliceParams->chroma_log2_weight_denom = slc->chroma_log2_weight_denom;
148 for (i = 0; i < 32; i++)
149 {
150 // list 0
151 avcSliceParams->Weights[0][i][0][0] = slc->luma_weight_l0[i]; // Y weight
152 avcSliceParams->Weights[0][i][0][1] = slc->luma_offset_l0[i]; // Y offset
153
154 avcSliceParams->Weights[0][i][1][0] = slc->chroma_weight_l0[i][0]; // Cb weight
155 avcSliceParams->Weights[0][i][1][1] = slc->chroma_offset_l0[i][0]; // Cb offset
156
157 avcSliceParams->Weights[0][i][2][0] = slc->chroma_weight_l0[i][1]; // Cr weight
158 avcSliceParams->Weights[0][i][2][1] = slc->chroma_offset_l0[i][1]; // Cr offset
159
160 // list 1
161 avcSliceParams->Weights[1][i][0][0] = slc->luma_weight_l1[i]; // Y weight
162 avcSliceParams->Weights[1][i][0][1] = slc->luma_offset_l1[i]; // Y offset
163
164 avcSliceParams->Weights[1][i][1][0] = slc->chroma_weight_l1[i][0]; // Cb weight
165 avcSliceParams->Weights[1][i][1][1] = slc->chroma_offset_l1[i][0]; // Cb offset
166
167 avcSliceParams->Weights[1][i][2][0] = slc->chroma_weight_l1[i][1]; // Cr weight
168 avcSliceParams->Weights[1][i][2][1] = slc->chroma_offset_l1[i][1]; // Cr offset
169 }
170 slc++;
171 }
172 avcSliceParams->slice_id = 0;
173 avcSliceParams++;
174 }
175
176 return VA_STATUS_SUCCESS;
177 }
178
ParsePicParams(DDI_MEDIA_CONTEXT * mediaCtx,VAPictureParameterBufferH264 * picParam)179 VAStatus DdiDecodeAVC::ParsePicParams(
180 DDI_MEDIA_CONTEXT * mediaCtx,
181 VAPictureParameterBufferH264 *picParam)
182 {
183 PCODEC_AVC_PIC_PARAMS avcPicParams;
184 avcPicParams = (PCODEC_AVC_PIC_PARAMS)(m_ddiDecodeCtx->DecodeParams.m_picParams);
185
186 if ((picParam == nullptr) ||
187 (avcPicParams == nullptr))
188 return VA_STATUS_ERROR_INVALID_PARAMETER;
189
190 SetupCodecPicture(mediaCtx,
191 &(m_ddiDecodeCtx->RTtbl),
192 &avcPicParams->CurrPic,
193 picParam->CurrPic,
194 picParam->pic_fields.bits.field_pic_flag,
195 false,
196 false);
197
198 //Check the current frame index
199 //Add the invalid surface id to RecList
200 if (avcPicParams->CurrPic.FrameIdx < CODEC_AVC_NUM_UNCOMPRESSED_SURFACE)
201 {
202 m_ddiDecodeCtx->RecListSurfaceID[avcPicParams->CurrPic.FrameIdx] =
203 picParam->CurrPic.picture_id;
204 }
205
206 uint32_t i;
207 uint32_t j;
208 avcPicParams->UsedForReferenceFlags = 0x0;
209 for (i = 0; i < CODEC_MAX_NUM_REF_FRAME; i++)
210 {
211 if (picParam->ReferenceFrames[i].picture_id != VA_INVALID_SURFACE)
212 {
213 UpdateRegisteredRTSurfaceFlag(&(m_ddiDecodeCtx->RTtbl),
214 DdiMedia_GetSurfaceFromVASurfaceID(mediaCtx,
215 picParam->ReferenceFrames[i].picture_id));
216 }
217
218 SetupCodecPicture(
219 mediaCtx,
220 &(m_ddiDecodeCtx->RTtbl),
221 &(avcPicParams->RefFrameList[i]),
222 picParam->ReferenceFrames[i],
223 picParam->pic_fields.bits.field_pic_flag,
224 true,
225 false);
226
227 if ((picParam->ReferenceFrames[i].flags & VA_PICTURE_H264_SHORT_TERM_REFERENCE) ||
228 (picParam->ReferenceFrames[i].flags & VA_PICTURE_H264_LONG_TERM_REFERENCE))
229 {
230 if (!m_ddiDecodeCtx->bShortFormatInUse)
231 {
232 avcPicParams->UsedForReferenceFlags = avcPicParams->UsedForReferenceFlags | (3 << (i * 2));
233 }
234 else if ((picParam->ReferenceFrames[i].flags & VA_PICTURE_H264_BOTTOM_FIELD) ||
235 (picParam->ReferenceFrames[i].flags & VA_PICTURE_H264_TOP_FIELD))
236 {
237 if (picParam->ReferenceFrames[i].flags & VA_PICTURE_H264_BOTTOM_FIELD)
238 avcPicParams->UsedForReferenceFlags = avcPicParams->UsedForReferenceFlags | (2 << (i * 2));
239
240 if (picParam->ReferenceFrames[i].flags & VA_PICTURE_H264_TOP_FIELD)
241 avcPicParams->UsedForReferenceFlags = avcPicParams->UsedForReferenceFlags | (1 << (i * 2));
242 }
243 else
244 {
245 avcPicParams->UsedForReferenceFlags = avcPicParams->UsedForReferenceFlags | (3 << (i * 2));
246 }
247 }
248 }
249
250 //Accoding to RecList, if the surface id is invalid, set PicFlags equal to PICTURE_INVALID
251 for (i = 0; i < CODEC_MAX_NUM_REF_FRAME; i++)
252 {
253 //Check the surface id of reference list
254 if (avcPicParams->RefFrameList[i].FrameIdx < CODEC_AVC_NUM_UNCOMPRESSED_SURFACE
255 && VA_INVALID_ID == m_ddiDecodeCtx->RecListSurfaceID[avcPicParams->RefFrameList[i].FrameIdx])
256 {
257 //Set invalid flag
258 avcPicParams->RefFrameList[i].PicFlags = PICTURE_INVALID;
259 }
260 }
261
262 avcPicParams->pic_width_in_mbs_minus1 = picParam->picture_width_in_mbs_minus1;
263 avcPicParams->pic_height_in_mbs_minus1 = picParam->picture_height_in_mbs_minus1;
264 avcPicParams->bit_depth_luma_minus8 = picParam->bit_depth_luma_minus8;
265 avcPicParams->bit_depth_chroma_minus8 = picParam->bit_depth_chroma_minus8;
266 avcPicParams->num_ref_frames = picParam->num_ref_frames;
267 avcPicParams->CurrFieldOrderCnt[0] = picParam->CurrPic.TopFieldOrderCnt;
268 avcPicParams->CurrFieldOrderCnt[1] = picParam->CurrPic.BottomFieldOrderCnt;
269 for (i = 0; i < CODEC_MAX_NUM_REF_FRAME; i++)
270 {
271 avcPicParams->FieldOrderCntList[i][0] = picParam->ReferenceFrames[i].TopFieldOrderCnt;
272 avcPicParams->FieldOrderCntList[i][1] = picParam->ReferenceFrames[i].BottomFieldOrderCnt;
273 }
274
275 avcPicParams->seq_fields.chroma_format_idc = picParam->seq_fields.bits.chroma_format_idc;
276 avcPicParams->seq_fields.residual_colour_transform_flag = picParam->seq_fields.bits.residual_colour_transform_flag;
277 avcPicParams->seq_fields.frame_mbs_only_flag = picParam->seq_fields.bits.frame_mbs_only_flag;
278 avcPicParams->seq_fields.mb_adaptive_frame_field_flag = picParam->seq_fields.bits.mb_adaptive_frame_field_flag;
279 avcPicParams->seq_fields.direct_8x8_inference_flag = picParam->seq_fields.bits.direct_8x8_inference_flag;
280 avcPicParams->seq_fields.log2_max_frame_num_minus4 = picParam->seq_fields.bits.log2_max_frame_num_minus4;
281 avcPicParams->seq_fields.pic_order_cnt_type = picParam->seq_fields.bits.pic_order_cnt_type;
282 avcPicParams->seq_fields.log2_max_pic_order_cnt_lsb_minus4 = picParam->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4;
283 avcPicParams->seq_fields.delta_pic_order_always_zero_flag = picParam->seq_fields.bits.delta_pic_order_always_zero_flag;
284
285 avcPicParams->num_slice_groups_minus1 = 0;
286 avcPicParams->slice_group_map_type = 0;
287 avcPicParams->slice_group_change_rate_minus1 = 0;
288 avcPicParams->pic_init_qp_minus26 = picParam->pic_init_qp_minus26;
289 avcPicParams->chroma_qp_index_offset = picParam->chroma_qp_index_offset;
290 avcPicParams->second_chroma_qp_index_offset = picParam->second_chroma_qp_index_offset;
291
292 avcPicParams->pic_fields.entropy_coding_mode_flag = picParam->pic_fields.bits.entropy_coding_mode_flag;
293 avcPicParams->pic_fields.weighted_pred_flag = picParam->pic_fields.bits.weighted_pred_flag;
294 avcPicParams->pic_fields.weighted_bipred_idc = picParam->pic_fields.bits.weighted_bipred_idc;
295 avcPicParams->pic_fields.transform_8x8_mode_flag = picParam->pic_fields.bits.transform_8x8_mode_flag;
296 avcPicParams->pic_fields.field_pic_flag = picParam->pic_fields.bits.field_pic_flag;
297 avcPicParams->pic_fields.constrained_intra_pred_flag = picParam->pic_fields.bits.constrained_intra_pred_flag;
298 avcPicParams->pic_fields.pic_order_present_flag = picParam->pic_fields.bits.pic_order_present_flag;
299 avcPicParams->pic_fields.deblocking_filter_control_present_flag = picParam->pic_fields.bits.deblocking_filter_control_present_flag;
300 avcPicParams->pic_fields.redundant_pic_cnt_present_flag = picParam->pic_fields.bits.redundant_pic_cnt_present_flag;
301 avcPicParams->pic_fields.reference_pic_flag = picParam->pic_fields.bits.reference_pic_flag;
302
303 for (i = 0; i < CODEC_MAX_NUM_REF_FRAME; i++)
304 {
305 avcPicParams->FrameNumList[i] = picParam->ReferenceFrames[i].frame_idx;
306 }
307
308 avcPicParams->frame_num = picParam->frame_num;
309
310 #if MOS_EVENT_TRACE_DUMP_SUPPORTED
311 // Picture Info
312 DECODE_EVENTDATA_INFO_PICTUREVA eventData = {0};
313 eventData.CodecFormat = m_ddiDecodeCtx->wMode;
314 eventData.FrameType = avcPicParams->pic_fields.IntraPicFlag == 1 ? I_TYPE : MIXED_TYPE;
315 eventData.PicStruct = avcPicParams->CurrPic.PicFlags; // 1-Top; 2-Bottom; 3-Frame
316 eventData.Width = (avcPicParams->pic_width_in_mbs_minus1 + 1) * MACROBLOCK_WIDTH;
317 eventData.Height = (avcPicParams->pic_height_in_mbs_minus1 + 1) * MACROBLOCK_HEIGHT;
318 eventData.Bitdepth = avcPicParams->bit_depth_luma_minus8 + 8;
319 eventData.ChromaFormat = avcPicParams->seq_fields.chroma_format_idc; // 0-4:0:0; 1-4:2:0; 2-4:2:2; 3-4:4:4
320 MOS_TraceEvent(EVENT_DECODE_INFO_PICTUREVA, EVENT_TYPE_INFO, &eventData, sizeof(eventData), NULL, 0);
321 #endif
322
323 return VA_STATUS_SUCCESS;
324 }
325
ParseIQMatrix(DDI_MEDIA_CONTEXT * mediaCtx,VAIQMatrixBufferH264 * matrix)326 VAStatus DdiDecodeAVC::ParseIQMatrix(
327 DDI_MEDIA_CONTEXT * mediaCtx,
328 VAIQMatrixBufferH264 *matrix)
329 {
330 PCODEC_AVC_IQ_MATRIX_PARAMS avcIqMatrix;
331
332 avcIqMatrix = (PCODEC_AVC_IQ_MATRIX_PARAMS)(m_ddiDecodeCtx->DecodeParams.m_iqMatrixBuffer);
333
334 if ((matrix == nullptr) || (avcIqMatrix == nullptr))
335 {
336 DDI_ASSERTMESSAGE("Invalid Parameter for Parsing AVC IQMatrix parameter\n");
337 return VA_STATUS_ERROR_INVALID_PARAMETER;
338 }
339 // 4x4 block
340 int32_t i;
341 for (i = 0; i < 6; i++)
342 {
343 MOS_SecureMemcpy(avcIqMatrix->ScalingList4x4[i],
344 16,
345 matrix->ScalingList4x4[i],
346 16);
347 }
348 // 8x8 block
349 for (i = 0; i < 2; i++)
350 {
351 MOS_SecureMemcpy(avcIqMatrix->ScalingList8x8[i],
352 64,
353 matrix->ScalingList8x8[i],
354 64);
355 }
356 return VA_STATUS_SUCCESS;
357 }
358
AllocSliceParamContext(uint32_t numSlices)359 VAStatus DdiDecodeAVC::AllocSliceParamContext(
360 uint32_t numSlices)
361 {
362 uint32_t baseSize = sizeof(CODEC_AVC_SLICE_PARAMS);
363
364 if (m_sliceParamBufNum < (m_ddiDecodeCtx->DecodeParams.m_numSlices + numSlices))
365 {
366 // in order to avoid that the buffer is reallocated multi-times,
367 // extra 10 slices are added.
368 uint32_t extraSlices = numSlices + 10;
369 m_ddiDecodeCtx->DecodeParams.m_sliceParams = realloc(m_ddiDecodeCtx->DecodeParams.m_sliceParams,
370 baseSize * (m_sliceParamBufNum + extraSlices));
371
372 if (m_ddiDecodeCtx->DecodeParams.m_sliceParams == nullptr)
373 {
374 return VA_STATUS_ERROR_ALLOCATION_FAILED;
375 }
376
377 memset((void *)((uint8_t *)m_ddiDecodeCtx->DecodeParams.m_sliceParams + baseSize * m_sliceParamBufNum),
378 0,
379 baseSize * extraSlices);
380
381 m_sliceParamBufNum += extraSlices;
382 }
383
384 return VA_STATUS_SUCCESS;
385 }
386
RenderPicture(VADriverContextP ctx,VAContextID context,VABufferID * buffers,int32_t numBuffers)387 VAStatus DdiDecodeAVC::RenderPicture(
388 VADriverContextP ctx,
389 VAContextID context,
390 VABufferID * buffers,
391 int32_t numBuffers)
392 {
393 VAStatus va = VA_STATUS_SUCCESS;
394
395 DDI_FUNCTION_ENTER();
396
397 PDDI_MEDIA_CONTEXT mediaCtx = DdiMedia_GetMediaContext(ctx);
398 void * data;
399 for (int32_t i = 0; i < numBuffers; i++)
400 {
401 DDI_MEDIA_BUFFER *buf = DdiMedia_GetBufferFromVABufferID(mediaCtx, buffers[i]);
402 if (nullptr == buf)
403 {
404 return VA_STATUS_ERROR_INVALID_BUFFER;
405 }
406 uint32_t dataSize = buf->iSize;
407
408 DdiMedia_MapBuffer(ctx, buffers[i], &data);
409
410 if (data == nullptr)
411 {
412 return VA_STATUS_ERROR_INVALID_BUFFER;
413 }
414
415 switch ((int32_t)buf->uiType)
416 {
417 case VASliceDataBufferType:
418 {
419 int32_t index = GetBitstreamBufIndexFromBuffer(&m_ddiDecodeCtx->BufMgr, buf);
420 if (index == DDI_CODEC_INVALID_BUFFER_INDEX)
421 {
422 return VA_STATUS_ERROR_INVALID_BUFFER;
423 }
424
425 DdiMedia_MediaBufferToMosResource(m_ddiDecodeCtx->BufMgr.pBitStreamBuffObject[index], &m_ddiDecodeCtx->BufMgr.resBitstreamBuffer);
426 m_ddiDecodeCtx->DecodeParams.m_dataSize += dataSize;
427
428 break;
429 }
430 case VASliceParameterBufferType:
431 {
432 VASliceParameterBufferH264 *slcInfoH264;
433 if (buf->uiNumElements == 0)
434 {
435 return VA_STATUS_ERROR_INVALID_BUFFER;
436 }
437
438 slcInfoH264 = (VASliceParameterBufferH264 *)data;
439 uint32_t numSlices = buf->uiNumElements;
440 DDI_CHK_RET(AllocSliceParamContext(numSlices),"AllocSliceParamContext failed!");
441 DDI_CHK_RET(ParseSliceParams(mediaCtx, slcInfoH264, numSlices),"ParseSliceParams failed!");
442 m_ddiDecodeCtx->DecodeParams.m_numSlices += numSlices;
443 m_groupIndex++;
444 break;
445 }
446 case VAIQMatrixBufferType:
447 {
448 VAIQMatrixBufferH264 *imxBuf = (VAIQMatrixBufferH264 *)data;
449 DDI_CHK_RET(ParseIQMatrix(mediaCtx, imxBuf),"ParseIQMatrix failed!");
450 break;
451 }
452 case VAPictureParameterBufferType:
453 {
454 VAPictureParameterBufferH264 *picParam;
455 picParam = (VAPictureParameterBufferH264 *)data;
456 DDI_CHK_RET(ParsePicParams(mediaCtx, picParam),"ParsePicParams failed!");
457 break;
458 }
459 case VAProcPipelineParameterBufferType:
460 {
461 DDI_CHK_RET(ParseProcessingBuffer(mediaCtx, data),"ParseProcessingBuffer failed!");
462 break;
463 }
464 case VADecodeStreamoutBufferType:
465 {
466 DdiMedia_MediaBufferToMosResource(buf, &m_ddiDecodeCtx->BufMgr.resExternalStreamOutBuffer);
467 m_streamOutEnabled = true;
468 break;
469 }
470
471 default:
472 va = m_ddiDecodeCtx->pCpDdiInterface->RenderCencPicture(ctx, context, buf, data);
473 break;
474 }
475 DdiMedia_UnmapBuffer(ctx, buffers[i]);
476 }
477
478 DDI_FUNCTION_EXIT(va);
479 return va;
480 }
481
SetDecodeParams()482 VAStatus DdiDecodeAVC::SetDecodeParams()
483 {
484 DDI_CHK_RET(DdiMediaDecode::SetDecodeParams(),"SetDecodeParams failed!");
485 #ifdef _DECODE_PROCESSING_SUPPORTED
486 // Bridge the SFC input with VDBOX output
487 if (m_decProcessingType == VA_DEC_PROCESSING)
488 {
489 auto procParams =
490 (DecodeProcessingParams *)m_ddiDecodeCtx->DecodeParams.m_procParams;
491 procParams->m_inputSurface = (&m_ddiDecodeCtx->DecodeParams)->m_destSurface;
492 // codechal_decode_sfc.c expects Input Width/Height information.
493 procParams->m_inputSurface->dwWidth = procParams->m_inputSurface->OsResource.iWidth;
494 procParams->m_inputSurface->dwHeight = procParams->m_inputSurface->OsResource.iHeight;
495 procParams->m_inputSurface->dwPitch = procParams->m_inputSurface->OsResource.iPitch;
496 procParams->m_inputSurface->Format = procParams->m_inputSurface->OsResource.Format;
497
498 if(m_requireInputRegion)
499 {
500 procParams->m_inputSurfaceRegion.m_x = 0;
501 procParams->m_inputSurfaceRegion.m_y = 0;
502 procParams->m_inputSurfaceRegion.m_width = procParams->m_inputSurface->dwWidth;
503 procParams->m_inputSurfaceRegion.m_height = procParams->m_inputSurface->dwHeight;
504 }
505 }
506 #endif
507
508 return VA_STATUS_SUCCESS;
509 }
510
DestroyContext(VADriverContextP ctx)511 void DdiDecodeAVC::DestroyContext(
512 VADriverContextP ctx)
513 {
514 FreeResourceBuffer();
515 // explicitly call the base function to do the further clean-up
516 DdiMediaDecode::DestroyContext(ctx);
517 return;
518 }
519
ContextInit(int32_t picWidth,int32_t picHeight)520 void DdiDecodeAVC::ContextInit(int32_t picWidth, int32_t picHeight)
521 {
522 // call the function in base class to initialize it.
523 DdiMediaDecode::ContextInit(picWidth, picHeight);
524
525 if (m_ddiDecodeAttr->uiDecSliceMode == VA_DEC_SLICE_MODE_BASE)
526 {
527 m_ddiDecodeCtx->bShortFormatInUse = true;
528 }
529 m_ddiDecodeCtx->wMode = CODECHAL_DECODE_MODE_AVCVLD;
530 return;
531 }
532
GetPicParamBuf(DDI_CODEC_COM_BUFFER_MGR * bufMgr)533 uint8_t* DdiDecodeAVC::GetPicParamBuf(
534 DDI_CODEC_COM_BUFFER_MGR *bufMgr)
535 {
536 return (uint8_t*)(&(bufMgr->Codec_Param.Codec_Param_H264.PicParam264));
537 }
538
AllocSliceControlBuffer(DDI_MEDIA_BUFFER * buf)539 VAStatus DdiDecodeAVC::AllocSliceControlBuffer(
540 DDI_MEDIA_BUFFER *buf)
541 {
542 DDI_CODEC_COM_BUFFER_MGR *bufMgr;
543 uint32_t availSize;
544 uint32_t newSize;
545
546 bufMgr = &(m_ddiDecodeCtx->BufMgr);
547 availSize = m_sliceCtrlBufNum - bufMgr->dwNumSliceControl;
548
549 if(m_ddiDecodeCtx->bShortFormatInUse)
550 {
551 if(availSize < buf->uiNumElements)
552 {
553 newSize = sizeof(VASliceParameterBufferBase) * (m_sliceCtrlBufNum - availSize + buf->uiNumElements);
554 bufMgr->Codec_Param.Codec_Param_H264.pVASliceParaBufH264Base = (VASliceParameterBufferBase *)realloc(bufMgr->Codec_Param.Codec_Param_H264.pVASliceParaBufH264Base, newSize);
555 if(bufMgr->Codec_Param.Codec_Param_H264.pVASliceParaBufH264Base == nullptr)
556 {
557 return VA_STATUS_ERROR_ALLOCATION_FAILED;
558 }
559 MOS_ZeroMemory(bufMgr->Codec_Param.Codec_Param_H264.pVASliceParaBufH264Base + m_sliceCtrlBufNum, sizeof(VASliceParameterBufferBase) * (buf->uiNumElements - availSize));
560 m_sliceCtrlBufNum = m_sliceCtrlBufNum - availSize + buf->uiNumElements;
561 }
562 buf->pData = (uint8_t*)bufMgr->Codec_Param.Codec_Param_H264.pVASliceParaBufH264Base;
563 buf->uiOffset = bufMgr->dwNumSliceControl * sizeof(VASliceParameterBufferBase);
564 }
565 else
566 {
567 if(availSize < buf->uiNumElements)
568 {
569 newSize = sizeof(VASliceParameterBufferH264) * (m_sliceCtrlBufNum - availSize + buf->uiNumElements);
570 bufMgr->Codec_Param.Codec_Param_H264.pVASliceParaBufH264 = (VASliceParameterBufferH264 *)realloc(bufMgr->Codec_Param.Codec_Param_H264.pVASliceParaBufH264, newSize);
571 if(bufMgr->Codec_Param.Codec_Param_H264.pVASliceParaBufH264 == nullptr)
572 {
573 return VA_STATUS_ERROR_ALLOCATION_FAILED;
574 }
575 MOS_ZeroMemory(bufMgr->Codec_Param.Codec_Param_H264.pVASliceParaBufH264 + m_sliceCtrlBufNum, sizeof(VASliceParameterBufferH264) * (buf->uiNumElements - availSize));
576 m_sliceCtrlBufNum = m_sliceCtrlBufNum - availSize + buf->uiNumElements;
577 }
578 buf->pData = (uint8_t*)bufMgr->Codec_Param.Codec_Param_H264.pVASliceParaBufH264;
579 buf->uiOffset = bufMgr->dwNumSliceControl * sizeof(VASliceParameterBufferH264);
580 }
581
582 bufMgr->dwNumSliceControl += buf->uiNumElements;
583
584 return VA_STATUS_SUCCESS;
585 }
586
CodecHalInit(DDI_MEDIA_CONTEXT * mediaCtx,void * ptr)587 VAStatus DdiDecodeAVC::CodecHalInit(
588 DDI_MEDIA_CONTEXT *mediaCtx,
589 void *ptr)
590 {
591 VAStatus vaStatus = VA_STATUS_SUCCESS;
592 MOS_CONTEXT *mosCtx = (MOS_CONTEXT *)ptr;
593
594 m_codechalSettings->shortFormatInUse = m_ddiDecodeCtx->bShortFormatInUse;
595
596 CODECHAL_FUNCTION codecFunction = CODECHAL_FUNCTION_DECODE;
597
598 CODECHAL_STANDARD_INFO standardInfo;
599 memset(&standardInfo, 0, sizeof(standardInfo));
600
601 standardInfo.CodecFunction = codecFunction;
602 standardInfo.Mode = (CODECHAL_MODE)m_ddiDecodeCtx->wMode;
603
604 m_codechalSettings->codecFunction = codecFunction;
605 m_codechalSettings->width = m_width;
606 m_codechalSettings->height = m_height;
607 //For Avc Decoding:
608 // if the slice header contains the emulation_prevention_three_byte, we need to set bIntelEntrypointInUse to false.
609 // Because in this case, driver can not get the correct BsdStartAddress by itself. We need to turn to GEN to calculate the correct address.
610 m_codechalSettings->intelEntrypointInUse = false;
611
612 m_codechalSettings->lumaChromaDepth = CODECHAL_LUMA_CHROMA_DEPTH_8_BITS;
613
614 m_codechalSettings->mode = CODECHAL_DECODE_MODE_AVCVLD;
615 m_codechalSettings->standard = CODECHAL_AVC;
616
617 m_ddiDecodeCtx->pCpDdiInterface->SetCpParams(m_ddiDecodeAttr->uiEncryptionType, m_codechalSettings);
618
619 m_ddiDecodeCtx->DecodeParams.m_iqMatrixBuffer = (void*)MOS_AllocAndZeroMemory(sizeof(CODEC_AVC_IQ_MATRIX_PARAMS));
620 if (m_ddiDecodeCtx->DecodeParams.m_iqMatrixBuffer == nullptr)
621 {
622 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
623 goto CleanUpandReturn;
624 }
625 m_ddiDecodeCtx->DecodeParams.m_picParams = (void*)MOS_AllocAndZeroMemory(sizeof(CODEC_AVC_PIC_PARAMS));
626 if (m_ddiDecodeCtx->DecodeParams.m_picParams == nullptr)
627 {
628 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
629 goto CleanUpandReturn;
630 }
631
632 m_sliceParamBufNum = m_picHeightInMB;
633 m_ddiDecodeCtx->DecodeParams.m_sliceParams = (void*)MOS_AllocAndZeroMemory(m_sliceParamBufNum * sizeof(CODEC_AVC_SLICE_PARAMS));
634 if (m_ddiDecodeCtx->DecodeParams.m_sliceParams == nullptr)
635 {
636 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
637 goto CleanUpandReturn;
638 }
639
640 #ifdef _DECODE_PROCESSING_SUPPORTED
641 if (m_decProcessingType == VA_DEC_PROCESSING)
642 {
643 DecodeProcessingParams *procParams = nullptr;
644
645 m_codechalSettings->downsamplingHinted = true;
646
647 procParams = (DecodeProcessingParams *)MOS_AllocAndZeroMemory(sizeof(DecodeProcessingParams));
648 if (procParams == nullptr)
649 {
650 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
651 goto CleanUpandReturn;
652 }
653
654 m_ddiDecodeCtx->DecodeParams.m_procParams = procParams;
655 procParams->m_outputSurface = (PMOS_SURFACE)MOS_AllocAndZeroMemory(sizeof(MOS_SURFACE));
656 if (procParams->m_outputSurface == nullptr)
657 {
658 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
659 goto CleanUpandReturn;
660 }
661 }
662 #endif
663 vaStatus = CreateCodecHal(mediaCtx,
664 ptr,
665 &standardInfo);
666
667 if (vaStatus != VA_STATUS_SUCCESS)
668 {
669 goto CleanUpandReturn;
670 }
671
672 if (InitResourceBuffer() != VA_STATUS_SUCCESS)
673 {
674 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
675 goto CleanUpandReturn;
676 }
677
678 return vaStatus;
679
680 CleanUpandReturn:
681 FreeResourceBuffer();
682
683 if (m_ddiDecodeCtx->pCodecHal)
684 {
685 m_ddiDecodeCtx->pCodecHal->Destroy();
686 MOS_Delete(m_ddiDecodeCtx->pCodecHal);
687 m_ddiDecodeCtx->pCodecHal = nullptr;
688 }
689 MOS_FreeMemory(m_ddiDecodeCtx->DecodeParams.m_iqMatrixBuffer);
690 m_ddiDecodeCtx->DecodeParams.m_iqMatrixBuffer = nullptr;
691 MOS_FreeMemory(m_ddiDecodeCtx->DecodeParams.m_picParams);
692 m_ddiDecodeCtx->DecodeParams.m_picParams = nullptr;
693 MOS_FreeMemory(m_ddiDecodeCtx->DecodeParams.m_huffmanTable);
694 m_ddiDecodeCtx->DecodeParams.m_huffmanTable = nullptr;
695 MOS_FreeMemory(m_ddiDecodeCtx->DecodeParams.m_sliceParams);
696 m_ddiDecodeCtx->DecodeParams.m_sliceParams = nullptr;
697
698 #ifdef _DECODE_PROCESSING_SUPPORTED
699 if (m_ddiDecodeCtx->DecodeParams.m_procParams)
700 {
701 auto procParams =
702 (DecodeProcessingParams *)m_ddiDecodeCtx->DecodeParams.m_procParams;
703 MOS_FreeMemory(procParams->m_outputSurface);
704
705 MOS_FreeMemory(m_ddiDecodeCtx->DecodeParams.m_procParams);
706 m_ddiDecodeCtx->DecodeParams.m_procParams = nullptr;
707 }
708 #endif
709 return vaStatus;
710 }
711
InitResourceBuffer()712 VAStatus DdiDecodeAVC::InitResourceBuffer()
713 {
714 VAStatus vaStatus;
715 DDI_CODEC_COM_BUFFER_MGR *bufMgr;
716
717 vaStatus = VA_STATUS_SUCCESS;
718 bufMgr = &(m_ddiDecodeCtx->BufMgr);
719 bufMgr->pSliceData = nullptr;
720
721 bufMgr->ui64BitstreamOrder = 0;
722
723 if(m_width * m_height < CODEC_720P_MAX_PIC_WIDTH * CODEC_720P_MAX_PIC_HEIGHT)
724 {
725 bufMgr->dwMaxBsSize = m_width * m_height * 3 / 2;
726 }
727 else if(m_width * m_height < CODEC_4K_MAX_PIC_WIDTH * CODEC_4K_MAX_PIC_HEIGHT)
728 {
729 bufMgr->dwMaxBsSize = m_width * m_height * 3 / 8;
730 }
731 else
732 {
733 bufMgr->dwMaxBsSize = m_width * m_height * 3 / 16;
734 }
735
736 // minimal 10k bytes for some special case. Will refractor this later
737 if (bufMgr->dwMaxBsSize < DDI_CODEC_MIN_VALUE_OF_MAX_BS_SIZE)
738 {
739 bufMgr->dwMaxBsSize = DDI_CODEC_MIN_VALUE_OF_MAX_BS_SIZE;
740 }
741
742 int32_t i, count;
743 // init decode bitstream buffer object
744 for (i = 0; i < DDI_CODEC_MAX_BITSTREAM_BUFFER; i++)
745 {
746 bufMgr->pBitStreamBuffObject[i] = (DDI_MEDIA_BUFFER *)MOS_AllocAndZeroMemory(sizeof(DDI_MEDIA_BUFFER));
747 if (bufMgr->pBitStreamBuffObject[i] == nullptr)
748 {
749 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
750 goto finish;
751 }
752 bufMgr->pBitStreamBuffObject[i]->iSize = bufMgr->dwMaxBsSize;
753 bufMgr->pBitStreamBuffObject[i]->uiType = VASliceDataBufferType;
754 bufMgr->pBitStreamBuffObject[i]->format = Media_Format_Buffer;
755 bufMgr->pBitStreamBuffObject[i]->uiOffset = 0;
756 bufMgr->pBitStreamBuffObject[i]->bo = nullptr;
757 bufMgr->pBitStreamBase[i] = nullptr;
758 }
759
760 // The pSliceData can be allocated on demand. So the default size is wPicHeightInMB.
761 bufMgr->m_maxNumSliceData = m_picHeightInMB;
762 bufMgr->pSliceData = (DDI_CODEC_BITSTREAM_BUFFER_INFO*)MOS_AllocAndZeroMemory(sizeof(bufMgr->pSliceData[0]) *
763 bufMgr->m_maxNumSliceData);
764
765 if (bufMgr->pSliceData == nullptr)
766 {
767 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
768 goto finish;
769 }
770
771 bufMgr->dwNumSliceData = 0;
772 bufMgr->dwNumSliceControl = 0;
773
774 m_sliceCtrlBufNum = m_picHeightInMB;
775 if (m_ddiDecodeCtx->bShortFormatInUse)
776 {
777 bufMgr->Codec_Param.Codec_Param_H264.pVASliceParaBufH264Base = (VASliceParameterBufferBase *)
778 MOS_AllocAndZeroMemory(sizeof(VASliceParameterBufferBase) * m_sliceCtrlBufNum);
779 if (bufMgr->Codec_Param.Codec_Param_H264.pVASliceParaBufH264Base == nullptr)
780 {
781 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
782 goto finish;
783 }
784 }
785 else
786 {
787 bufMgr->Codec_Param.Codec_Param_H264.pVASliceParaBufH264 = (VASliceParameterBufferH264 *)
788 MOS_AllocAndZeroMemory(sizeof(VASliceParameterBufferH264) * m_sliceCtrlBufNum);
789 if (bufMgr->Codec_Param.Codec_Param_H264.pVASliceParaBufH264 == nullptr)
790 {
791 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
792 goto finish;
793 }
794 }
795
796 return VA_STATUS_SUCCESS;
797
798 finish:
799 FreeResourceBuffer();
800 return vaStatus;
801 }
802
FreeResourceBuffer()803 void DdiDecodeAVC::FreeResourceBuffer()
804 {
805 DDI_CODEC_COM_BUFFER_MGR *bufMgr;
806 int32_t i;
807
808 bufMgr = &(m_ddiDecodeCtx->BufMgr);
809
810 for (i = 0; i < DDI_CODEC_MAX_BITSTREAM_BUFFER; i++)
811 {
812 if (bufMgr->pBitStreamBase[i])
813 {
814 DdiMediaUtil_UnlockBuffer(bufMgr->pBitStreamBuffObject[i]);
815 bufMgr->pBitStreamBase[i] = nullptr;
816 }
817 if (bufMgr->pBitStreamBuffObject[i])
818 {
819 DdiMediaUtil_FreeBuffer(bufMgr->pBitStreamBuffObject[i]);
820 MOS_FreeMemory(bufMgr->pBitStreamBuffObject[i]);
821 bufMgr->pBitStreamBuffObject[i] = nullptr;
822 }
823 }
824
825 if (bufMgr->Codec_Param.Codec_Param_H264.pVASliceParaBufH264)
826 {
827 MOS_FreeMemory(bufMgr->Codec_Param.Codec_Param_H264.pVASliceParaBufH264);
828 bufMgr->Codec_Param.Codec_Param_H264.pVASliceParaBufH264 = nullptr;
829 }
830 if (bufMgr->Codec_Param.Codec_Param_H264.pVASliceParaBufH264Base)
831 {
832 MOS_FreeMemory(bufMgr->Codec_Param.Codec_Param_H264.pVASliceParaBufH264Base);
833 bufMgr->Codec_Param.Codec_Param_H264.pVASliceParaBufH264Base = nullptr;
834 }
835
836 // free decode bitstream buffer object
837 MOS_FreeMemory(bufMgr->pSliceData);
838 bufMgr->pSliceData = nullptr;
839 }
840
GetSlcRefIdx(CODEC_PICTURE * picReference,CODEC_PICTURE * slcReference)841 void DdiDecodeAVC::GetSlcRefIdx(CODEC_PICTURE *picReference, CODEC_PICTURE *slcReference)
842 {
843 if (nullptr == picReference|| nullptr == slcReference)
844 {return;}
845
846 int32_t i = 0;
847 if (slcReference->FrameIdx != CODEC_AVC_NUM_UNCOMPRESSED_SURFACE)
848 {
849 for (i = 0; i < CODEC_MAX_NUM_REF_FRAME; i++)
850 {
851 if (slcReference->FrameIdx == picReference[i].FrameIdx)
852 {
853 slcReference->FrameIdx = i;
854 break;
855 }
856 }
857 if (i == CODEC_MAX_NUM_REF_FRAME)
858 {
859 slcReference->FrameIdx = CODEC_AVC_NUM_UNCOMPRESSED_SURFACE;
860 }
861 }
862 }
863
SetupCodecPicture(DDI_MEDIA_CONTEXT * mediaCtx,DDI_CODEC_RENDER_TARGET_TABLE * rtTbl,CODEC_PICTURE * codecHalPic,VAPictureH264 vaPic,bool fieldPicFlag,bool picReference,bool sliceReference)864 void DdiDecodeAVC::SetupCodecPicture(
865 DDI_MEDIA_CONTEXT *mediaCtx,
866 DDI_CODEC_RENDER_TARGET_TABLE *rtTbl,
867 CODEC_PICTURE *codecHalPic,
868 VAPictureH264 vaPic,
869 bool fieldPicFlag,
870 bool picReference,
871 bool sliceReference)
872 {
873 if(vaPic.picture_id != DDI_CODEC_INVALID_FRAME_INDEX)
874 {
875 DDI_MEDIA_SURFACE *surface = DdiMedia_GetSurfaceFromVASurfaceID(mediaCtx, vaPic.picture_id);
876 vaPic.frame_idx = GetRenderTargetID(rtTbl, surface);
877 if(vaPic.frame_idx == DDI_CODEC_INVALID_FRAME_INDEX)
878 {
879 codecHalPic->FrameIdx = CODEC_AVC_NUM_UNCOMPRESSED_SURFACE - 1;
880 }
881 else
882 {
883 codecHalPic->FrameIdx = (uint8_t)vaPic.frame_idx;
884 }
885 }
886 else
887 {
888 vaPic.frame_idx = DDI_CODEC_INVALID_FRAME_INDEX;
889 codecHalPic->FrameIdx = CODEC_AVC_NUM_UNCOMPRESSED_SURFACE - 1;
890 }
891
892 if (picReference)
893 {
894 if (vaPic.frame_idx == DDI_CODEC_INVALID_FRAME_INDEX)
895 {
896 codecHalPic->PicFlags = PICTURE_INVALID;
897 }
898 else if ((vaPic.flags&VA_PICTURE_H264_LONG_TERM_REFERENCE) == VA_PICTURE_H264_LONG_TERM_REFERENCE)
899 {
900 codecHalPic->PicFlags = PICTURE_LONG_TERM_REFERENCE;
901 }
902 else
903 {
904 codecHalPic->PicFlags = PICTURE_SHORT_TERM_REFERENCE;
905 }
906 }
907 else
908 {
909 if (fieldPicFlag)
910 {
911 if ((vaPic.flags&VA_PICTURE_H264_BOTTOM_FIELD) == VA_PICTURE_H264_BOTTOM_FIELD)
912 {
913 codecHalPic->PicFlags = PICTURE_BOTTOM_FIELD;
914 }
915 else
916 {
917 codecHalPic->PicFlags = PICTURE_TOP_FIELD;
918 }
919 }
920 else
921 {
922 codecHalPic->PicFlags = PICTURE_FRAME;
923 }
924 }
925
926 if (sliceReference && (vaPic.picture_id == VA_INVALID_ID))//VA_INVALID_ID is used to indicate invalide picture in LIBVA.
927 {
928 codecHalPic->PicFlags = PICTURE_INVALID;
929 }
930 }
931
932 extern template class MediaDdiFactory<DdiMediaDecode, DDI_DECODE_CONFIG_ATTR>;
933
934 static bool h264Registered =
935 MediaDdiFactory<DdiMediaDecode, DDI_DECODE_CONFIG_ATTR>::
936 RegisterCodec<DdiDecodeAVC>(DECODE_ID_AVC);
937