xref: /aosp_15_r20/external/intel-media-driver/media_driver/linux/common/codec/ddi/media_ddi_encode_avc.cpp (revision ba62d9d3abf0e404f2022b4cd7a85e107f48596f)
1 /*
2 * Copyright (c) 2017-2020, Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22 //!
23 //! \file     media_ddi_encode_avc.cpp
24 //! \brief    Implements class for DDI media avc encode
25 //!
26 
27 #include "media_libva.h"
28 #include "media_libva_encoder.h"
29 #include "media_libva_util.h"
30 #include "hwinfo_linux.h"
31 #include "media_ddi_encode_base.h"
32 #include "media_ddi_encode_avc.h"
33 #include "media_ddi_encode_const.h"
34 #include "media_ddi_factory.h"
35 #include "media_libva_caps.h"
36 
37 // refer to spec section E.2.2, bit rate and cbp buffer size are shifted left with several bits, k is 1024
38 static const uint16_t vuiKbps = 1024;
39 
40 static const uint8_t sliceTypeP = 0;
41 static const uint8_t sliceTypeB = 1;
42 static const uint8_t sliceTypeI = 2;
43 static const uint8_t maxPassesNum = 4;
44 
45 //Inter MB partition 16x16 can't be disabled.
46 static const uint8_t disMbPartMask      = 0x7E;
47 static const uint8_t subpelModeMask     = 0x3;
48 static const uint8_t subpelModeQuant    = 0x3;
49 static const uint8_t subpelModeReserved = 0x2;
50 static const uint8_t subpelModeHalf     = 0x1;
51 extern template class MediaDdiFactoryNoArg<DdiEncodeBase>;
52 static bool isEncodeAvcRegistered =
53     MediaDdiFactoryNoArg<DdiEncodeBase>::RegisterCodec<DdiEncodeAvc>(ENCODE_ID_AVC);
54 
~DdiEncodeAvc()55 DdiEncodeAvc::~DdiEncodeAvc()
56 {
57     if (nullptr == m_encodeCtx)
58     {
59         return;
60     }
61     MOS_FreeMemory(m_encodeCtx->pSeqParams);
62     m_encodeCtx->pSeqParams = nullptr;
63 
64     MOS_FreeMemory(m_encodeCtx->pPicParams);
65     m_encodeCtx->pPicParams = nullptr;
66 
67     if (nullptr != m_encodeCtx->ppNALUnitParams)
68     {
69         // Allocate one contiguous memory for the NALUnitParams buffers
70         // only need to free one time
71         MOS_FreeMemory(m_encodeCtx->ppNALUnitParams[0]);
72         m_encodeCtx->ppNALUnitParams[0] = nullptr;
73 
74         MOS_FreeMemory(m_encodeCtx->ppNALUnitParams);
75         m_encodeCtx->ppNALUnitParams = nullptr;
76     }
77 
78     MOS_FreeMemory(m_encodeCtx->pVuiParams);
79     m_encodeCtx->pVuiParams = nullptr;
80 
81     MOS_FreeMemory(m_encodeCtx->pSliceParams);
82     m_encodeCtx->pSliceParams = nullptr;
83 
84     MOS_FreeMemory(m_encodeCtx->pEncodeStatusReport);
85     m_encodeCtx->pEncodeStatusReport = nullptr;
86 
87     if (m_encodeCtx->pSEIFromApp)
88     {
89         MOS_FreeMemory(m_encodeCtx->pSEIFromApp->pSEIBuffer);
90         m_encodeCtx->pSEIFromApp->pSEIBuffer = nullptr;
91 
92         MOS_FreeMemory(m_encodeCtx->pSEIFromApp);
93         m_encodeCtx->pSEIFromApp = nullptr;
94     }
95 
96     MOS_FreeMemory(m_encodeCtx->pSliceHeaderData);
97     m_encodeCtx->pSliceHeaderData = nullptr;
98 
99     if (m_encodeCtx->pbsBuffer)
100     {
101         MOS_FreeMemory(m_encodeCtx->pbsBuffer->pBase);
102         m_encodeCtx->pbsBuffer->pBase = nullptr;
103 
104         MOS_FreeMemory(m_encodeCtx->pbsBuffer);
105         m_encodeCtx->pbsBuffer = nullptr;
106     }
107 
108     MOS_FreeMemory(m_qcParams);
109     m_qcParams = nullptr;
110 
111     MOS_FreeMemory(m_roundingParams);
112     m_roundingParams = nullptr;
113 
114     MOS_FreeMemory(iqMatrixParams);
115     iqMatrixParams = nullptr;
116 
117     MOS_FreeMemory(iqWeightScaleLists);
118     iqWeightScaleLists = nullptr;
119 }
120 
ConvertSliceStruct(uint32_t vaSliceStruct)121 uint8_t DdiEncodeAvc::ConvertSliceStruct(uint32_t vaSliceStruct)
122 {
123     switch (vaSliceStruct)
124     {
125     case VA_ENC_SLICE_STRUCTURE_ARBITRARY_ROWS:
126         return CODECHAL_SLICE_STRUCT_ARBITRARYROWSLICE;
127     case VA_ENC_SLICE_STRUCTURE_POWER_OF_TWO_ROWS:
128         return CODECHAL_SLICE_STRUCT_POW2ROWS;
129     case VA_ENC_SLICE_STRUCTURE_ARBITRARY_MACROBLOCKS:
130         return CODECHAL_SLICE_STRUCT_ARBITRARYMBSLICE;
131     case VA_ENC_SLICE_STRUCTURE_EQUAL_MULTI_ROWS:
132     case VA_ENC_SLICE_STRUCTURE_EQUAL_ROWS:
133         return CODECHAL_SLICE_STRUCT_ROWSLICE;
134     default:
135         return CODECHAL_SLICE_STRUCT_ONESLICE;
136     }
137 }
138 
GetAVCProfileFromVAProfile()139 CODEC_AVC_PROFILE_IDC DdiEncodeAvc::GetAVCProfileFromVAProfile()
140 {
141     switch (m_encodeCtx->vaProfile)
142     {
143     case VAProfileH264ConstrainedBaseline:
144         return CODEC_AVC_BASE_PROFILE;
145     case VAProfileH264Main:
146         return CODEC_AVC_MAIN_PROFILE;
147     case VAProfileH264High:
148         return CODEC_AVC_HIGH_PROFILE;
149     default:
150         return CODEC_AVC_MAIN_PROFILE;
151     }
152 }
153 
CodechalPicTypeFromVaSlcType(uint8_t vaSliceType)154 uint8_t DdiEncodeAvc::CodechalPicTypeFromVaSlcType(uint8_t vaSliceType)
155 {
156     switch (vaSliceType)
157     {
158     case sliceTypeI:
159     case (sliceTypeI + 5):
160         return I_TYPE;
161     case sliceTypeP:
162     case (sliceTypeP + 5):
163         return P_TYPE;
164     case sliceTypeB:
165     case (sliceTypeB + 5):
166         return B_TYPE;
167     default:
168         return 0;
169     }
170 }
171 
ParseMiscParamHRD(void * data)172 VAStatus DdiEncodeAvc::ParseMiscParamHRD(void *data)
173 {
174     DDI_CHK_NULL(data, "nullptr data", VA_STATUS_ERROR_INVALID_PARAMETER);
175 
176     VAEncMiscParameterHRD          *vaEncMiscParamHRD = (VAEncMiscParameterHRD *)data;
177     CODECHAL_ENCODE_AVC_VUI_PARAMS *vuiParam          = (CODECHAL_ENCODE_AVC_VUI_PARAMS *)m_encodeCtx->pVuiParams;
178     // Assume only one SPS here, modify when enable multiple SPS support
179     PCODEC_AVC_ENCODE_SEQUENCE_PARAMS seqParams = (PCODEC_AVC_ENCODE_SEQUENCE_PARAMS)(m_encodeCtx->pSeqParams);
180     DDI_CHK_NULL(vuiParam, "nullptr vuiParam", VA_STATUS_ERROR_INVALID_PARAMETER);
181     DDI_CHK_NULL(seqParams, "nullptr seqParams", VA_STATUS_ERROR_INVALID_PARAMETER);
182 
183     vuiParam->cbr_flag                    = 0x1;
184     seqParams->VBVBufferSizeInBit         = vaEncMiscParamHRD->buffer_size;
185     seqParams->InitVBVBufferFullnessInBit = vaEncMiscParamHRD->initial_buffer_fullness;
186     vuiParam->cpb_size_value_minus1[0]    = MOS_ROUNDUP_DIVIDE(seqParams->VBVBufferSizeInBit, vuiKbps) - 1;
187 
188     return VA_STATUS_SUCCESS;
189 }
190 
ParseMiscParamFR(void * data)191 VAStatus DdiEncodeAvc::ParseMiscParamFR(void *data)
192 {
193     DDI_CHK_NULL(data, "nullptr data", VA_STATUS_ERROR_INVALID_PARAMETER);
194 
195     // Assume only one SPS here, modify when enable multiple SPS support
196     PCODEC_AVC_ENCODE_SEQUENCE_PARAMS seqParams      = (PCODEC_AVC_ENCODE_SEQUENCE_PARAMS)(m_encodeCtx->pSeqParams);
197     VAEncMiscParameterFrameRate      *encMiscParamFR = (VAEncMiscParameterFrameRate *)data;
198     DDI_CHK_NULL(seqParams, "nullptr seqParams", VA_STATUS_ERROR_INVALID_PARAMETER);
199 
200     uint32_t numerator = (encMiscParamFR->framerate & 0xffff) * 100; /** 100*/;
201     auto denominator = (encMiscParamFR->framerate >> 16)&0xfff;
202     if(denominator == 0)
203     {
204        denominator = 1;
205     }
206 
207     // Pass frame rate value to seqParams and set BRC reset flag and bNewSeq to true while dynamic BRC occures
208     seqParams->FramesPer100Sec = (uint16_t)(numerator / denominator);
209     if(m_previousFRper100sec != 0)
210     {
211         if(m_previousFRper100sec != seqParams->FramesPer100Sec)
212         {
213             seqParams->bResetBRC = 0x1;
214             m_encodeCtx->bNewSeq = true;
215         }
216     }
217     m_previousFRper100sec = seqParams->FramesPer100Sec;
218 
219     return VA_STATUS_SUCCESS;
220 }
221 
ParseMiscParamRC(void * data)222 VAStatus DdiEncodeAvc::ParseMiscParamRC(void *data)
223 {
224     DDI_CHK_NULL(data, "nullptr data", VA_STATUS_ERROR_INVALID_PARAMETER);
225 
226     CODECHAL_ENCODE_AVC_VUI_PARAMS *vuiParam = (CODECHAL_ENCODE_AVC_VUI_PARAMS *)m_encodeCtx->pVuiParams;
227 
228     // Assume only one SPS here, modify when enable multiple SPS support
229     PCODEC_AVC_ENCODE_SEQUENCE_PARAMS seqParams      = (PCODEC_AVC_ENCODE_SEQUENCE_PARAMS)(m_encodeCtx->pSeqParams) + current_seq_parameter_set_id;
230     PCODEC_AVC_ENCODE_PIC_PARAMS      picParams      = (PCODEC_AVC_ENCODE_PIC_PARAMS)(m_encodeCtx->pPicParams) + current_pic_parameter_set_id;
231     VAEncMiscParameterRateControl    *encMiscParamRC = (VAEncMiscParameterRateControl *)data;
232     DDI_CHK_NULL(vuiParam, "nullptr vuiParam", VA_STATUS_ERROR_INVALID_PARAMETER);
233     DDI_CHK_NULL(seqParams, "nullptr seqParams", VA_STATUS_ERROR_INVALID_PARAMETER);
234     DDI_CHK_NULL(picParams, "nullptr picParams", VA_STATUS_ERROR_INVALID_PARAMETER);
235 
236     seqParams->TargetBitRate           = encMiscParamRC->bits_per_second;
237     vuiParam->bit_rate_value_minus1[0] = MOS_ROUNDUP_SHIFT(encMiscParamRC->bits_per_second, 6 + vuiParam->bit_rate_scale) - 1;
238 
239     // Assuming picParams are sent before MiscParams
240     picParams->ucMinimumQP = encMiscParamRC->min_qp;
241     picParams->ucMaximumQP = encMiscParamRC->max_qp;
242     if (picParams->ucMaximumQP == 0 && picParams->ucMinimumQP)
243         picParams->ucMaximumQP = 51;
244 
245     if ((VA_RC_CBR == m_encodeCtx->uiRCMethod) || ((VA_RC_CBR | VA_RC_MB) == m_encodeCtx->uiRCMethod))
246     {
247         seqParams->MaxBitRate = seqParams->TargetBitRate;
248         seqParams->MinBitRate = seqParams->TargetBitRate;
249         vuiParam->cbr_flag    = 0x1;
250         if (m_encodeCtx->uiTargetBitRate != seqParams->TargetBitRate)
251         {
252             if (m_encodeCtx->uiTargetBitRate)
253             {
254                 seqParams->bResetBRC = 0x1;
255                 m_encodeCtx->bNewSeq = true;
256             }
257             m_encodeCtx->uiTargetBitRate = seqParams->TargetBitRate;
258             m_encodeCtx->uiMaxBitRate    = seqParams->TargetBitRate;
259         }
260     }
261     else if (VA_RC_ICQ == m_encodeCtx->uiRCMethod)
262     {
263         seqParams->ICQQualityFactor = encMiscParamRC->ICQ_quality_factor;
264     }
265     else if (VA_RC_AVBR == m_encodeCtx->uiRCMethod)
266     {
267         seqParams->AVBRAccuracy = encMiscParamRC->target_percentage;
268         seqParams->AVBRConvergence = encMiscParamRC->window_size;
269     }
270     else
271     {
272         seqParams->MaxBitRate    = seqParams->TargetBitRate;
273         seqParams->TargetBitRate = (uint32_t)((uint64_t)seqParams->TargetBitRate * encMiscParamRC->target_percentage / 100);
274         seqParams->MinBitRate    = seqParams->TargetBitRate;
275         vuiParam->cbr_flag       = 0x0;
276 
277         if (VA_RC_QVBR == m_encodeCtx->uiRCMethod)
278         {
279             seqParams->ICQQualityFactor = encMiscParamRC->quality_factor;
280         }
281 
282         if ((m_encodeCtx->uiTargetBitRate != seqParams->TargetBitRate) ||
283             (m_encodeCtx->uiMaxBitRate != seqParams->MaxBitRate))
284         {
285             if ((m_encodeCtx->uiTargetBitRate != 0) && (m_encodeCtx->uiMaxBitRate != 0))
286             {
287                 seqParams->bResetBRC = 0x1;
288                 m_encodeCtx->bNewSeq = true;
289             }
290             m_encodeCtx->uiTargetBitRate = seqParams->TargetBitRate;
291             m_encodeCtx->uiMaxBitRate    = seqParams->MaxBitRate;
292         }
293     }
294     //if RateControl method is VBR/CBR and VA_RC_MB bit is set, we can set MBBRC to enable or disable
295     if (VA_RC_CQP != m_encodeCtx->uiRCMethod && (VA_RC_MB & m_encodeCtx->uiRCMethod) && encMiscParamRC->rc_flags.bits.mb_rate_control <= mbBrcDisabled)
296     {
297         seqParams->MBBRC = encMiscParamRC->rc_flags.bits.mb_rate_control;
298     }
299     else
300     {
301         seqParams->MBBRC = mbBrcDisabled;
302     }
303 
304 #ifndef ANDROID
305     seqParams->FrameSizeTolerance = static_cast<ENCODE_FRAMESIZE_TOLERANCE>(encMiscParamRC->rc_flags.bits.frame_tolerance_mode);
306 #endif
307 
308 #if VA_CHECK_VERSION(1, 10, 0)
309     if (m_encodeCtx->bVdencActive &&
310         (m_encodeCtx->uiRCMethod & (VA_RC_VBR | VA_RC_QVBR | VA_RC_VCM)))
311     {
312         picParams->TargetFrameSize = encMiscParamRC->target_frame_size;
313         // to force VC scenario for TCBRC
314         seqParams->bAutoMaxPBFrameSizeForSceneChange = encMiscParamRC->target_frame_size != 0;
315     }
316 #endif
317 
318     return VA_STATUS_SUCCESS;
319 }
320 
ParseMiscParamSkipFrame(void * data)321 VAStatus DdiEncodeAvc::ParseMiscParamSkipFrame(void *data)
322 {
323     DDI_CHK_NULL(data, "nullptr data", VA_STATUS_ERROR_INVALID_PARAMETER);
324 
325     // Assume only one PPS here, modify when enable multiple PPS support
326     PCODEC_AVC_ENCODE_PIC_PARAMS picParams               = (PCODEC_AVC_ENCODE_PIC_PARAMS)(m_encodeCtx->pPicParams) + current_pic_parameter_set_id;
327     VAEncMiscParameterSkipFrame *vaEncMiscParamSkipFrame = (VAEncMiscParameterSkipFrame *)data;
328     DDI_CHK_NULL(picParams, "nullptr picParams", VA_STATUS_ERROR_INVALID_PARAMETER);
329 
330     // populate skipped frame params from DDI
331     picParams->SkipFrameFlag  = vaEncMiscParamSkipFrame->skip_frame_flag;
332     picParams->NumSkipFrames  = vaEncMiscParamSkipFrame->num_skip_frames;
333     picParams->SizeSkipFrames = vaEncMiscParamSkipFrame->size_skip_frames;
334 
335     if (FRAME_SKIP_NORMAL < picParams->SkipFrameFlag)
336     {
337         return VA_STATUS_ERROR_INVALID_PARAMETER;
338     }
339 
340     return VA_STATUS_SUCCESS;
341 }
342 
ParseMiscParamMaxFrameSize(void * data)343 VAStatus DdiEncodeAvc::ParseMiscParamMaxFrameSize(void *data)
344 {
345     DDI_CHK_NULL(data, "nullptr data", VA_STATUS_ERROR_INVALID_PARAMETER);
346 
347     // Assume only one SPS here, modify when enable multiple SPS support
348     PCODEC_AVC_ENCODE_SEQUENCE_PARAMS     seqParams                  = (PCODEC_AVC_ENCODE_SEQUENCE_PARAMS)(m_encodeCtx->pSeqParams);
349     VAEncMiscParameterBufferMaxFrameSize *vaEncMiscParamMaxFrameSize = (VAEncMiscParameterBufferMaxFrameSize *)data;
350     DDI_CHK_NULL(seqParams, "nullptr seqParams", VA_STATUS_ERROR_INVALID_PARAMETER);
351 
352     if (seqParams->UserMaxFrameSize != vaEncMiscParamMaxFrameSize->max_frame_size >> 3)
353     {
354         seqParams->bResetBRC = 0x1;
355     }
356 
357     // populate MaxFrameSize from DDI
358     seqParams->UserMaxFrameSize = vaEncMiscParamMaxFrameSize->max_frame_size >> 3;  // convert to byte
359 
360     return VA_STATUS_SUCCESS;
361 }
362 
ParseMiscParamMultiPassFrameSize(void * data)363 VAStatus DdiEncodeAvc::ParseMiscParamMultiPassFrameSize(void *data)
364 {
365     DDI_CHK_NULL(data, "nullptr data", VA_STATUS_ERROR_INVALID_PARAMETER);
366 
367     PCODEC_AVC_ENCODE_PIC_PARAMS picParams = (PCODEC_AVC_ENCODE_PIC_PARAMS)(m_encodeCtx->pPicParams) + current_pic_parameter_set_id;
368     VAEncMiscParameterBufferMultiPassFrameSize *vaEncMiscParamMultiPassFrameSize = (VAEncMiscParameterBufferMultiPassFrameSize *)data;
369     DDI_CHK_NULL(picParams, "nullptr picParams", VA_STATUS_ERROR_INVALID_PARAMETER);
370 
371     //add for multiple pass pak
372     picParams->dwMaxFrameSize = vaEncMiscParamMultiPassFrameSize->max_frame_size;
373     if (picParams->dwMaxFrameSize)
374     {
375         picParams->dwNumPasses = vaEncMiscParamMultiPassFrameSize->num_passes;
376         if ((picParams->dwNumPasses == 0) || (picParams->dwNumPasses > maxPassesNum))
377         {
378             return VA_STATUS_ERROR_INVALID_PARAMETER;
379         }
380         if (picParams->pDeltaQp != nullptr)
381         {
382             MOS_FreeMemory(picParams->pDeltaQp);
383         }
384         picParams->pDeltaQp = (uint8_t *)MOS_AllocAndZeroMemory(sizeof(uint8_t) * picParams->dwNumPasses);
385         if (!picParams->pDeltaQp)
386         {
387             return VA_STATUS_ERROR_INVALID_PARAMETER;
388         }
389 
390         if (MOS_STATUS_SUCCESS != MOS_SecureMemcpy(picParams->pDeltaQp, picParams->dwNumPasses, vaEncMiscParamMultiPassFrameSize->delta_qp, picParams->dwNumPasses))
391         {
392             return VA_STATUS_ERROR_INVALID_PARAMETER;
393         }
394     }
395 
396     return VA_STATUS_SUCCESS;
397 }
398 
ParseMiscParamEncQuality(void * data)399 VAStatus DdiEncodeAvc::ParseMiscParamEncQuality(void *data)
400 {
401     DDI_CHK_NULL(data, "nullptr data", VA_STATUS_ERROR_INVALID_PARAMETER);
402 
403     // Assume only one SPS here, modify when enable multiple SPS support
404     PCODEC_AVC_ENCODE_SEQUENCE_PARAMS seqParams                = (PCODEC_AVC_ENCODE_SEQUENCE_PARAMS)(m_encodeCtx->pSeqParams) + current_seq_parameter_set_id;
405 
406     VAEncMiscParameterEncQuality     *vaEncMiscParamEncQuality = (VAEncMiscParameterEncQuality *)data;
407     PCODEC_AVC_ENCODE_PIC_PARAMS      picParams                = (PCODEC_AVC_ENCODE_PIC_PARAMS)(m_encodeCtx->pPicParams) + current_pic_parameter_set_id;
408 
409     DDI_CHK_NULL(seqParams, "nullptr seqParams", VA_STATUS_ERROR_INVALID_PARAMETER);
410 
411     seqParams->bForcePanicModeControl = 0;
412     seqParams->bPanicModeDisable = (uint8_t)vaEncMiscParamEncQuality->PanicModeDisable;
413     picParams->UserFlags.bUseRawPicForRef = vaEncMiscParamEncQuality->useRawPicForRef;
414     m_qcParams->skipCheckDisable            = vaEncMiscParamEncQuality->skipCheckDisable;
415     m_qcParams->FTQOverride                 = vaEncMiscParamEncQuality->FTQOverride;
416     if (m_qcParams->FTQOverride)
417     {
418         m_qcParams->FTQEnable = vaEncMiscParamEncQuality->FTQEnable;
419     }
420     m_qcParams->FTQSkipThresholdLUTInput = vaEncMiscParamEncQuality->FTQSkipThresholdLUTInput;
421     if (m_qcParams->FTQSkipThresholdLUTInput)
422     {
423         MOS_SecureMemcpy(m_qcParams->FTQSkipThresholdLUT, 52, vaEncMiscParamEncQuality->FTQSkipThresholdLUT, 52);
424     }
425     m_qcParams->NonFTQSkipThresholdLUTInput = vaEncMiscParamEncQuality->NonFTQSkipThresholdLUTInput;
426     if (m_qcParams->NonFTQSkipThresholdLUTInput)
427     {
428         MOS_SecureMemcpy(m_qcParams->NonFTQSkipThresholdLUT, 52, vaEncMiscParamEncQuality->NonFTQSkipThresholdLUT, 52);
429     }
430 
431     m_qcParams->directBiasAdjustmentEnable       = vaEncMiscParamEncQuality->directBiasAdjustmentEnable;
432     m_qcParams->globalMotionBiasAdjustmentEnable = vaEncMiscParamEncQuality->globalMotionBiasAdjustmentEnable;
433     m_qcParams->HMEMVCostScalingFactor           = vaEncMiscParamEncQuality->HMEMVCostScalingFactor;
434     //disable HME
435     m_qcParams->HMEDisable = vaEncMiscParamEncQuality->HMEDisable;
436     //disable Super HME
437     m_qcParams->SuperHMEDisable = vaEncMiscParamEncQuality->SuperHMEDisable;
438     //disable Ultra HME
439     m_qcParams->UltraHMEDisable = vaEncMiscParamEncQuality->UltraHMEDisable;
440 
441     // Force RepartitionCheck
442     m_qcParams->ForceRepartitionCheck = vaEncMiscParamEncQuality->ForceRepartitionCheck;
443 
444     return VA_STATUS_SUCCESS;
445 }
446 
ParseMiscParamQuantization(void * data)447 VAStatus DdiEncodeAvc::ParseMiscParamQuantization(void *data)
448 {
449     DDI_CHK_NULL(data, "nullptr data", VA_STATUS_ERROR_INVALID_PARAMETER);
450 
451     PCODEC_AVC_ENCODE_SEQUENCE_PARAMS seqParams                  = (PCODEC_AVC_ENCODE_SEQUENCE_PARAMS)(m_encodeCtx->pSeqParams);
452     VAEncMiscParameterQuantization   *vaEncMiscParamQuantization = (VAEncMiscParameterQuantization *)data;
453     DDI_CHK_NULL(seqParams, "nullptr seqParams", VA_STATUS_ERROR_INVALID_PARAMETER);
454 
455     seqParams->Trellis = trellisInternal;
456 
457     if (vaEncMiscParamQuantization->quantization_flags.bits.disable_trellis)
458     {
459         seqParams->Trellis = trellisDisabled;
460     }
461     else
462     {
463         if (vaEncMiscParamQuantization->quantization_flags.bits.enable_trellis_I)
464         {
465             seqParams->Trellis |= trellisEnabledI;
466         }
467         if (vaEncMiscParamQuantization->quantization_flags.bits.enable_trellis_P)
468         {
469             seqParams->Trellis |= trellisEnabledP;
470         }
471         if (vaEncMiscParamQuantization->quantization_flags.bits.enable_trellis_B)
472         {
473             seqParams->Trellis |= trellisEnabledB;
474         }
475         if (!seqParams->Trellis)
476         {
477             DDI_ASSERTMESSAGE("trellis enabled, but the input parameters is invalided");
478         }
479     }
480 
481     return VA_STATUS_SUCCESS;
482 }
483 
ParseMiscParameterRIR(void * data)484 VAStatus DdiEncodeAvc::ParseMiscParameterRIR(void *data)
485 {
486     DDI_CHK_NULL(data, "nullptr data", VA_STATUS_ERROR_INVALID_PARAMETER);
487 
488     PCODEC_AVC_ENCODE_PIC_PARAMS      picParams         = (PCODEC_AVC_ENCODE_PIC_PARAMS)(m_encodeCtx->pPicParams) + current_pic_parameter_set_id;
489     PCODEC_AVC_ENCODE_SEQUENCE_PARAMS seqParams         = (PCODEC_AVC_ENCODE_SEQUENCE_PARAMS)(m_encodeCtx->pSeqParams) + current_seq_parameter_set_id;
490     VAEncMiscParameterRIR            *vaEncMiscParamRIR = (VAEncMiscParameterRIR *)data;
491     DDI_CHK_NULL(picParams, "nullptr picParams", VA_STATUS_ERROR_INVALID_PARAMETER);
492     DDI_CHK_NULL(seqParams, "nullptr seqParams", VA_STATUS_ERROR_INVALID_PARAMETER);
493 
494     picParams->EnableRollingIntraRefresh = vaEncMiscParamRIR->rir_flags.value & 0x3;  //only lower two bits are valid
495 
496 #ifdef Android
497     //Convert row based rolling I to suqare region based rolling I before MSDK is ready to support square region based rolling I
498     if (ROLLING_I_ROW == picParams->EnableRollingIntraRefresh)
499     {
500         if (GFX_IS_PRODUCT(m_encodeCtx->pMediaCtx->platform, IGFX_BROADWELL))
501         {
502             picParams->EnableRollingIntraRefresh = ROLLING_I_SQUARE;
503         }
504         vaEncMiscParamRIR->intra_insert_size *= (seqParams->FrameWidth / CODECHAL_ENCODE_AVC_ROI_WIDTH_SCALE_FACTOR);
505         // From the experiment result, -6 could be the proper setting
506         vaEncMiscParamRIR->qp_delta_for_inserted_intra = -6;
507     }
508 #endif
509     // Set for all frames since pic type is not known yet. Disable in slice params if its I or B type.
510     switch (picParams->EnableRollingIntraRefresh)
511     {
512     case ROLLING_I_COLUMN:
513         picParams->IntraRefreshMBx      = (uint8_t)vaEncMiscParamRIR->intra_insertion_location;
514         picParams->IntraRefreshMBNum    = (uint8_t)vaEncMiscParamRIR->intra_insertion_location;
515         picParams->IntraRefreshUnitinMB = (uint8_t)vaEncMiscParamRIR->intra_insert_size;
516         break;
517     case ROLLING_I_ROW:
518         picParams->IntraRefreshMBy      = (uint8_t)vaEncMiscParamRIR->intra_insertion_location;
519         picParams->IntraRefreshMBNum    = (uint8_t)vaEncMiscParamRIR->intra_insertion_location;
520         picParams->IntraRefreshUnitinMB = (uint8_t)vaEncMiscParamRIR->intra_insert_size;
521         break;
522     case ROLLING_I_SQUARE:
523         picParams->IntraRefreshUnitinMB = (uint8_t)GFX_UF_ROUND(sqrt((double)vaEncMiscParamRIR->intra_insert_size));
524         break;
525     case ROLLING_I_DISABLED:
526         break;
527     default:
528         return MOS_STATUS_INVALID_PARAMETER;
529     }
530     picParams->IntraRefreshQPDelta = vaEncMiscParamRIR->qp_delta_for_inserted_intra;
531 
532     // UMD tracks the MBx/MBy for the intra square
533     uint32_t rightBorder  = ((seqParams->FrameWidth + CODECHAL_ENCODE_AVC_ROI_WIDTH_SCALE_FACTOR - 1) / CODECHAL_ENCODE_AVC_ROI_WIDTH_SCALE_FACTOR) - 1;
534     uint32_t bottomBorder = ((seqParams->FrameHeight + CODECHAL_ENCODE_AVC_ROI_FRAME_HEIGHT_SCALE_FACTOR - 1) / CODECHAL_ENCODE_AVC_ROI_FRAME_HEIGHT_SCALE_FACTOR) - 1;
535     if ((ROLLING_I_SQUARE == picParams->EnableRollingIntraRefresh))
536     {
537         if (m_encodeCtx->uiIntraRefreshFrameCnt == 0)
538         {
539             m_encodeCtx->uiIntraRefreshFrameCnt = 1;
540             m_encodeCtx->uiIntraRefreshMBx      = 0;
541             m_encodeCtx->uiIntraRefreshMBy      = 0;
542         }
543         else
544         {
545             m_encodeCtx->uiIntraRefreshMBx += picParams->IntraRefreshUnitinMB;
546             if (m_encodeCtx->uiIntraRefreshMBx >= rightBorder)
547             {
548                 m_encodeCtx->uiIntraRefreshMBx = 0;
549                 m_encodeCtx->uiIntraRefreshMBy += picParams->IntraRefreshUnitinMB;
550                 if (m_encodeCtx->uiIntraRefreshMBy >= bottomBorder)
551                 {
552                     m_encodeCtx->uiIntraRefreshMBx = 0;
553                     m_encodeCtx->uiIntraRefreshMBy = 0;
554                 }
555             }
556         }
557         // set MBx/MBy to CODECHAL
558         picParams->IntraRefreshMBx = m_encodeCtx->uiIntraRefreshMBx;
559         picParams->IntraRefreshMBy = m_encodeCtx->uiIntraRefreshMBy;
560     }
561 
562     return VA_STATUS_SUCCESS;
563 }
564 
ParseMiscParamQualityLevel(void * data)565 VAStatus DdiEncodeAvc::ParseMiscParamQualityLevel(void *data)
566 {
567     // Assume only one SPS here, modify when enable multiple SPS support
568     VAEncMiscParameterBufferQualityLevel *vaEncMiscParamQualityLevel = (VAEncMiscParameterBufferQualityLevel *)data;
569 
570     m_encodeCtx->targetUsage = (uint8_t)vaEncMiscParamQualityLevel->quality_level;
571 
572     // check if TU setting is valid, otherwise change to default
573     if ((m_encodeCtx->targetUsage > TARGETUSAGE_BEST_SPEED) || (0 == m_encodeCtx->targetUsage))
574     {
575         m_encodeCtx->targetUsage = TARGETUSAGE_RT_SPEED;
576         DDI_ASSERTMESSAGE("Quality Level setting from application is not correct, should be in (0,%d].", TARGETUSAGE_BEST_SPEED);
577     }
578 
579 #ifdef _FULL_OPEN_SOURCE
580     if (!GFX_IS_PRODUCT(m_encodeCtx->pMediaCtx->platform, IGFX_ICELAKE_LP) && m_encodeCtx->targetUsage <= 3)
581     {
582         m_encodeCtx->targetUsage = 4;
583     }
584 #endif
585 
586     return VA_STATUS_SUCCESS;
587 }
588 
ParseMiscParamDirtyROI(void * data)589 VAStatus DdiEncodeAvc::ParseMiscParamDirtyROI(void *data)
590 {
591     PCODEC_AVC_ENCODE_PIC_PARAMS      picParams = (PCODEC_AVC_ENCODE_PIC_PARAMS)(m_encodeCtx->pPicParams) + current_pic_parameter_set_id;
592     PCODEC_AVC_ENCODE_SEQUENCE_PARAMS seqParams = (PCODEC_AVC_ENCODE_SEQUENCE_PARAMS)(m_encodeCtx->pSeqParams) + current_seq_parameter_set_id;
593     VAEncMiscParameterBufferDirtyRect *dirtyRect = (VAEncMiscParameterBufferDirtyRect *)data;
594     DDI_CHK_NULL(picParams, "nullptr picParams", VA_STATUS_ERROR_INVALID_PARAMETER);
595     DDI_CHK_NULL(seqParams, "nullptr seqParams", VA_STATUS_ERROR_INVALID_PARAMETER);
596     DDI_CHK_NULL(dirtyRect, "nullptr dirtyRect", VA_STATUS_ERROR_INVALID_PARAMETER);
597     DDI_CHK_NULL(dirtyRect->roi_rectangle, "nullptr dirtyRect->roi_rectangle", VA_STATUS_ERROR_INVALID_PARAMETER);
598 
599     if (dirtyRect->num_roi_rectangle > 0)
600     {
601         uint16_t mbHeightScaleFactor = picParams->FieldCodingFlag ? CODECHAL_ENCODE_AVC_ROI_FIELD_HEIGHT_SCALE_FACTOR : CODECHAL_ENCODE_AVC_ROI_FRAME_HEIGHT_SCALE_FACTOR;
602 
603         // Support upto 4 Dirty rectangles
604         int32_t maxDirtyRects = (dirtyRect->num_roi_rectangle > CODEC_AVC_NUM_MAX_DIRTY_RECT) ? CODEC_AVC_NUM_MAX_DIRTY_RECT : dirtyRect->num_roi_rectangle;
605 
606         picParams->NumDirtyROI = 0;
607 
608         MOS_ZeroMemory(picParams->DirtyROI, CODEC_AVC_NUM_MAX_DIRTY_RECT * sizeof(CODEC_ROI));
609 
610         PCODEC_ROI roi;
611         for (int32_t i = 0; i < maxDirtyRects; i++)
612         {
613             if (nullptr != dirtyRect->roi_rectangle)
614             {
615                 roi         = &picParams->DirtyROI[picParams->NumDirtyROI];
616                 roi->Left   = MOS_MIN(MOS_MAX(dirtyRect->roi_rectangle->x, 0), seqParams->FrameWidth - 1);
617                 roi->Top    = MOS_MIN(MOS_MAX(dirtyRect->roi_rectangle->y, 0), seqParams->FrameHeight - 1);
618                 roi->Right  = MOS_MIN(dirtyRect->roi_rectangle->x + dirtyRect->roi_rectangle->width, seqParams->FrameWidth - 1);
619                 roi->Bottom = MOS_MIN(dirtyRect->roi_rectangle->y + dirtyRect->roi_rectangle->height, seqParams->FrameHeight - 1);
620 
621                 // Check and adjust if ROI not within frame boundaries
622                 roi->Left   = MOS_MIN(roi->Left, seqParams->FrameWidth - 1);
623                 roi->Top    = MOS_MIN(roi->Top, seqParams->FrameHeight - 1);
624                 roi->Right  = MOS_MIN(roi->Right, seqParams->FrameWidth - 1);
625                 roi->Bottom = MOS_MIN(roi->Bottom, seqParams->FrameHeight - 1);
626 
627                 roi->Right  = MOS_ALIGN_CEIL(roi->Right, CODECHAL_ENCODE_AVC_ROI_WIDTH_SCALE_FACTOR);
628                 roi->Bottom = MOS_ALIGN_CEIL(roi->Bottom, mbHeightScaleFactor);
629 
630                 // Convert from pixel units to MB units
631                 roi->Left /= CODECHAL_ENCODE_AVC_ROI_WIDTH_SCALE_FACTOR;
632                 roi->Right /= CODECHAL_ENCODE_AVC_ROI_WIDTH_SCALE_FACTOR;
633                 roi->Top /= mbHeightScaleFactor;
634                 roi->Bottom /= mbHeightScaleFactor;
635 
636                 dirtyRect->roi_rectangle++;
637                 picParams->NumDirtyROI++;
638             }
639             else
640             {
641                 continue;
642             }
643         }
644     }
645 
646     return VA_STATUS_SUCCESS;
647 }
648 
ParseMiscParamROI(void * data)649 VAStatus DdiEncodeAvc::ParseMiscParamROI(void *data)
650 {
651     DDI_CHK_NULL(m_encodeCtx, "nullptr m_encodeCtx", VA_STATUS_ERROR_INVALID_PARAMETER);
652     DDI_CHK_NULL(data, "nullptr data", VA_STATUS_ERROR_INVALID_PARAMETER);
653 
654     PCODEC_AVC_ENCODE_PIC_PARAMS      picParams = (PCODEC_AVC_ENCODE_PIC_PARAMS)(m_encodeCtx->pPicParams) + current_pic_parameter_set_id;
655     PCODEC_AVC_ENCODE_SEQUENCE_PARAMS seqParams = (PCODEC_AVC_ENCODE_SEQUENCE_PARAMS)(m_encodeCtx->pSeqParams) + current_seq_parameter_set_id;
656     DDI_CHK_NULL(picParams, "nullptr picParams", VA_STATUS_ERROR_INVALID_PARAMETER);
657     DDI_CHK_NULL(seqParams, "nullptr seqParams", VA_STATUS_ERROR_INVALID_PARAMETER);
658 
659     VAEncMiscParameterBufferROI *vaEncMiscParamROI = (VAEncMiscParameterBufferROI *)data;
660     PCODEC_ROI                   roi               = &picParams->ROI[0];
661 
662     DDI_CHK_NULL(m_encodeCtx->pMediaCtx, "nullptr pMediaCtx", VA_STATUS_ERROR_INVALID_PARAMETER);
663     DDI_CHK_NULL(m_encodeCtx->pMediaCtx->m_caps, "nullptr m_caps", VA_STATUS_ERROR_INVALID_PARAMETER);
664 
665     uint32_t maxROIsupported = 0;
666     bool isROIValueInDeltaQP = false;
667     m_encodeCtx->pMediaCtx->m_caps->QueryAVCROIMaxNum(m_encodeCtx->uiRCMethod, m_encodeCtx->bVdencActive, &maxROIsupported, &isROIValueInDeltaQP);
668     if (maxROIsupported == 0)
669     {
670         return MOS_STATUS_INVALID_PARAMETER;
671     }
672 
673     seqParams->ROIValueInDeltaQP = (isROIValueInDeltaQP ? 1 : 0);
674 
675     picParams->NumROI     = MOS_MIN(vaEncMiscParamROI->num_roi, maxROIsupported);
676     picParams->MaxDeltaQp = vaEncMiscParamROI->max_delta_qp;
677     picParams->MinDeltaQp = vaEncMiscParamROI->min_delta_qp;
678 
679     uint8_t mbHeightScaleFactor = picParams->FieldCodingFlag ? CODECHAL_ENCODE_AVC_ROI_FIELD_HEIGHT_SCALE_FACTOR : CODECHAL_ENCODE_AVC_ROI_FRAME_HEIGHT_SCALE_FACTOR;
680 
681     // Process  information for all ROIs and pass to codecHAL
682     for (uint8_t i = 0; i < picParams->NumROI; i++)
683     {
684         DDI_CHK_NULL(vaEncMiscParamROI->roi, "nullptr vaEncMiscParamROI->roi", VA_STATUS_ERROR_INVALID_PARAMETER);
685         DDI_CHK_NULL(roi, "nullptr roi", VA_STATUS_ERROR_INVALID_PARAMETER);
686 
687         // Check and adjust if ROI not within frame boundaries
688         roi->Left   = MOS_MIN(MOS_MAX(vaEncMiscParamROI->roi->roi_rectangle.x, 0), seqParams->FrameWidth - 1);
689         roi->Top    = MOS_MIN(MOS_MAX(vaEncMiscParamROI->roi->roi_rectangle.y, 0), seqParams->FrameHeight - 1);
690         roi->Right  = MOS_MIN(roi->Left + vaEncMiscParamROI->roi->roi_rectangle.width, seqParams->FrameWidth - 1);
691         roi->Bottom = MOS_MIN(roi->Top + vaEncMiscParamROI->roi->roi_rectangle.height, seqParams->FrameHeight - 1);
692 
693         // Convert from pixel units to MB units
694         roi->Left /= CODECHAL_ENCODE_AVC_ROI_WIDTH_SCALE_FACTOR;
695         roi->Top /= mbHeightScaleFactor;
696         roi->Right  = (roi->Right + CODECHAL_ENCODE_AVC_ROI_WIDTH_SCALE_FACTOR - 1) / CODECHAL_ENCODE_AVC_ROI_WIDTH_SCALE_FACTOR;
697         roi->Bottom = (roi->Bottom + mbHeightScaleFactor - 1) / mbHeightScaleFactor;
698 
699         roi->PriorityLevelOrDQp = vaEncMiscParamROI->roi->roi_value;
700 
701         // Move to next ROI
702         vaEncMiscParamROI->roi++;
703         roi++;
704     }
705 #ifndef ANDROID
706     seqParams->ROIValueInDeltaQP = vaEncMiscParamROI->roi_flags.bits.roi_value_is_qp_delta;
707     if(picParams->NumROI != 0 && seqParams->ROIValueInDeltaQP == 0)
708     {
709         DDI_ASSERTMESSAGE("ROI does not support priority level now.");
710         return VA_STATUS_ERROR_INVALID_PARAMETER;
711     }
712 #endif
713     return VA_STATUS_SUCCESS;
714 }
715 
ParseMiscParamMaxSliceSize(void * data)716 VAStatus DdiEncodeAvc::ParseMiscParamMaxSliceSize(void *data)
717 {
718     DDI_CHK_NULL(m_encodeCtx, "nullptr m_encodeCtx", VA_STATUS_ERROR_INVALID_PARAMETER);
719     DDI_CHK_NULL(data, "nullptr data", VA_STATUS_ERROR_INVALID_PARAMETER);
720 
721     m_encodeCtx->EnableSliceLevelRateCtrl = true;
722 
723     PCODEC_AVC_ENCODE_PIC_PARAMS      picParams = (PCODEC_AVC_ENCODE_PIC_PARAMS)(m_encodeCtx->pPicParams) + current_pic_parameter_set_id;
724     PCODEC_AVC_ENCODE_SEQUENCE_PARAMS seqParams = (PCODEC_AVC_ENCODE_SEQUENCE_PARAMS)(m_encodeCtx->pSeqParams) + current_seq_parameter_set_id;
725     DDI_CHK_NULL(picParams, "nullptr picParams", VA_STATUS_ERROR_INVALID_PARAMETER);
726     DDI_CHK_NULL(seqParams, "nullptr seqParams", VA_STATUS_ERROR_INVALID_PARAMETER);
727 
728     seqParams->EnableSliceLevelRateCtrl                        = m_encodeCtx->EnableSliceLevelRateCtrl;
729     VAEncMiscParameterMaxSliceSize *vaEncMiscParamMaxSliceSize = (VAEncMiscParameterMaxSliceSize *)data;
730 
731     picParams->SliceSizeInBytes = vaEncMiscParamMaxSliceSize->max_slice_size;
732 
733     return VA_STATUS_SUCCESS;
734 }
735 
ParseMiscParamRounding(void * data)736 VAStatus DdiEncodeAvc::ParseMiscParamRounding(void *data)
737 {
738     DDI_CHK_NULL(m_encodeCtx, "nullptr m_encodeCtx", VA_STATUS_ERROR_INVALID_PARAMETER);
739     DDI_CHK_NULL(data, "nullptr data", VA_STATUS_ERROR_INVALID_PARAMETER);
740 
741     VAEncMiscParameterCustomRoundingControl *vaEncMiscParamRounding = (VAEncMiscParameterCustomRoundingControl *)data;
742 
743     if (vaEncMiscParamRounding->rounding_offset_setting.bits.enable_custom_rouding_intra)
744     {
745         m_roundingParams->bEnableCustomRoudingIntra = vaEncMiscParamRounding->rounding_offset_setting.bits.enable_custom_rouding_intra;
746         m_roundingParams->dwRoundingIntra           = vaEncMiscParamRounding->rounding_offset_setting.bits.rounding_offset_intra;
747     }
748     if (vaEncMiscParamRounding->rounding_offset_setting.bits.enable_custom_rounding_inter)
749     {
750         m_roundingParams->bEnableCustomRoudingInter = vaEncMiscParamRounding->rounding_offset_setting.bits.enable_custom_rounding_inter;
751         m_roundingParams->dwRoundingInter           = vaEncMiscParamRounding->rounding_offset_setting.bits.rounding_offset_inter;
752     }
753 
754     return VA_STATUS_SUCCESS;
755 }
756 
ParseMiscParamSubMbPartPel(void * data)757 VAStatus DdiEncodeAvc::ParseMiscParamSubMbPartPel(void *data)
758 {
759     DDI_CHK_NULL(m_encodeCtx, "nullptr m_encodeCtx", VA_STATUS_ERROR_INVALID_PARAMETER);
760     DDI_CHK_NULL(data, "nullptr data", VA_STATUS_ERROR_INVALID_PARAMETER);
761 
762     PCODEC_AVC_ENCODE_PIC_PARAMS picParams = (PCODEC_AVC_ENCODE_PIC_PARAMS)(m_encodeCtx->pPicParams) + current_pic_parameter_set_id;
763     DDI_CHK_NULL(picParams, "nullptr picParams", VA_STATUS_ERROR_INVALID_PARAMETER);
764 
765     VAEncMiscParameterSubMbPartPelH264 *vaEncMiscParamSubMbPartPel = (VAEncMiscParameterSubMbPartPelH264*)data;
766     if (vaEncMiscParamSubMbPartPel->disable_inter_sub_mb_partition)
767     {
768         picParams->bEnableSubMbPartMask = true;
769         //Inter 16x16 can't be disabled
770         picParams->SubMbPartMask = vaEncMiscParamSubMbPartPel->inter_sub_mb_partition_mask.value & disMbPartMask;
771     }
772 
773     if (vaEncMiscParamSubMbPartPel->enable_sub_pel_mode)
774     {
775         picParams->bEnableSubPelMode = true;
776         picParams->SubPelMode        = vaEncMiscParamSubMbPartPel->sub_pel_mode & subpelModeMask;
777         if (picParams->SubPelMode == subpelModeReserved)
778         {
779             //When Quarter-pel mode is enabled, Half-pel must be enabled as well.
780             picParams->SubPelMode = subpelModeQuant;
781         }
782     }
783 
784     return VA_STATUS_SUCCESS;
785 }
786 
ContextInitialize(CodechalSetting * codecHalSettings)787 VAStatus DdiEncodeAvc::ContextInitialize(CodechalSetting * codecHalSettings)
788 {
789     DDI_CHK_NULL(m_encodeCtx, "nullptr m_encodeCtx.", VA_STATUS_ERROR_INVALID_CONTEXT);
790     DDI_CHK_NULL(m_encodeCtx->pCpDdiInterface, "nullptr m_encodeCtx->pCpDdiInterface.", VA_STATUS_ERROR_INVALID_CONTEXT);
791     DDI_CHK_NULL(codecHalSettings, "nullptr codecHalSettings.", VA_STATUS_ERROR_INVALID_CONTEXT);
792 
793     if (m_encodeCtx->bVdencActive == true)
794     {
795         codecHalSettings->codecFunction = CODECHAL_FUNCTION_ENC_VDENC_PAK;
796     }
797     else
798     {
799         codecHalSettings->codecFunction = m_encodeCtx->codecFunction;
800     }
801 
802     codecHalSettings->width  = m_encodeCtx->dworiFrameWidth;
803     codecHalSettings->height = m_encodeCtx->dworiFrameHeight;
804     codecHalSettings->mode     = m_encodeCtx->wModeType;
805     codecHalSettings->standard = CODECHAL_AVC;
806 
807     m_encodeCtx->pSeqParams = (void *)MOS_AllocAndZeroMemory(CODEC_AVC_MAX_SPS_NUM * sizeof(CODEC_AVC_ENCODE_SEQUENCE_PARAMS));
808     DDI_CHK_NULL(m_encodeCtx->pSeqParams, "nullptr m_encodeCtx->pSeqParams", VA_STATUS_ERROR_ALLOCATION_FAILED);
809 
810     m_encodeCtx->pPicParams = (void *)MOS_AllocAndZeroMemory(CODEC_AVC_MAX_PPS_NUM * sizeof(CODEC_AVC_ENCODE_PIC_PARAMS));
811     DDI_CHK_NULL(m_encodeCtx->pPicParams, "nullptr m_encodeCtx->pPicParams", VA_STATUS_ERROR_ALLOCATION_FAILED);
812 
813     // Allocate NAL unit params
814     m_encodeCtx->ppNALUnitParams = (PCODECHAL_NAL_UNIT_PARAMS *)MOS_AllocAndZeroMemory(sizeof(PCODECHAL_NAL_UNIT_PARAMS) * CODECHAL_ENCODE_AVC_MAX_NAL_TYPE);
815     DDI_CHK_NULL(m_encodeCtx->ppNALUnitParams, "nullptr m_encodeCtx->ppNALUnitParams", VA_STATUS_ERROR_ALLOCATION_FAILED);
816 
817     PCODECHAL_NAL_UNIT_PARAMS nalUnitParams = (PCODECHAL_NAL_UNIT_PARAMS)MOS_AllocAndZeroMemory(sizeof(CODECHAL_NAL_UNIT_PARAMS) * CODECHAL_ENCODE_AVC_MAX_NAL_TYPE);
818     DDI_CHK_NULL(nalUnitParams, "nullptr nalUnitParams", VA_STATUS_ERROR_ALLOCATION_FAILED);
819 
820     for (int32_t i = 0; i < CODECHAL_ENCODE_AVC_MAX_NAL_TYPE; i++)
821     {
822         m_encodeCtx->ppNALUnitParams[i] = &(nalUnitParams[i]);
823     }
824 
825     VAStatus status = m_encodeCtx->pCpDdiInterface->ParseCpParamsForEncode();
826     if (VA_STATUS_SUCCESS != status)
827     {
828         return status;
829     }
830 
831     m_encodeCtx->pVuiParams = (void *)MOS_AllocAndZeroMemory(sizeof(CODECHAL_ENCODE_AVC_VUI_PARAMS));
832     DDI_CHK_NULL(m_encodeCtx->pVuiParams, "nullptr m_encodeCtx->pVuiParams", VA_STATUS_ERROR_ALLOCATION_FAILED);
833 
834     // Allocate SliceParams
835     // Supports equal row slices.
836     m_encodeCtx->pSliceParams = (void *)MOS_AllocAndZeroMemory(ENCODE_AVC_MAX_SLICES_SUPPORTED * sizeof(CODEC_AVC_ENCODE_SLICE_PARAMS));
837     DDI_CHK_NULL(m_encodeCtx->pSliceParams, "nullptr m_encodeCtx->pSliceParams", VA_STATUS_ERROR_ALLOCATION_FAILED);
838 
839     // Allocate Encode Status Report
840     m_encodeCtx->pEncodeStatusReport = (void *)MOS_AllocAndZeroMemory(CODECHAL_ENCODE_STATUS_NUM * sizeof(EncodeStatusReport));
841     DDI_CHK_NULL(m_encodeCtx->pEncodeStatusReport, "nullptr m_encodeCtx->pEncodeStatusReport", VA_STATUS_ERROR_ALLOCATION_FAILED);
842 
843     // Allocate SEI structure
844     m_encodeCtx->pSEIFromApp = (CodechalEncodeSeiData*)MOS_AllocAndZeroMemory(sizeof(CodechalEncodeSeiData));
845     DDI_CHK_NULL(m_encodeCtx->pSEIFromApp, "nullptr m_encodeCtx->pSEIFromApp", VA_STATUS_ERROR_ALLOCATION_FAILED);
846 
847     // for slice header from application
848     m_encodeCtx->pSliceHeaderData = (PCODEC_ENCODER_SLCDATA)MOS_AllocAndZeroMemory(ENCODE_AVC_MAX_SLICES_SUPPORTED *
849                                                                                    sizeof(CODEC_ENCODER_SLCDATA));
850     DDI_CHK_NULL(m_encodeCtx->pSliceHeaderData, "nullptr m_encodeCtx->pSliceHeaderData", VA_STATUS_ERROR_ALLOCATION_FAILED);
851 
852     // Create the bit stream buffer to hold the packed headers from application
853     m_encodeCtx->pbsBuffer = (PBSBuffer)MOS_AllocAndZeroMemory(sizeof(BSBuffer));
854     DDI_CHK_NULL(m_encodeCtx->pbsBuffer, "nullptr m_encodeCtx->pbsBuffer", VA_STATUS_ERROR_ALLOCATION_FAILED);
855 
856     m_encodeCtx->pbsBuffer->pBase = (uint8_t *)MOS_AllocAndZeroMemory(ENCODE_AVC_MAX_SLICES_SUPPORTED * PACKED_HEADER_SIZE_PER_ROW);
857     DDI_CHK_NULL(m_encodeCtx->pbsBuffer->pBase, "nullptr m_encodeCtx->pbsBuffer->pBase", VA_STATUS_ERROR_ALLOCATION_FAILED);
858 
859     m_encodeCtx->pbsBuffer->BufferSize = ENCODE_AVC_MAX_SLICES_SUPPORTED * PACKED_HEADER_SIZE_PER_ROW;
860 
861     m_qcParams = (CODECHAL_ENCODE_AVC_QUALITY_CTRL_PARAMS *)MOS_AllocAndZeroMemory(sizeof(CODECHAL_ENCODE_AVC_QUALITY_CTRL_PARAMS));
862     DDI_CHK_NULL(m_qcParams, "nullptr m_qcParams", VA_STATUS_ERROR_ALLOCATION_FAILED);
863 
864     m_roundingParams = (CODECHAL_ENCODE_AVC_ROUNDING_PARAMS *)MOS_AllocAndZeroMemory(sizeof(CODECHAL_ENCODE_AVC_ROUNDING_PARAMS));
865     DDI_CHK_NULL(m_roundingParams, "nullptr m_roundingParams", VA_STATUS_ERROR_ALLOCATION_FAILED);
866 
867     iqMatrixParams = (PCODEC_AVC_IQ_MATRIX_PARAMS)MOS_AllocAndZeroMemory(sizeof(CODEC_AVC_IQ_MATRIX_PARAMS));
868     DDI_CHK_NULL(iqMatrixParams, "nullptr iqMatrixParams", VA_STATUS_ERROR_ALLOCATION_FAILED);
869 
870     iqWeightScaleLists = (PCODEC_AVC_ENCODE_IQ_WEIGTHSCALE_LISTS)MOS_AllocAndZeroMemory(sizeof(CODEC_AVC_ENCODE_IQ_WEIGTHSCALE_LISTS));
871     DDI_CHK_NULL(iqWeightScaleLists, "nullptr iqWeightScaleLists", VA_STATUS_ERROR_ALLOCATION_FAILED);
872 
873     return VA_STATUS_SUCCESS;
874 }
875 
RenderPicture(VADriverContextP ctx,VAContextID context,VABufferID * buffers,int32_t numBuffers)876 VAStatus DdiEncodeAvc::RenderPicture(
877     VADriverContextP ctx,
878     VAContextID      context,
879     VABufferID       *buffers,
880     int32_t          numBuffers)
881 {
882     DDI_FUNCTION_ENTER();
883 
884     DDI_CHK_NULL(ctx, "nullptr ctx", VA_STATUS_ERROR_INVALID_CONTEXT);
885     PDDI_MEDIA_CONTEXT mediaCtx = DdiMedia_GetMediaContext(ctx);
886     DDI_CHK_NULL(mediaCtx, "nullptr mediaCtx", VA_STATUS_ERROR_INVALID_CONTEXT);
887 
888     // assume the VAContextID is encoder ID
889     DDI_CHK_NULL(m_encodeCtx, "nullptr m_encodeCtx", VA_STATUS_ERROR_INVALID_CONTEXT);
890 
891     uint32_t numSlices = 0;
892     VAStatus vaStatus  = VA_STATUS_SUCCESS;
893 
894     DDI_MEDIA_BUFFER *buf;
895     void             *data;
896     uint32_t         dataSize;
897     for (int32_t i = 0; i < numBuffers; i++)
898     {
899         buf = DdiMedia_GetBufferFromVABufferID(mediaCtx, buffers[i]);
900         DDI_CHK_NULL(buf, "Invalid buffer.", VA_STATUS_ERROR_INVALID_BUFFER);
901         if (buf->uiType == VAEncMacroblockDisableSkipMapBufferType)
902         {
903             DdiMedia_MediaBufferToMosResource(buf, &(m_encodeCtx->resPerMBSkipMapBuffer));
904             m_encodeCtx->bMbDisableSkipMapEnabled = true;
905             continue;
906         }
907         dataSize = buf->iSize;
908         // can use internal function instead of DdiMedia_MapBuffer here?
909         DdiMedia_MapBuffer(ctx, buffers[i], &data);
910 
911         DDI_CHK_NULL(data, "nullptr data", VA_STATUS_ERROR_INVALID_BUFFER);
912 
913         switch (buf->uiType)
914         {
915         case VAIQMatrixBufferType:
916         case VAQMatrixBufferType:
917             DDI_CHK_STATUS(Qmatrix(data), VA_STATUS_ERROR_INVALID_BUFFER);
918             break;
919 
920         case VAEncSequenceParameterBufferType:
921             DDI_CHK_STATUS(ParseSeqParams(data), VA_STATUS_ERROR_INVALID_BUFFER);
922             m_encodeCtx->bNewSeq = true;
923             break;
924 
925         case VAEncPictureParameterBufferType:
926             DDI_CHK_STATUS(ParsePicParams(mediaCtx, data), VA_STATUS_ERROR_INVALID_BUFFER);
927 
928             DDI_CHK_STATUS(
929                     AddToStatusReportQueue((void *)m_encodeCtx->resBitstreamBuffer.bo),
930                     VA_STATUS_ERROR_INVALID_BUFFER);
931             break;
932 
933         case VAEncSliceParameterBufferType:
934             numSlices = buf->uiNumElements;
935             DDI_CHK_STATUS(ParseSlcParams(mediaCtx, data, numSlices), VA_STATUS_ERROR_INVALID_BUFFER);
936             break;
937 
938         case VAEncPackedHeaderParameterBufferType:
939             DDI_CHK_STATUS(ParsePackedHeaderParams(data), VA_STATUS_ERROR_INVALID_BUFFER);
940             break;
941 
942         case VAEncPackedHeaderDataBufferType:
943             DDI_CHK_STATUS(ParsePackedHeaderData(data), VA_STATUS_ERROR_INVALID_BUFFER);
944             break;
945 
946         case VAEncMiscParameterBufferType:
947             DDI_CHK_STATUS(ParseMiscParams(data), VA_STATUS_ERROR_INVALID_BUFFER);
948             break;
949 
950         case VAEncQPBufferType:
951             DdiMedia_MediaBufferToMosResource(buf, &m_encodeCtx->resMBQpBuffer);
952             m_encodeCtx->bMBQpEnable = true;
953             break;
954 
955         default:
956             if(m_encodeCtx->pCpDdiInterface)
957             {
958                 vaStatus = m_encodeCtx->pCpDdiInterface->RenderCencPicture(ctx, context, buf, data);
959             }
960             else
961             {
962                 vaStatus = VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE;
963             }
964             break;
965         }
966         DdiMedia_UnmapBuffer(ctx, buffers[i]);
967     }
968 
969     DDI_FUNCTION_EXIT(vaStatus);
970     return vaStatus;
971 }
972 
EncodeInCodecHal(uint32_t numSlices)973 VAStatus DdiEncodeAvc::EncodeInCodecHal(uint32_t numSlices)
974 {
975     uint8_t   ppsIdx, spsIdx;
976     PCODEC_AVC_ENCODE_PIC_PARAMS  picParams;
977 
978     DDI_CHK_NULL(m_encodeCtx, "nullptr m_encodeCtx", VA_STATUS_ERROR_INVALID_PARAMETER);
979     DDI_CHK_NULL(m_encodeCtx->pMediaCtx, "nullptr m_encodeCtx->pMediaCtx", VA_STATUS_ERROR_INVALID_PARAMETER);
980     DDI_CHK_NULL(m_encodeCtx->pCpDdiInterface, "nullptr m_encodeCtx->pCpDdiInterface.", VA_STATUS_ERROR_INVALID_PARAMETER);
981 
982     DDI_CODEC_RENDER_TARGET_TABLE *rtTbl     = &(m_encodeCtx->RTtbl);
983 
984     EncoderParams *encodeParams = &m_encodeCtx->EncodeParams;
985     MOS_ZeroMemory(encodeParams, sizeof(EncoderParams));
986 
987     encodeParams->newSeqHeader           = m_newSeqHeader;
988     encodeParams->newPpsHeader           = m_newPpsHeader;
989     encodeParams->arbitraryNumMbsInSlice = m_arbitraryNumMbsInSlice;
990 
991     if (m_encodeCtx->bVdencActive == true)
992     {
993         encodeParams->ExecCodecFunction = CODECHAL_FUNCTION_ENC_VDENC_PAK;
994     }
995     else
996     {
997         encodeParams->ExecCodecFunction = CODECHAL_FUNCTION_ENC_PAK;
998     }
999 
1000     // Raw Surface
1001     PMOS_SURFACE rawSurface = &encodeParams->rawSurface;
1002     rawSurface->Format   = Format_NV12;
1003     rawSurface->dwOffset = 0;
1004 
1005     DdiMedia_MediaSurfaceToMosResource(rtTbl->pCurrentRT, &(rawSurface->OsResource));
1006 
1007     PMOS_INTERFACE osInterface = m_encodeCtx->pCodecHal->GetOsInterface();
1008     m_encodeCtx->pCpDdiInterface->SetInputResourceEncryption(osInterface, &(rawSurface->OsResource));
1009 
1010     // Recon Surface
1011     PMOS_SURFACE reconSurface = &encodeParams->reconSurface;
1012     reconSurface->Format   = Format_NV12;
1013     reconSurface->dwOffset = 0;
1014 
1015     DdiMedia_MediaSurfaceToMosResource(rtTbl->pCurrentReconTarget, &(reconSurface->OsResource));
1016 
1017     //clear registered recon/ref surface flags
1018     DDI_CHK_RET(ClearRefList(&m_encodeCtx->RTtbl, false), "ClearRefList failed!");
1019 
1020     // Bitstream surface
1021     PMOS_RESOURCE bitstreamSurface = &encodeParams->resBitstreamBuffer;
1022     *bitstreamSurface        = m_encodeCtx->resBitstreamBuffer;  // in render picture
1023     bitstreamSurface->Format = Format_Buffer;
1024 
1025     encodeParams->psRawSurface = &encodeParams->rawSurface;
1026     encodeParams->psReconSurface = &encodeParams->reconSurface;
1027     encodeParams->presBitstreamBuffer = &encodeParams->resBitstreamBuffer;
1028 
1029     PMOS_SURFACE mbQpSurface = &encodeParams->mbQpSurface;
1030     if (m_encodeCtx->bMBQpEnable)
1031     {
1032         mbQpSurface->Format             = Format_Buffer_2D;
1033         mbQpSurface->dwOffset           = 0;
1034         mbQpSurface->OsResource         = m_encodeCtx->resMBQpBuffer;
1035         encodeParams->psMbQpDataSurface = &encodeParams->mbQpSurface;
1036         encodeParams->bMbQpDataEnabled  = true;
1037     }
1038 
1039     PMOS_SURFACE disableSkipMapSurface = &encodeParams->disableSkipMapSurface;
1040     encodeParams->bMbDisableSkipMapEnabled = m_encodeCtx->bMbDisableSkipMapEnabled;
1041     if (encodeParams->bMbDisableSkipMapEnabled)
1042     {
1043         disableSkipMapSurface->Format           = Format_Buffer;
1044         disableSkipMapSurface->dwOffset         = 0;
1045         disableSkipMapSurface->OsResource       = m_encodeCtx->resPerMBSkipMapBuffer;
1046         encodeParams->psMbDisableSkipMapSurface = &encodeParams->disableSkipMapSurface;
1047     }
1048 
1049     // correct some params
1050     PCODEC_AVC_ENCODE_SEQUENCE_PARAMS seqParams;
1051     CODECHAL_ENCODE_AVC_VUI_PARAMS    *vuiParam;
1052 
1053     vuiParam  = (CODECHAL_ENCODE_AVC_VUI_PARAMS *)m_encodeCtx->pVuiParams;
1054     seqParams = (PCODEC_AVC_ENCODE_SEQUENCE_PARAMS)(m_encodeCtx->pSeqParams);
1055     seqParams->TargetUsage = m_encodeCtx->targetUsage;
1056     if (VA_RC_CQP == m_encodeCtx->uiRCMethod)
1057     {
1058         vuiParam->bit_rate_value_minus1[0]    = 0;
1059         vuiParam->cpb_size_value_minus1[0]    = 0;
1060         seqParams->TargetBitRate              = 0;
1061         seqParams->MaxBitRate                 = 0;
1062         seqParams->MinBitRate                 = 0;
1063         seqParams->InitVBVBufferFullnessInBit = 0;
1064         seqParams->VBVBufferSizeInBit         = 0;
1065     }
1066 
1067     encodeParams->uiSlcStructCaps = CODECHAL_SLICE_STRUCT_ARBITRARYMBSLICE;
1068 
1069     ppsIdx                           = ((PCODEC_AVC_ENCODE_SLICE_PARAMS)(m_encodeCtx->pSliceParams))->pic_parameter_set_id;
1070     picParams                        = (PCODEC_AVC_ENCODE_PIC_PARAMS)m_encodeCtx->pPicParams + ppsIdx;
1071     spsIdx                           = picParams->seq_parameter_set_id;
1072     encodeParams->pSeqParams         = (PCODEC_AVC_ENCODE_SEQUENCE_PARAMS)m_encodeCtx->pSeqParams + spsIdx;
1073     encodeParams->pPicParams         = picParams;
1074 
1075     encodeParams->pVuiParams         = m_encodeCtx->pVuiParams;
1076     encodeParams->pSliceParams       = m_encodeCtx->pSliceParams;
1077     encodeParams->pAVCQCParams       = m_qcParams;
1078     encodeParams->pAVCRoundingParams = m_roundingParams;
1079 
1080     // Sequence data
1081     encodeParams->bNewSeq = m_encodeCtx->bNewSeq;
1082     // VUI
1083     encodeParams->bNewVuiData = m_encodeCtx->bNewVuiData;
1084 
1085     // Slice level data
1086     encodeParams->dwNumSlices = numSlices;
1087 
1088     // IQmatrix params
1089     encodeParams->bNewQmatrixData = m_encodeCtx->bNewQmatrixData;
1090     encodeParams->bPicQuant       = m_encodeCtx->bPicQuant;
1091     encodeParams->ppNALUnitParams = m_encodeCtx->ppNALUnitParams;
1092     encodeParams->pSeiData        = m_encodeCtx->pSEIFromApp;
1093     encodeParams->pSeiParamBuffer = m_encodeCtx->pSEIFromApp->pSEIBuffer;
1094     encodeParams->dwSEIDataOffset = 0;
1095 
1096     MOS_STATUS status = MOS_SecureMemcpy(&iqMatrixParams->ScalingList4x4,
1097         6 * 16 * sizeof(uint8_t),
1098         &m_scalingLists4x4,
1099         6 * 16 * sizeof(uint8_t));
1100     if (MOS_STATUS_SUCCESS != status)
1101     {
1102         DDI_ASSERTMESSAGE("DDI:Failed to copy scaling list 4x4!");
1103         return VA_STATUS_ERROR_INVALID_PARAMETER;
1104     }
1105 
1106     status = MOS_SecureMemcpy(&iqMatrixParams->ScalingList8x8,
1107         2 * 64 * sizeof(uint8_t),
1108         &m_scalingLists8x8,
1109         2 * 64 * sizeof(uint8_t));
1110     if (MOS_STATUS_SUCCESS != status)
1111     {
1112         DDI_ASSERTMESSAGE("DDI:Failed to copy scaling list 8x8!");
1113         return VA_STATUS_ERROR_INVALID_PARAMETER;
1114     }
1115     encodeParams->pIQMatrixBuffer = iqMatrixParams;
1116 
1117     status = MOS_SecureMemcpy(&iqWeightScaleLists->WeightScale4x4,
1118         (CODEC_AVC_WEIGHT_SCALE_4x4 * sizeof(uint32_t)),
1119         &m_weightScale4x4,
1120         (CODEC_AVC_WEIGHT_SCALE_4x4 * sizeof(uint32_t)));
1121     if (MOS_STATUS_SUCCESS != status)
1122     {
1123         DDI_ASSERTMESSAGE("DDI:Failed to copy weight scale list 4x4!");
1124         return VA_STATUS_ERROR_INVALID_PARAMETER;
1125     }
1126 
1127     status = MOS_SecureMemcpy(&iqWeightScaleLists->WeightScale8x8,
1128         (CODEC_AVC_WEIGHT_SCALE_8x8 * sizeof(uint32_t)),
1129         &m_weightScale8x8,
1130         (CODEC_AVC_WEIGHT_SCALE_8x8 * sizeof(uint32_t)));
1131     if (MOS_STATUS_SUCCESS != status)
1132     {
1133         DDI_ASSERTMESSAGE("DDI:Failed to copy weight scale list 8x8!");
1134         return VA_STATUS_ERROR_INVALID_PARAMETER;
1135     }
1136     encodeParams->pIQWeightScaleLists = iqWeightScaleLists;
1137 
1138     // whether driver need to pack slice header
1139     if (true == m_encodeCtx->bHavePackedSliceHdr)
1140     {
1141         encodeParams->bAcceleratorHeaderPackingCaps = false;
1142     }
1143     else
1144     {
1145         encodeParams->bAcceleratorHeaderPackingCaps = true;
1146     }
1147 
1148     encodeParams->pBSBuffer      = m_encodeCtx->pbsBuffer;
1149     encodeParams->pSlcHeaderData = (void *)m_encodeCtx->pSliceHeaderData;
1150 
1151     if (m_encodeCtx->pCodecHal->IsApogeiosEnabled())
1152     {
1153         status = m_encodeCtx->pCodecHal->Execute(encodeParams);
1154         if (MOS_STATUS_SUCCESS != status)
1155         {
1156             DDI_ASSERTMESSAGE("DDI:Failed in Codechal!");
1157             return VA_STATUS_ERROR_ENCODING_ERROR;
1158         }
1159     }
1160     else
1161     {
1162         CodechalEncoderState *encoder = dynamic_cast<CodechalEncoderState *>(m_encodeCtx->pCodecHal);
1163         DDI_CHK_NULL(encoder, "nullptr Codechal encode", VA_STATUS_ERROR_INVALID_PARAMETER);
1164 
1165         if (!encoder->m_mfeEnabled)
1166         {
1167             status = m_encodeCtx->pCodecHal->Execute(encodeParams);
1168             if (MOS_STATUS_SUCCESS != status)
1169             {
1170                 DDI_ASSERTMESSAGE("DDI:Failed in Codechal!");
1171                 return VA_STATUS_ERROR_ENCODING_ERROR;
1172             }
1173         }
1174     }
1175 
1176     return VA_STATUS_SUCCESS;
1177 }
1178 
ResetAtFrameLevel()1179 VAStatus DdiEncodeAvc::ResetAtFrameLevel()
1180 {
1181     DDI_CHK_NULL(m_encodeCtx, "nullptr m_encodeCtx", VA_STATUS_ERROR_INVALID_PARAMETER);
1182 
1183     // Assume there is only one SPS parameter
1184     PCODEC_AVC_ENCODE_SEQUENCE_PARAMS seqParams = (PCODEC_AVC_ENCODE_SEQUENCE_PARAMS)(m_encodeCtx->pSeqParams);
1185     seqParams->bInitBRC                         = 0x0;
1186     seqParams->bResetBRC                        = 0x0;
1187 
1188     m_encodeCtx->dwNumSlices      = 0x0;
1189     m_encodeCtx->indexNALUnit     = 0x0;
1190     m_encodeCtx->uiSliceHeaderCnt = 0x0;
1191 
1192     // reset bsbuffer every frame
1193     m_encodeCtx->pbsBuffer->pCurrent    = m_encodeCtx->pbsBuffer->pBase;
1194     m_encodeCtx->pbsBuffer->SliceOffset = 0x0;
1195     m_encodeCtx->pbsBuffer->BitOffset   = 0x0;
1196     m_encodeCtx->pbsBuffer->BitSize     = 0x0;
1197 
1198     // clear the packed header information
1199     if (nullptr != m_encodeCtx->ppNALUnitParams)
1200     {
1201         MOS_ZeroMemory(m_encodeCtx->ppNALUnitParams[0], sizeof(CODECHAL_NAL_UNIT_PARAMS) * CODECHAL_ENCODE_AVC_MAX_NAL_TYPE);
1202     }
1203 
1204     m_encodeCtx->bHavePackedSliceHdr      = false;
1205     m_encodeCtx->bLastPackedHdrIsSlice    = false;
1206     m_encodeCtx->bMbDisableSkipMapEnabled = false;
1207     m_encodeCtx->bMBQpEnable              = false;
1208 
1209     if (nullptr != m_roundingParams)
1210     {
1211         MOS_ZeroMemory(m_roundingParams, sizeof(CODECHAL_ENCODE_AVC_ROUNDING_PARAMS));
1212     }
1213 
1214     return VA_STATUS_SUCCESS;
1215 }
1216 
Qmatrix(void * ptr)1217 VAStatus DdiEncodeAvc::Qmatrix(void *ptr)
1218 {
1219     DDI_CHK_NULL(m_encodeCtx, "nullptr m_encodeCtx", VA_STATUS_ERROR_INVALID_PARAMETER);
1220     DDI_CHK_NULL(ptr, "nullptr ptr", VA_STATUS_ERROR_INVALID_PARAMETER);
1221 
1222     VAIQMatrixBufferH264 *qm = (VAIQMatrixBufferH264 *)ptr;
1223 
1224     MOS_STATUS status = MOS_SecureMemcpy((void *)&m_scalingLists4x4,
1225         6 * 16 * sizeof(uint8_t),
1226         (void *)&qm->ScalingList4x4,
1227         6 * 16 * sizeof(uint8_t));
1228     if (MOS_STATUS_SUCCESS != status)
1229     {
1230         DDI_ASSERTMESSAGE("Failed to copy QM scaling list 4x4.");
1231         return VA_STATUS_ERROR_INVALID_PARAMETER;
1232     }
1233 
1234     status = MOS_SecureMemcpy((void *)&m_scalingLists8x8,
1235         2 * 64 * sizeof(uint8_t),
1236         (void *)&qm->ScalingList8x8,
1237         2 * 64 * sizeof(uint8_t));
1238     if (MOS_STATUS_SUCCESS != status)
1239     {
1240         DDI_ASSERTMESSAGE("Failed to copy QM scaling list 8x8.");
1241         return VA_STATUS_ERROR_INVALID_PARAMETER;
1242     }
1243 
1244     uint8_t idx1, idx2;
1245     // 4x4 block
1246     for (idx2 = 0; idx2 < 6; idx2++)
1247     {
1248         for (idx1 = 0; idx1 < 16; idx1++)
1249         {
1250             m_weightScale4x4[idx2][CODEC_AVC_Qmatrix_scan_4x4[idx1]] = qm->ScalingList4x4[idx2][idx1];
1251         }
1252     }
1253     // 8x8 block
1254     for (idx2 = 0; idx2 < 2; idx2++)
1255     {
1256         for (idx1 = 0; idx1 < 64; idx1++)
1257         {
1258             m_weightScale8x8[idx2][CODEC_AVC_Qmatrix_scan_8x8[idx1]] = qm->ScalingList8x8[idx2][idx1];
1259         }
1260     }
1261 
1262     return VA_STATUS_SUCCESS;
1263 }
1264 
ParseSeqParams(void * ptr)1265 VAStatus DdiEncodeAvc::ParseSeqParams(void *ptr)
1266 {
1267     DDI_CHK_NULL(m_encodeCtx, "nullptr m_encodeCtx", VA_STATUS_ERROR_INVALID_PARAMETER);
1268     DDI_CHK_NULL(ptr, "nullptr ptr", VA_STATUS_ERROR_INVALID_PARAMETER);
1269 
1270     VAEncSequenceParameterBufferH264 *seq       = (VAEncSequenceParameterBufferH264 *)ptr;
1271     PCODEC_AVC_ENCODE_SEQUENCE_PARAMS seqParams = (PCODEC_AVC_ENCODE_SEQUENCE_PARAMS)((uint8_t *)m_encodeCtx->pSeqParams + seq->seq_parameter_set_id * sizeof(CODEC_AVC_ENCODE_SEQUENCE_PARAMS));
1272 
1273     if (seq->seq_parameter_set_id >= CODEC_AVC_MAX_SPS_NUM)
1274     {
1275         return VA_STATUS_ERROR_INVALID_PARAMETER;
1276     }
1277 
1278     seqParams->FrameWidth  = seq->picture_width_in_mbs * 16;
1279     seqParams->FrameHeight = seq->picture_height_in_mbs * 16;
1280     if ((seq->picture_width_in_mbs <= m_encodeCtx->wContextPicWidthInMB) && (seq->picture_height_in_mbs <= m_encodeCtx->wContextPicHeightInMB) && (seq->picture_width_in_mbs != m_encodeCtx->wOriPicWidthInMB) && (seq->picture_height_in_mbs != m_encodeCtx->wOriPicHeightInMB))
1281     {
1282         m_encodeCtx->wPicWidthInMB     = seq->picture_width_in_mbs;
1283         m_encodeCtx->wPicHeightInMB    = seq->picture_height_in_mbs;
1284         m_encodeCtx->wOriPicWidthInMB  = m_encodeCtx->wPicWidthInMB;
1285         m_encodeCtx->wOriPicHeightInMB = m_encodeCtx->wPicHeightInMB;
1286         seqParams->bInitBRC            = true;
1287     }
1288     else if ((seq->picture_width_in_mbs > m_encodeCtx->wContextPicWidthInMB) || (seq->picture_height_in_mbs > m_encodeCtx->wContextPicHeightInMB))
1289     {
1290         return VA_STATUS_ERROR_INVALID_PARAMETER;
1291     }
1292 
1293     seqParams->Profile              = GetAVCProfileFromVAProfile();
1294     seqParams->Level                = seq->level_idc;
1295     seqParams->seq_parameter_set_id = seq->seq_parameter_set_id;
1296     seqParams->chroma_format_idc    = 1;
1297 
1298     seqParams->bit_depth_luma_minus8   = seq->bit_depth_luma_minus8;
1299     seqParams->bit_depth_chroma_minus8 = seq->bit_depth_chroma_minus8;
1300 
1301     seqParams->GopPicSize = seq->intra_period ? seq->intra_period : seq->intra_idr_period;
1302     seqParams->GopRefDist = seq->ip_period;
1303     seqParams->RateControlMethod = VARC2HalRC(m_encodeCtx->uiRCMethod);
1304 
1305     seqParams->TargetBitRate = seq->bits_per_second;
1306     seqParams->MaxBitRate    = seq->bits_per_second;
1307     seqParams->MinBitRate    = seq->bits_per_second;
1308     // fps it set to 30 by default, can be overwritten by misc paramter
1309     if(!seqParams->FramesPer100Sec)
1310     {
1311         seqParams->FramesPer100Sec = 3000;
1312     }
1313 
1314 
1315     // set default same as MSDK, can be overwritten by HRD params
1316     seqParams->InitVBVBufferFullnessInBit = seq->bits_per_second;
1317     seqParams->VBVBufferSizeInBit         = seq->bits_per_second << 1;
1318 
1319     seqParams->NumRefFrames = seq->max_num_ref_frames;
1320 
1321     seqParams->log2_max_frame_num_minus4             = seq->seq_fields.bits.log2_max_frame_num_minus4;
1322     seqParams->pic_order_cnt_type                    = seq->seq_fields.bits.pic_order_cnt_type;
1323     seqParams->log2_max_pic_order_cnt_lsb_minus4     = seq->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4;
1324     seqParams->num_ref_frames_in_pic_order_cnt_cycle = seq->num_ref_frames_in_pic_order_cnt_cycle;
1325     seqParams->delta_pic_order_always_zero_flag      = seq->seq_fields.bits.delta_pic_order_always_zero_flag;
1326     seqParams->direct_8x8_inference_flag             = seq->seq_fields.bits.direct_8x8_inference_flag;
1327     seqParams->vui_parameters_present_flag           = seq->vui_parameters_present_flag;
1328     seqParams->frame_mbs_only_flag                   = seq->seq_fields.bits.frame_mbs_only_flag;
1329     seqParams->offset_for_non_ref_pic                = seq->offset_for_non_ref_pic;
1330     seqParams->offset_for_top_to_bottom_field        = seq->offset_for_top_to_bottom_field;
1331     for (uint8_t i = 0; i < seqParams->num_ref_frames_in_pic_order_cnt_cycle; i++)
1332     {
1333         seqParams->offset_for_ref_frame[i] = seq->offset_for_ref_frame[i];
1334     }
1335 
1336     seqParams->frame_cropping_flag      = seq->frame_cropping_flag;
1337     seqParams->frame_crop_bottom_offset = seq->frame_crop_bottom_offset;
1338     seqParams->frame_crop_left_offset   = seq->frame_crop_left_offset;
1339     seqParams->frame_crop_right_offset  = seq->frame_crop_right_offset;
1340     seqParams->frame_crop_top_offset    = seq->frame_crop_top_offset;
1341 
1342     // set up VUI parameter if rate control is enabled
1343     if (seqParams->vui_parameters_present_flag)
1344     {
1345         CODECHAL_ENCODE_AVC_VUI_PARAMS *vuiParam;
1346 
1347         vuiParam                                          = (CODECHAL_ENCODE_AVC_VUI_PARAMS *)m_encodeCtx->pVuiParams;
1348         vuiParam->nal_hrd_parameters_present_flag         = 1;
1349         vuiParam->cpb_cnt_minus1                          = 0;
1350         vuiParam->bit_rate_scale                          = 0;
1351         vuiParam->cpb_size_scale                          = 6;
1352         vuiParam->bit_rate_value_minus1[0]                = MOS_ROUNDUP_SHIFT(seq->bits_per_second, 6 + vuiParam->bit_rate_scale) - 1;
1353         vuiParam->cpb_size_value_minus1[0]                = MOS_ROUNDUP_DIVIDE(seqParams->VBVBufferSizeInBit, vuiKbps) - 1;
1354         vuiParam->cbr_flag                                = 0x0;
1355         vuiParam->initial_cpb_removal_delay_length_minus1 = 23;
1356         vuiParam->cpb_removal_delay_length_minus1         = 23;
1357         vuiParam->dpb_output_delay_length_minus1          = 23;
1358         vuiParam->time_offset_length                      = 24;
1359 
1360         vuiParam->timing_info_present_flag = seq->vui_fields.bits.timing_info_present_flag;
1361         vuiParam->num_units_in_tick        = seq->num_units_in_tick;
1362         vuiParam->time_scale               = seq->time_scale;
1363         vuiParam->fixed_frame_rate_flag    = 1;
1364 
1365         vuiParam->bitstream_restriction_flag              = seq->vui_fields.bits.bitstream_restriction_flag;
1366         vuiParam->motion_vectors_over_pic_boundaries_flag = 1;
1367         vuiParam->max_bytes_per_pic_denom                 = 2;
1368         vuiParam->max_bits_per_mb_denom                   = 1;
1369         vuiParam->max_dec_frame_buffering                 = seq->max_num_ref_frames + 1;
1370         vuiParam->num_reorder_frames                      = seq->max_num_ref_frames;
1371         vuiParam->log2_max_mv_length_horizontal           = seq->vui_fields.bits.log2_max_mv_length_horizontal;
1372         vuiParam->log2_max_mv_length_vertical             = seq->vui_fields.bits.log2_max_mv_length_vertical;
1373     }
1374 
1375     return VA_STATUS_SUCCESS;
1376 }
1377 
ParsePicParams(PDDI_MEDIA_CONTEXT mediaCtx,void * ptr)1378 VAStatus DdiEncodeAvc::ParsePicParams(
1379     PDDI_MEDIA_CONTEXT mediaCtx,
1380     void               *ptr)
1381 {
1382     DDI_CHK_NULL(mediaCtx, "nullptr mediaCtx", VA_STATUS_ERROR_INVALID_PARAMETER);
1383     DDI_CHK_NULL(m_encodeCtx, "nullptr m_encodeCtx", VA_STATUS_ERROR_INVALID_PARAMETER);
1384     DDI_CHK_NULL(ptr, "nullptr ptr", VA_STATUS_ERROR_INVALID_PARAMETER);
1385 
1386     VAEncPictureParameterBufferH264 *pic       = (VAEncPictureParameterBufferH264 *)ptr;
1387     PCODEC_AVC_ENCODE_PIC_PARAMS     picParams = (PCODEC_AVC_ENCODE_PIC_PARAMS)((uint8_t *)m_encodeCtx->pPicParams + pic->pic_parameter_set_id * sizeof(CODEC_AVC_ENCODE_PIC_PARAMS));
1388     DDI_CHK_NULL(picParams, "nullptr picParams", VA_STATUS_ERROR_INVALID_PARAMETER);
1389 
1390     current_pic_parameter_set_id = pic->pic_parameter_set_id;
1391     current_seq_parameter_set_id = pic->seq_parameter_set_id;
1392     //save ucMinimumQP and ucMaximumQP
1393     uint8_t ucMinQP = picParams->ucMinimumQP, ucMaxQP = picParams->ucMaximumQP;
1394     MOS_ZeroMemory(picParams, sizeof(CODEC_AVC_ENCODE_PIC_PARAMS));
1395     if(ucMinQP || ucMaxQP)
1396     {
1397         if (ucMaxQP == 0 && ucMinQP)
1398             ucMaxQP = 51;
1399         picParams->ucMinimumQP = ucMinQP;
1400         picParams->ucMaximumQP = ucMaxQP;
1401     }
1402 
1403 
1404     PCODEC_AVC_ENCODE_SEQUENCE_PARAMS seqParams = (PCODEC_AVC_ENCODE_SEQUENCE_PARAMS)((uint8_t *)m_encodeCtx->pSeqParams + pic->seq_parameter_set_id * sizeof(CODEC_AVC_ENCODE_SEQUENCE_PARAMS));
1405     if ((pic->seq_parameter_set_id >= CODEC_AVC_MAX_SPS_NUM) ||
1406         (pic->pic_parameter_set_id >= CODEC_AVC_MAX_PPS_NUM))
1407     {
1408         return VA_STATUS_ERROR_INVALID_PARAMETER;
1409     }
1410 
1411     if (pic->CurrPic.flags == VA_PICTURE_H264_TOP_FIELD ||
1412         pic->CurrPic.flags == VA_PICTURE_H264_BOTTOM_FIELD)
1413     {
1414         picParams->FieldCodingFlag = 1;
1415     }
1416 
1417     if (pic->CurrPic.picture_id != VA_INVALID_SURFACE)
1418     {
1419         DDI_CHK_RET(RegisterRTSurfaces(&(m_encodeCtx->RTtbl),
1420                         DdiMedia_GetSurfaceFromVASurfaceID(mediaCtx,
1421                             pic->CurrPic.picture_id)),
1422                     "RegisterRTSurfaces failed!");
1423     }
1424 
1425     // Curr Recon Pic
1426     SetupCodecPicture(mediaCtx, &(m_encodeCtx->RTtbl), &picParams->CurrReconstructedPic,pic->CurrPic, picParams->FieldCodingFlag, false, false);
1427     DDI_CODEC_RENDER_TARGET_TABLE *rtTbl = &(m_encodeCtx->RTtbl);
1428 
1429     rtTbl->pCurrentReconTarget = DdiMedia_GetSurfaceFromVASurfaceID(mediaCtx, pic->CurrPic.picture_id);
1430     // The surface for reconstructed frame is not registered, return error to app
1431     if (nullptr == rtTbl->pCurrentReconTarget)
1432     {
1433         DDI_ASSERTMESSAGE("invalid surface for reconstructed frame");
1434         return VA_STATUS_ERROR_INVALID_PARAMETER;
1435     }
1436 
1437     // curr orig pic
1438     // Hard to understand here!
1439     picParams->CurrOriginalPic.FrameIdx = (uint8_t)GetRenderTargetID(rtTbl, rtTbl->pCurrentReconTarget);
1440     picParams->CurrOriginalPic.PicFlags = picParams->CurrReconstructedPic.PicFlags;
1441 
1442     // The surface for reconstructed frame is not registered, return error to app
1443     if (picParams->CurrOriginalPic.FrameIdx == 0xFF)
1444     {
1445         DDI_ASSERTMESSAGE("unregistered surface for reconstructed frame");
1446         return VA_STATUS_ERROR_INVALID_PARAMETER;
1447     }
1448 
1449     // RefFrame List
1450     for (uint32_t i = 0; i < DDI_CODEC_NUM_MAX_REF_FRAME; i++)
1451     {
1452         if(pic->ReferenceFrames[i].picture_id!= VA_INVALID_SURFACE)
1453         {
1454             UpdateRegisteredRTSurfaceFlag(&(m_encodeCtx->RTtbl),
1455                 DdiMedia_GetSurfaceFromVASurfaceID(mediaCtx,
1456                     pic->ReferenceFrames[i].picture_id));
1457         }
1458         SetupCodecPicture(mediaCtx, &(m_encodeCtx->RTtbl), &(picParams->RefFrameList[i]), pic->ReferenceFrames[i], picParams->FieldCodingFlag, true, false);
1459     }
1460 
1461     for (uint32_t i = 0; i < DDI_CODEC_NUM_MAX_REF_FRAME; i++)
1462     {
1463         picParams->FieldOrderCntList[i][0] = pic->ReferenceFrames[i].TopFieldOrderCnt;
1464         picParams->FieldOrderCntList[i][1] = pic->ReferenceFrames[i].BottomFieldOrderCnt;
1465     }
1466 
1467     picParams->seq_parameter_set_id = pic->seq_parameter_set_id;
1468     picParams->pic_parameter_set_id = pic->pic_parameter_set_id;
1469     /* pic->coding_type; App is always setting this to 0 */
1470     picParams->CodingType                    = I_TYPE;
1471     picParams->second_chroma_qp_index_offset = pic->second_chroma_qp_index_offset;
1472     picParams->num_ref_idx_l0_active_minus1  = pic->num_ref_idx_l0_active_minus1;
1473     picParams->num_ref_idx_l1_active_minus1  = pic->num_ref_idx_l1_active_minus1;
1474     picParams->QpY                           = pic->pic_init_qp;
1475 
1476     if (pic->CurrPic.flags == VA_PICTURE_H264_SHORT_TERM_REFERENCE ||
1477         pic->CurrPic.flags == VA_PICTURE_H264_LONG_TERM_REFERENCE)
1478     {
1479         picParams->UsedForReferenceFlags = 1;
1480     }
1481     picParams->CurrFieldOrderCnt[0] = pic->CurrPic.TopFieldOrderCnt;
1482     picParams->CurrFieldOrderCnt[1] = pic->CurrPic.BottomFieldOrderCnt;
1483     picParams->frame_num            = pic->frame_num;
1484 
1485     picParams->bLastPicInSeq          = (pic->last_picture & H264_LAST_PICTURE_EOSEQ) ? 1 : 0;
1486     picParams->bLastPicInStream       = (pic->last_picture & H264_LAST_PICTURE_EOSTREAM) ? 1 : 0;
1487     picParams->chroma_qp_index_offset = pic->chroma_qp_index_offset;
1488     picParams->bIdrPic                         = pic->pic_fields.bits.idr_pic_flag;
1489     picParams->RefPicFlag                      = pic->pic_fields.bits.reference_pic_flag;
1490     picParams->entropy_coding_mode_flag        = pic->pic_fields.bits.entropy_coding_mode_flag;
1491     picParams->weighted_pred_flag              = pic->pic_fields.bits.weighted_pred_flag;
1492     picParams->weighted_bipred_idc             = pic->pic_fields.bits.weighted_bipred_idc;
1493     picParams->constrained_intra_pred_flag     = pic->pic_fields.bits.constrained_intra_pred_flag;
1494     picParams->transform_8x8_mode_flag         = pic->pic_fields.bits.transform_8x8_mode_flag;
1495     picParams->pic_order_present_flag          = pic->pic_fields.bits.pic_order_present_flag;
1496     picParams->pic_scaling_matrix_present_flag = pic->pic_fields.bits.pic_scaling_matrix_present_flag;
1497     picParams->bDisplayFormatSwizzle           = NeedDisplayFormatSwizzle(rtTbl->pCurrentRT);
1498     for (uint32_t i = 0; i < 12; i++)
1499     {
1500         picParams->pic_scaling_list_present_flag[i] = pic->pic_fields.bits.pic_scaling_matrix_present_flag;
1501     }
1502 
1503     // pps, sps header packing in app
1504     //Slice header packing will be done in app where bDisableAccelaratorHeaderPacking flag is defaulted to 0
1505     //this flag shouldnt be true for slice header packing
1506     picParams->UserFlags.bDisableAcceleratorHeaderPacking = true;
1507     picParams->UserFlags.bUseRawPicForRef                 = false;  //true;
1508 
1509     //Reset it to zero now
1510     picParams->NumSlice = 0;
1511 
1512     //Hardcode SFD mvThreshold to 80.
1513     picParams->dwZMvThreshold = 80;
1514 
1515     DDI_MEDIA_BUFFER *buf = DdiMedia_GetBufferFromVABufferID(mediaCtx, pic->coded_buf);
1516     DDI_CHK_NULL(buf, "nullptr buf", VA_STATUS_ERROR_INVALID_PARAMETER);
1517 
1518     // MSDK will re-use the buffer so need to remove before adding to status report again
1519     RemoveFromStatusReportQueue(buf);
1520     DdiMedia_MediaBufferToMosResource(buf, &(m_encodeCtx->resBitstreamBuffer));
1521 
1522     return VA_STATUS_SUCCESS;
1523 }
1524 
ParseSlcParams(PDDI_MEDIA_CONTEXT mediaCtx,void * ptr,uint32_t numSlices)1525 VAStatus DdiEncodeAvc::ParseSlcParams(
1526     PDDI_MEDIA_CONTEXT mediaCtx,
1527     void               *ptr,
1528     uint32_t           numSlices)
1529 {
1530     DDI_CHK_NULL(mediaCtx, "nullptr mediaCtx", VA_STATUS_ERROR_INVALID_PARAMETER);
1531     DDI_CHK_NULL(m_encodeCtx, "nullptr m_encodeCtx", VA_STATUS_ERROR_INVALID_PARAMETER);
1532     DDI_CHK_NULL(ptr, "nullptr ptr", VA_STATUS_ERROR_INVALID_PARAMETER);
1533 
1534     if (!m_encodeCtx->pCodecHal->IsApogeiosEnabled())
1535     {
1536         CodechalEncoderState *encoder = dynamic_cast<CodechalEncoderState *>(m_encodeCtx->pCodecHal);
1537         DDI_CHK_NULL(encoder, "nullptr codechal encoder", VA_STATUS_ERROR_INVALID_CONTEXT);
1538     }
1539     VAEncSliceParameterBufferH264 *slc       = (VAEncSliceParameterBufferH264 *)ptr;
1540     PCODEC_AVC_ENCODE_SLICE_PARAMS slcParams = (CODEC_AVC_ENCODE_SLICE_PARAMS *)m_encodeCtx->pSliceParams;
1541     PCODEC_AVC_ENCODE_PIC_PARAMS   picParams = (PCODEC_AVC_ENCODE_PIC_PARAMS)((uint8_t *)m_encodeCtx->pPicParams + slc->pic_parameter_set_id * sizeof(CODEC_AVC_ENCODE_PIC_PARAMS));
1542     DDI_CHK_NULL(slcParams, "nullptr slcParams", VA_STATUS_ERROR_INVALID_PARAMETER);
1543     DDI_CHK_NULL(picParams, "nullptr picParams", VA_STATUS_ERROR_INVALID_PARAMETER);
1544 
1545     uint8_t  numSlcs          = 0;
1546     uint32_t totalMBs         = m_encodeCtx->wPicWidthInMB * m_encodeCtx->wPicHeightInMB;
1547     uint32_t usedMBs          = 0;
1548     uint32_t mBScalerForField = 1;  //related with frame/field coding
1549     uint32_t sliceHeightInMB  = 1;
1550     uint32_t sliceActualMBs   = 0;
1551 
1552     if (slc->pic_parameter_set_id >= CODEC_AVC_MAX_PPS_NUM)
1553     {
1554         return VA_STATUS_ERROR_INVALID_PARAMETER;
1555     }
1556 
1557     numSlcs = picParams->NumSlice;
1558 
1559     if (numSlcs == 0)
1560     {
1561         picParams->CodingType = CodechalPicTypeFromVaSlcType(slc->slice_type);
1562     }
1563 
1564     // Disable rolling intra refresh if not a P-type picture
1565     if ((picParams->EnableRollingIntraRefresh != ROLLING_I_DISABLED) && (picParams->CodingType != P_TYPE))
1566     {
1567         picParams->EnableRollingIntraRefresh = ROLLING_I_DISABLED;
1568         m_encodeCtx->uiIntraRefreshFrameCnt  = 0;
1569         m_encodeCtx->uiIntraRefreshMBx       = 0;
1570         m_encodeCtx->uiIntraRefreshMBy       = 0;
1571     }
1572 
1573     slcParams += numSlcs;
1574     MOS_ZeroMemory(
1575         slcParams,
1576         numSlices * sizeof(CODEC_AVC_ENCODE_SLICE_PARAMS));
1577 
1578     if (numSlcs != 0)
1579     {
1580         slcParams--;
1581         usedMBs = (slcParams->NumMbsForSlice + slcParams->first_mb_in_slice) / mBScalerForField;
1582         if (usedMBs >= totalMBs)
1583         {
1584             return VA_STATUS_SUCCESS;
1585         }
1586         slcParams++;
1587     }
1588 
1589     uint32_t slcCount;
1590     uint32_t i;
1591     for (slcCount = 0; slcCount < numSlices; slcCount++)
1592     {
1593         if (usedMBs >= totalMBs)
1594             break;
1595 
1596         sliceActualMBs = slc->num_macroblocks;
1597         if (sliceActualMBs % m_encodeCtx->wPicWidthInMB)  // If any slice is a partial row of macroblocks, then set flag to indicate sliceMapSurface is required.
1598         {
1599             m_arbitraryNumMbsInSlice = 1;
1600         }
1601 
1602         if (sliceActualMBs + usedMBs > totalMBs)
1603             sliceActualMBs = totalMBs - usedMBs;
1604 
1605         slcParams->NumMbsForSlice    = sliceActualMBs * mBScalerForField;
1606         slcParams->first_mb_in_slice = usedMBs * mBScalerForField;
1607         usedMBs += sliceActualMBs;
1608 
1609         slcParams->slice_type                       = slc->slice_type;
1610         slcParams->pic_parameter_set_id             = slc->pic_parameter_set_id;
1611         slcParams->idr_pic_id                       = slc->idr_pic_id;
1612         slcParams->pic_order_cnt_lsb                = slc->pic_order_cnt_lsb;
1613         slcParams->delta_pic_order_cnt_bottom       = slc->delta_pic_order_cnt_bottom;
1614         slcParams->delta_pic_order_cnt[0]           = slc->delta_pic_order_cnt[0];
1615         slcParams->delta_pic_order_cnt[1]           = slc->delta_pic_order_cnt[1];
1616         slcParams->direct_spatial_mv_pred_flag      = slc->direct_spatial_mv_pred_flag;
1617         slcParams->num_ref_idx_active_override_flag = slc->num_ref_idx_active_override_flag;
1618         slcParams->num_ref_idx_l0_active_minus1     = slc->num_ref_idx_l0_active_minus1;
1619         slcParams->num_ref_idx_l1_active_minus1     = slc->num_ref_idx_l1_active_minus1;
1620         slcParams->luma_log2_weight_denom           = slc->luma_log2_weight_denom;
1621         slcParams->chroma_log2_weight_denom         = slc->chroma_log2_weight_denom;
1622         slcParams->cabac_init_idc                   = slc->cabac_init_idc;
1623         slcParams->slice_qp_delta                   = slc->slice_qp_delta;
1624         slcParams->disable_deblocking_filter_idc    = slc->disable_deblocking_filter_idc;
1625         slcParams->slice_alpha_c0_offset_div2       = slc->slice_alpha_c0_offset_div2;
1626         slcParams->slice_beta_offset_div2           = slc->slice_beta_offset_div2;
1627 
1628         slcParams->num_ref_idx_l0_active_minus1_from_DDI = slcParams->num_ref_idx_l0_active_minus1;
1629         slcParams->num_ref_idx_l1_active_minus1_from_DDI = slcParams->num_ref_idx_l1_active_minus1;
1630         slcParams->slice_id              = numSlcs + slcCount;
1631         slcParams->luma_weight_flag[0]   = slc->luma_weight_l0_flag;
1632         slcParams->chroma_weight_flag[0] = slc->chroma_weight_l0_flag;
1633         slcParams->luma_weight_flag[1]   = slc->luma_weight_l1_flag;
1634         slcParams->chroma_weight_flag[1] = slc->chroma_weight_l1_flag;
1635 
1636         for (i = 0; i < 32; i++)
1637         {
1638             // list 0
1639             if ((slc->luma_weight_l0_flag) &&
1640                 ((slc->luma_weight_l0[i] != 0) || (slc->luma_offset_l0[i] != 0)))
1641             {
1642                 slcParams->Weights[0][i][0][0] = slc->luma_weight_l0[i];  // Y weight
1643                 slcParams->Weights[0][i][0][1] = slc->luma_offset_l0[i];  // Y offset
1644             }
1645             else
1646             {
1647                 slcParams->Weights[0][i][0][0] = 1 << slcParams->luma_log2_weight_denom;  // Y weight
1648                 slcParams->Weights[0][i][0][1] = 0;                                       // Y offset
1649             }
1650 
1651             if ((slc->chroma_weight_l0_flag) &&
1652                 ((slc->chroma_weight_l0[i][0] != 0) || (slc->chroma_offset_l0[i][0] != 0) ||
1653                     (slc->chroma_weight_l0[i][1] != 0) || (slc->chroma_offset_l0[i][1] != 0)))
1654             {
1655                 slcParams->Weights[0][i][1][0] = slc->chroma_weight_l0[i][0];  // Cb weight
1656                 slcParams->Weights[0][i][1][1] = slc->chroma_offset_l0[i][0];  // Cb offset
1657                 slcParams->Weights[0][i][2][0] = slc->chroma_weight_l0[i][1];  // Cr weight
1658                 slcParams->Weights[0][i][2][1] = slc->chroma_offset_l0[i][1];  // Cr offset
1659             }
1660             else
1661             {
1662                 slcParams->Weights[0][i][1][0] = 1;  // Cb weight
1663                 slcParams->Weights[0][i][1][1] = 0;  // Cb offset
1664                 slcParams->Weights[0][i][2][0] = 1;  // Cr weight
1665                 slcParams->Weights[0][i][2][1] = 0;  // Cr offset
1666             }
1667 
1668             // list 1
1669             if ((slc->luma_weight_l1_flag) &&
1670                 ((slc->luma_weight_l1[i] != 0) || (slc->luma_offset_l1[i] != 0)))
1671             {
1672                 slcParams->Weights[1][i][0][0] = slc->luma_weight_l1[i];  // Y weight
1673                 slcParams->Weights[1][i][0][1] = slc->luma_offset_l1[i];  // Y offset
1674             }
1675             else
1676             {
1677                 slcParams->Weights[1][i][0][0] = 1 << slcParams->luma_log2_weight_denom;  // Y weight
1678                 slcParams->Weights[1][i][0][1] = 0;                                       // Y offset
1679             }
1680 
1681             if ((slc->chroma_weight_l1_flag) &&
1682                 ((slc->chroma_weight_l1[i][0] != 0) || (slc->chroma_offset_l1[i][0] != 0) ||
1683                     (slc->chroma_weight_l1[i][1] != 0) || (slc->chroma_offset_l1[i][1] != 0)))
1684             {
1685                 slcParams->Weights[1][i][1][0] = slc->chroma_weight_l1[i][0];  // Cb weight
1686                 slcParams->Weights[1][i][1][1] = slc->chroma_offset_l1[i][0];  // Cb offset
1687 
1688                 slcParams->Weights[1][i][2][0] = slc->chroma_weight_l1[i][1];  // Cr weight
1689                 slcParams->Weights[1][i][2][1] = slc->chroma_offset_l1[i][1];  // Cr offset
1690             }
1691             else
1692             {
1693                 slcParams->Weights[1][i][1][0] = 1;  // Cb weight
1694                 slcParams->Weights[1][i][1][1] = 0;  // Cb offset
1695 
1696                 slcParams->Weights[1][i][2][0] = 1;  // Cr weight
1697                 slcParams->Weights[1][i][2][1] = 0;  // Cr offset
1698             }
1699         }
1700 
1701         for (i = 0; i < CODEC_MAX_NUM_REF_FIELD; i++)
1702         {
1703             SetupCodecPicture(mediaCtx, &(m_encodeCtx->RTtbl), &(slcParams->RefPicList[0][i]), slc->RefPicList0[i], picParams->FieldCodingFlag, false, true);
1704             GetSlcRefIdx(&(picParams->RefFrameList[0]), &(slcParams->RefPicList[0][i]));
1705         }
1706         for (i = 0; i < CODEC_MAX_NUM_REF_FIELD; i++)
1707         {
1708             SetupCodecPicture(mediaCtx, &(m_encodeCtx->RTtbl), &(slcParams->RefPicList[1][i]), slc->RefPicList1[i], picParams->FieldCodingFlag, false, true);
1709             GetSlcRefIdx(&(picParams->RefFrameList[0]), &(slcParams->RefPicList[1][i]));
1710         }
1711 
1712         slc++;
1713         slcParams++;
1714     }
1715 
1716     picParams->NumSlice += slcCount;
1717     if (picParams->NumSlice > ENCODE_AVC_MAX_SLICES_SUPPORTED)
1718     {
1719         DDI_ASSERTMESSAGE("Number of slices exceeds max supported");
1720         return VA_STATUS_ERROR_INVALID_PARAMETER;
1721     }
1722 
1723     m_encodeCtx->dwNumSlices = picParams->NumSlice;
1724 
1725     return VA_STATUS_SUCCESS;
1726 }
1727 
FindNalUnitStartCodes(uint8_t * buf,uint32_t size,uint32_t * startCodesOffset,uint32_t * startCodesLength)1728 VAStatus DdiEncodeAvc::FindNalUnitStartCodes(
1729     uint8_t * buf,
1730     uint32_t size,
1731     uint32_t * startCodesOffset,
1732     uint32_t * startCodesLength)
1733 {
1734     uint8_t i = 0;
1735 
1736     while (((i + 3) < size) &&
1737            (buf[i] != 0 || buf[i+1] != 0 || buf[i+2] != 0x01) &&
1738            (buf[i] != 0 || buf[i+1] != 0 || buf[i+2] != 0 || buf[i+3] != 0x01))
1739     {
1740         i++;
1741     }
1742 
1743     if ((i + 3) == size)
1744     {
1745         if (buf[i] != 0 || buf[i+1] != 0 || buf[i+2] != 0x01)
1746         {
1747             return VA_STATUS_ERROR_INVALID_BUFFER; //NALU start codes doesn't exit
1748         }
1749         else
1750         {
1751             *startCodesOffset = size - 3;
1752             *startCodesLength = 3;
1753             return VA_STATUS_SUCCESS;
1754         }
1755     }
1756 
1757     if (buf[i] != 0 || buf[i+1] != 0 || buf[i+2] != 0x01)
1758     {
1759         *startCodesOffset = i;
1760         *startCodesLength = 4;
1761     }
1762     else
1763     {
1764         *startCodesOffset = i;
1765         *startCodesLength = 3;
1766     }
1767 
1768     return VA_STATUS_SUCCESS;
1769 }
1770 
ParsePackedHeaderParams(void * ptr)1771 VAStatus DdiEncodeAvc::ParsePackedHeaderParams(void *ptr)
1772 {
1773     DDI_CHK_NULL(m_encodeCtx, "nullptr m_encodeCtx", VA_STATUS_ERROR_INVALID_PARAMETER);
1774     DDI_CHK_NULL(ptr, "nullptr ptr", VA_STATUS_ERROR_INVALID_PARAMETER);
1775 
1776     m_encodeCtx->bLastPackedHdrIsSlice                        = false;
1777     VAEncPackedHeaderParameterBuffer *encPackedHeaderParamBuf = (VAEncPackedHeaderParameterBuffer *)ptr;
1778     CODECHAL_ENCODE_AVC_NAL_UNIT_TYPE nalUnitType;
1779     if (encPackedHeaderParamBuf->type == VAEncPackedHeaderH264_SPS)
1780     {
1781         nalUnitType    = CODECHAL_ENCODE_AVC_NAL_UT_SPS;
1782         m_newSeqHeader = 1;
1783     }
1784     else if (encPackedHeaderParamBuf->type == VAEncPackedHeaderH264_PPS)
1785     {
1786         nalUnitType    = CODECHAL_ENCODE_AVC_NAL_UT_PPS;
1787         m_newPpsHeader = 1;
1788     }
1789     else if (encPackedHeaderParamBuf->type == VAEncPackedHeaderH264_Slice)
1790     {
1791         nalUnitType                        = CODECHAL_ENCODE_AVC_NAL_UT_SLICE;
1792         m_encodeCtx->bLastPackedHdrIsSlice = true;
1793         m_encodeCtx->bHavePackedSliceHdr   = true;
1794 
1795         // check the slice header number. Max supported is AVC_ENCODE_MAX_SLICES_SUPPORTED
1796         if (m_encodeCtx->uiSliceHeaderCnt >= ENCODE_AVC_MAX_SLICES_SUPPORTED)
1797         {
1798             DDI_ASSERTMESSAGE("Number of slices exceeds max supported");
1799             return VA_STATUS_ERROR_MAX_NUM_EXCEEDED;
1800         }
1801 
1802         // get the packed header size
1803         m_encodeCtx->pSliceHeaderData[m_encodeCtx->uiSliceHeaderCnt].BitSize                = encPackedHeaderParamBuf->bit_length;
1804         //don't know NALU start codes now, assign to 4 here when has_emulation_bytes is 0 and later will correct it
1805         m_encodeCtx->pSliceHeaderData[m_encodeCtx->uiSliceHeaderCnt].SkipEmulationByteCount = (encPackedHeaderParamBuf->has_emulation_bytes) ? (encPackedHeaderParamBuf->bit_length + 7) / 8 : 4;
1806     }
1807     else if (encPackedHeaderParamBuf->type == VAEncPackedHeaderRawData)
1808     {
1809         // currently RawData is packed nal unit beside SPS,PPS,SLICE HEADER etc.
1810         // use AUD just because we need a Type to distinguish with Slice header
1811         nalUnitType = CODECHAL_ENCODE_AVC_NAL_UT_AUD;
1812     }
1813     else
1814     {
1815         nalUnitType = CODECHAL_ENCODE_AVC_MAX_NAL_TYPE;
1816     }
1817 
1818     if (encPackedHeaderParamBuf->type != VAEncPackedHeaderH264_Slice)
1819     {
1820         m_encodeCtx->ppNALUnitParams[m_encodeCtx->indexNALUnit]->uiNalUnitType             = nalUnitType;
1821         m_encodeCtx->ppNALUnitParams[m_encodeCtx->indexNALUnit]->bInsertEmulationBytes     = (encPackedHeaderParamBuf->has_emulation_bytes) ? false : true;
1822         //don't know NALU start codes now, assign to 4 here when has_emulation_bytes is 0 and later will correct it
1823         m_encodeCtx->ppNALUnitParams[m_encodeCtx->indexNALUnit]->uiSkipEmulationCheckCount = (encPackedHeaderParamBuf->has_emulation_bytes) ? (encPackedHeaderParamBuf->bit_length + 7) / 8 : 4;
1824         m_encodeCtx->ppNALUnitParams[m_encodeCtx->indexNALUnit]->uiSize                    = (encPackedHeaderParamBuf->bit_length + 7) / 8;
1825         m_encodeCtx->ppNALUnitParams[m_encodeCtx->indexNALUnit]->uiOffset                  = 0;
1826     }
1827 
1828     return VA_STATUS_SUCCESS;
1829 }
1830 
AvcOutBits(uint8_t * pOutBits,uint32_t BitSize)1831 AvcOutBits::AvcOutBits(uint8_t *pOutBits, uint32_t BitSize)
1832 {
1833     m_pOutBits = pOutBits;
1834     m_BitSize = BitSize;
1835     m_BitOffset = 0;
1836 }
1837 
GetBitOffset()1838 inline uint32_t AvcOutBits::GetBitOffset()
1839 {
1840     return m_BitOffset;
1841 }
1842 
PutBit(uint32_t v)1843 void AvcOutBits::PutBit(uint32_t v)
1844 {
1845     DDI_ASSERT(m_BitOffset + 1 <= m_BitSize);
1846 
1847     uint32_t LeftOffset = m_BitOffset % 8;
1848     uint8_t *p = m_pOutBits + m_BitOffset / 8;
1849     (*p) |= ((v & 1) << (7 - LeftOffset));
1850 
1851     m_BitOffset++;
1852 }
1853 
PutBits(uint32_t v,uint32_t n)1854 void AvcOutBits::PutBits(uint32_t v, uint32_t n)
1855 {
1856     DDI_ASSERT((n > 0) && (n <= 32));
1857 
1858     uint32_t t = 0;
1859 
1860     if (!(m_BitOffset % 8) && !(n % 8))
1861     {
1862         uint32_t nBytes = n / 8;
1863         uint8_t *p = m_pOutBits + m_BitOffset / 8;
1864 
1865         while (nBytes-- > 0)
1866             (*p++) = (v >> nBytes) & 0xFF;
1867 
1868         m_BitOffset += n;
1869         return;
1870     }
1871 
1872     while (n-- > 0)
1873         PutBit((v >> n) & 1);
1874 }
1875 
AvcInBits(uint8_t * pInBits,uint32_t BitSize)1876 AvcInBits::AvcInBits(uint8_t *pInBits, uint32_t BitSize)
1877 {
1878     m_pInBits = pInBits;
1879     m_BitSize = BitSize;
1880     m_BitOffset = 0;
1881 }
1882 
SkipBits(uint32_t n)1883 void AvcInBits::SkipBits(uint32_t n)
1884 {
1885     DDI_ASSERT(n > 0);
1886     DDI_ASSERT(m_BitOffset + n <= m_BitSize);
1887 
1888     m_BitOffset += n;
1889 }
1890 
GetBit()1891 uint32_t AvcInBits::GetBit()
1892 {
1893     DDI_ASSERT(m_BitOffset + 1 <= m_BitSize);
1894 
1895     uint32_t LeftOffset = m_BitOffset % 8;
1896     uint8_t const *p = m_pInBits + m_BitOffset / 8;
1897     uint32_t v = (*p >> (7 - LeftOffset)) & 1;
1898 
1899     m_BitOffset++;
1900     return v;
1901 }
1902 
GetBits(uint32_t n)1903 uint32_t AvcInBits::GetBits(uint32_t n)
1904 {
1905     DDI_ASSERT((n > 0) && (n <= 32));
1906 
1907     uint32_t v = 0;
1908 
1909     if (!(m_BitOffset % 8) && !(n % 8))
1910     {
1911         uint32_t nBytes = n / 8;
1912         uint8_t const *p = m_pInBits + m_BitOffset / 8;
1913 
1914         while (nBytes-- > 0)
1915             v = (v << 8) | (*p++);
1916 
1917         m_BitOffset += n;
1918         return v;
1919     }
1920 
1921     while (n-- > 0)
1922         v = (v << 1) | GetBit();
1923 
1924     return v;
1925 }
1926 
GetUE()1927 uint32_t AvcInBits::AvcInBits::GetUE()
1928 {
1929     uint32_t nZero = 0;
1930     while(!GetBit())
1931         nZero++;
1932 
1933     return nZero ? ((1 << nZero) | GetBits(nZero)) - 1 : 0;
1934 }
1935 
GetBitOffset()1936 inline uint32_t AvcInBits::GetBitOffset()
1937 {
1938     return m_BitOffset;
1939 }
1940 
ResetBitOffset()1941 inline void AvcInBits::ResetBitOffset()
1942 {
1943     m_BitOffset = 0;
1944 }
1945 
CheckPackedSlcHeaderData(void * pInSlcHdr,uint32_t InBitSize,void ** ppOutSlcHdr,uint32_t & OutBitSize)1946 MOS_STATUS DdiEncodeAvc::CheckPackedSlcHeaderData(
1947     void *pInSlcHdr,
1948     uint32_t InBitSize,
1949     void **ppOutSlcHdr,
1950     uint32_t &OutBitSize)
1951 {
1952     MOS_STATUS status;
1953     uint32_t HdrBitSize = 0;
1954 
1955     *ppOutSlcHdr = NULL;
1956     OutBitSize = 0;
1957 
1958     if (VAEntrypointEncSliceLP != m_encodeCtx->vaEntrypoint)
1959         return MOS_STATUS_SUCCESS;
1960 
1961     if (0 == InBitSize || NULL == pInSlcHdr)
1962         return MOS_STATUS_SUCCESS;
1963 
1964     AvcInBits InBits((uint8_t*)pInSlcHdr, InBitSize);
1965 
1966     // Skip start code
1967     uint8_t StartCode = 0;
1968     while (1 != StartCode) {
1969         StartCode = InBits.GetBits(8);
1970         HdrBitSize += 8;
1971     }
1972 
1973     uint32_t StartBitSize = HdrBitSize;
1974 
1975     // Check NAL Unit type
1976     HdrBitSize += 8;
1977     InBits.SkipBits(1);
1978     InBits.SkipBits(2);
1979     uint32_t nalUnitType = InBits.GetBits(5);
1980     if (20 == nalUnitType)
1981     {
1982         // MVC enxtension
1983         InBits.SkipBits(24);
1984         HdrBitSize += 24;
1985     }
1986 
1987     // find first_mb_in_slice
1988     uint32_t first_mb_in_slice = InBits.GetUE();
1989     if (0 == first_mb_in_slice)
1990         return MOS_STATUS_SUCCESS;
1991 
1992     // Force first_mb_in_slice to 0 for AVC VDENC
1993     uint32_t LeftBitSize = InBitSize - InBits.GetBitOffset();
1994     OutBitSize = LeftBitSize + HdrBitSize + 1;
1995     *ppOutSlcHdr = MOS_AllocAndZeroMemory((OutBitSize + 7) / 8);
1996 
1997     AvcOutBits OutBits((uint8_t*)(*ppOutSlcHdr), OutBitSize);
1998 
1999     InBits.ResetBitOffset();
2000     OutBits.PutBits(InBits.GetBits(StartBitSize), StartBitSize);
2001     OutBits.PutBits(InBits.GetBits(8), 8);
2002     if (20 == nalUnitType)
2003         OutBits.PutBits(InBits.GetBits(24), 24);
2004 
2005     // Replace first_mb_in_slice
2006     first_mb_in_slice = InBits.GetUE();
2007     OutBits.PutBit(0);
2008 
2009     // Copy the left data
2010     while (LeftBitSize >= 32)
2011     {
2012         OutBits.PutBits(InBits.GetBits(32), 32);
2013         LeftBitSize -= 32;
2014     }
2015 
2016     if (LeftBitSize)
2017         OutBits.PutBits(InBits.GetBits(LeftBitSize), LeftBitSize);
2018 
2019     return MOS_STATUS_SUCCESS;
2020 }
2021 
ParsePackedHeaderData(void * ptr)2022 VAStatus DdiEncodeAvc::ParsePackedHeaderData(void *ptr)
2023 {
2024     DDI_CHK_NULL(m_encodeCtx, "nullptr m_encodeCtx", VA_STATUS_ERROR_INVALID_PARAMETER);
2025     DDI_CHK_NULL(ptr, "nullptr ptr", VA_STATUS_ERROR_INVALID_PARAMETER);
2026 
2027     BSBuffer *bsBuffer = m_encodeCtx->pbsBuffer;
2028     DDI_CHK_NULL(bsBuffer, "nullptr bsBuffer", VA_STATUS_ERROR_INVALID_PARAMETER);
2029 
2030     if ((m_encodeCtx->indexNALUnit == 0) && (m_encodeCtx->uiSliceHeaderCnt == 0))
2031     {
2032         *(bsBuffer->pBase)    = 0;
2033         bsBuffer->pCurrent    = bsBuffer->pBase;
2034         bsBuffer->SliceOffset = 0;
2035         bsBuffer->BitOffset   = 0;
2036         bsBuffer->BitSize     = 0;
2037     }
2038 
2039     uint32_t hdrDataSize;
2040     if (true == m_encodeCtx->bLastPackedHdrIsSlice)
2041     {
2042         void *temp_ptr = NULL;
2043         uint32_t temp_size = 0;
2044 
2045         MOS_STATUS status = CheckPackedSlcHeaderData(ptr,
2046             m_encodeCtx->pSliceHeaderData[m_encodeCtx->uiSliceHeaderCnt].BitSize,
2047             &temp_ptr, temp_size);
2048         if (MOS_STATUS_SUCCESS != status)
2049         {
2050             DDI_ASSERTMESSAGE("DDI:packed slice header is not supported!");
2051             return VA_STATUS_ERROR_INVALID_PARAMETER;
2052         }
2053 
2054         if (temp_size && temp_ptr)
2055         {
2056             m_encodeCtx->pSliceHeaderData[m_encodeCtx->uiSliceHeaderCnt].BitSize = temp_size;
2057         }
2058 
2059         hdrDataSize = (m_encodeCtx->pSliceHeaderData[m_encodeCtx->uiSliceHeaderCnt].BitSize + 7) / 8;
2060 
2061         status = MOS_SecureMemcpy(bsBuffer->pCurrent,
2062             bsBuffer->BufferSize - bsBuffer->SliceOffset,
2063             (uint8_t *)(temp_ptr ? temp_ptr : ptr),
2064             hdrDataSize);
2065 
2066         if (temp_ptr)
2067         {
2068             MOS_FreeMemory(temp_ptr);
2069             temp_size = 0;
2070             temp_ptr = NULL;
2071         }
2072 
2073         if (MOS_STATUS_SUCCESS != status)
2074         {
2075             DDI_ASSERTMESSAGE("DDI:packed slice header size is too large to be supported!");
2076             return VA_STATUS_ERROR_INVALID_PARAMETER;
2077         }
2078 
2079         m_encodeCtx->pSliceHeaderData[m_encodeCtx->uiSliceHeaderCnt].SliceOffset = bsBuffer->pCurrent - bsBuffer->pBase;
2080 
2081         // correct SkipEmulationByteCount
2082         // according to LibVA principle, one packed header buffer should only contain one NALU,
2083         // so when has_emulation_bytes is 0, SkipEmulationByteCount only needs to skip the NALU start codes
2084         if (m_encodeCtx->pSliceHeaderData[m_encodeCtx->uiSliceHeaderCnt].SkipEmulationByteCount != hdrDataSize)
2085         {
2086             uint32_t startCodesOffset = 0;
2087             uint32_t startCodesLength = 0;
2088             VAStatus vaSts = VA_STATUS_SUCCESS;
2089             vaSts = FindNalUnitStartCodes((uint8_t *)ptr, hdrDataSize, &startCodesOffset, &startCodesLength);
2090             if (VA_STATUS_SUCCESS != vaSts)
2091             {
2092                 DDI_ASSERTMESSAGE("DDI: packed slice header doesn't include NAL unit start codes!");
2093                 return vaSts;
2094             }
2095             m_encodeCtx->pSliceHeaderData[m_encodeCtx->uiSliceHeaderCnt].SkipEmulationByteCount = MOS_MIN(15, (startCodesOffset + startCodesLength));
2096         }
2097 
2098         m_encodeCtx->uiSliceHeaderCnt++;
2099         m_encodeCtx->bLastPackedHdrIsSlice = false;
2100     }
2101     else
2102     {
2103         // copy sps and pps header data
2104         hdrDataSize       = m_encodeCtx->ppNALUnitParams[m_encodeCtx->indexNALUnit]->uiSize;
2105         MOS_STATUS status = MOS_SecureMemcpy(bsBuffer->pCurrent,
2106             bsBuffer->BufferSize - bsBuffer->SliceOffset,
2107             (uint8_t *)ptr,
2108             hdrDataSize);
2109         if (MOS_STATUS_SUCCESS != status)
2110         {
2111             DDI_ASSERTMESSAGE("DDI:packed header size is too large to be supported!");
2112             return VA_STATUS_ERROR_INVALID_PARAMETER;
2113         }
2114 
2115         // correct uiSkipEmulationCheckCount
2116         // according to LibVA principle, one packed header buffer should only contain one NALU,
2117         // so when has_emulation_bytes is 0, uiSkipEmulationCheckCount only needs to skip the NALU start codes
2118         if (m_encodeCtx->ppNALUnitParams[m_encodeCtx->indexNALUnit]->uiSkipEmulationCheckCount != hdrDataSize)
2119         {
2120             uint32_t startCodesOffset = 0;
2121             uint32_t startCodesLength = 0;
2122             VAStatus vaSts = VA_STATUS_SUCCESS;
2123             vaSts = FindNalUnitStartCodes((uint8_t *)ptr, hdrDataSize, &startCodesOffset, &startCodesLength);
2124             if (VA_STATUS_SUCCESS != vaSts)
2125             {
2126                 DDI_ASSERTMESSAGE("DDI: packed header doesn't include NAL unit start codes!");
2127                 return vaSts;
2128             }
2129             m_encodeCtx->ppNALUnitParams[m_encodeCtx->indexNALUnit]->uiSkipEmulationCheckCount = MOS_MIN(15, (startCodesOffset + startCodesLength));
2130         }
2131 
2132         m_encodeCtx->ppNALUnitParams[m_encodeCtx->indexNALUnit]->uiOffset = bsBuffer->pCurrent - bsBuffer->pBase;
2133         m_encodeCtx->indexNALUnit++;
2134     }
2135     bsBuffer->pCurrent += hdrDataSize;
2136     bsBuffer->SliceOffset += hdrDataSize;
2137     bsBuffer->BitSize += hdrDataSize * 8;
2138 
2139     return VA_STATUS_SUCCESS;
2140 }
2141 
ParseMiscParams(void * ptr)2142 VAStatus DdiEncodeAvc::ParseMiscParams(void *ptr)
2143 {
2144     DDI_CHK_NULL(m_encodeCtx, "nullptr m_encodeCtx", VA_STATUS_ERROR_INVALID_PARAMETER);
2145     DDI_CHK_NULL(ptr, "nullptr ptr", VA_STATUS_ERROR_INVALID_PARAMETER);
2146 
2147     VAEncMiscParameterBuffer *miscParamBuf = (VAEncMiscParameterBuffer *)ptr;
2148     DDI_CHK_NULL(miscParamBuf->data, "nullptr miscParamBuf->data", VA_STATUS_ERROR_INVALID_PARAMETER);
2149 
2150     VAStatus status = VA_STATUS_SUCCESS;
2151     switch ((int32_t)(miscParamBuf->type))
2152     {
2153     case VAEncMiscParameterTypeHRD:
2154         status = ParseMiscParamHRD((void *)miscParamBuf->data);
2155         break;
2156 
2157     case VAEncMiscParameterTypeFrameRate:
2158         status = ParseMiscParamFR((void *)miscParamBuf->data);
2159         break;
2160 
2161     case VAEncMiscParameterTypeRateControl:
2162         status = ParseMiscParamRC((void *)miscParamBuf->data);
2163         break;
2164 
2165     case VAEncMiscParameterTypeEncQuality:
2166         status = ParseMiscParamEncQuality((void *)miscParamBuf->data);
2167         break;
2168 
2169     case VAEncMiscParameterTypeQuantization:
2170         status = ParseMiscParamQuantization((void *)miscParamBuf->data);
2171         break;
2172 
2173     case VAEncMiscParameterTypeRIR:
2174         status = ParseMiscParameterRIR((void *)miscParamBuf->data);
2175         break;
2176 
2177     case VAEncMiscParameterTypeSkipFrame:
2178         status = ParseMiscParamSkipFrame((void *)miscParamBuf->data);
2179         break;
2180 
2181     case VAEncMiscParameterTypeMaxFrameSize:
2182         status = ParseMiscParamMaxFrameSize((void *)miscParamBuf->data);
2183         break;
2184 
2185     case VAEncMiscParameterTypeMultiPassFrameSize:
2186         status = ParseMiscParamMultiPassFrameSize((void *)miscParamBuf->data);
2187         break;
2188 
2189     case VAEncMiscParameterTypeQualityLevel:
2190         status = ParseMiscParamQualityLevel((void *)miscParamBuf->data);
2191         break;
2192 
2193     case VAEncMiscParameterTypeMaxSliceSize:
2194         status = ParseMiscParamMaxSliceSize((void *)miscParamBuf->data);
2195         break;
2196 
2197     case VAEncMiscParameterTypeROI:
2198         status = ParseMiscParamROI((void *)miscParamBuf->data);
2199         break;
2200 
2201     case VAEncMiscParameterTypeDirtyRect:
2202         status = ParseMiscParamDirtyROI((void *)miscParamBuf->data);
2203         break;
2204 
2205     case VAEncMiscParameterTypeCustomRoundingControl:
2206         status = ParseMiscParamRounding((void *)miscParamBuf->data);
2207         break;
2208 
2209     case VAEncMiscParameterTypeSubMbPartPel:
2210         status = ParseMiscParamSubMbPartPel((void *)miscParamBuf->data);
2211         break;
2212 
2213     default:
2214         DDI_ASSERTMESSAGE("unsupported misc parameter type.");
2215         status = VA_STATUS_ERROR_INVALID_PARAMETER;
2216         break;
2217     }
2218 
2219     return status;
2220 }
2221 
GetSlcRefIdx(CODEC_PICTURE * picReference,CODEC_PICTURE * slcReference)2222 void DdiEncodeAvc::GetSlcRefIdx(CODEC_PICTURE *picReference, CODEC_PICTURE *slcReference)
2223 {
2224     if (nullptr == picReference || nullptr == slcReference)
2225     {return;}
2226 
2227     int32_t i = 0;
2228     if (slcReference->FrameIdx != CODEC_AVC_NUM_UNCOMPRESSED_SURFACE)
2229     {
2230         for (i = 0; i < CODEC_MAX_NUM_REF_FRAME; i++)
2231         {
2232             if (slcReference->FrameIdx == picReference[i].FrameIdx)
2233             {
2234                 slcReference->FrameIdx = i;
2235                 break;
2236             }
2237         }
2238         if (i == CODEC_MAX_NUM_REF_FRAME)
2239         {
2240             slcReference->FrameIdx = CODEC_AVC_NUM_UNCOMPRESSED_SURFACE;
2241             slcReference->PicFlags = PICTURE_INVALID;
2242         }
2243     }
2244 }
2245 
SetupCodecPicture(DDI_MEDIA_CONTEXT * mediaCtx,DDI_CODEC_RENDER_TARGET_TABLE * rtTbl,CODEC_PICTURE * codecHalPic,VAPictureH264 vaPic,bool fieldPicFlag,bool picReference,bool sliceReference)2246 void DdiEncodeAvc::SetupCodecPicture(
2247     DDI_MEDIA_CONTEXT                   *mediaCtx,
2248     DDI_CODEC_RENDER_TARGET_TABLE       *rtTbl,
2249     CODEC_PICTURE                       *codecHalPic,
2250     VAPictureH264                       vaPic,
2251     bool                                fieldPicFlag,
2252     bool                                picReference,
2253     bool                                sliceReference)
2254 {
2255     if(vaPic.picture_id != DDI_CODEC_INVALID_FRAME_INDEX)
2256     {
2257         DDI_MEDIA_SURFACE *surface = DdiMedia_GetSurfaceFromVASurfaceID(mediaCtx, vaPic.picture_id);
2258         vaPic.frame_idx    = GetRenderTargetID(rtTbl, surface);
2259         codecHalPic->FrameIdx = (uint8_t)vaPic.frame_idx;
2260     }
2261     else
2262     {
2263         vaPic.frame_idx    = DDI_CODEC_INVALID_FRAME_INDEX;
2264         codecHalPic->FrameIdx = CODEC_AVC_NUM_UNCOMPRESSED_SURFACE - 1;
2265     }
2266 
2267     if (picReference)
2268     {
2269         if (vaPic.frame_idx == DDI_CODEC_INVALID_FRAME_INDEX)
2270         {
2271             codecHalPic->PicFlags = PICTURE_INVALID;
2272         }
2273         else if ((vaPic.flags&VA_PICTURE_H264_LONG_TERM_REFERENCE) == VA_PICTURE_H264_LONG_TERM_REFERENCE)
2274         {
2275             codecHalPic->PicFlags = PICTURE_LONG_TERM_REFERENCE;
2276         }
2277         else
2278         {
2279             codecHalPic->PicFlags = PICTURE_SHORT_TERM_REFERENCE;
2280         }
2281     }
2282     else
2283     {
2284         if (fieldPicFlag)
2285         {
2286             if ((vaPic.flags&VA_PICTURE_H264_BOTTOM_FIELD) == VA_PICTURE_H264_BOTTOM_FIELD)
2287             {
2288                 codecHalPic->PicFlags = PICTURE_BOTTOM_FIELD;
2289             }
2290             else
2291             {
2292                 codecHalPic->PicFlags = PICTURE_TOP_FIELD;
2293             }
2294         }
2295         else
2296         {
2297             codecHalPic->PicFlags = PICTURE_FRAME;
2298         }
2299     }
2300 
2301     if (sliceReference && (vaPic.picture_id == VA_INVALID_ID))//VA_INVALID_ID is used to indicate invalide picture in LIBVA.
2302     {
2303         codecHalPic->PicFlags = PICTURE_INVALID;
2304     }
2305 }
2306 
getSliceParameterBufferSize()2307 uint32_t DdiEncodeAvc::getSliceParameterBufferSize()
2308 {
2309     return sizeof(VAEncSliceParameterBufferH264);
2310 }
2311 
getSequenceParameterBufferSize()2312 uint32_t DdiEncodeAvc::getSequenceParameterBufferSize()
2313 {
2314     return sizeof(VAEncSequenceParameterBufferH264);
2315 }
2316 
getPictureParameterBufferSize()2317 uint32_t DdiEncodeAvc::getPictureParameterBufferSize()
2318 {
2319     return sizeof(VAEncPictureParameterBufferH264);
2320 }
2321 
getQMatrixBufferSize()2322 uint32_t DdiEncodeAvc::getQMatrixBufferSize()
2323 {
2324     return sizeof(VAIQMatrixBufferH264);
2325 }
2326 
ClearPicParams()2327 void DdiEncodeAvc::ClearPicParams()
2328 {
2329     uint8_t ppsIdx = ((PCODEC_AVC_ENCODE_SLICE_PARAMS)(m_encodeCtx->pSliceParams))->pic_parameter_set_id;
2330     PCODEC_AVC_ENCODE_PIC_PARAMS  picParams = (PCODEC_AVC_ENCODE_PIC_PARAMS)m_encodeCtx->pPicParams + ppsIdx;
2331 
2332     if (picParams != nullptr && picParams->pDeltaQp != nullptr)
2333     {
2334         MOS_FreeMemory(picParams->pDeltaQp);
2335         picParams->pDeltaQp = nullptr;
2336     }
2337 }
2338