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), &params.compressionFormatRecon));
1223             ENCODE_CHK_STATUS_RETURN(m_mmcState->GetSurfaceMmcState(m_rawSurfaceToPak, &params.mmcStateRaw));
1224             ENCODE_CHK_STATUS_RETURN(m_mmcState->GetSurfaceMmcFormat(m_rawSurfaceToPak, &params.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, &params.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, &params.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