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