1 /*
2 * Copyright (c) 2020-2023, Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22 //!
23 //! \file encode_avc_basic_feature.cpp
24 //! \brief Defines the common interface for encode avc parameter
25 //!
26
27 #include "encode_avc_basic_feature.h"
28 #include "encode_avc_header_packer.h"
29 #include "encode_avc_vdenc_const_settings.h"
30 #include "mos_os_cp_interface_specific.h"
31
32 namespace encode
33 {
~AvcBasicFeature()34 AvcBasicFeature::~AvcBasicFeature()
35 {
36 if (m_colocatedMVBufferForIFrames) {
37 m_allocator->DestroyResource(m_colocatedMVBufferForIFrames);
38 m_colocatedMVBufferForIFrames = nullptr;
39 }
40 }
41
Init(void * setting)42 MOS_STATUS AvcBasicFeature::Init(void *setting)
43 {
44 ENCODE_FUNC_CALL();
45 ENCODE_CHK_NULL_RETURN(setting);
46
47 ENCODE_CHK_STATUS_RETURN(EncodeBasicFeature::Init(setting));
48
49 ENCODE_CHK_STATUS_RETURN(InitRefFrames());
50
51 MediaUserSetting::Value outValue;
52
53 ReadUserSetting(
54 m_userSettingPtr,
55 outValue,
56 "Encode Suppress Recon Pic",
57 MediaUserSetting::Group::Sequence);
58
59 m_suppressReconPicSupported = (outValue.Get<int32_t>()) ? true : false;
60
61 outValue = 0;
62
63 ReadUserSetting(
64 m_userSettingPtr,
65 outValue,
66 "AVC Encode Adaptive Rounding Inter Enable",
67 MediaUserSetting::Group::Sequence);
68
69 m_adaptiveRoundingInterEnable = (outValue.Get<int32_t>()) ? true : false;
70
71 m_targetUsageOverride = (uint8_t)0;
72
73 m_brcAdaptiveRegionBoostSupported = true;
74
75 #if (_DEBUG || _RELEASE_INTERNAL)
76
77 outValue = 0;
78
79 ReadUserSettingForDebug(
80 m_userSettingPtr,
81 outValue,
82 "Encode TU Override",
83 MediaUserSetting::Group::Sequence);
84
85 m_targetUsageOverride = uint8_t(outValue.Get<uint32_t>());
86
87 outValue = 0;
88
89 ReadUserSettingForDebug(
90 m_userSettingPtr,
91 outValue,
92 "AVC VDEnc PerMB StreamOut Enable",
93 MediaUserSetting::Group::Sequence);
94
95 m_perMBStreamOutEnable = (outValue.Get<int32_t>()) ? true : false;
96
97 outValue = 0;
98
99 ReadUserSettingForDebug(
100 m_userSettingPtr,
101 outValue,
102 "AVC VDEnc TCBRC ARB Disable",
103 MediaUserSetting::Group::Sequence);
104
105 m_brcAdaptiveRegionBoostSupported = (outValue.Get<int32_t>()) ? false : m_brcAdaptiveRegionBoostSupported;
106
107 #endif // _DEBUG || _RELEASE_INTERNAL
108
109 return MOS_STATUS_SUCCESS;
110 }
111
InitRefFrames()112 MOS_STATUS AvcBasicFeature::InitRefFrames()
113 {
114 ENCODE_FUNC_CALL();
115
116 m_ref = std::make_shared<AvcReferenceFrames>();
117 ENCODE_CHK_NULL_RETURN(m_ref);
118
119 ENCODE_CHK_STATUS_RETURN(m_ref->Init(this, m_allocator));
120
121 return MOS_STATUS_SUCCESS;
122 }
123
Update(void * params)124 MOS_STATUS AvcBasicFeature::Update(void *params)
125 {
126 ENCODE_FUNC_CALL();
127
128 ENCODE_CHK_NULL_RETURN(params);
129 ENCODE_CHK_STATUS_RETURN(EncodeBasicFeature::Update(params));
130
131 EncoderParams* encodeParams = (EncoderParams*)params;
132 ENCODE_CHK_NULL_RETURN(encodeParams->pSeqParams);
133 ENCODE_CHK_NULL_RETURN(encodeParams->pPicParams);
134 ENCODE_CHK_NULL_RETURN(encodeParams->pSliceParams);
135 ENCODE_CHK_NULL_RETURN(encodeParams->pVuiParams);
136 ENCODE_CHK_NULL_RETURN(encodeParams->pIQMatrixBuffer);
137 ENCODE_CHK_NULL_RETURN(encodeParams->pIQWeightScaleLists);
138 ENCODE_CHK_NULL_RETURN(encodeParams->ppNALUnitParams);
139
140 auto ppsidx = ((PCODEC_AVC_ENCODE_SLICE_PARAMS)(encodeParams->pSliceParams))->pic_parameter_set_id;
141 auto spsidx = ((PCODEC_AVC_ENCODE_PIC_PARAMS)(encodeParams->pPicParams))->seq_parameter_set_id;
142 if (ppsidx >= CODEC_AVC_MAX_PPS_NUM || spsidx >= CODEC_AVC_MAX_SPS_NUM)
143 {
144 //should never happen
145 ENCODE_ASSERTMESSAGE("Invalid ppsidx/spsidx");
146 return MOS_STATUS_UNKNOWN;
147 }
148
149 m_seqParam = m_seqParams[spsidx] = (PCODEC_AVC_ENCODE_SEQUENCE_PARAMS)(encodeParams->pSeqParams);
150 m_picParam = m_picParams[ppsidx] = (PCODEC_AVC_ENCODE_PIC_PARAMS)(encodeParams->pPicParams);
151 m_vuiParams = (PCODECHAL_ENCODE_AVC_VUI_PARAMS)encodeParams->pVuiParams;
152 m_sliceParams = (PCODEC_AVC_ENCODE_SLICE_PARAMS)encodeParams->pSliceParams;
153 m_iqMatrixParams = (PCODEC_AVC_IQ_MATRIX_PARAMS)encodeParams->pIQMatrixBuffer;
154 m_iqWeightScaleLists = (PCODEC_AVC_ENCODE_IQ_WEIGTHSCALE_LISTS)encodeParams->pIQWeightScaleLists;
155 m_nalUnitParams = encodeParams->ppNALUnitParams;
156 m_sliceStructCaps = encodeParams->uiSlcStructCaps;
157 m_madEnabled = encodeParams->bMADEnabled;
158 m_acceleratorHeaderPackingCaps = encodeParams->bAcceleratorHeaderPackingCaps;
159 m_skipFrameFlag = m_picParam->SkipFrameFlag;
160
161 if (encodeParams->pSeiData != nullptr)
162 {
163 ENCODE_CHK_STATUS_RETURN(UpdateSeiParameters(encodeParams));
164 }
165
166 m_deblockingEnabled = 0;
167 for (uint32_t i = 0; i < m_numSlices; i++)
168 {
169 if (m_sliceParams[i].disable_deblocking_filter_idc != 1)
170 {
171 m_deblockingEnabled = 1;
172 break;
173 }
174 }
175
176 if (m_newSeq)
177 {
178 ENCODE_CHK_STATUS_RETURN(SetSequenceStructs());
179 }
180
181 ENCODE_CHK_STATUS_RETURN(SetPictureStructs());
182 ENCODE_CHK_STATUS_RETURN(SetSliceStructs());
183
184 m_useRawForRef = m_userFlags.bUseRawPicForRef;
185
186 // Set min/max QP values in AVC State based on frame type if atleast one of them is non-zero
187 if (m_picParam->ucMinimumQP || m_picParam->ucMaximumQP)
188 {
189 UpdateMinMaxQp();
190 }
191
192 if (m_codecFunction != CODECHAL_FUNCTION_ENC && !m_userFlags.bDisableAcceleratorHeaderPacking && m_acceleratorHeaderPackingCaps)
193 {
194 ENCODE_CHK_STATUS_RETURN(PackPictureHeader());
195 }
196
197 CheckResolutionChange();
198
199 if (m_resolutionChanged)
200 {
201 ENCODE_CHK_STATUS_RETURN(UpdateTrackedBufferParameters());
202 }
203
204 ENCODE_CHK_STATUS_RETURN(GetTrackedBuffers());
205
206 m_brcAdaptiveRegionBoostEnabled = m_brcAdaptiveRegionBoostSupported && (m_picParam->TargetFrameSize != 0) && m_lookaheadDepth == 0;
207
208 // HW limitation, skip block count for B frame must be acquired in GetAvcVdencMBLevelStatusExt
209 if (m_picParam->StatusReportEnable.fields.BlockStats ||
210 (m_picParam->StatusReportEnable.fields.FrameStats && m_picParam->CodingType == B_TYPE))
211 {
212 m_perMBStreamOutEnable = true;
213 }
214
215 #if MHW_HWCMDPARSER_ENABLED
216 char frameType = '\0';
217 switch (m_picParam->CodingType)
218 {
219 case I_TYPE:
220 frameType = 'I';
221 break;
222 case P_TYPE:
223 frameType = 'P';
224 break;
225 case B_TYPE:
226 frameType = (m_picParam->RefPicFlag) ? 'B' : 'b';
227 break;
228 }
229
230 auto instance = mhw::HwcmdParser::GetInstance();
231 if (instance)
232 {
233 instance->Update(frameType, (void *)m_featureManager);
234 }
235 #endif
236
237 return MOS_STATUS_SUCCESS;
238 }
239
SetSequenceStructs()240 MOS_STATUS AvcBasicFeature::SetSequenceStructs()
241 {
242 ENCODE_FUNC_CALL();
243
244 ENCODE_CHK_NULL_RETURN(m_osInterface->osCpInterface);
245
246 auto seqParams = m_seqParam;
247
248 // For G12+ TCBRC is used instead of LowDelayBRC, also needs TargetFrameSize in PPS.
249 m_forcedTCBRC = false;
250 if (seqParams->FrameSizeTolerance == EFRAMESIZETOL_EXTREMELY_LOW && !seqParams->LookaheadDepth)
251 {
252 ENCODE_NORMALMESSAGE("LDBRC switched to TCBRC\n");
253 m_forcedTCBRC = true;
254 seqParams->FrameSizeTolerance = EFRAMESIZETOL_NORMAL;
255 seqParams->MBBRC = mbBrcDisabled; // no need with ARB
256 }
257
258 if (m_targetUsageOverride)
259 {
260 seqParams->TargetUsage = m_targetUsageOverride;
261 }
262
263 // seq_scaling_matrix_present_flag and chroma_format_idc
264 // shall not be present for main profile
265 if (seqParams->Profile == CODEC_AVC_MAIN_PROFILE)
266 {
267 seqParams->seq_scaling_matrix_present_flag = 0;
268 for (uint8_t i = 0; i < 12; i++)
269 {
270 seqParams->seq_scaling_list_present_flag[i] = 0;
271 }
272 seqParams->chroma_format_idc = 1;
273 }
274 // high profile chroma_format_idc in the range of 0 to 1 inclusive
275 if (seqParams->chroma_format_idc > 1)
276 {
277 seqParams->chroma_format_idc = 1;
278 }
279
280 // main & high profile support only 8bpp
281 seqParams->bit_depth_luma_minus8 = 0;
282 seqParams->bit_depth_chroma_minus8 = 0;
283
284 // setup parameters corresponding to H264 bit stream definition
285 seqParams->pic_height_in_map_units_minus1 = seqParams->frame_mbs_only_flag ? CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(seqParams->FrameHeight) - 1 : (CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(seqParams->FrameHeight) + 1) / 2 - 1;
286 seqParams->pic_width_in_mbs_minus1 = CODECHAL_GET_WIDTH_IN_MACROBLOCKS(seqParams->FrameWidth) - 1;
287 seqParams->constraint_set0_flag = 0;
288 seqParams->constraint_set1_flag = (seqParams->Profile == CODEC_AVC_BASE_PROFILE) ? 1 : 0;
289 seqParams->constraint_set2_flag = 0;
290 seqParams->constraint_set3_flag = 0;
291 seqParams->gaps_in_frame_num_value_allowed_flag = 0;
292 seqParams->qpprime_y_zero_transform_bypass_flag = 0;
293 seqParams->separate_colour_plane_flag = 0;
294
295 // setup internal parameters
296 m_picWidthInMb = CODECHAL_GET_WIDTH_IN_MACROBLOCKS(seqParams->FrameWidth);
297 m_picHeightInMb = CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(seqParams->FrameHeight);
298 m_frameWidth = m_picWidthInMb * CODECHAL_MACROBLOCK_WIDTH;
299 m_frameHeight = m_picHeightInMb * CODECHAL_MACROBLOCK_HEIGHT;
300
301 m_downscaledWidth4x = CODECHAL_GET_WIDTH_IN_MACROBLOCKS(m_frameWidth / SCALE_FACTOR_4x) * CODECHAL_MACROBLOCK_WIDTH;
302 m_downscaledHeight4x = ((CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(m_frameHeight / SCALE_FACTOR_4x) + 1) >> 1) * CODECHAL_MACROBLOCK_HEIGHT;
303 m_downscaledHeight4x = MOS_ALIGN_CEIL(m_downscaledHeight4x, MOS_YTILE_H_ALIGNMENT) << 1;
304
305 m_targetUsage = seqParams->TargetUsage & 0x7;
306
307 if (!seqParams->frame_cropping_flag)
308 {
309 // do cropping only when the picture dimension is not MB aligned...
310 seqParams->frame_crop_left_offset = 0;
311 seqParams->frame_crop_top_offset = 0;
312
313 if (m_frameWidth != seqParams->FrameWidth ||
314 m_frameHeight != seqParams->FrameHeight)
315 {
316 seqParams->frame_cropping_flag = 1;
317 seqParams->frame_crop_right_offset = (uint16_t)((m_frameWidth - seqParams->FrameWidth) >> 1); // 4:2:0
318 seqParams->frame_crop_bottom_offset = (uint16_t)((m_frameHeight - seqParams->FrameHeight) >> (2 - seqParams->frame_mbs_only_flag)); // 4:2:0
319 }
320 else
321 {
322 seqParams->frame_cropping_flag = 0;
323 seqParams->frame_crop_right_offset = 0;
324 seqParams->frame_crop_bottom_offset = 0;
325 }
326 }
327
328 // App does tail insertion in VDEnc dynamic slice non-CP case
329 m_vdencNoTailInsertion =
330 seqParams->EnableSliceLevelRateCtrl &&
331 (!m_osInterface->osCpInterface->IsCpEnabled());
332
333 m_maxNumSlicesAllowed = GetMaxNumSlicesAllowed(
334 (CODEC_AVC_PROFILE_IDC)(seqParams->Profile),
335 (CODEC_AVC_LEVEL_IDC)(seqParams->Level),
336 seqParams->FramesPer100Sec);
337
338 // Lookahead setup
339 m_lookaheadDepth = seqParams->LookaheadDepth;
340 if (m_lookaheadDepth > 0)
341 {
342 uint64_t targetBitRate = (uint64_t)seqParams->TargetBitRate;
343 if ((seqParams->FramesPer100Sec < 100) || ((targetBitRate * 100) < seqParams->FramesPer100Sec))
344 {
345 ENCODE_ASSERTMESSAGE("Invalid FrameRate or TargetBitRate in lookahead pass!");
346 return MOS_STATUS_INVALID_PARAMETER;
347 }
348 m_averageFrameSize = (uint32_t)(targetBitRate * 100 / seqParams->FramesPer100Sec);
349
350 if (seqParams->VBVBufferSizeInBit < seqParams->InitVBVBufferFullnessInBit)
351 {
352 ENCODE_ASSERTMESSAGE("VBVBufferSizeInBit is less than InitVBVBufferFullnessInBit\n");
353 return MOS_STATUS_INVALID_PARAMETER;
354 }
355
356 if (m_targetBufferFulness == 0)
357 {
358 m_targetBufferFulness = seqParams->VBVBufferSizeInBit - seqParams->InitVBVBufferFullnessInBit;
359 }
360 }
361
362 m_bitDepth = m_seqParam->bit_depth_luma_minus8 + 8;
363 m_chromaFormat = m_seqParam->chroma_format_idc;
364
365 return MOS_STATUS_SUCCESS;
366 }
367
SetPictureStructs()368 MOS_STATUS AvcBasicFeature::SetPictureStructs()
369 {
370 ENCODE_FUNC_CALL();
371
372 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
373
374 auto picParams = m_picParam;
375 auto seqParams = m_seqParam;
376 auto slcParams = m_sliceParams;
377
378 // TCBRC forced from LowDelayBRC also needs TargetFrameSize
379 if (m_forcedTCBRC)
380 {
381 picParams->TargetFrameSize = uint32_t(seqParams->TargetBitRate * (100. / 8) / seqParams->FramesPer100Sec);
382 }
383
384 m_userFlags = picParams->UserFlags;
385 m_nalUnitType = picParams->bIdrPic ? CODECHAL_ENCODE_AVC_NAL_UT_IDR_SLICE : CODECHAL_ENCODE_AVC_NAL_UT_SLICE;
386 m_lastPicInSeq = picParams->bLastPicInSeq;
387 m_lastPicInStream = picParams->bLastPicInStream;
388
389 ENCODE_CHK_STATUS_RETURN(m_ref->UpdatePicture());
390 m_pictureCodingType = m_ref->GetPictureCodingType();
391
392 auto prevPic = m_currOriginalPic;
393 auto prevIdx = prevPic.FrameIdx;
394 auto currPic = picParams->CurrOriginalPic;
395 auto currIdx = currPic.FrameIdx;
396
397 m_currOriginalPic = currPic;
398 m_currReconstructedPic = picParams->CurrReconstructedPic;
399
400 m_prevReconFrameIdx = m_currReconFrameIdx;
401 m_currReconFrameIdx = picParams->CurrReconstructedPic.FrameIdx;
402
403 if (Mos_ResourceIsNull(&m_reconSurface.OsResource) &&
404 (!picParams->UserFlags.bUseRawPicForRef || m_codecFunction != CODECHAL_FUNCTION_ENC))
405 {
406 return MOS_STATUS_INVALID_PARAMETER;
407 }
408
409 if (seqParams->Profile == CODEC_AVC_MAIN_PROFILE || seqParams->Profile == CODEC_AVC_BASE_PROFILE)
410 {
411 picParams->transform_8x8_mode_flag = 0;
412 picParams->pic_scaling_matrix_present_flag = 0;
413 for (uint8_t i = 0; i < 12; i++)
414 {
415 picParams->pic_scaling_list_present_flag[i] = 0;
416 }
417 picParams->second_chroma_qp_index_offset = picParams->chroma_qp_index_offset;
418 }
419 if (picParams->QpY < 0)
420 {
421 picParams->QpY = 25; // Set to default, recommended value used in simulation.
422 }
423 else if (picParams->QpY > CODECHAL_ENCODE_AVC_MAX_SLICE_QP)
424 {
425 picParams->QpY = CODECHAL_ENCODE_AVC_MAX_SLICE_QP; // Crop to 51 if larger
426 }
427 picParams->pic_init_qp_minus26 = picParams->QpY - 26;
428
429 if (!seqParams->seq_scaling_matrix_present_flag)
430 {
431 if (!picParams->pic_scaling_matrix_present_flag)
432 ScalingListFlat();
433 else if (!picParams->pic_scaling_list_present_flag[0])
434 ScalingListFallbackRuleA();
435 }
436 else if (!seqParams->seq_scaling_list_present_flag[0] &&
437 !picParams->pic_scaling_list_present_flag[0])
438 { // fall-back rule A
439 ScalingListFallbackRuleA();
440 }
441
442 picParams->num_slice_groups_minus1 = 0; // do not support flexible MB ordering
443 picParams->deblocking_filter_control_present_flag = 1; // always set to 1
444 picParams->redundant_pic_cnt_present_flag = 0;
445 picParams->pic_init_qs_minus26 = 0; // not used
446
447 // App handles tail insertion for VDEnc dynamic slice in non-cp case
448 if (m_vdencNoTailInsertion)
449 {
450 m_lastPicInSeq = m_lastPicInStream = 0;
451 }
452
453 m_frameFieldHeight = m_frameHeight;
454 m_frameFieldHeightInMb = m_picHeightInMb;
455 m_firstField = 1;
456
457 seqParams->mb_adaptive_frame_field_flag = 0;
458 m_mbaffEnabled = 0;
459
460 if ((m_lookaheadDepth > 0) && (m_prevTargetFrameSize > 0))
461 {
462 int64_t targetBufferFulness = (int64_t)m_targetBufferFulness;
463 targetBufferFulness += (((int64_t)m_prevTargetFrameSize) << 3) - (int64_t)m_averageFrameSize;
464 m_targetBufferFulness = (uint32_t)MOS_CLAMP_MIN_MAX(targetBufferFulness, 0, 0xFFFFFFFF);
465 }
466 m_prevTargetFrameSize = picParams->TargetFrameSize;
467
468 if (picParams->FieldCodingFlag || picParams->FieldFrameCodingFlag)
469 {
470 ENCODE_ASSERTMESSAGE("VDEnc does not support interlaced picture\n");
471 eStatus = MOS_STATUS_INVALID_PARAMETER;
472 return eStatus;
473 }
474
475 return eStatus;
476 }
477
SetSliceStructs()478 MOS_STATUS AvcBasicFeature::SetSliceStructs()
479 {
480 ENCODE_FUNC_CALL();
481
482 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
483
484 ENCODE_CHK_STATUS_RETURN(m_ref->UpdateSlice());
485
486 auto slcParams = m_sliceParams;
487 auto seqParams = m_seqParam;
488 auto picParams = m_picParam;
489
490 uint32_t numMbsInPrevSlice = slcParams->NumMbsForSlice; // Initiailize to num mbs in first slice
491 uint32_t numMbsForFirstSlice;
492 uint32_t numMbs = 0;
493
494 for (uint32_t sliceCount = 0; sliceCount < m_numSlices; sliceCount++)
495 {
496 if (m_sliceStructCaps != CODECHAL_SLICE_STRUCT_ARBITRARYMBSLICE)
497 {
498 if (sliceCount == 0)
499 {
500 numMbsForFirstSlice = slcParams->NumMbsForSlice;
501 if (numMbsForFirstSlice % m_picWidthInMb)
502 {
503 eStatus = MOS_STATUS_INVALID_PARAMETER;
504 return eStatus;
505 }
506 m_sliceHeight = numMbsForFirstSlice / m_picWidthInMb;
507 if (m_sliceStructCaps == CODECHAL_SLICE_STRUCT_POW2ROWS && (m_sliceHeight & (m_sliceHeight - 1)))
508 {
509 // app can only pass orig numMBs in picture for single slice, set slice height to the nearest pow2
510 if (m_numSlices == 1)
511 {
512 uint16_t sliceHeightPow2 = 1;
513 while (sliceHeightPow2 < m_sliceHeight)
514 {
515 sliceHeightPow2 <<= 1;
516 }
517 m_sliceHeight = sliceHeightPow2;
518 }
519 else
520 {
521 eStatus = MOS_STATUS_INVALID_PARAMETER;
522 return eStatus;
523 }
524 }
525 }
526 else if (m_sliceStructCaps == CODECHAL_SLICE_STRUCT_ROWSLICE)
527 {
528 if ((sliceCount < m_numSlices - 1 && numMbsForFirstSlice != slcParams->NumMbsForSlice) ||
529 (sliceCount == m_numSlices - 1 && numMbsForFirstSlice < slcParams->NumMbsForSlice))
530 {
531 eStatus = MOS_STATUS_INVALID_PARAMETER;
532 return eStatus;
533 }
534 }
535
536 // Gaps between slices are not allowed
537 if (slcParams->first_mb_in_slice != numMbs)
538 {
539 eStatus = MOS_STATUS_INVALID_PARAMETER;
540 return eStatus;
541 }
542 numMbs += slcParams->NumMbsForSlice;
543 }
544 else // SLICE_STRUCT_ARBITRARYMBSLICE
545 {
546 if ((slcParams->NumMbsForSlice % m_picWidthInMb) || // If slice is partial MB row,
547 ((sliceCount < m_numSlices - 1) && (numMbsInPrevSlice != slcParams->NumMbsForSlice)) || // OR not the last slice and num mbs is not same as prev slice
548 ((sliceCount == m_numSlices - 1) && ((numMbsInPrevSlice < slcParams->NumMbsForSlice)))) // OR it is the last slice and num mbs is not less than prev slice
549 {
550 m_sliceHeight = 1; // Slice height doesn't matter if using slicemap just set to any non-zero value.
551 }
552 else if ((m_numSlices == 1) || (sliceCount == 0))
553 {
554 m_sliceHeight = slcParams->NumMbsForSlice / m_picWidthInMb;
555 }
556 numMbsInPrevSlice = slcParams->NumMbsForSlice;
557 }
558
559 if ((picParams->pic_init_qp_minus26 + 26 + slcParams->slice_qp_delta) > CODECHAL_ENCODE_AVC_MAX_SLICE_QP)
560 {
561 slcParams->slice_qp_delta = CODECHAL_ENCODE_AVC_MAX_SLICE_QP - (picParams->pic_init_qp_minus26 + 26);
562 }
563 slcParams->redundant_pic_cnt = 0;
564 slcParams->sp_for_switch_flag = 0;
565 slcParams->slice_qs_delta = 0;
566 slcParams->ref_pic_list_reordering_flag_l1 = 0;
567 slcParams->no_output_of_prior_pics_flag = 0;
568 slcParams->redundant_pic_cnt = 0;
569
570 slcParams->MaxFrameNum = 1 << (seqParams[picParams->seq_parameter_set_id].log2_max_frame_num_minus4 + 4);
571 slcParams->frame_num = picParams->frame_num;
572 slcParams->field_pic_flag = picParams->FieldCodingFlag;
573 slcParams->bottom_field_flag = (CodecHal_PictureIsBottomField(picParams->CurrOriginalPic)) ? 1 : 0;
574
575 slcParams++;
576 }
577
578 return MOS_STATUS_SUCCESS;
579 }
580
CheckResolutionChange()581 void AvcBasicFeature::CheckResolutionChange()
582 {
583 ENCODE_FUNC_CALL();
584
585 uint32_t frameWidth = m_seqParam->FrameWidth;
586 uint32_t frameHeight = m_seqParam->FrameHeight;
587 uint16_t frame_crop_bottom_offset = m_seqParam->frame_crop_bottom_offset;
588 uint16_t frame_mbs_only_flag = m_seqParam->frame_mbs_only_flag;
589 uint16_t frame_cropping_flag = m_seqParam->frame_cropping_flag;
590
591 // Only for first frame
592 if (m_frameNum == 0)
593 {
594 m_oriFrameHeight = frameHeight;
595 m_oriFrameWidth = frameWidth;
596 m_frame_crop_bottom_offset = frame_crop_bottom_offset;
597 m_frame_mbs_only_flag = frame_mbs_only_flag;
598 m_frame_cropping_flag = frame_cropping_flag;
599 m_resolutionChanged = true;
600 }
601 else
602 {
603 // check if there is a dynamic resolution change
604 if ((m_oriFrameHeight && (m_oriFrameHeight != frameHeight)) ||
605 (m_oriFrameWidth && (m_oriFrameWidth != frameWidth)))
606 {
607 m_resolutionChanged = true;
608 m_oriFrameHeight = frameHeight;
609 m_oriFrameWidth = frameWidth;
610 m_frame_crop_bottom_offset = frame_crop_bottom_offset;
611 m_frame_mbs_only_flag = frame_mbs_only_flag;
612 m_frame_cropping_flag = frame_cropping_flag;
613 }
614 else
615 {
616 m_resolutionChanged = false;
617 }
618 }
619 }
620
PackPictureHeader()621 MOS_STATUS AvcBasicFeature::PackPictureHeader()
622 {
623 ENCODE_FUNC_CALL();
624
625 CODECHAL_ENCODE_AVC_PACK_PIC_HEADER_PARAMS packPicHeaderParams;
626 packPicHeaderParams.pBsBuffer = &m_bsBuffer;
627 packPicHeaderParams.pPicParams = m_picParam;
628 packPicHeaderParams.pSeqParams = m_seqParam;
629 packPicHeaderParams.pAvcVuiParams = m_vuiParams;
630 packPicHeaderParams.pAvcIQMatrixParams = m_iqMatrixParams;
631 packPicHeaderParams.ppNALUnitParams = m_nalUnitParams;
632 packPicHeaderParams.pSeiData = &m_seiData;
633 packPicHeaderParams.dwFrameHeight = m_frameHeight;
634 packPicHeaderParams.dwOriFrameHeight = m_oriFrameHeight;
635 packPicHeaderParams.wPictureCodingType = m_picParam->CodingType;
636 packPicHeaderParams.bNewSeq = m_newSeq;
637 packPicHeaderParams.pbNewPPSHeader = &m_newPpsHeader;
638 packPicHeaderParams.pbNewSeqHeader = &m_newSeqHeader;
639
640 ENCODE_CHK_STATUS_RETURN(AvcEncodeHeaderPacker::PackPictureHeader(&packPicHeaderParams));
641
642 return MOS_STATUS_SUCCESS;
643 }
644
InputSurfaceNeedsExtraCopy(const MOS_SURFACE & input)645 bool AvcBasicFeature::InputSurfaceNeedsExtraCopy(const MOS_SURFACE &input)
646 {
647 #if _DEBUG || _RELEASE_INTERNAL
648 static int8_t supported = -1;
649
650 if (supported == -1)
651 {
652 MediaUserSetting::Value outValue{};
653
654 ReadUserSettingForDebug(
655 m_userSettingPtr,
656 outValue,
657 "DisableInputSurfaceCopy",
658 MediaUserSetting::Group::Sequence);
659
660 supported = !outValue.Get<bool>();
661 }
662
663 if (!supported)
664 {
665 return false;
666 }
667 #endif
668
669 if (m_osInterface->osCpInterface && m_osInterface->osCpInterface->IsCpEnabled())
670 {
671 return false;
672 }
673
674 uint32_t alignedSize = 0;
675 switch (input.Format)
676 {
677 case Format_NV12:
678 alignedSize = MOS_MAX((uint32_t)m_seqParam->FrameWidth, (uint32_t)input.dwPitch) * m_seqParam->FrameHeight * 3 / 2;
679 break;
680 case Format_A8R8G8B8:
681 alignedSize = MOS_MAX((uint32_t)m_seqParam->FrameWidth * 4, (uint32_t)input.dwPitch) * m_seqParam->FrameHeight;
682 break;
683 default:
684 alignedSize = 0;
685 break;
686 }
687
688 return input.dwSize < alignedSize;
689 }
690
UpdateTrackedBufferParameters()691 MOS_STATUS AvcBasicFeature::UpdateTrackedBufferParameters()
692 {
693 ENCODE_FUNC_CALL();
694 ENCODE_CHK_NULL_RETURN(m_trackedBuf);
695
696 ENCODE_CHK_STATUS_RETURN(m_trackedBuf->OnSizeChange());
697
698 uint32_t fieldNumMBs = (uint32_t)m_picWidthInMb * ((m_picHeightInMb + 1) >> 1);
699
700 m_mbCodeSize = MOS_ALIGN_CEIL(fieldNumMBs * 16 * 4, CODECHAL_PAGE_SIZE) + fieldNumMBs * 16 * 4;
701 m_mvDataSize = 0;
702
703 uint32_t widthInMbRoundUp = (m_frameWidth + 31) >> 4;
704 uint32_t heightInMbRoundUp = (m_frameHeight + 15) >> 4;
705 m_colocatedMVBufferSize = widthInMbRoundUp * heightInMbRoundUp * CODECHAL_CACHELINE_SIZE / 2; // Cacheline per 2 MBs
706
707 MOS_ALLOC_GFXRES_PARAMS allocParams;
708 MOS_ZeroMemory(&allocParams, sizeof(MOS_ALLOC_GFXRES_PARAMS));
709 allocParams.Type = MOS_GFXRES_BUFFER;
710 allocParams.TileType = MOS_TILE_LINEAR;
711 allocParams.Format = Format_Buffer;
712
713 if (m_colocatedMVBufferSize > 0)
714 {
715 allocParams.dwBytes = m_colocatedMVBufferSize;
716 allocParams.pBufName = "mvTemporalBuffer";
717 allocParams.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_READ_WRITE_NOCACHE;
718 ENCODE_CHK_STATUS_RETURN(m_trackedBuf->RegisterParam(encode::BufferType::mvTemporalBuffer, allocParams));
719
720 if (m_colocatedMVBufferForIFrames) {
721 m_allocator->DestroyResource(m_colocatedMVBufferForIFrames);
722 m_colocatedMVBufferForIFrames = nullptr;
723 }
724 allocParams.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_READ_WRITE_CACHE;
725 m_colocatedMVBufferForIFrames = m_allocator->AllocateResource(allocParams, true);
726 ENCODE_CHK_NULL_RETURN(m_colocatedMVBufferForIFrames);
727 uint8_t* pData = (uint8_t*)m_allocator->LockResourceForWrite(m_colocatedMVBufferForIFrames);
728 ENCODE_CHK_NULL_RETURN(pData);
729
730 uint32_t* pT = (uint32_t*)(pData)+7;
731 for (uint32_t j = 0; j < m_picHeightInMb; j++)
732 {
733 for (uint32_t i = 0; i < m_picWidthInMb; i++)
734 {
735 *pT = 0x4000; pT += 8;
736 }
737 }
738 m_allocator->UnLock(m_colocatedMVBufferForIFrames);
739 }
740
741 // Input surface copy is needed if height is not MB aligned
742 if (InputSurfaceNeedsExtraCopy(m_rawSurface))
743 {
744 MOS_ALLOC_GFXRES_PARAMS allocParamsForAlignedRawSurface{};
745 allocParamsForAlignedRawSurface.Type = MOS_GFXRES_2D;
746 allocParamsForAlignedRawSurface.Format = m_rawSurface.Format;
747 allocParamsForAlignedRawSurface.TileType = MOS_TILE_Y;
748 allocParamsForAlignedRawSurface.dwWidth = m_picWidthInMb * CODECHAL_MACROBLOCK_WIDTH;
749 allocParamsForAlignedRawSurface.dwHeight = m_picHeightInMb * CODECHAL_MACROBLOCK_HEIGHT;
750 allocParamsForAlignedRawSurface.pBufName = "Aligned Raw Surface";
751 ENCODE_CHK_STATUS_RETURN(m_trackedBuf->RegisterParam(BufferType::AlignedRawSurface, allocParamsForAlignedRawSurface));
752 }
753
754 ENCODE_CHK_STATUS_RETURN(EncodeBasicFeature::UpdateTrackedBufferParameters());
755
756 return MOS_STATUS_SUCCESS;
757 }
758
UpdateSeiParameters(EncoderParams * params)759 MOS_STATUS AvcBasicFeature::UpdateSeiParameters(EncoderParams* params)
760 {
761 ENCODE_FUNC_CALL();
762 ENCODE_CHK_NULL_RETURN(params);
763
764 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
765
766 if (params->pSeiData->dwSEIBufSize > 0) // sei is present
767 {
768 if (params->pSeiData->dwSEIBufSize > m_seiData.dwSEIBufSize)
769 {
770 // Destroy and re-allocate
771 if (m_seiData.pSEIBuffer)
772 {
773 MOS_FreeMemory(m_seiData.pSEIBuffer);
774 m_seiData.pSEIBuffer = nullptr;
775 }
776 m_seiData.dwSEIBufSize = params->pSeiData->dwSEIBufSize;
777 m_seiData.pSEIBuffer = (uint8_t *)MOS_AllocAndZeroMemory(m_seiData.dwSEIBufSize);
778 ENCODE_CHK_NULL_RETURN(m_seiData.pSEIBuffer);
779 }
780
781 m_seiParamBuffer = params->pSeiParamBuffer;
782 m_seiDataOffset = params->dwSEIDataOffset;
783 m_seiData.newSEIData = params->pSeiData->newSEIData;
784 m_seiData.dwSEIDataSize = params->pSeiData->dwSEIDataSize;
785
786 eStatus = MOS_SecureMemcpy(m_seiData.pSEIBuffer,
787 m_seiData.dwSEIDataSize,
788 (m_seiParamBuffer + m_seiDataOffset),
789 m_seiData.dwSEIDataSize);
790 if (eStatus != MOS_STATUS_SUCCESS)
791 {
792 ENCODE_ASSERTMESSAGE("Failed to copy memory.");
793 return eStatus;
794 }
795 }
796
797 m_extraPictureStatesSize = m_seiData.dwSEIDataSize;
798
799 return eStatus;
800 }
801
UpdateMinMaxQp()802 void AvcBasicFeature::UpdateMinMaxQp()
803 {
804 ENCODE_FUNC_CALL();
805
806 m_minMaxQpControlEnabled = true;
807 if (m_picParam->CodingType == I_TYPE)
808 {
809 m_iMaxQp = MOS_MIN(MOS_MAX(m_picParam->ucMaximumQP, 10), 51); // Clamp maxQP to [10, 51]
810 m_iMinQp = MOS_MIN(MOS_MAX(m_picParam->ucMinimumQP, 10), m_iMaxQp); // Clamp minQP to [10, maxQP] to make sure minQP <= maxQP
811 if (!m_pFrameMinMaxQpControl)
812 {
813 m_pMinQp = m_iMinQp;
814 m_pMaxQp = m_iMaxQp;
815 }
816 if (!m_bFrameMinMaxQpControl)
817 {
818 m_bMinQp = m_iMinQp;
819 m_bMaxQp = m_iMaxQp;
820 }
821 }
822 else if (m_picParam->CodingType == P_TYPE)
823 {
824 m_pFrameMinMaxQpControl = true;
825 m_pMaxQp = MOS_MIN(MOS_MAX(m_picParam->ucMaximumQP, 10), 51); // Clamp maxQP to [10, 51]
826 m_pMinQp = MOS_MIN(MOS_MAX(m_picParam->ucMinimumQP, 10), m_pMaxQp); // Clamp minQP to [10, maxQP] to make sure minQP <= maxQP
827 if (!m_bFrameMinMaxQpControl)
828 {
829 m_bMinQp = m_pMinQp;
830 m_bMaxQp = m_pMaxQp;
831 }
832 }
833 else // B_TYPE
834 {
835 m_bFrameMinMaxQpControl = true;
836 m_bMaxQp = MOS_MIN(MOS_MAX(m_picParam->ucMaximumQP, 10), 51); // Clamp maxQP to [10, 51]
837 m_bMinQp = MOS_MIN(MOS_MAX(m_picParam->ucMinimumQP, 10), m_bMaxQp); // Clamp minQP to [10, maxQP] to make sure minQP <= maxQP
838 }
839 // Zero out the QP values, so we don't update the AVCState settings until new values are sent in MiscParamsRC
840 m_picParam->ucMinimumQP = 0;
841 m_picParam->ucMaximumQP = 0;
842 }
843
GetMaxMBPS(uint8_t levelIdc)844 int32_t AvcBasicFeature::GetMaxMBPS(uint8_t levelIdc)
845 {
846 int maxMBPS = 11880;
847
848 // See JVT Spec Annex A Table A-1 Level limits for below mapping
849 // maxMBPS is in MB/s
850 switch (levelIdc)
851 {
852 case CODEC_AVC_LEVEL_1:
853 case CODEC_AVC_LEVEL_1b:
854 maxMBPS = 1485;
855 break;
856 case CODEC_AVC_LEVEL_11:
857 maxMBPS = 3000;
858 break;
859 case CODEC_AVC_LEVEL_12:
860 maxMBPS = 6000;
861 break;
862 case CODEC_AVC_LEVEL_13:
863 case CODEC_AVC_LEVEL_2:
864 maxMBPS = 11880;
865 break;
866 case CODEC_AVC_LEVEL_21:
867 maxMBPS = 19800;
868 break;
869 case CODEC_AVC_LEVEL_22:
870 maxMBPS = 20250;
871 break;
872 case CODEC_AVC_LEVEL_3:
873 maxMBPS = 40500;
874 break;
875 case CODEC_AVC_LEVEL_31:
876 maxMBPS = 108000;
877 break;
878 case CODEC_AVC_LEVEL_32:
879 maxMBPS = 216000;
880 break;
881 case CODEC_AVC_LEVEL_4:
882 case CODEC_AVC_LEVEL_41:
883 maxMBPS = 245760;
884 break;
885 case CODEC_AVC_LEVEL_42:
886 maxMBPS = 522240;
887 break;
888 case CODEC_AVC_LEVEL_5:
889 maxMBPS = 589824;
890 break;
891 case CODEC_AVC_LEVEL_51:
892 maxMBPS = 983040;
893 break;
894 case CODEC_AVC_LEVEL_52:
895 maxMBPS = 2073600;
896 break;
897 default:
898 maxMBPS = 0;
899 break;
900 }
901
902 return maxMBPS;
903 }
904
GetProfileLevelMaxFrameSize()905 uint32_t AvcBasicFeature::GetProfileLevelMaxFrameSize()
906 {
907 ENCODE_FUNC_CALL();
908
909 double bitsPerMB, tmpf;
910 int32_t iMaxMBPS, numMBPerFrame, minCR;
911 uint64_t maxBytePerPic, maxBytePerPicNot0;
912 uint32_t profileLevelMaxFrame, userMaxFrameSize;
913 double frameRateD = 100;
914
915 minCR = 4;
916
917 if (m_seqParam->Level >= CODEC_AVC_LEVEL_31 && m_seqParam->Level <= CODEC_AVC_LEVEL_4)
918 {
919 bitsPerMB = 96;
920 }
921 else
922 {
923 bitsPerMB = 192;
924 minCR = 2;
925 }
926
927 iMaxMBPS = GetMaxMBPS(m_seqParam->Level);
928 if (!iMaxMBPS)
929 {
930 ENCODE_ASSERTMESSAGE("Unsupported LevelIDC setting.");
931 return 0;
932 }
933
934 numMBPerFrame = m_picWidthInMb * m_frameFieldHeightInMb;
935
936 tmpf = (double)numMBPerFrame;
937 if (tmpf < iMaxMBPS / 172.)
938 {
939 tmpf = iMaxMBPS / 172.;
940 }
941
942 maxBytePerPic = (uint64_t)(tmpf * bitsPerMB);
943 maxBytePerPicNot0 =
944 (uint64_t)((((double)iMaxMBPS * frameRateD) /
945 (double)m_seqParam->FramesPer100Sec) *
946 bitsPerMB);
947 userMaxFrameSize = m_seqParam->UserMaxFrameSize;
948
949 if ((m_pictureCodingType != I_TYPE) && (m_seqParam->UserMaxPBFrameSize > 0))
950 {
951 userMaxFrameSize = m_seqParam->UserMaxPBFrameSize;
952 }
953
954 if (userMaxFrameSize != 0)
955 {
956 profileLevelMaxFrame = (uint32_t)MOS_MIN(userMaxFrameSize, maxBytePerPic);
957 profileLevelMaxFrame = (uint32_t)MOS_MIN(maxBytePerPicNot0, profileLevelMaxFrame);
958 }
959 else
960 {
961 profileLevelMaxFrame = (uint32_t)MOS_MIN(maxBytePerPicNot0, maxBytePerPic);
962 }
963
964 profileLevelMaxFrame = (uint32_t)MOS_MIN((m_frameHeight * m_frameHeight), profileLevelMaxFrame);
965
966 return profileLevelMaxFrame;
967 }
968
GetTrackedBuffers()969 MOS_STATUS AvcBasicFeature::GetTrackedBuffers()
970 {
971 ENCODE_CHK_NULL_RETURN(m_trackedBuf);
972 ENCODE_CHK_NULL_RETURN(m_picParams);
973 ENCODE_CHK_NULL_RETURN(m_allocator);
974
975 auto currRefList = m_ref->GetCurrRefList();
976 ENCODE_CHK_STATUS_RETURN(m_trackedBuf->Acquire(currRefList, false));
977
978 m_resMbCodeBuffer = m_trackedBuf->GetBuffer(BufferType::mbCodedBuffer, m_trackedBuf->GetCurrIndex());
979 ENCODE_CHK_NULL_RETURN(m_resMbCodeBuffer);
980
981 m_4xDSSurface = m_trackedBuf->GetSurface(BufferType::ds4xSurface, m_trackedBuf->GetCurrIndex());
982 ENCODE_CHK_NULL_RETURN(m_4xDSSurface);
983 ENCODE_CHK_STATUS_RETURN(m_allocator->GetSurfaceInfo(m_4xDSSurface));
984
985 // Input surface copy is needed if height is not MB aligned
986 if (InputSurfaceNeedsExtraCopy(m_rawSurface))
987 {
988 auto alignedRawSurf = m_trackedBuf->GetSurface(BufferType::AlignedRawSurface, m_trackedBuf->GetCurrIndex());
989 ENCODE_CHK_NULL_RETURN(alignedRawSurf);
990 m_allocator->GetSurfaceInfo(alignedRawSurf);
991 alignedRawSurf->OsResource.pGmmResInfo->GetSetCpSurfTag(true, m_rawSurface.OsResource.pGmmResInfo->GetSetCpSurfTag(false, 0));
992 ENCODE_CHK_STATUS_RETURN(m_allocator->UpdateResourceUsageType(&alignedRawSurf->OsResource, MOS_HW_RESOURCE_USAGE_ENCODE_INPUT_RAW));
993
994 if (m_mediaCopyWrapper)
995 {
996 ENCODE_CHK_STATUS_RETURN(m_mediaCopyWrapper->MediaCopy(
997 &m_rawSurface.OsResource,
998 &alignedRawSurf->OsResource,
999 MCPY_METHOD_DEFAULT));
1000
1001 m_rawSurface = *alignedRawSurf;
1002 m_rawSurfaceToEnc = m_rawSurfaceToPak = &m_rawSurface;
1003 }
1004 else
1005 {
1006 ENCODE_ASSERTMESSAGE("Input surface height %d is not 16-aligned, needs extra copy but MediaCopy is not avaliable.", m_rawSurface.dwHeight);
1007 }
1008 }
1009
1010 return MOS_STATUS_SUCCESS;
1011 }
1012
ScalingListFlat()1013 void AvcBasicFeature::ScalingListFlat()
1014 {
1015 // 4x4 block
1016 for (uint8_t idx2 = 0; idx2 < 6; idx2++)
1017 {
1018 for (uint8_t idx1 = 0; idx1 < 16; idx1++)
1019 {
1020 m_iqWeightScaleLists->WeightScale4x4[idx2][idx1] = 16;
1021 }
1022 }
1023 // 8x8 block
1024 for (uint8_t idx2 = 0; idx2 < 2; idx2++)
1025 {
1026 for (uint8_t idx1 = 0; idx1 < 64; idx1++)
1027 {
1028 m_iqWeightScaleLists->WeightScale8x8[idx2][idx1] = 16;
1029 }
1030 }
1031 }
1032
ScalingListFallbackRuleA()1033 void AvcBasicFeature::ScalingListFallbackRuleA()
1034 {
1035 for (uint8_t idx1 = 0; idx1 < 16; idx1++)
1036 {
1037 for (uint8_t idx2 = 0; idx2 < 3; idx2++)
1038 {
1039 m_iqWeightScaleLists->WeightScale4x4[idx2][CODEC_AVC_Qmatrix_scan_4x4[idx1]] =
1040 CODEC_AVC_Default_4x4_Intra[idx1];
1041 }
1042 for (uint8_t idx2 = 3; idx2 < 6; idx2++)
1043 {
1044 m_iqWeightScaleLists->WeightScale4x4[idx2][CODEC_AVC_Qmatrix_scan_4x4[idx1]] =
1045 CODEC_AVC_Default_4x4_Inter[idx1];
1046 }
1047 }
1048 // 8x8 block
1049 for (uint8_t idx1 = 0; idx1 < 64; idx1++)
1050 {
1051 m_iqWeightScaleLists->WeightScale8x8[0][CODEC_AVC_Qmatrix_scan_8x8[idx1]] =
1052 CODEC_AVC_Default_8x8_Intra[idx1];
1053 m_iqWeightScaleLists->WeightScale8x8[1][CODEC_AVC_Qmatrix_scan_8x8[idx1]] =
1054 CODEC_AVC_Default_8x8_Inter[idx1];
1055 }
1056 }
1057
GetMaxNumSlicesAllowed(CODEC_AVC_PROFILE_IDC profileIdc,CODEC_AVC_LEVEL_IDC levelIdc,uint32_t framesPer100Sec)1058 uint16_t AvcBasicFeature::GetMaxNumSlicesAllowed(
1059 CODEC_AVC_PROFILE_IDC profileIdc,
1060 CODEC_AVC_LEVEL_IDC levelIdc,
1061 uint32_t framesPer100Sec)
1062 {
1063 uint16_t maxAllowedNumSlices = 0;
1064
1065 if ((profileIdc == CODEC_AVC_MAIN_PROFILE) ||
1066 (profileIdc == CODEC_AVC_HIGH_PROFILE) ||
1067 (profileIdc == CODEC_AVC_HIGH10_PROFILE) ||
1068 (profileIdc == CODEC_AVC_HIGH422_PROFILE) ||
1069 (profileIdc == CODEC_AVC_HIGH444_PROFILE) ||
1070 (profileIdc == CODEC_AVC_CAVLC444_INTRA_PROFILE))
1071 {
1072 switch (levelIdc)
1073 {
1074 case CODEC_AVC_LEVEL_3:
1075 maxAllowedNumSlices = (uint16_t)(40500.0 * 100 / 22.0 / framesPer100Sec);
1076 break;
1077 case CODEC_AVC_LEVEL_31:
1078 maxAllowedNumSlices = (uint16_t)(108000.0 * 100 / 60.0 / framesPer100Sec);
1079 break;
1080 case CODEC_AVC_LEVEL_32:
1081 maxAllowedNumSlices = (uint16_t)(216000.0 * 100 / 60.0 / framesPer100Sec);
1082 break;
1083 case CODEC_AVC_LEVEL_4:
1084 case CODEC_AVC_LEVEL_41:
1085 maxAllowedNumSlices = (uint16_t)(245760.0 * 100 / 24.0 / framesPer100Sec);
1086 break;
1087 case CODEC_AVC_LEVEL_42:
1088 maxAllowedNumSlices = (uint16_t)(522240.0 * 100 / 24.0 / framesPer100Sec);
1089 break;
1090 case CODEC_AVC_LEVEL_5:
1091 maxAllowedNumSlices = (uint16_t)(589824.0 * 100 / 24.0 / framesPer100Sec);
1092 break;
1093 case CODEC_AVC_LEVEL_51:
1094 maxAllowedNumSlices = (uint16_t)(983040.0 * 100 / 24.0 / framesPer100Sec);
1095 break;
1096 case CODEC_AVC_LEVEL_52:
1097 maxAllowedNumSlices = (uint16_t)(2073600.0 * 100 / 24.0 / framesPer100Sec);
1098 break;
1099 default:
1100 maxAllowedNumSlices = 0;
1101 }
1102 }
1103
1104 return maxAllowedNumSlices;
1105 }
1106
IsAvcPSlice(uint8_t sliceType) const1107 bool AvcBasicFeature::IsAvcPSlice(uint8_t sliceType) const
1108 {
1109 return (sliceType < MHW_ARRAY_SIZE(Slice_Type)) ?
1110 (Slice_Type[sliceType] == SLICE_P) : false;
1111 }
1112
IsAvcBSlice(uint8_t sliceType) const1113 bool AvcBasicFeature::IsAvcBSlice(uint8_t sliceType) const
1114 {
1115 return (sliceType < MHW_ARRAY_SIZE(Slice_Type)) ?
1116 (Slice_Type[sliceType] == SLICE_B) : false;
1117 }
1118
MHW_SETPAR_DECL_SRC(VDENC_PIPE_MODE_SELECT,AvcBasicFeature)1119 MHW_SETPAR_DECL_SRC(VDENC_PIPE_MODE_SELECT, AvcBasicFeature)
1120 {
1121 params.standardSelect = (uint8_t)CodecHal_GetStandardFromMode(m_mode);
1122 params.dynamicSlice = m_seqParam->EnableSliceLevelRateCtrl;
1123 params.chromaType = m_seqParam->chroma_format_idc;
1124 params.randomAccess = (m_picParam->CodingType == B_TYPE);
1125 params.frameStatisticsStreamOut = m_picParam->StatusReportEnable.fields.FrameStats;
1126
1127 // override perf settings for AVC codec on B-stepping
1128 static const uint8_t par1table[] = { 0, 0, 1, 1, 1, 1, 1 };
1129 params.verticalShift32Minus1 = 0;
1130 params.hzShift32Minus1 = 15;
1131 params.numVerticalReqMinus1 = 5;
1132 params.numHzReqMinus1 = 0;
1133 params.VdencPipeModeSelectPar1 = par1table[m_seqParam->TargetUsage - 1];
1134 params.VdencPipeModeSelectPar0 = 1;
1135
1136 return MOS_STATUS_SUCCESS;
1137 }
1138
MHW_SETPAR_DECL_SRC(VDENC_SRC_SURFACE_STATE,AvcBasicFeature)1139 MHW_SETPAR_DECL_SRC(VDENC_SRC_SURFACE_STATE, AvcBasicFeature)
1140 {
1141 params.pitch = m_rawSurfaceToPak->dwPitch;
1142 params.tileType = m_rawSurfaceToPak->TileType;
1143 params.tileModeGmm = m_rawSurfaceToPak->TileModeGMM;
1144 params.format = m_rawSurfaceToPak->Format;
1145 params.gmmTileEn = m_rawSurfaceToPak->bGMMTileEnabled;
1146 params.uOffset = m_rawSurfaceToPak->YoffsetForUplane;
1147 params.vOffset = m_rawSurfaceToPak->YoffsetForVplane;
1148 params.displayFormatSwizzle = m_picParam->bDisplayFormatSwizzle;
1149 params.width = m_seqParam->FrameWidth;
1150 params.height = m_seqParam->FrameHeight;
1151 params.colorSpaceSelection = (m_seqParam->InputColorSpace == ECOLORSPACE_P709) ? 1 : 0;
1152 params.chromaDownsampleFilterControl = 7;
1153
1154 return MOS_STATUS_SUCCESS;
1155 }
1156
MHW_SETPAR_DECL_SRC(VDENC_REF_SURFACE_STATE,AvcBasicFeature)1157 MHW_SETPAR_DECL_SRC(VDENC_REF_SURFACE_STATE, AvcBasicFeature)
1158 {
1159 params.pitch = m_reconSurface.dwPitch;
1160 params.tileType = m_reconSurface.TileType;
1161 params.tileModeGmm = m_reconSurface.TileModeGMM;
1162 params.format = m_reconSurface.Format;
1163 params.gmmTileEn = m_reconSurface.bGMMTileEnabled;
1164 params.uOffset = m_reconSurface.YoffsetForUplane;
1165 params.vOffset = m_reconSurface.YoffsetForVplane;
1166 params.width = m_reconSurface.dwWidth;
1167 params.height = m_reconSurface.dwHeight;
1168
1169 if (m_reconSurface.Format == Format_Y410 || m_reconSurface.Format == Format_444P || m_reconSurface.Format == Format_AYUV)
1170 {
1171 if (m_reconSurface.Format == Format_Y410)
1172 {
1173 params.pitch = m_reconSurface.dwPitch / 2;
1174 }
1175 else
1176 {
1177 params.pitch = m_reconSurface.dwPitch / 4;
1178 }
1179 params.uOffset = m_rawSurfaceToPak->dwHeight;
1180 params.vOffset = m_rawSurfaceToPak->dwHeight << 1;
1181 }
1182 else if (m_reconSurface.Format == Format_Y216 || m_reconSurface.Format == Format_YUY2 || m_reconSurface.Format == Format_YUYV)
1183 {
1184 params.uOffset = m_rawSurfaceToPak->dwHeight;
1185 params.vOffset = m_rawSurfaceToPak->dwHeight;
1186 }
1187
1188 return MOS_STATUS_SUCCESS;
1189 }
1190
MHW_SETPAR_DECL_SRC(VDENC_DS_REF_SURFACE_STATE,AvcBasicFeature)1191 MHW_SETPAR_DECL_SRC(VDENC_DS_REF_SURFACE_STATE, AvcBasicFeature)
1192 {
1193 params.widthStage1 = m_4xDSSurface->dwWidth;
1194 params.heightStage1 = m_4xDSSurface->dwHeight;
1195 params.tileTypeStage1 = m_4xDSSurface->TileType;
1196 params.tileModeGmmStage1 = m_4xDSSurface->TileModeGMM;
1197 params.gmmTileEnStage1 = m_4xDSSurface->bGMMTileEnabled;
1198 params.pitchStage1 = m_4xDSSurface->dwPitch;
1199 params.uOffsetStage1 = m_4xDSSurface->YoffsetForUplane;
1200 params.vOffsetStage1 = m_4xDSSurface->YoffsetForVplane;
1201
1202 return MOS_STATUS_SUCCESS;
1203 }
1204
MHW_SETPAR_DECL_SRC(VDENC_PIPE_BUF_ADDR_STATE,AvcBasicFeature)1205 MHW_SETPAR_DECL_SRC(VDENC_PIPE_BUF_ADDR_STATE, AvcBasicFeature)
1206 {
1207 params.surfaceRaw = m_rawSurfaceToPak;
1208 params.streamOutBuffer = m_recycleBuf->GetBuffer(VdencStatsBuffer, 0);
1209 params.surfaceDsStage1 = m_4xDSSurface;
1210
1211 #ifdef _MMC_SUPPORTED
1212 ENCODE_CHK_NULL_RETURN(m_mmcState);
1213 if (m_mmcState->IsMmcEnabled())
1214 {
1215 ENCODE_CHK_NULL_RETURN(m_rawSurfaceToPak)
1216
1217 params.mmcEnabled = true;
1218
1219 MOS_MEMCOMP_STATE reconSurfMmcState = MOS_MEMCOMP_DISABLED;
1220
1221 ENCODE_CHK_STATUS_RETURN(m_mmcState->GetSurfaceMmcState(const_cast<PMOS_SURFACE>(&m_reconSurface), &reconSurfMmcState));
1222 ENCODE_CHK_STATUS_RETURN(m_mmcState->GetSurfaceMmcFormat(const_cast<PMOS_SURFACE>(&m_reconSurface), ¶ms.compressionFormatRecon));
1223 ENCODE_CHK_STATUS_RETURN(m_mmcState->GetSurfaceMmcState(m_rawSurfaceToPak, ¶ms.mmcStateRaw));
1224 ENCODE_CHK_STATUS_RETURN(m_mmcState->GetSurfaceMmcFormat(m_rawSurfaceToPak, ¶ms.compressionFormatRaw));
1225
1226 if (m_deblockingEnabled)
1227 {
1228 params.mmcStatePreDeblock = MOS_MEMCOMP_DISABLED;
1229 params.mmcStatePostDeblock = reconSurfMmcState;
1230 }
1231 else
1232 {
1233 params.mmcStatePreDeblock = reconSurfMmcState;
1234 params.mmcStatePostDeblock = MOS_MEMCOMP_DISABLED;
1235 }
1236 }
1237 else
1238 {
1239 params.mmcEnabled = false;
1240 params.mmcStatePreDeblock = MOS_MEMCOMP_DISABLED;
1241 params.mmcStateRaw = MOS_MEMCOMP_DISABLED;
1242 }
1243 #endif
1244
1245 if (m_ref->GetRefList()[m_currReconstructedPic.FrameIdx]->bUsedAsRef)
1246 {
1247 auto curIdx = m_trackedBuf->GetCurrIndex();
1248
1249 m_ref->GetRefList()[m_currReconstructedPic.FrameIdx]->bIsIntra = (m_pictureCodingType == I_TYPE);
1250 params.colocatedMvWriteBuffer = (m_pictureCodingType == I_TYPE) ? nullptr : m_trackedBuf->GetBuffer(BufferType::mvTemporalBuffer, curIdx);
1251 }
1252 else
1253 {
1254 params.colocatedMvWriteBuffer = nullptr;
1255 }
1256
1257 if (m_pictureCodingType == B_TYPE)
1258 {
1259 auto refPic = m_sliceParams->RefPicList[1][0];
1260 if (!CodecHal_PictureIsInvalid(refPic))
1261 {
1262 auto picIdx = m_ref->GetRefListIndex(refPic.FrameIdx);
1263 if (m_ref->GetRefList()[picIdx]->bIsIntra)
1264 {
1265 params.colocatedMvReadBuffer = m_colocatedMVBufferForIFrames;
1266 }
1267 else
1268 {
1269 auto mvTempBufIdx = m_ref->GetRefList()[picIdx]->ucScalingIdx;
1270 params.colocatedMvReadBuffer = m_trackedBuf->GetBuffer(BufferType::mvTemporalBuffer, mvTempBufIdx);
1271 }
1272 }
1273 else
1274 {
1275 params.colocatedMvReadBuffer = nullptr;
1276 }
1277 }
1278
1279 return MOS_STATUS_SUCCESS;
1280 }
1281
MHW_SETPAR_DECL_SRC(VDENC_CMD3,AvcBasicFeature)1282 MHW_SETPAR_DECL_SRC(VDENC_CMD3, AvcBasicFeature)
1283 {
1284 auto settings = static_cast<AvcVdencFeatureSettings *>(m_constSettings);
1285 ENCODE_CHK_NULL_RETURN(settings);
1286
1287 for (const auto &lambda : settings->vdencCmd3Settings)
1288 {
1289 ENCODE_CHK_STATUS_RETURN(lambda(params));
1290 }
1291
1292 return MOS_STATUS_SUCCESS;
1293 }
1294
MHW_SETPAR_DECL_SRC(VDENC_AVC_IMG_STATE,AvcBasicFeature)1295 MHW_SETPAR_DECL_SRC(VDENC_AVC_IMG_STATE, AvcBasicFeature)
1296 {
1297 params.pictureType = m_picParam->CodingType - 1;
1298 params.transform8X8Flag = m_picParam->transform_8x8_mode_flag;
1299
1300 params.pictureHeightMinusOne = m_picHeightInMb - 1;
1301 params.pictureWidth = m_picWidthInMb;
1302
1303 ENCODE_CHK_STATUS_RETURN(m_ref->MHW_SETPAR_F(VDENC_AVC_IMG_STATE)(params));
1304
1305 if (m_ref->GetRefList()[m_currReconstructedPic.FrameIdx]->bUsedAsRef && m_pictureCodingType != I_TYPE)
1306 params.colMVWriteEnable = true;
1307
1308 if (m_pictureCodingType == B_TYPE) {
1309 if (!CodecHal_PictureIsInvalid(m_sliceParams->RefPicList[1][0])) {
1310 params.colMVReadEnable = true;
1311 }
1312 }
1313
1314 // Rolling-I settings
1315 if (m_picParam->CodingType != I_TYPE && m_picParam->EnableRollingIntraRefresh != ROLLING_I_DISABLED)
1316 {
1317 params.intraRefreshMbPos = m_picParam->IntraRefreshMBNum;
1318 params.intraRefreshMbSizeMinusOne = m_picParam->IntraRefreshUnitinMB;
1319 params.intraRefreshEnableRollingIEnable = m_picParam->EnableRollingIntraRefresh != ROLLING_I_DISABLED ? 1 : 0;
1320 params.intraRefreshMode = m_picParam->EnableRollingIntraRefresh == ROLLING_I_ROW ? 0 : 1;
1321 params.qpAdjustmentForRollingI = m_picParam->IntraRefreshQPDelta;
1322 }
1323
1324 if (m_minMaxQpControlEnabled)
1325 {
1326 params.minQp = (m_pictureCodingType == I_TYPE) ? m_iMinQp
1327 : ((m_pictureCodingType == P_TYPE) ? m_pMinQp
1328 : m_bMinQp);
1329 params.maxQp = (m_pictureCodingType == I_TYPE) ? m_iMaxQp
1330 : ((m_pictureCodingType == P_TYPE) ? m_pMaxQp
1331 : m_bMaxQp);
1332 }
1333
1334 params.mbLevelDeltaQpEnable = m_mbQpDataEnabled && m_picParam->NumDeltaQpForNonRectROI;
1335 params.qpPrimeY = m_picParam->QpY + m_sliceParams->slice_qp_delta;
1336
1337 auto settings = static_cast<AvcVdencFeatureSettings *>(m_constSettings);
1338 ENCODE_CHK_NULL_RETURN(settings);
1339
1340 for (const auto &lambda : settings->vdencAvcImgStateSettings)
1341 {
1342 ENCODE_CHK_STATUS_RETURN(lambda(params));
1343 }
1344
1345 return MOS_STATUS_SUCCESS;
1346 }
1347
MHW_SETPAR_DECL_SRC(VDENC_AVC_SLICE_STATE,AvcBasicFeature)1348 MHW_SETPAR_DECL_SRC(VDENC_AVC_SLICE_STATE, AvcBasicFeature)
1349 {
1350 auto sliceParams = &m_sliceParams[m_curNumSlices];
1351
1352 params.log2WeightDenomLuma = sliceParams->luma_log2_weight_denom;
1353 if (sliceParams->slice_type == 1 || sliceParams->slice_type == 6) // B slice
1354 {
1355 if (m_picParam->weighted_bipred_idc == IMPLICIT_WEIGHTED_INTER_PRED_MODE)
1356 {
1357 params.log2WeightDenomLuma = 0;
1358 }
1359 }
1360
1361 return MOS_STATUS_SUCCESS;
1362 }
1363
MHW_SETPAR_DECL_SRC(VDENC_WALKER_STATE,AvcBasicFeature)1364 MHW_SETPAR_DECL_SRC(VDENC_WALKER_STATE, AvcBasicFeature)
1365 {
1366 auto sliceParams = &m_sliceParams[m_curNumSlices];
1367 auto frameHeight = static_cast<uint32_t>(CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(m_seqParam->FrameHeight));
1368 auto frameWidth = static_cast<uint32_t>(CODECHAL_GET_WIDTH_IN_MACROBLOCKS(m_seqParam->FrameWidth));
1369
1370 params.tileSliceStartLcuMbY = sliceParams->first_mb_in_slice / frameWidth;
1371 params.firstSuperSlice = (m_curNumSlices == 0);
1372
1373 auto nextsliceMbStartYPosition = (sliceParams->first_mb_in_slice + sliceParams->NumMbsForSlice) / frameWidth;
1374 params.nextTileSliceStartLcuMbY = nextsliceMbStartYPosition > frameHeight ? frameHeight : nextsliceMbStartYPosition;
1375
1376 return MOS_STATUS_SUCCESS;
1377 }
1378
MHW_SETPAR_DECL_SRC(MFX_PIPE_MODE_SELECT,AvcBasicFeature)1379 MHW_SETPAR_DECL_SRC(MFX_PIPE_MODE_SELECT, AvcBasicFeature)
1380 {
1381 bool suppressReconPic = ((!m_ref->GetRefList()[m_currReconstructedPic.FrameIdx]->bUsedAsRef) && m_suppressReconPicSupported);
1382
1383 params.standardSelect = CodecHal_GetStandardFromMode(m_mode);
1384 params.codecSelect = encoderCodec;
1385 // Enable PAK statistics streamout
1386 params.frameStatisticsStreamoutEnable = true;
1387 params.scaledSurfaceEnable = false;
1388 params.preDeblockingOutputEnablePredeblockoutenable = !m_deblockingEnabled && !suppressReconPic;
1389 params.postDeblockingOutputEnablePostdeblockoutenable = m_deblockingEnabled && !suppressReconPic;
1390
1391 // Disable PAK streamout from previous PAK pass, as VDEnc does not support standalone PAK
1392 params.streamOutEnable = false;
1393 if (m_perMBStreamOutEnable)
1394 {
1395 // Enable PerMB streamOut PAK Statistics
1396 params.streamOutEnable = true;
1397 params.extendedStreamOutEnable = true;
1398 }
1399
1400 params.deblockerStreamOutEnable = 0;
1401 params.vdencMode = 1;
1402 params.decoderShortFormatMode = 1;
1403 params.sliceSizeStreamout32bit = true;
1404
1405 return MOS_STATUS_SUCCESS;
1406 }
1407
GetHwTileType(MOS_TILE_TYPE tileType,MOS_TILE_MODE_GMM tileModeGMM,bool gmmTileEnabled)1408 static inline uint32_t GetHwTileType(MOS_TILE_TYPE tileType, MOS_TILE_MODE_GMM tileModeGMM, bool gmmTileEnabled)
1409 {
1410 uint32_t tileMode = 0;
1411
1412 if (gmmTileEnabled)
1413 {
1414 return tileModeGMM;
1415 }
1416
1417 switch (tileType)
1418 {
1419 case MOS_TILE_LINEAR:
1420 tileMode = 0;
1421 break;
1422 case MOS_TILE_YS:
1423 tileMode = 1;
1424 break;
1425 case MOS_TILE_X:
1426 tileMode = 2;
1427 break;
1428 default:
1429 tileMode = 3;
1430 break;
1431 }
1432
1433 return tileMode;
1434 }
1435
MosToMediaStateFormat(MOS_FORMAT format)1436 uint8_t MosToMediaStateFormat(MOS_FORMAT format)
1437 {
1438 switch (format)
1439 {
1440 case Format_A8R8G8B8:
1441 case Format_X8R8G8B8:
1442 case Format_A8B8G8R8:
1443 return MHW_MEDIASTATE_SURFACEFORMAT_R8G8B8A8_UNORM;
1444 case Format_422H:
1445 case Format_422V:
1446 return MHW_MEDIASTATE_SURFACEFORMAT_PLANAR_422_8;
1447 case Format_AYUV:
1448 case Format_AUYV:
1449 return MHW_MEDIASTATE_SURFACEFORMAT_A8Y8U8V8_UNORM;
1450 case Format_NV12:
1451 case Format_NV11:
1452 case Format_P208:
1453 case Format_IMC1:
1454 case Format_IMC3:
1455 return MHW_MEDIASTATE_SURFACEFORMAT_PLANAR_420_8;
1456 case Format_400P:
1457 case Format_P8:
1458 return MHW_MEDIASTATE_SURFACEFORMAT_Y8_UNORM;
1459 case Format_411P:
1460 case Format_411R:
1461 return MHW_MEDIASTATE_SURFACEFORMAT_PLANAR_411_8;
1462 case Format_UYVY:
1463 return MHW_MEDIASTATE_SURFACEFORMAT_YCRCB_SWAPY;
1464 case Format_YVYU:
1465 return MHW_MEDIASTATE_SURFACEFORMAT_YCRCB_SWAPUV;
1466 case Format_VYUY:
1467 return MHW_MEDIASTATE_SURFACEFORMAT_YCRCB_SWAPUVY;
1468 case Format_YUY2:
1469 case Format_YUYV:
1470 case Format_444P:
1471 case Format_IMC2:
1472 case Format_IMC4:
1473 default:
1474 return MHW_MEDIASTATE_SURFACEFORMAT_YCRCB_NORMAL;
1475 }
1476
1477 return MHW_MEDIASTATE_SURFACEFORMAT_YCRCB_NORMAL;
1478 }
1479
IsVPlanePresent(MOS_FORMAT format)1480 bool IsVPlanePresent(MOS_FORMAT format)
1481 {
1482 switch (format)
1483 {
1484 case Format_NV12:
1485 case Format_NV11:
1486 case Format_P208:
1487 case Format_IMC1:
1488 case Format_IMC3:
1489 case Format_YUY2:
1490 case Format_YUYV:
1491 case Format_YVYU:
1492 case Format_UYVY:
1493 case Format_VYUY:
1494 case Format_422H:
1495 case Format_422V:
1496 // Adding RGB formats because RGB is treated like YUV for JPEG encode and decode
1497 case Format_RGBP:
1498 case Format_BGRP:
1499 case Format_A8R8G8B8:
1500 case Format_X8R8G8B8:
1501 case Format_A8B8G8R8:
1502 case Format_411P:
1503 case Format_411R:
1504 case Format_444P:
1505 case Format_IMC2:
1506 case Format_IMC4:
1507 return true;
1508 default:
1509 return false;
1510 }
1511 }
1512
MHW_SETPAR_DECL_SRC(MFX_SURFACE_STATE,AvcBasicFeature)1513 MHW_SETPAR_DECL_SRC(MFX_SURFACE_STATE, AvcBasicFeature)
1514 {
1515 PMOS_SURFACE psSurface = nullptr;
1516 uint32_t uvPlaneAlignment = 0;
1517
1518 switch (params.surfaceId)
1519 {
1520 case CODECHAL_MFX_REF_SURFACE_ID:
1521 psSurface = const_cast<PMOS_SURFACE>(&m_reconSurface);
1522 params.height = psSurface->dwHeight - 1;
1523 params.width = psSurface->dwWidth - 1;
1524 uvPlaneAlignment = MHW_VDBOX_MFX_RECON_UV_PLANE_ALIGNMENT;
1525 break;
1526 case CODECHAL_MFX_SRC_SURFACE_ID:
1527 psSurface = m_rawSurfaceToPak;
1528 params.height = m_seqParam->FrameHeight - 1;
1529 params.width = m_seqParam->FrameWidth - 1;
1530 uvPlaneAlignment = MHW_VDBOX_MFX_RAW_UV_PLANE_ALIGNMENT_GEN9;
1531 break;
1532 case CODECHAL_MFX_DSRECON_SURFACE_ID:
1533 psSurface = m_4xDSSurface;
1534 params.height = psSurface->dwHeight - 1;
1535 params.width = psSurface->dwWidth - 1;
1536 uvPlaneAlignment = MHW_VDBOX_MFX_RECON_UV_PLANE_ALIGNMENT;
1537 break;
1538 }
1539
1540 ENCODE_CHK_NULL_RETURN(psSurface);
1541
1542 params.tilemode = GetHwTileType(psSurface->TileType, psSurface->TileModeGMM, psSurface->bGMMTileEnabled);
1543 params.surfacePitch = psSurface->dwPitch - 1;
1544 params.interleaveChroma = psSurface->Format == Format_P8 ? 0 : 1;
1545 params.surfaceFormat = MosToMediaStateFormat(psSurface->Format);
1546
1547 params.yOffsetForUCb = params.yOffsetForVCr =
1548 MOS_ALIGN_CEIL((psSurface->UPlaneOffset.iSurfaceOffset - psSurface->dwOffset)/psSurface->dwPitch + psSurface->RenderOffset.YUV.U.YOffset, uvPlaneAlignment);
1549 if (IsVPlanePresent(psSurface->Format))
1550 {
1551 params.yOffsetForVCr =
1552 MOS_ALIGN_CEIL((psSurface->VPlaneOffset.iSurfaceOffset - psSurface->dwOffset)/psSurface->dwPitch + psSurface->RenderOffset.YUV.V.YOffset, uvPlaneAlignment);
1553 }
1554
1555 #ifdef _MMC_SUPPORTED
1556 if (m_mmcState && m_mmcState->IsMmcEnabled())
1557 {
1558 ENCODE_CHK_STATUS_RETURN(m_mmcState->GetSurfaceMmcFormat(psSurface, ¶ms.compressionFormat));
1559 }
1560 #endif
1561 return MOS_STATUS_SUCCESS;
1562 }
1563
MHW_SETPAR_DECL_SRC(MFX_PIPE_BUF_ADDR_STATE,AvcBasicFeature)1564 MHW_SETPAR_DECL_SRC(MFX_PIPE_BUF_ADDR_STATE, AvcBasicFeature)
1565 {
1566 params.decodeInUse = false;
1567 params.oneOnOneMapping = false;
1568 params.psPreDeblockSurface = const_cast<PMOS_SURFACE>(&m_reconSurface);
1569 params.psPostDeblockSurface = const_cast<PMOS_SURFACE>(&m_reconSurface);
1570 params.psRawSurface = m_rawSurfaceToPak;
1571 params.presSliceSizeStreamOutBuffer = m_recycleBuf->GetBuffer(PakSliceSizeStreamOutBuffer, m_frameNum);
1572
1573 ENCODE_CHK_STATUS_RETURN(m_ref->MHW_SETPAR_F(MFX_PIPE_BUF_ADDR_STATE)(params));
1574
1575 #ifdef _MMC_SUPPORTED
1576 MOS_MEMCOMP_STATE reconSurfMmcState = MOS_MEMCOMP_DISABLED;
1577 if (m_mmcState->IsMmcEnabled())
1578 {
1579 ENCODE_CHK_STATUS_RETURN(m_mmcState->GetSurfaceMmcState(m_rawSurfaceToPak, ¶ms.RawSurfMmcState));
1580 ENCODE_CHK_STATUS_RETURN(m_mmcState->GetSurfaceMmcState(const_cast<PMOS_SURFACE>(&m_reconSurface), &reconSurfMmcState));
1581
1582 if (m_deblockingEnabled)
1583 {
1584 params.PreDeblockSurfMmcState = MOS_MEMCOMP_DISABLED;
1585 params.PostDeblockSurfMmcState = reconSurfMmcState;
1586 }
1587 else
1588 {
1589 params.PreDeblockSurfMmcState = reconSurfMmcState;
1590 params.PostDeblockSurfMmcState = MOS_MEMCOMP_DISABLED;
1591 }
1592 }
1593 else
1594 {
1595 params.PreDeblockSurfMmcState = MOS_MEMCOMP_DISABLED;
1596 params.RawSurfMmcState = MOS_MEMCOMP_DISABLED;
1597 }
1598
1599 CODECHAL_DEBUG_TOOL(
1600 params.psPreDeblockSurface->MmcState = reconSurfMmcState;)
1601 #endif
1602 return MOS_STATUS_SUCCESS;
1603 }
1604
MHW_SETPAR_DECL_SRC(MFX_IND_OBJ_BASE_ADDR_STATE,AvcBasicFeature)1605 MHW_SETPAR_DECL_SRC(MFX_IND_OBJ_BASE_ADDR_STATE, AvcBasicFeature)
1606 {
1607 params.Mode = CODECHAL_ENCODE_MODE_AVC;
1608 params.presPakBaseObjectBuffer = const_cast<PMOS_RESOURCE>(&m_resBitstreamBuffer);
1609 params.dwPakBaseObjectSize = m_bitstreamSize;
1610
1611 return MOS_STATUS_SUCCESS;
1612 }
1613
MHW_SETPAR_DECL_SRC(MFX_AVC_IMG_STATE,AvcBasicFeature)1614 MHW_SETPAR_DECL_SRC(MFX_AVC_IMG_STATE, AvcBasicFeature)
1615 {
1616 auto settings = static_cast<AvcVdencFeatureSettings *>(m_constSettings);
1617 ENCODE_CHK_NULL_RETURN(settings);
1618
1619 if (m_seqParam->EnableSliceLevelRateCtrl)
1620 {
1621 params.targetSliceSizeInBytes = m_picParam->SliceSizeInBytes;
1622 }
1623
1624 uint32_t numMBs = m_picWidthInMb * m_picHeightInMb;
1625 params.frameSize = (numMBs > 0xFFFF) ? 0xFFFF : numMBs;
1626
1627 params.frameHeight = m_picHeightInMb - 1;
1628 params.frameWidth = m_picWidthInMb - 1;
1629
1630 params.imgstructImageStructureImgStructure10 = (CodecHal_PictureIsFrame(m_picParam->CurrOriginalPic) ?
1631 avcFrame : (CodecHal_PictureIsTopField(m_picParam->CurrOriginalPic) ?
1632 avcTopField : avcBottomField));
1633
1634 params.weightedBipredIdc = m_picParam->weighted_bipred_idc;
1635 params.weightedPredFlag = m_picParam->weighted_pred_flag;
1636
1637 params.firstChromaQpOffset = m_picParam->chroma_qp_index_offset;
1638 params.secondChromaQpOffset = m_picParam->second_chroma_qp_index_offset;
1639
1640 params.fieldpicflag = CodecHal_PictureIsField(m_picParam->CurrOriginalPic);
1641 params.mbaffflameflag = m_seqParam->mb_adaptive_frame_field_flag;
1642 params.framembonlyflag = m_seqParam->frame_mbs_only_flag;
1643 params.transform8X8Flag = m_picParam->transform_8x8_mode_flag;
1644 params.direct8X8Infflag = m_seqParam->direct_8x8_inference_flag;
1645 params.constrainedipredflag = m_picParam->constrained_intra_pred_flag;
1646 params.entropycodingflag = m_picParam->entropy_coding_mode_flag;
1647 params.mbmvformatflag = 1;
1648 params.chromaformatidc = m_seqParam->chroma_format_idc;
1649 params.mvunpackedflag = 1;
1650
1651 params.intrambmaxbitflagIntrambmaxsizereportmask = 1;
1652 params.intermbmaxbitflagIntermbmaxsizereportmask = 1;
1653 params.frameszoverflagFramebitratemaxreportmask = 1;
1654 params.frameszunderflagFramebitrateminreportmask = 1;
1655 params.intraIntermbipcmflagForceipcmcontrolmask = 1;
1656 params.mbratectrlflagMbLevelRateControlEnablingFlag = 0;
1657
1658 params.intrambmaxsz = settings->intraMbMaxSize;
1659 params.intermbmaxsz = settings->interMbMaxSize;
1660
1661 // Set this to New mode (= 1) - FrameBitRateMaxUnit and FrameBitRateMinUnit are in new mode (32byte/4Kb)
1662 params.framebitratemaxunitmode = params.framebitrateminunitmode = 1;
1663 // Set this to Kilo Byte (= 1) - FrameBitRateMax and FrameBitRateMin are in units of 4KBytes when FrameBitrateMaxUnitMode and FrameBitRateMinUnitMode are set to 1
1664 params.framebitratemaxunit = params.framebitrateminunit = 1;
1665 // We have 14 bits available when FrameBitRateMaxUnitMode is set to 1, so set it to max value
1666 params.framebitratemax = (1 << 14) - 1;
1667 // Set this to min available value
1668 params.framebitratemin = 0;
1669 // Set frame bitrate max and min delta to 0
1670 params.framebitratemindelta = params.framebitratemaxdelta = 0;
1671
1672 params.sliceStatsStreamoutEnable = true;
1673 params.extendedRhodomainStatisticsEnable = true;
1674
1675 if (m_seqParam->EnableSliceLevelRateCtrl)
1676 {
1677 uint8_t qpY = m_picParam->QpY;
1678 uint32_t dwVdencSliceMinusBytes = (m_pictureCodingType == I_TYPE) ? settings->SliceSizeThrsholdsI[qpY] : settings->SliceSizeThrsholdsP[qpY];
1679 params.thresholdSizeInBytes = m_picParam->SliceSizeInBytes - MOS_MIN(m_picParam->SliceSizeInBytes, dwVdencSliceMinusBytes);
1680 }
1681
1682 return MOS_STATUS_SUCCESS;
1683 }
1684
MHW_SETPAR_DECL_SRC(MFX_AVC_REF_IDX_STATE,AvcBasicFeature)1685 MHW_SETPAR_DECL_SRC(MFX_AVC_REF_IDX_STATE, AvcBasicFeature)
1686 {
1687 PCODEC_AVC_ENCODE_SLICE_PARAMS sliceParams = &m_sliceParams[m_curNumSlices];
1688 PCODEC_REF_LIST * avcRefList = m_ref->GetRefList();
1689 AvcRefListWrite * cmdAvcRefListWrite = (AvcRefListWrite *)&(params.referenceListEntry);
1690
1691 int32_t uiNumRefForList[2] = {sliceParams->num_ref_idx_l0_active_minus1 + 1, sliceParams->num_ref_idx_l1_active_minus1 + 1};
1692
1693 for (auto i = 0; i < uiNumRefForList[params.uiList]; i++)
1694 {
1695 uint8_t idx = sliceParams->RefPicList[params.uiList][i].FrameIdx;
1696 if (idx >= CODEC_MAX_NUM_REF_FRAME)
1697 {
1698 ENCODE_ASSERT(false); // Idx must be within 0 to 15
1699 idx = 0;
1700 }
1701 idx = m_ref->GetPicIndex()[idx].ucPicIdx;
1702
1703 cmdAvcRefListWrite->UC[i].frameStoreID = avcRefList[idx]->ucFrameId;
1704 cmdAvcRefListWrite->UC[i].bottomField = CodecHal_PictureIsBottomField(sliceParams->RefPicList[params.uiList][i]);
1705 cmdAvcRefListWrite->UC[i].fieldPicFlag = CodecHal_PictureIsField(sliceParams->RefPicList[params.uiList][i]);
1706 cmdAvcRefListWrite->UC[i].longTermFlag = CodecHal_PictureIsLongTermRef(avcRefList[idx]->RefPic);
1707 cmdAvcRefListWrite->UC[i].nonExisting = 0;
1708 }
1709
1710 for (auto i = uiNumRefForList[params.uiList]; i < 32; i++)
1711 {
1712 cmdAvcRefListWrite->UC[i].value = 0x80;
1713 }
1714
1715 return MOS_STATUS_SUCCESS;
1716 }
1717
MHW_SETPAR_DECL_SRC(MFX_AVC_SLICE_STATE,AvcBasicFeature)1718 MHW_SETPAR_DECL_SRC(MFX_AVC_SLICE_STATE, AvcBasicFeature)
1719 {
1720 auto sliceParams = &m_sliceParams[m_curNumSlices];
1721
1722 uint16_t widthInMb = m_seqParam->pic_width_in_mbs_minus1 + 1;
1723 uint32_t startMbNum = sliceParams->first_mb_in_slice * (1 + m_seqParam->mb_adaptive_frame_field_flag);
1724
1725 params.sliceType = Slice_Type[sliceParams->slice_type];
1726
1727 params.log2WeightDenomLuma = sliceParams->luma_log2_weight_denom;
1728 params.log2WeightDenomChroma = sliceParams->chroma_log2_weight_denom;
1729 params.numberOfReferencePicturesInInterPredictionList0 = 0;
1730 params.numberOfReferencePicturesInInterPredictionList1 = 0;
1731
1732 params.sliceAlphaC0OffsetDiv2 = sliceParams->slice_alpha_c0_offset_div2;
1733 params.sliceBetaOffsetDiv2 = sliceParams->slice_beta_offset_div2;
1734 params.sliceQuantizationParameter = 26 + m_picParam->pic_init_qp_minus26 + sliceParams->slice_qp_delta;
1735 params.cabacInitIdc10 = sliceParams->cabac_init_idc;
1736 params.disableDeblockingFilterIndicator = sliceParams->disable_deblocking_filter_idc;
1737 params.directPredictionType = IsAvcBSlice(sliceParams->slice_type) ? sliceParams->direct_spatial_mv_pred_flag : 0;
1738 params.weightedPredictionIndicator = DEFAULT_WEIGHTED_INTER_PRED_MODE;
1739
1740 params.sliceHorizontalPosition = startMbNum % widthInMb;
1741 params.sliceVerticalPosition = startMbNum / widthInMb;
1742 params.nextSliceHorizontalPosition = (startMbNum + sliceParams->NumMbsForSlice) % widthInMb;
1743 params.nextSliceVerticalPosition = (startMbNum + sliceParams->NumMbsForSlice) / widthInMb;
1744
1745 params.sliceId30 = (uint8_t)sliceParams->slice_id;
1746 params.cabaczerowordinsertionenable = 0;
1747 params.emulationbytesliceinsertenable = 1;
1748 params.tailInsertionPresentInBitstream = m_vdencNoTailInsertion ? 0 : (m_picParam->bLastPicInSeq || m_picParam->bLastPicInStream);
1749 params.slicedataInsertionPresentInBitstream = 1;
1750 params.headerInsertionPresentInBitstream = 1;
1751 params.isLastSlice = (startMbNum + sliceParams->NumMbsForSlice) >= (uint32_t)(widthInMb * m_frameFieldHeightInMb);
1752
1753 if (IsAvcPSlice(sliceParams->slice_type))
1754 {
1755 params.numberOfReferencePicturesInInterPredictionList0 = sliceParams->num_ref_idx_l0_active_minus1_from_DDI + 1;
1756 params.weightedPredictionIndicator = m_picParam->weighted_pred_flag;
1757 }
1758 else if (IsAvcBSlice(sliceParams->slice_type))
1759 {
1760 params.numberOfReferencePicturesInInterPredictionList1 = sliceParams->num_ref_idx_l1_active_minus1_from_DDI + 1;
1761 params.numberOfReferencePicturesInInterPredictionList0 = sliceParams->num_ref_idx_l0_active_minus1_from_DDI + 1;
1762 params.weightedPredictionIndicator = m_picParam->weighted_bipred_idc;
1763 if (m_picParam->weighted_bipred_idc == IMPLICIT_WEIGHTED_INTER_PRED_MODE)
1764 {
1765 params.log2WeightDenomLuma = 0;
1766 params.log2WeightDenomChroma = 0;
1767 }
1768 }
1769
1770 return MOS_STATUS_SUCCESS;
1771 }
1772
MHW_SETPAR_DECL_SRC(MFX_AVC_DIRECTMODE_STATE,AvcBasicFeature)1773 MHW_SETPAR_DECL_SRC(MFX_AVC_DIRECTMODE_STATE, AvcBasicFeature)
1774 {
1775 params.CurrPic = m_picParam->CurrReconstructedPic;
1776 params.uiUsedForReferenceFlags = 0xFFFFFFFF;
1777 params.pAvcPicIdx = m_ref->GetPicIndex();
1778 params.avcRefList = (void**)m_ref->GetRefList();
1779 params.bPicIdRemappingInUse = false;
1780 params.bDisableDmvBuffers = true;
1781
1782 return MOS_STATUS_SUCCESS;
1783 }
1784
MHW_SETPAR_DECL_SRC(MI_FORCE_WAKEUP,AvcBasicFeature)1785 MHW_SETPAR_DECL_SRC(MI_FORCE_WAKEUP, AvcBasicFeature)
1786 {
1787 params.bMFXPowerWellControl = true;
1788 params.bMFXPowerWellControlMask = true;
1789 params.bHEVCPowerWellControl = false;
1790 params.bHEVCPowerWellControlMask = true;
1791 return MOS_STATUS_SUCCESS;
1792 }
1793
MHW_SETPAR_DECL_SRC(MFX_WAIT,AvcBasicFeature)1794 MHW_SETPAR_DECL_SRC(MFX_WAIT, AvcBasicFeature)
1795 {
1796 params.iStallVdboxPipeline = true;
1797
1798 return MOS_STATUS_SUCCESS;
1799 }
1800
MHW_SETPAR_DECL_SRC(HUC_PIPE_MODE_SELECT,AvcBasicFeature)1801 MHW_SETPAR_DECL_SRC(HUC_PIPE_MODE_SELECT, AvcBasicFeature)
1802 {
1803 params.mode = m_mode;
1804
1805 return MOS_STATUS_SUCCESS;
1806 }
1807
1808 } // namespace encode
1809