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