xref: /aosp_15_r20/external/intel-media-driver/media_driver/linux/common/codec/ddi/media_ddi_decode_vc1.cpp (revision ba62d9d3abf0e404f2022b4cd7a85e107f48596f)
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_vc1.cpp
24 //! \brief     libva(and its extension) decoder implementation
25 //!
26 #include "media_libva_decoder.h"
27 #include "media_libva_util.h"
28 
29 #include "media_ddi_decode_vc1.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 
35 static const int32_t FractionToScaleFactor[21] = {
36     128, 85,  170, 64,  192,
37     51,  102, 153, 204, 43,
38     215, 37,  74,  111, 148,
39     185, 222, 32,  96,  160,
40     224,
41 };
42 
CalculateQuantParams(VAPictureParameterBufferVC1 * picParam,uint32_t * outAltPquantConfig,uint32_t * outAltPquantEdgeMask)43 void DdiDecodeVC1::CalculateQuantParams(
44     VAPictureParameterBufferVC1 *picParam,
45     uint32_t                    *outAltPquantConfig,
46     uint32_t                    *outAltPquantEdgeMask)
47 {
48     uint32_t dquant    = picParam->pic_quantizer_fields.bits.dquant;
49     uint32_t dqFrame   = picParam->pic_quantizer_fields.bits.dq_frame;
50     uint32_t dqProfile = picParam->pic_quantizer_fields.bits.dq_profile;
51     uint32_t dqDbedge  = picParam->pic_quantizer_fields.bits.dq_db_edge;
52     uint32_t dqSbedge  = picParam->pic_quantizer_fields.bits.dq_sb_edge;
53     uint32_t dqBilevel = picParam->pic_quantizer_fields.bits.dq_binary_level;
54 
55     uint32_t altPquantConfig   = 0;
56     uint32_t altPquantEdgeMask = 0;
57 
58     if (dquant == 0)
59     {
60         altPquantConfig   = 0;
61         altPquantEdgeMask = 0;
62     }
63     else if (dquant == 1)
64     {
65         if (dqFrame == 0)
66         {
67             altPquantConfig   = 0;
68             altPquantEdgeMask = 0;
69         }
70         else if (dqFrame == 1)
71         {
72             altPquantConfig   = 1;
73             altPquantEdgeMask = 0;
74             switch (dqProfile)
75             {
76             case 0:  //all edge with altpquant
77                 altPquantEdgeMask = 0xf;
78                 break;
79 
80             case 1:  //double edge with altpquant
81                 if (dqDbedge == 3)
82                 {
83                     altPquantEdgeMask = 0x9;
84                 }
85                 else
86                 {
87                     altPquantEdgeMask = (0x3 << dqDbedge);
88                 }
89                 break;
90 
91             case 2:  //single edge with altpquant
92                 altPquantEdgeMask = (0x1 << dqSbedge);
93                 break;
94 
95             case 3:  //all mbs
96                 if (dqBilevel == 0)
97                 {
98                     altPquantConfig   = 2;
99                     altPquantEdgeMask = 0;
100                 }
101                 else
102                 {
103                     altPquantConfig   = 3;
104                     altPquantEdgeMask = 0;
105                 }
106                 break;
107 
108             default:
109                 break;
110             }
111         }
112     }
113     else
114     {
115         altPquantConfig   = 1;
116         altPquantEdgeMask = 0xf;
117     }
118 
119     *outAltPquantConfig   = altPquantConfig;
120     *outAltPquantEdgeMask = altPquantEdgeMask;
121 }
122 
IsBIField(bool isFirstField,int16_t picType)123 static inline bool IsBIField(
124     bool                isFirstField,
125     int16_t             picType)
126 {
127     bool isBI = false;
128 
129     if (picType == vc1BBIField)
130     {
131         isBI = (!isFirstField);
132     }
133     else if (picType == vc1BIBField)
134     {
135         isBI = isFirstField;
136     }
137     else if (picType == vc1BIBIField)
138     {
139         isBI = true;
140     }
141 
142     return isBI;
143 }
144 
IsBField(bool isFirstField,int16_t picType)145 static inline bool IsBField(
146     bool                isFirstField,
147     int16_t             picType)
148 {
149     bool isBottom = false;
150 
151     if (picType == vc1BBIField)
152     {
153         isBottom = isFirstField;
154     }
155     else if (picType == vc1BIBField)
156     {
157         isBottom = (!isFirstField);
158     }
159     else if (picType == vc1BBField)
160     {
161         isBottom = true;
162     }
163 
164     return isBottom;
165 }
166 
IsIField(bool isFirstField,int16_t picType)167 static inline bool IsIField(
168     bool                isFirstField,
169     int16_t             picType)
170 {
171     bool isIF = false;
172 
173     if (picType == vc1IPField)
174     {
175         isIF = isFirstField;
176     }
177     else if (picType == vc1PIField)
178     {
179         isIF = !isFirstField;
180     }
181     else if (picType == vc1IIField)
182     {
183         isIF = true;
184     }
185 
186     return isIF;
187 }
188 
ParsePicParams(DDI_MEDIA_CONTEXT * mediaCtx,VAPictureParameterBufferVC1 * picParam)189 VAStatus DdiDecodeVC1::ParsePicParams(
190     DDI_MEDIA_CONTEXT             *mediaCtx,
191     VAPictureParameterBufferVC1   *picParam)
192 {
193     PCODEC_VC1_PIC_PARAMS codecPicParam = (PCODEC_VC1_PIC_PARAMS)(m_ddiDecodeCtx->DecodeParams.m_picParams);
194 
195     if ((codecPicParam == nullptr) ||
196         (picParam == nullptr))
197     {
198         DDI_ASSERTMESSAGE("nullptr pointer in Parsing VC1 Picture parameter\n");
199         return VA_STATUS_ERROR_INVALID_PARAMETER;
200     }
201     uint32_t scaleFactor = 0;
202     // See spec, table 40 && Figure 70
203     if (picParam->b_picture_fraction < 21)
204     {
205         scaleFactor = FractionToScaleFactor[picParam->b_picture_fraction];
206     }
207     else
208     {
209         // Use one value for it if the picParam->b_picture_fraction is out of range.
210         // Since in some cases, although driver gets the invalid bFraction, HW still can handle this.
211         scaleFactor = FractionToScaleFactor[0];
212     }
213 
214     uint32_t fwdRefDist = picParam->reference_fields.bits.reference_distance;
215     int32_t  bwdRefDist = 0;
216 
217     if (picParam->inloop_decoded_picture != DDI_CODEC_INVALID_FRAME_INDEX)
218     {
219         codecPicParam->DeblockedPicIdx = GetRenderTargetID(&(m_ddiDecodeCtx->RTtbl), m_ddiDecodeCtx->RTtbl.pCurrentRT);
220         DDI_CHK_RET(RegisterRTSurfaces(&m_ddiDecodeCtx->RTtbl, DdiMedia_GetSurfaceFromVASurfaceID(mediaCtx, picParam->inloop_decoded_picture)), "RegisterRTSurfaces failed!");
221 
222         codecPicParam->CurrPic.FrameIdx = (uint16_t)GetRenderTargetID(&(m_ddiDecodeCtx->RTtbl),
223             DdiMedia_GetSurfaceFromVASurfaceID(mediaCtx, picParam->inloop_decoded_picture));
224         m_deblockPicIdx                 = codecPicParam->DeblockedPicIdx;
225         m_currPicIdx                    = codecPicParam->CurrPic.FrameIdx;
226     }
227     else
228     {
229         codecPicParam->CurrPic.FrameIdx = GetRenderTargetID(&(m_ddiDecodeCtx->RTtbl), m_ddiDecodeCtx->RTtbl.pCurrentRT);
230         codecPicParam->DeblockedPicIdx  = codecPicParam->CurrPic.FrameIdx;
231         m_deblockPicIdx                 = DDI_CODEC_INVALID_FRAME_INDEX;
232         m_currPicIdx                    = codecPicParam->CurrPic.FrameIdx;
233     }
234 
235     if (picParam->forward_reference_picture == DDI_CODEC_INVALID_FRAME_INDEX)
236     {
237         codecPicParam->ForwardRefIdx = codecPicParam->CurrPic.FrameIdx;
238     }
239     else
240     {
241         if (UpdateRegisteredRTSurfaceFlag(&(m_ddiDecodeCtx->RTtbl), DdiMedia_GetSurfaceFromVASurfaceID(mediaCtx, picParam->forward_reference_picture)) != VA_STATUS_SUCCESS)
242         {
243             DDI_CHK_RET(RegisterRTSurfaces(&(m_ddiDecodeCtx->RTtbl), DdiMedia_GetSurfaceFromVASurfaceID(mediaCtx, picParam->forward_reference_picture)), "RegisterRTSurfaces failed!");
244         }
245         codecPicParam->ForwardRefIdx = (uint16_t)GetRenderTargetID(&(m_ddiDecodeCtx->RTtbl), DdiMedia_GetSurfaceFromVASurfaceID(mediaCtx, picParam->forward_reference_picture));
246     }
247 
248     if (picParam->backward_reference_picture == DDI_CODEC_INVALID_FRAME_INDEX)
249     {
250         codecPicParam->BackwardRefIdx = codecPicParam->CurrPic.FrameIdx;
251     }
252     else
253     {
254         if (UpdateRegisteredRTSurfaceFlag(&(m_ddiDecodeCtx->RTtbl), DdiMedia_GetSurfaceFromVASurfaceID(mediaCtx, picParam->backward_reference_picture)) != VA_STATUS_SUCCESS)
255         {
256             DDI_CHK_RET(RegisterRTSurfaces(&(m_ddiDecodeCtx->RTtbl), DdiMedia_GetSurfaceFromVASurfaceID(mediaCtx, picParam->backward_reference_picture)), "RegisterRTSurfaces failed!");
257         }
258         codecPicParam->BackwardRefIdx = (uint16_t)GetRenderTargetID(&(m_ddiDecodeCtx->RTtbl), DdiMedia_GetSurfaceFromVASurfaceID(mediaCtx, picParam->backward_reference_picture));
259     }
260 
261     //add protection checking to prevent ref pic index larger than DPB size
262     if (codecPicParam->ForwardRefIdx >= CODECHAL_NUM_UNCOMPRESSED_SURFACE_VC1)
263     {
264         codecPicParam->ForwardRefIdx = CODECHAL_NUM_UNCOMPRESSED_SURFACE_VC1 - 1;
265     }
266     if (codecPicParam->BackwardRefIdx >= CODECHAL_NUM_UNCOMPRESSED_SURFACE_VC1)
267     {
268         codecPicParam->BackwardRefIdx = CODECHAL_NUM_UNCOMPRESSED_SURFACE_VC1 - 1;
269     }
270 
271     if (picParam->picture_fields.bits.frame_coding_mode == 0)
272     {
273         codecPicParam->CurrPic.PicFlags = PICTURE_FRAME;
274     }
275     else if (picParam->picture_fields.bits.frame_coding_mode == 1)
276     {
277         codecPicParam->CurrPic.PicFlags = PICTURE_INTERLACED_FRAME;
278     }
279     else
280     {
281         codecPicParam->CurrPic.PicFlags = (picParam->picture_fields.bits.is_first_field ^ picParam->picture_fields.bits.top_field_first) ? PICTURE_BOTTOM_FIELD : PICTURE_TOP_FIELD;
282     }
283 
284     if (picParam->picture_fields.bits.frame_coding_mode < 2)  //frame structure
285     {
286         codecPicParam->picture_fields.frame_coding_mode = picParam->picture_fields.bits.frame_coding_mode;
287         codecPicParam->luma_scale                       = (uint16_t)picParam->luma_scale;
288         codecPicParam->luma_shift                       = (uint16_t)picParam->luma_shift;
289     }
290     else
291     {
292         if (picParam->picture_fields.bits.top_field_first)
293         {
294             codecPicParam->picture_fields.frame_coding_mode = 2;
295         }
296         else
297         {
298             codecPicParam->picture_fields.frame_coding_mode = 3;
299         }
300         if (picParam->picture_fields.bits.picture_type >= vc1BBField)  // B interlaced frames
301         {
302             fwdRefDist = (scaleFactor * picParam->reference_fields.bits.reference_distance) >> 8;
303             bwdRefDist = picParam->reference_fields.bits.reference_distance - fwdRefDist - 1;
304             if (bwdRefDist < 0)
305             {
306                 bwdRefDist = 0;
307             }
308         }
309         codecPicParam->luma_scale = (uint16_t)(picParam->luma_scale2 + (picParam->luma_scale << 8));
310         codecPicParam->luma_shift = (uint16_t)(picParam->luma_shift2 + (picParam->luma_shift << 8));
311     }
312 
313     codecPicParam->sequence_fields.AdvancedProfileFlag = (picParam->sequence_fields.bits.profile == 3) ? 1 : 0;
314     codecPicParam->picture_fields.picture_type         = picParam->picture_fields.bits.picture_type;
315 
316     if (codecPicParam->sequence_fields.AdvancedProfileFlag)
317     {
318         codecPicParam->sequence_fields.overlap = picParam->sequence_fields.bits.overlap;
319     }
320     else
321     {
322         // see 7.1.1.14 in VC spec
323         if ((picParam->b_picture_fraction == 0x7F) && (picParam->picture_fields.bits.picture_type == vc1IFrame))
324         {
325             codecPicParam->picture_fields.picture_type = vc1BIFrame;
326         }
327 
328         codecPicParam->sequence_fields.overlap = picParam->sequence_fields.bits.overlap && (picParam->pic_quantizer_fields.bits.pic_quantizer_scale >= 9);
329     }
330 
331     codecPicParam->coded_width                           = picParam->coded_width;
332     codecPicParam->coded_height                          = picParam->coded_height;
333     codecPicParam->sequence_fields.syncmarker            = picParam->sequence_fields.bits.syncmarker;
334     codecPicParam->sequence_fields.pulldown              = picParam->sequence_fields.bits.pulldown;
335     codecPicParam->sequence_fields.interlace             = picParam->sequence_fields.bits.interlace;
336     codecPicParam->sequence_fields.tfcntrflag            = picParam->sequence_fields.bits.tfcntrflag;
337     codecPicParam->sequence_fields.psf                   = picParam->sequence_fields.bits.psf;
338     codecPicParam->sequence_fields.multires              = picParam->sequence_fields.bits.multires;
339     codecPicParam->sequence_fields.rangered              = picParam->sequence_fields.bits.rangered;
340     codecPicParam->sequence_fields.max_b_frames          = picParam->sequence_fields.bits.max_b_frames;
341     codecPicParam->entrypoint_fields.loopfilter          = picParam->entrypoint_fields.bits.loopfilter;
342     codecPicParam->entrypoint_fields.broken_link         = picParam->entrypoint_fields.bits.broken_link;
343     codecPicParam->entrypoint_fields.closed_entry        = picParam->entrypoint_fields.bits.closed_entry;
344     codecPicParam->entrypoint_fields.panscan_flag        = picParam->entrypoint_fields.bits.panscan_flag;
345     codecPicParam->picture_fields.is_first_field         = picParam->picture_fields.bits.is_first_field;
346     codecPicParam->picture_fields.top_field_first        = picParam->picture_fields.bits.top_field_first;
347     codecPicParam->picture_fields.intensity_compensation = picParam->picture_fields.bits.intensity_compensation;
348 
349     if (picParam->mv_fields.bits.mv_mode == VAMvModeIntensityCompensation)
350     {
351         codecPicParam->mv_fields.UnifiedMvMode = (picParam->mv_fields.bits.mv_mode2 + 1) & 0x3;
352         codecPicParam->picture_fields.intensity_compensation = 1;
353     }
354     else
355     {
356         codecPicParam->mv_fields.UnifiedMvMode = (picParam->mv_fields.bits.mv_mode + 1) & 0x3;
357     }
358 
359     if (picParam->mv_fields.bits.mv_mode == VAMvMode1MvHalfPelBilinear ||
360         (picParam->mv_fields.bits.mv_mode == VAMvModeIntensityCompensation && picParam->mv_fields.bits.mv_mode2 == VAMvMode1MvHalfPelBilinear))
361     {
362         codecPicParam->mv_fields.MvMode = picParam->fast_uvmc_flag ? 9 : 8;
363     }
364     else
365     {
366         codecPicParam->mv_fields.MvMode = picParam->fast_uvmc_flag ? 1 : 0;
367     }
368 
369     uint32_t altPquantConfig   = 0;
370     uint32_t altPquantEdgeMask = 0;
371     CalculateQuantParams(picParam, &altPquantConfig, &altPquantEdgeMask);
372 
373     codecPicParam->pic_quantizer_fields.quantizer                 = picParam->pic_quantizer_fields.bits.quantizer;
374     codecPicParam->pic_quantizer_fields.pic_quantizer_scale       = picParam->pic_quantizer_fields.bits.pic_quantizer_scale;
375     codecPicParam->pic_quantizer_fields.alt_pic_quantizer         = picParam->pic_quantizer_fields.bits.alt_pic_quantizer;
376     codecPicParam->pic_quantizer_fields.pic_quantizer_type        = picParam->pic_quantizer_fields.bits.pic_quantizer_type;
377     codecPicParam->pic_quantizer_fields.half_qp                   = picParam->pic_quantizer_fields.bits.half_qp;
378     codecPicParam->pic_quantizer_fields.AltPQuantConfig           = altPquantConfig;
379     codecPicParam->pic_quantizer_fields.AltPQuantEdgeMask         = altPquantEdgeMask;
380     codecPicParam->pic_quantizer_fields.dquant                    = picParam->pic_quantizer_fields.bits.dquant;
381     codecPicParam->mv_fields.extended_mv_flag                     = picParam->mv_fields.bits.extended_mv_flag;
382     codecPicParam->mv_fields.extended_dmv_flag                    = picParam->mv_fields.bits.extended_dmv_flag;
383     codecPicParam->mv_fields.extended_mv_range                    = picParam->mv_fields.bits.extended_mv_range;
384     codecPicParam->mv_fields.extended_dmv_range                   = picParam->mv_fields.bits.extended_dmv_range;
385     codecPicParam->mv_fields.four_mv_switch                       = picParam->mv_fields.bits.four_mv_switch;
386     codecPicParam->mv_fields.two_mv_block_pattern_table           = picParam->mv_fields.bits.two_mv_block_pattern_table;
387     codecPicParam->mv_fields.four_mv_block_pattern_table          = picParam->mv_fields.bits.four_mv_block_pattern_table;
388     codecPicParam->mv_fields.mv_table                             = picParam->mv_fields.bits.mv_table;
389     codecPicParam->reference_fields.reference_distance_flag       = picParam->reference_fields.bits.reference_distance_flag;
390     codecPicParam->reference_fields.reference_distance            = fwdRefDist;  //picParam->reference_fields.bits.reference_distance;
391     codecPicParam->reference_fields.BwdReferenceDistance          = bwdRefDist;  //picParam->reference_fields.bits.reference_distance;
392     codecPicParam->reference_fields.num_reference_pictures        = picParam->reference_fields.bits.num_reference_pictures;
393     codecPicParam->reference_fields.reference_field_pic_indicator = picParam->reference_fields.bits.reference_field_pic_indicator;
394 
395     codecPicParam->raw_coding.value = 0xFE;
396     if (picParam->picture_fields.bits.frame_coding_mode < 2)  //frame structure
397     {
398         if ((picParam->picture_fields.bits.picture_type == vc1IFrame) ||
399             (picParam->picture_fields.bits.picture_type == vc1BIFrame))
400         {
401             if (picParam->picture_fields.bits.frame_coding_mode == 1)  //interlaced frame
402             {
403                 codecPicParam->raw_coding.field_tx = !picParam->bitplane_present.flags.bp_field_tx;
404             }
405             codecPicParam->raw_coding.ac_pred   = !picParam->bitplane_present.flags.bp_ac_pred;
406             codecPicParam->raw_coding.overflags = !picParam->bitplane_present.flags.bp_overflags;
407         }
408         else if (picParam->picture_fields.bits.picture_type == vc1PFrame)
409         {
410             codecPicParam->raw_coding.skip_mb = !picParam->bitplane_present.flags.bp_skip_mb;
411             if (picParam->picture_fields.bits.frame_coding_mode == 0)  //progressive frame
412             {
413                 codecPicParam->raw_coding.mv_type_mb = !picParam->bitplane_present.flags.bp_mv_type_mb;
414             }
415         }
416         else
417         {
418             codecPicParam->raw_coding.direct_mb = !picParam->bitplane_present.flags.bp_direct_mb;
419             codecPicParam->raw_coding.skip_mb   = !picParam->bitplane_present.flags.bp_skip_mb;
420         }
421     }
422     else
423     {
424         if ((IsIField(picParam->picture_fields.bits.is_first_field, picParam->picture_fields.bits.picture_type)) ||
425             (IsBIField(picParam->picture_fields.bits.is_first_field, picParam->picture_fields.bits.picture_type)))
426         {
427             codecPicParam->raw_coding.ac_pred   = !picParam->bitplane_present.flags.bp_ac_pred;
428             codecPicParam->raw_coding.overflags = !picParam->bitplane_present.flags.bp_overflags;
429         }
430         else if (IsBField(picParam->picture_fields.bits.is_first_field, picParam->picture_fields.bits.picture_type))
431         {
432             codecPicParam->raw_coding.forward_mb = !picParam->bitplane_present.flags.bp_forward_mb;
433         }
434     }
435     uint32_t rawCoding                         = codecPicParam->raw_coding.value & 0xFE;
436     codecPicParam->raw_coding.bitplane_present = (rawCoding == 0xFE) ? 0 : 1;
437 
438     codecPicParam->transform_fields.intra_transform_dc_table      = picParam->transform_fields.bits.intra_transform_dc_table;
439     codecPicParam->transform_fields.transform_ac_codingset_idx1   = picParam->transform_fields.bits.transform_ac_codingset_idx1;
440     codecPicParam->transform_fields.transform_ac_codingset_idx2   = picParam->transform_fields.bits.transform_ac_codingset_idx2;
441     codecPicParam->transform_fields.variable_sized_transform_flag = picParam->transform_fields.bits.variable_sized_transform_flag;
442     codecPicParam->transform_fields.mb_level_transform_type_flag  = picParam->transform_fields.bits.mb_level_transform_type_flag;
443     codecPicParam->transform_fields.frame_level_transform_type    = picParam->transform_fields.bits.frame_level_transform_type;
444 
445     codecPicParam->conditional_overlap_flag = picParam->conditional_overlap_flag ? (picParam->conditional_overlap_flag + 1) : 0;
446     codecPicParam->fast_uvmc_flag           = picParam->fast_uvmc_flag;
447     codecPicParam->cbp_table                = picParam->cbp_table;
448     codecPicParam->mb_mode_table            = picParam->mb_mode_table;
449     codecPicParam->b_picture_fraction       = picParam->b_picture_fraction;  //not used
450     codecPicParam->range_reduction_frame    = picParam->range_reduction_frame;
451     codecPicParam->ScaleFactor              = scaleFactor;
452     codecPicParam->post_processing          = picParam->post_processing;
453     codecPicParam->picture_resolution_index = 0;
454     codecPicParam->rounding_control         = picParam->rounding_control;
455 
456     codecPicParam->UpsamplingFlag = picParam->sequence_fields.bits.multires ? (picParam->picture_resolution_index & 0x3) : 0;
457 
458     //rangemap
459     if (codecPicParam->sequence_fields.AdvancedProfileFlag)
460     {
461         codecPicParam->range_mapping_fields.luma_flag             = picParam->range_mapping_fields.bits.luma_flag;
462         codecPicParam->range_mapping_fields.luma                  = picParam->range_mapping_fields.bits.luma;
463         codecPicParam->range_mapping_fields.chroma_flag           = picParam->range_mapping_fields.bits.chroma_flag;
464         codecPicParam->range_mapping_fields.chroma                = picParam->range_mapping_fields.bits.chroma;
465         codecPicParam->range_mapping_fields.range_mapping_enabled = picParam->range_mapping_fields.value;
466     }
467     else
468     {
469         codecPicParam->range_mapping_fields.range_mapping_enabled = picParam->range_reduction_frame;
470     }
471 
472     // Check if OLP is needed
473     // OLP output surface must be present
474     if ((m_deblockPicIdx != DDI_CODEC_INVALID_FRAME_INDEX) &&
475         ((codecPicParam->DeblockedPicIdx != codecPicParam->CurrPic.FrameIdx) ||
476             codecPicParam->UpsamplingFlag ||
477             codecPicParam->range_mapping_fields.range_mapping_enabled))
478     {
479         m_olpNeeded = 1;
480     }
481     else
482     {
483         m_olpNeeded = 0;
484     }
485 
486     return VA_STATUS_SUCCESS;
487 }
488 
ParseSliceParams(DDI_MEDIA_CONTEXT * mediaCtx,VASliceParameterBufferVC1 * slcParam,uint32_t numSlices)489 VAStatus DdiDecodeVC1::ParseSliceParams(
490         DDI_MEDIA_CONTEXT            *mediaCtx,
491         VASliceParameterBufferVC1    *slcParam,
492         uint32_t                      numSlices)
493 {
494     PCODEC_VC1_SLICE_PARAMS codecSlcParam = (PCODEC_VC1_SLICE_PARAMS)(m_ddiDecodeCtx->DecodeParams.m_sliceParams);
495 
496     codecSlcParam += m_ddiDecodeCtx->DecodeParams.m_numSlices;
497 
498     if ((slcParam == nullptr) || (codecSlcParam == nullptr))
499     {
500         DDI_ASSERTMESSAGE("Null pointer for Parsing VC1 Slice parameter\n");
501         return VA_STATUS_ERROR_INVALID_PARAMETER;
502     }
503 
504     uint32_t sliceBaseOffset = GetBsBufOffset(m_groupIndex);
505     for (uint32_t slcCount = 0; slcCount < numSlices; slcCount++)
506     {
507         codecSlcParam[slcCount].slice_data_size   = slcParam[slcCount].slice_data_size << 3;
508         codecSlcParam[slcCount].slice_data_offset = slcParam[slcCount].slice_data_offset +
509                                                     sliceBaseOffset;
510         if (slcParam[slcCount].slice_data_flag)
511         {
512             DDI_NORMALMESSAGE("The whole slice is not in the bitstream buffer for this Execute call");
513         }
514         codecSlcParam[slcCount].macroblock_offset       = slcParam[slcCount].macroblock_offset;
515         codecSlcParam[slcCount].slice_vertical_position = slcParam[slcCount].slice_vertical_position;
516     }
517 
518     return VA_STATUS_SUCCESS;
519 }
520 
AllocBitPlaneBuffer()521 VAStatus DdiDecodeVC1::AllocBitPlaneBuffer()
522 {
523     DDI_CODEC_COM_BUFFER_MGR *bufMgr = &(m_ddiDecodeCtx->BufMgr);
524 
525     DDI_CHK_NULL(bufMgr, "Null bufMgr in AllocBpBuffer", VA_STATUS_ERROR_INVALID_PARAMETER);
526 
527     if (bufMgr->Codec_Param.Codec_Param_VC1.VC1BitPlane[bufMgr->Codec_Param.Codec_Param_VC1.dwVC1BitPlaneIndex].bUsed)
528     {
529         // wait until decode complete
530         mos_bo_wait_rendering(bufMgr->Codec_Param.Codec_Param_VC1.pVC1BitPlaneBuffObject[bufMgr->Codec_Param.Codec_Param_VC1.dwVC1BitPlaneIndex]->bo);
531     }
532 
533     bufMgr->Codec_Param.Codec_Param_VC1.VC1BitPlane[bufMgr->Codec_Param.Codec_Param_VC1.dwVC1BitPlaneIndex].bUsed = true;
534 
535     return VA_STATUS_SUCCESS;
536 }
537 
AllocSliceParamContext(uint32_t numSlices)538 VAStatus DdiDecodeVC1::AllocSliceParamContext(
539     uint32_t numSlices)
540 {
541     uint32_t baseSize = sizeof(CODEC_VC1_SLICE_PARAMS);
542 
543     if (m_sliceParamBufNum < (m_ddiDecodeCtx->DecodeParams.m_numSlices + numSlices))
544     {
545         // in order to avoid that the buffer is reallocated multi-times,
546         // extra 10 slices are added.
547         uint32_t extraSlices = numSlices + 10;
548 
549         m_ddiDecodeCtx->DecodeParams.m_sliceParams = realloc(m_ddiDecodeCtx->DecodeParams.m_sliceParams,
550             baseSize * (m_sliceParamBufNum + extraSlices));
551 
552         if (m_ddiDecodeCtx->DecodeParams.m_sliceParams == nullptr)
553         {
554             return VA_STATUS_ERROR_ALLOCATION_FAILED;
555         }
556 
557         memset((void *)((uint8_t *)m_ddiDecodeCtx->DecodeParams.m_sliceParams + baseSize * m_sliceParamBufNum), 0, baseSize * extraSlices);
558         m_sliceParamBufNum += extraSlices;
559     }
560 
561     return VA_STATUS_SUCCESS;
562 }
563 
DestroyContext(VADriverContextP ctx)564 void DdiDecodeVC1::DestroyContext(
565     VADriverContextP ctx)
566 {
567     FreeResourceBuffer();
568     // explicitly call the base function to do the further clean-up
569     DdiMediaDecode::DestroyContext(ctx);
570 }
571 
GetPicParamBuf(DDI_CODEC_COM_BUFFER_MGR * bufMgr)572 uint8_t* DdiDecodeVC1::GetPicParamBuf(
573     DDI_CODEC_COM_BUFFER_MGR    *bufMgr)
574 {
575     return (uint8_t*)(&(bufMgr->Codec_Param.Codec_Param_VC1.PicParamVC1));
576 }
577 
AllocSliceControlBuffer(DDI_MEDIA_BUFFER * buf)578 VAStatus DdiDecodeVC1::AllocSliceControlBuffer(
579     DDI_MEDIA_BUFFER       *buf)
580 {
581     DDI_CODEC_COM_BUFFER_MGR   *bufMgr;
582     uint32_t                    availSize;
583     uint32_t                    newSize;
584 
585     bufMgr     = &(m_ddiDecodeCtx->BufMgr);
586     availSize  = m_sliceCtrlBufNum - bufMgr->dwNumSliceControl;
587     if(availSize < buf->uiNumElements)
588     {
589         newSize   = sizeof(VASliceParameterBufferVC1) * (m_sliceCtrlBufNum - availSize + buf->uiNumElements);
590         bufMgr->Codec_Param.Codec_Param_VC1.pVASliceParaBufVC1 = (VASliceParameterBufferVC1 *)realloc(bufMgr->Codec_Param.Codec_Param_VC1.pVASliceParaBufVC1, newSize);
591         if(bufMgr->Codec_Param.Codec_Param_VC1.pVASliceParaBufVC1 == nullptr)
592         {
593             return VA_STATUS_ERROR_ALLOCATION_FAILED;
594         }
595         MOS_ZeroMemory(bufMgr->Codec_Param.Codec_Param_VC1.pVASliceParaBufVC1 + m_sliceCtrlBufNum, sizeof(VASliceParameterBufferVC1) * (buf->uiNumElements - availSize));
596         m_sliceCtrlBufNum = m_sliceCtrlBufNum - availSize + buf->uiNumElements;
597     }
598     buf->pData      = (uint8_t*)bufMgr->Codec_Param.Codec_Param_VC1.pVASliceParaBufVC1;
599     buf->uiOffset   = sizeof(VASliceParameterBufferVC1) * bufMgr->dwNumSliceControl;
600 
601     bufMgr->dwNumSliceControl += buf->uiNumElements;
602 
603     return VA_STATUS_SUCCESS;
604 }
605 
ContextInit(int32_t picWidth,int32_t picHeight)606 void DdiDecodeVC1::ContextInit(
607     int32_t picWidth,
608     int32_t picHeight)
609 {
610     // call the function in base class to initialize it.
611     DdiMediaDecode::ContextInit(picWidth, picHeight);
612 
613     m_ddiDecodeCtx->wMode    = CODECHAL_DECODE_MODE_VC1VLD;
614     m_olpNeeded     = false;
615     m_currPicIdx    = DDI_CODEC_INVALID_FRAME_INDEX;
616     m_deblockPicIdx = DDI_CODEC_INVALID_FRAME_INDEX;
617 
618     if (m_ddiDecodeAttr->profile == VAProfileVC1Advanced)
619     {
620         int32_t alignedHeight = MOS_ALIGN_CEIL(picHeight, 32);
621         m_height = alignedHeight;
622         m_picHeightInMB    = (int16_t)(DDI_CODEC_NUM_MACROBLOCKS_HEIGHT(alignedHeight));
623     }
624 }
625 
BeginPicture(VADriverContextP ctx,VAContextID context,VASurfaceID renderTarget)626 VAStatus DdiDecodeVC1::BeginPicture(
627     VADriverContextP ctx,
628     VAContextID      context,
629     VASurfaceID      renderTarget)
630 {
631     VAStatus vaStatus = DdiMediaDecode::BeginPicture(ctx, context, renderTarget);
632 
633     if (vaStatus != VA_STATUS_SUCCESS)
634     {
635         return vaStatus;
636     }
637 
638     m_ddiDecodeCtx->DecodeParams.m_vc1BitplaneSize = 0;
639 
640     return VA_STATUS_SUCCESS;
641 }
642 
ParseBitPlane(struct _DDI_MEDIA_BUFFER * bitPlaneBuffObject,uint8_t * buf)643 void DdiDecodeVC1::ParseBitPlane(
644     struct _DDI_MEDIA_BUFFER  *bitPlaneBuffObject,
645     uint8_t                   *buf)
646 {
647     if (bitPlaneBuffObject->pData)
648     {
649         PCODEC_VC1_PIC_PARAMS picParam = (PCODEC_VC1_PIC_PARAMS)(m_ddiDecodeCtx->DecodeParams.m_picParams);
650 
651         uint8_t *destBp = (uint8_t *)bitPlaneBuffObject->pData;
652         uint8_t *srcBp  = (uint8_t *)buf;
653 
654         uint32_t heightInMbs   = MOS_ALIGN_CEIL(picParam->coded_height, CODECHAL_MACROBLOCK_HEIGHT) / CODECHAL_MACROBLOCK_HEIGHT;
655         uint32_t widthInMbs    = MOS_ALIGN_CEIL(picParam->coded_width, CODECHAL_MACROBLOCK_WIDTH) / CODECHAL_MACROBLOCK_WIDTH;
656         uint32_t bitPlanePitch = MOS_ALIGN_CEIL(widthInMbs, 2) / 2;
657 
658         uint32_t srcIdx, dstIdx;
659         uint32_t srcShift;
660         uint32_t i, j;
661         uint8_t  srcValue = 0;
662         for (i = 0; i < heightInMbs; i++)
663         {
664             for (j = 0; j < widthInMbs; j++)
665             {
666                 srcIdx   = (i * widthInMbs + j) / 2;
667                 dstIdx   = j / 2;
668                 srcShift = ((i * widthInMbs + j) & 1) ? 0 : 4;
669                 srcValue = (srcBp[srcIdx] >> srcShift) & 0xf;
670                 if (j % 2)
671                     destBp[dstIdx] = destBp[dstIdx] + (srcValue << 4);
672                 else
673                     destBp[dstIdx] = srcValue;
674             }
675             destBp += bitPlanePitch;
676         }
677     }
678 }
679 
RenderPicture(VADriverContextP ctx,VAContextID context,VABufferID * buffers,int32_t numBuffers)680 VAStatus DdiDecodeVC1::RenderPicture(
681     VADriverContextP ctx,
682     VAContextID      context,
683     VABufferID       *buffers,
684     int32_t          numBuffers)
685 {
686     DDI_FUNCTION_ENTER();
687 
688     VAStatus           va = VA_STATUS_SUCCESS;
689     PDDI_MEDIA_CONTEXT mediaCtx;
690 
691     mediaCtx = DdiMedia_GetMediaContext(ctx);
692 
693     void             *data = nullptr;
694     for (int32_t i = 0; i < numBuffers; i++)
695     {
696         if (!buffers || (buffers[i] == VA_INVALID_ID))
697         {
698             return VA_STATUS_ERROR_INVALID_BUFFER;
699         }
700 
701         DDI_MEDIA_BUFFER *buf = DdiMedia_GetBufferFromVABufferID(mediaCtx, buffers[i]);
702         if (nullptr == buf)
703         {
704             return VA_STATUS_ERROR_INVALID_BUFFER;
705         }
706 
707         uint32_t dataSize = buf->iSize;
708         DdiMedia_MapBuffer(ctx, buffers[i], &data);
709 
710         if (data == nullptr)
711         {
712             return VA_STATUS_ERROR_INVALID_BUFFER;
713         }
714 
715         switch ((int32_t)buf->uiType)
716         {
717         case VABitPlaneBufferType:
718         {
719             int32_t index = m_ddiDecodeCtx->BufMgr.Codec_Param.Codec_Param_VC1.dwVC1BitPlaneIndex;
720             if (index == DDI_CODEC_INVALID_BUFFER_INDEX)
721             {
722                 return VA_STATUS_ERROR_INVALID_BUFFER;
723             }
724             if (index >= DDI_CODEC_MAX_BITSTREAM_BUFFER)
725             {
726                 return VA_STATUS_ERROR_INVALID_BUFFER;
727             }
728             DDI_CHK_RET(AllocBitPlaneBuffer(),"AllocBitPlaneBuffer failed!");
729             /* Before accessing it on CPU, Use the DdiMediaUtil_LockBuffer to map it into CPU */
730             DdiMediaUtil_LockBuffer(m_ddiDecodeCtx->BufMgr.Codec_Param.Codec_Param_VC1.pVC1BitPlaneBuffObject[index], MOS_LOCKFLAG_WRITEONLY);
731             ParseBitPlane(m_ddiDecodeCtx->BufMgr.Codec_Param.Codec_Param_VC1.pVC1BitPlaneBuffObject[index], (uint8_t *)data);
732 
733             DdiMediaUtil_UnlockBuffer(m_ddiDecodeCtx->BufMgr.Codec_Param.Codec_Param_VC1.pVC1BitPlaneBuffObject[index]);
734 
735             DdiMedia_MediaBufferToMosResource(m_ddiDecodeCtx->BufMgr.Codec_Param.Codec_Param_VC1.pVC1BitPlaneBuffObject[index], &m_ddiDecodeCtx->BufMgr.Codec_Param.Codec_Param_VC1.resBitPlaneBuffer);
736             m_ddiDecodeCtx->DecodeParams.m_vc1BitplaneSize = dataSize;
737 
738             m_ddiDecodeCtx->BufMgr.Codec_Param.Codec_Param_VC1.dwVC1BitPlaneIndex++;
739             if (m_ddiDecodeCtx->BufMgr.Codec_Param.Codec_Param_VC1.dwVC1BitPlaneIndex >= DDI_CODEC_MAX_BITSTREAM_BUFFER)
740             {
741                 m_ddiDecodeCtx->BufMgr.Codec_Param.Codec_Param_VC1.dwVC1BitPlaneIndex = 0;
742             }
743             break;
744         }
745 
746         case VASliceDataBufferType:
747         {
748             int32_t index = GetBitstreamBufIndexFromBuffer(&m_ddiDecodeCtx->BufMgr, buf);
749             if (index == DDI_CODEC_INVALID_BUFFER_INDEX)
750             {
751                 return VA_STATUS_ERROR_INVALID_BUFFER;
752             }
753 
754             DdiMedia_MediaBufferToMosResource(m_ddiDecodeCtx->BufMgr.pBitStreamBuffObject[index], &m_ddiDecodeCtx->BufMgr.resBitstreamBuffer);
755             m_ddiDecodeCtx->DecodeParams.m_dataSize += dataSize;
756             break;
757         }
758         case VASliceParameterBufferType:
759         {
760             if (buf->uiNumElements == 0)
761             {
762                 return VA_STATUS_ERROR_INVALID_BUFFER;
763             }
764 
765             VASliceParameterBufferVC1 *slcInfo =
766                 (VASliceParameterBufferVC1 *)data;
767             uint32_t numSlices = buf->uiNumElements;
768             DDI_CHK_RET(AllocSliceParamContext(numSlices),"AllocSliceParamContext failed!");
769             DDI_CHK_RET(ParseSliceParams(mediaCtx, slcInfo, numSlices),"ParseSliceParams failed!");
770             m_ddiDecodeCtx->DecodeParams.m_numSlices += numSlices;
771             m_groupIndex++;
772             break;
773         }
774         case VAPictureParameterBufferType:
775         {
776             VAPictureParameterBufferVC1 *picParam = (VAPictureParameterBufferVC1 *)data;
777             DDI_CHK_RET(ParsePicParams(mediaCtx, picParam),"ParsePicParams failed!");
778             break;
779         }
780         case VADecodeStreamoutBufferType:
781         {
782             DdiMedia_MediaBufferToMosResource(buf, &m_ddiDecodeCtx->BufMgr.resExternalStreamOutBuffer);
783             m_streamOutEnabled = true;
784             break;
785         }
786         default:
787             va = VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE;
788             break;
789         }
790         DdiMedia_UnmapBuffer(ctx, buffers[i]);
791     }
792 
793     DDI_FUNCTION_EXIT(va);
794     return va;
795 }
796 
SetDecodeParams()797 VAStatus DdiDecodeVC1::SetDecodeParams()
798 {
799     if ((&m_ddiDecodeCtx->DecodeParams)->m_numSlices == 0)
800     {
801         return VA_STATUS_ERROR_INVALID_PARAMETER;
802     }
803 
804     m_destSurface.dwOffset      = 0;
805     MOS_FORMAT expectedFormat = Format_NV12;
806     DDI_CODEC_COM_BUFFER_MGR *bufMgr = &(m_ddiDecodeCtx->BufMgr);
807     m_destSurface.Format = expectedFormat;
808 
809     if (m_deblockPicIdx != DDI_CODEC_INVALID_FRAME_INDEX)
810     {
811         DdiMedia_MediaSurfaceToMosResource((&(m_ddiDecodeCtx->RTtbl))->pRT[m_currPicIdx], &(m_destSurface.OsResource));
812     }
813     else
814     {
815         DdiMedia_MediaSurfaceToMosResource((&(m_ddiDecodeCtx->RTtbl))->pCurrentRT, &(m_destSurface.OsResource));
816     }
817 
818     if (m_destSurface.OsResource.Format != expectedFormat)
819     {
820         DDI_NORMALMESSAGE("Surface fomrat of decoded surface is inconsistent with Mpeg2 bitstream\n");
821         return VA_STATUS_ERROR_INVALID_PARAMETER;
822     }
823 
824     (&m_ddiDecodeCtx->DecodeParams)->m_destSurface = &m_destSurface;
825 
826     memset(&m_deblockSurface, 0, sizeof(MOS_SURFACE));
827     if (m_olpNeeded)
828     {
829         memset(&m_deblockSurface, 0, sizeof(MOS_SURFACE));
830         m_deblockSurface.Format   = Format_NV12;
831         m_deblockSurface.dwOffset = 0;
832         DdiMedia_MediaSurfaceToMosResource((&(m_ddiDecodeCtx->RTtbl))->pRT[m_deblockPicIdx], &(m_deblockSurface.OsResource));
833         (&m_ddiDecodeCtx->DecodeParams)->m_deblockSurface = &m_deblockSurface;
834     }
835     else
836     {
837         (&m_ddiDecodeCtx->DecodeParams)->m_deblockSurface = nullptr;
838     }
839 
840     (&m_ddiDecodeCtx->DecodeParams)->m_dataBuffer       = &bufMgr->resBitstreamBuffer;
841     (&m_ddiDecodeCtx->DecodeParams)->m_bitStreamBufData = bufMgr->pBitstreamBuffer;
842     Mos_Solo_OverrideBufferSize((&m_ddiDecodeCtx->DecodeParams)->m_dataSize, (&m_ddiDecodeCtx->DecodeParams)->m_dataBuffer);
843 
844     (&m_ddiDecodeCtx->DecodeParams)->m_bitplaneBuffer = &(m_ddiDecodeCtx->BufMgr.Codec_Param.Codec_Param_VC1.resBitPlaneBuffer);
845 
846     if (m_streamOutEnabled)
847     {
848         (&m_ddiDecodeCtx->DecodeParams)->m_streamOutEnabled        = true;
849         (&m_ddiDecodeCtx->DecodeParams)->m_externalStreamOutBuffer = &bufMgr->resExternalStreamOutBuffer;
850     }
851     else
852     {
853         (&m_ddiDecodeCtx->DecodeParams)->m_streamOutEnabled        = false;
854         (&m_ddiDecodeCtx->DecodeParams)->m_externalStreamOutBuffer = nullptr;
855     }
856 
857     m_olpNeeded     = false;
858     m_currPicIdx    = DDI_CODEC_INVALID_FRAME_INDEX;
859     m_deblockPicIdx = DDI_CODEC_INVALID_FRAME_INDEX;
860 
861     return VA_STATUS_SUCCESS;
862 }
863 
InitResourceBuffer(DDI_MEDIA_CONTEXT * mediaCtx)864 VAStatus DdiDecodeVC1::InitResourceBuffer(DDI_MEDIA_CONTEXT *mediaCtx)
865 {
866     VAStatus                  vaStatus = VA_STATUS_SUCCESS;
867     DDI_CODEC_COM_BUFFER_MGR *bufMgr   = &(m_ddiDecodeCtx->BufMgr);
868 
869     bufMgr->pSliceData = nullptr;
870 
871     bufMgr->ui64BitstreamOrder = 0;
872     bufMgr->dwMaxBsSize        = m_width *
873                           m_height * 3 / 2;
874     // minimal 10k bytes for some special case. Will refractor this later
875     if (bufMgr->dwMaxBsSize < DDI_CODEC_MIN_VALUE_OF_MAX_BS_SIZE)
876     {
877         bufMgr->dwMaxBsSize = DDI_CODEC_MIN_VALUE_OF_MAX_BS_SIZE;
878     }
879 
880     int32_t i;
881     // init decode bitstream buffer object
882     for (i = 0; i < DDI_CODEC_MAX_BITSTREAM_BUFFER; i++)
883     {
884         bufMgr->pBitStreamBuffObject[i] = (DDI_MEDIA_BUFFER *)MOS_AllocAndZeroMemory(sizeof(DDI_MEDIA_BUFFER));
885         if (bufMgr->pBitStreamBuffObject[i] == nullptr)
886         {
887             vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
888             goto finish;
889         }
890         bufMgr->pBitStreamBuffObject[i]->iSize    = bufMgr->dwMaxBsSize;
891         bufMgr->pBitStreamBuffObject[i]->uiType   = VASliceDataBufferType;
892         bufMgr->pBitStreamBuffObject[i]->format   = Media_Format_Buffer;
893         bufMgr->pBitStreamBuffObject[i]->uiOffset = 0;
894         bufMgr->pBitStreamBuffObject[i]->bo       = nullptr;
895         bufMgr->pBitStreamBase[i]                 = nullptr;
896     }
897 
898     bufMgr->m_maxNumSliceData = m_picHeightInMB;
899     bufMgr->pSliceData        = (DDI_CODEC_BITSTREAM_BUFFER_INFO *)MOS_AllocAndZeroMemory(sizeof(bufMgr->pSliceData[0]) *
900                                                                                    bufMgr->m_maxNumSliceData);
901 
902     if (bufMgr->pSliceData == nullptr)
903     {
904         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
905         goto finish;
906     }
907 
908     for (i = 0; i < DDI_CODEC_MAX_BITSTREAM_BUFFER; i++)
909     {
910         bufMgr->Codec_Param.Codec_Param_VC1.pVC1BitPlaneBuffObject[i] = (DDI_MEDIA_BUFFER *)MOS_AllocAndZeroMemory(sizeof(DDI_MEDIA_BUFFER));
911         if (bufMgr->Codec_Param.Codec_Param_VC1.pVC1BitPlaneBuffObject[i] == nullptr)
912         {
913             vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
914             goto finish;
915         }
916         bufMgr->Codec_Param.Codec_Param_VC1.pVC1BitPlaneBuffObject[i]->iSize     = MOS_ALIGN_CEIL(m_width, CODECHAL_MACROBLOCK_WIDTH) * MOS_ALIGN_CEIL(m_height, CODECHAL_MACROBLOCK_HEIGHT) * 2 / (CODECHAL_MACROBLOCK_HEIGHT * CODECHAL_MACROBLOCK_WIDTH);
917         bufMgr->Codec_Param.Codec_Param_VC1.pVC1BitPlaneBuffObject[i]->uiType    = VABitPlaneBufferType;
918         bufMgr->Codec_Param.Codec_Param_VC1.pVC1BitPlaneBuffObject[i]->format    = Media_Format_Buffer;
919         bufMgr->Codec_Param.Codec_Param_VC1.pVC1BitPlaneBuffObject[i]->uiOffset  = 0;
920         bufMgr->Codec_Param.Codec_Param_VC1.pVC1BitPlaneBuffObject[i]->pMediaCtx = mediaCtx;
921 
922         vaStatus = DdiMediaUtil_CreateBuffer(bufMgr->Codec_Param.Codec_Param_VC1.pVC1BitPlaneBuffObject[i], mediaCtx->pDrmBufMgr);
923         if (vaStatus != VA_STATUS_SUCCESS)
924         {
925             goto finish;
926         }
927 
928         bufMgr->Codec_Param.Codec_Param_VC1.VC1BitPlane[i].pBitPlaneBase = nullptr;
929         bufMgr->Codec_Param.Codec_Param_VC1.VC1BitPlane[i].bUsed         = false;
930     }
931 
932     bufMgr->dwNumSliceData    = 0;
933     bufMgr->dwNumSliceControl = 0;
934 
935     m_sliceCtrlBufNum                      = m_picHeightInMB;
936     bufMgr->Codec_Param.Codec_Param_VC1.pVASliceParaBufVC1 = (VASliceParameterBufferVC1 *)MOS_AllocAndZeroMemory(sizeof(VASliceParameterBufferVC1) * m_sliceCtrlBufNum);
937     if (bufMgr->Codec_Param.Codec_Param_VC1.pVASliceParaBufVC1 == nullptr)
938     {
939         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
940         goto finish;
941     }
942     bufMgr->Codec_Param.Codec_Param_VC1.pBitPlaneBuffer = (uint8_t *)MOS_AllocAndZeroMemory(m_picWidthInMB * m_picHeightInMB);
943     if (bufMgr->Codec_Param.Codec_Param_VC1.pBitPlaneBuffer == nullptr)
944     {
945         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
946         goto finish;
947     }
948 
949     return VA_STATUS_SUCCESS;
950 
951 finish:
952     FreeResourceBuffer();
953     return vaStatus;
954 }
955 
FreeResourceBuffer()956 void DdiDecodeVC1::FreeResourceBuffer()
957 {
958     DDI_CODEC_COM_BUFFER_MGR *bufMgr = &(m_ddiDecodeCtx->BufMgr);
959 
960     int32_t i;
961     for (i = 0; i < DDI_CODEC_MAX_BITSTREAM_BUFFER; i++)
962     {
963         if (bufMgr->pBitStreamBase[i])
964         {
965             DdiMediaUtil_UnlockBuffer(bufMgr->pBitStreamBuffObject[i]);
966             bufMgr->pBitStreamBase[i] = nullptr;
967         }
968         if (bufMgr->pBitStreamBuffObject[i])
969         {
970             DdiMediaUtil_FreeBuffer(bufMgr->pBitStreamBuffObject[i]);
971             MOS_FreeMemory(bufMgr->pBitStreamBuffObject[i]);
972             bufMgr->pBitStreamBuffObject[i] = nullptr;
973         }
974     }
975 
976     if (bufMgr->Codec_Param.Codec_Param_VC1.pVASliceParaBufVC1)
977     {
978         MOS_FreeMemory(bufMgr->Codec_Param.Codec_Param_VC1.pVASliceParaBufVC1);
979         bufMgr->Codec_Param.Codec_Param_VC1.pVASliceParaBufVC1 = nullptr;
980     }
981     if (bufMgr->Codec_Param.Codec_Param_VC1.pBitPlaneBuffer)
982     {
983         MOS_FreeMemory(bufMgr->Codec_Param.Codec_Param_VC1.pBitPlaneBuffer);
984         bufMgr->Codec_Param.Codec_Param_VC1.pBitPlaneBuffer = nullptr;
985     }
986     for (i = 0; i < DDI_CODEC_MAX_BITSTREAM_BUFFER; i++)
987     {
988         if (bufMgr->Codec_Param.Codec_Param_VC1.pVC1BitPlaneBuffObject[i])
989         {
990             DdiMediaUtil_UnlockBuffer(bufMgr->Codec_Param.Codec_Param_VC1.pVC1BitPlaneBuffObject[i]);
991             DdiMediaUtil_FreeBuffer(bufMgr->Codec_Param.Codec_Param_VC1.pVC1BitPlaneBuffObject[i]);
992             MOS_FreeMemory(bufMgr->Codec_Param.Codec_Param_VC1.pVC1BitPlaneBuffObject[i]);
993             bufMgr->Codec_Param.Codec_Param_VC1.pVC1BitPlaneBuffObject[i] = nullptr;
994         }
995     }
996 
997     // free decode bitstream buffer object
998     MOS_FreeMemory(bufMgr->pSliceData);
999     bufMgr->pSliceData = nullptr;
1000 
1001     return;
1002 }
1003 
CodecHalInit(DDI_MEDIA_CONTEXT * mediaCtx,void * ptr)1004 VAStatus DdiDecodeVC1::CodecHalInit(
1005     DDI_MEDIA_CONTEXT *mediaCtx,
1006     void              *ptr)
1007 {
1008     VAStatus     vaStatus = VA_STATUS_SUCCESS;
1009     MOS_CONTEXT *mosCtx   = (MOS_CONTEXT *)ptr;
1010 
1011     CODECHAL_FUNCTION codecFunction = CODECHAL_FUNCTION_DECODE;
1012     m_ddiDecodeCtx->pCpDdiInterface->SetCpParams(m_ddiDecodeAttr->uiEncryptionType, m_codechalSettings);
1013 
1014     CODECHAL_STANDARD_INFO standardInfo;
1015     memset(&standardInfo, 0, sizeof(standardInfo));
1016 
1017     standardInfo.CodecFunction = codecFunction;
1018     standardInfo.Mode          = (CODECHAL_MODE)m_ddiDecodeCtx->wMode;
1019 
1020     m_codechalSettings->codecFunction                = codecFunction;
1021     m_codechalSettings->width                      = m_width;
1022     m_codechalSettings->height                     = m_height;
1023 
1024     m_codechalSettings->lumaChromaDepth = CODECHAL_LUMA_CHROMA_DEPTH_8_BITS;
1025 
1026     m_codechalSettings->shortFormatInUse = m_ddiDecodeCtx->bShortFormatInUse;
1027 
1028     m_codechalSettings->mode     = CODECHAL_DECODE_MODE_VC1VLD;
1029     m_codechalSettings->standard = CODECHAL_VC1;
1030     /* VC1 uses the Intel-specific Format */
1031     m_codechalSettings->intelEntrypointInUse = true;
1032 
1033     m_ddiDecodeCtx->DecodeParams.m_picParams = MOS_AllocAndZeroMemory(sizeof(CODEC_VC1_PIC_PARAMS));
1034     if (m_ddiDecodeCtx->DecodeParams.m_picParams == nullptr)
1035     {
1036         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
1037         goto CleanUpandReturn;
1038     }
1039 
1040     m_sliceParamBufNum         = m_picHeightInMB;
1041     m_ddiDecodeCtx->DecodeParams.m_sliceParams = MOS_AllocAndZeroMemory(m_sliceParamBufNum * sizeof(CODEC_VC1_SLICE_PARAMS));
1042     if (m_ddiDecodeCtx->DecodeParams.m_sliceParams == nullptr)
1043     {
1044         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
1045         goto CleanUpandReturn;
1046     }
1047 
1048     vaStatus = CreateCodecHal(mediaCtx,
1049         ptr,
1050         &standardInfo);
1051 
1052     if (vaStatus != VA_STATUS_SUCCESS)
1053     {
1054         goto CleanUpandReturn;
1055     }
1056 
1057     if (InitResourceBuffer(mediaCtx) != VA_STATUS_SUCCESS)
1058     {
1059         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
1060         goto CleanUpandReturn;
1061     }
1062 
1063     return vaStatus;
1064 
1065 CleanUpandReturn:
1066     FreeResourceBuffer();
1067 
1068     if (m_ddiDecodeCtx->pCodecHal)
1069     {
1070         m_ddiDecodeCtx->pCodecHal->Destroy();
1071         MOS_Delete(m_ddiDecodeCtx->pCodecHal);
1072         m_ddiDecodeCtx->pCodecHal = nullptr;
1073     }
1074 
1075     MOS_FreeMemory(m_ddiDecodeCtx->DecodeParams.m_picParams);
1076     m_ddiDecodeCtx->DecodeParams.m_picParams = nullptr;
1077     MOS_FreeMemory(m_ddiDecodeCtx->DecodeParams.m_sliceParams);
1078     m_ddiDecodeCtx->DecodeParams.m_sliceParams = nullptr;
1079 
1080     return vaStatus;
1081 }
1082 
1083 extern template class MediaDdiFactory<DdiMediaDecode, DDI_DECODE_CONFIG_ATTR>;
1084 
1085 static bool vc1Registered =
1086     MediaDdiFactory<DdiMediaDecode, DDI_DECODE_CONFIG_ATTR>::RegisterCodec<DdiDecodeVC1>(DECODE_ID_VC1);
1087