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_av1_brc.cpp
24 //! \brief    Defines the common interface for av1 brc features
25 //!
26 #include "encode_av1_basic_feature.h"
27 #include "encode_av1_brc.h"
28 #include "encode_av1_vdenc_feature_manager.h"
29 #include "encode_av1_vdenc_const_settings.h"
30 #include "encode_av1_brc_init_packet.h"
31 #include "encode_av1_brc_update_packet.h"
32 namespace encode
33 {
Av1Brc(MediaFeatureManager * featureManager,EncodeAllocator * allocator,CodechalHwInterfaceNext * hwInterface,void * constSettings)34     Av1Brc::Av1Brc(
35         MediaFeatureManager *featureManager,
36         EncodeAllocator *allocator,
37         CodechalHwInterfaceNext *hwInterface,
38         void *constSettings) :
39         MediaFeature(constSettings, hwInterface ? hwInterface->GetOsInterface() : nullptr),
40         m_hwInterface(hwInterface),
41         m_allocator(allocator)
42     {
43         m_featureManager = featureManager;
44 
45         ENCODE_CHK_NULL_NO_STATUS_RETURN(featureManager);
46         m_basicFeature = dynamic_cast<Av1BasicFeature*>(featureManager->GetFeature(Av1FeatureIDs::basicFeature));
47         ENCODE_CHK_NULL_NO_STATUS_RETURN(m_basicFeature);
48 
49         ENCODE_CHK_NULL_NO_STATUS_RETURN(hwInterface);
50     }
51 
~Av1Brc()52     Av1Brc::~Av1Brc()
53     {
54         FreeBrcResources();
55     }
56 
Init(void * setting)57     MOS_STATUS Av1Brc::Init(void *setting)
58     {
59         ENCODE_FUNC_CALL();
60 
61         ENCODE_CHK_STATUS_RETURN(AllocateResources());
62 
63         return MOS_STATUS_SUCCESS;
64     }
65 
Update(void * params)66     MOS_STATUS Av1Brc::Update(void *params)
67     {
68         ENCODE_FUNC_CALL();
69         ENCODE_CHK_NULL_RETURN(params);
70 
71         EncoderParams *encodeParams = (EncoderParams *)params;
72 
73         ENCODE_CHK_STATUS_RETURN(SetSequenceStructs());
74 
75         const auto& seqParams = *m_basicFeature->m_av1SeqParams;
76 
77 #if (_DEBUG || _RELEASE_INTERNAL)
78         ReportUserSetting(
79             m_userSettingPtr,
80             "Encode RateControl Method",
81             m_rcMode,
82             MediaUserSetting::Group::Sequence);
83 #endif
84         return MOS_STATUS_SUCCESS;
85     }
86 
AllocateResources()87     MOS_STATUS Av1Brc::AllocateResources()
88     {
89         ENCODE_FUNC_CALL();
90 
91         ENCODE_CHK_NULL_RETURN(m_allocator);
92         ENCODE_CHK_NULL_RETURN(m_basicFeature);
93         ENCODE_CHK_NULL_RETURN(m_basicFeature->m_recycleBuf);
94 
95         MOS_ALLOC_GFXRES_PARAMS allocParamsForBufferLinear;
96         MOS_ZeroMemory(&allocParamsForBufferLinear, sizeof(MOS_ALLOC_GFXRES_PARAMS));
97         allocParamsForBufferLinear.Type = MOS_GFXRES_BUFFER;
98         allocParamsForBufferLinear.TileType = MOS_TILE_LINEAR;
99         allocParamsForBufferLinear.Format = Format_Buffer;
100 
101         // BRC history buffer
102         allocParamsForBufferLinear.dwBytes = MOS_ALIGN_CEIL(m_brcHistoryBufSize, CODECHAL_PAGE_SIZE);
103         allocParamsForBufferLinear.pBufName = "VDENC BRC History Buffer";
104         allocParamsForBufferLinear.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_READ_WRITE_CACHE;
105         m_basicFeature->m_recycleBuf->RegisterResource(VdencBRCHistoryBuffer, allocParamsForBufferLinear, 1);
106 
107         // VDENC BRC PAK MMIO buffer
108         allocParamsForBufferLinear.dwBytes = sizeof(Av1BrcPakMmio);
109         allocParamsForBufferLinear.pBufName = "VDENC BRC PAK MMIO Buffer";
110         allocParamsForBufferLinear.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_READ_WRITE_CACHE;
111         m_basicFeature->m_recycleBuf->RegisterResource(VdencBrcPakMmioBuffer, allocParamsForBufferLinear, 1);
112 
113         // BRC HuC Data Buffer
114         allocParamsForBufferLinear.dwBytes = MOS_ALIGN_CEIL(BRC_DATA_SIZE, CODECHAL_PAGE_SIZE);
115         allocParamsForBufferLinear.pBufName = "BRC HuC Data Buffer";
116         allocParamsForBufferLinear.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_READ;
117         MOS_RESOURCE* brcDataBuffer = m_allocator->AllocateResource(
118             allocParamsForBufferLinear,
119             true);
120         ENCODE_CHK_NULL_RETURN(brcDataBuffer);
121         m_resBrcDataBuffer = *brcDataBuffer;
122 
123         for (auto j = 0; j < CODECHAL_ENCODE_RECYCLED_BUFFER_NUM; j++)
124         {
125             // VDENC uses second level batch buffer
126             MOS_ZeroMemory(&m_vdenc2ndLevelBatchBuffer[j], sizeof(MHW_BATCH_BUFFER));
127             m_vdenc2ndLevelBatchBuffer[j].bSecondLevel = true;
128             ENCODE_CHK_STATUS_RETURN(Mhw_AllocateBb(
129                 m_hwInterface->GetOsInterface(),
130                 &m_vdenc2ndLevelBatchBuffer[j],
131                 nullptr,
132                 m_hwInterface->m_vdenc2ndLevelBatchBufferSize));
133 
134             // VDENC uses second level batch buffer
135             MOS_ZeroMemory(&m_pakInsertOutputBatchBuffer[j], sizeof(MHW_BATCH_BUFFER));
136             m_pakInsertOutputBatchBuffer[j].bSecondLevel = true;
137             ENCODE_CHK_STATUS_RETURN(Mhw_AllocateBb(
138                 m_hwInterface->GetOsInterface(),
139                 &m_pakInsertOutputBatchBuffer[j],
140                 nullptr,
141                 CODECHAL_PAGE_SIZE));
142         }
143 
144         return MOS_STATUS_SUCCESS;
145     }
146 
GetBrcDataBuffer(MOS_RESOURCE * & buffer)147     MOS_STATUS Av1Brc::GetBrcDataBuffer(MOS_RESOURCE *&buffer)
148     {
149         ENCODE_FUNC_CALL();
150         buffer = &m_resBrcDataBuffer;
151         return MOS_STATUS_SUCCESS;
152     }
153 
MapTCBRCScenarioInfo(ENCODE_SCENARIO & scenarioInfo)154     inline uint8_t MapTCBRCScenarioInfo(ENCODE_SCENARIO& scenarioInfo)
155     {
156         uint8_t TCBRCScenarioInfo = 0;
157         switch (scenarioInfo)
158         {
159         case ESCENARIO_REMOTEGAMING:
160             TCBRCScenarioInfo = 0;
161             break;
162         case ESCENARIO_VIDEOCONFERENCE:
163             TCBRCScenarioInfo = 1;
164             break;
165         default:
166             ENCODE_ASSERTMESSAGE("TCBRC mode not supported!");
167             break;
168         }
169         return TCBRCScenarioInfo;
170     }
171 
SetDmemForUpdate(VdencAv1HucBrcUpdateDmem * dmem) const172     MOS_STATUS Av1Brc::SetDmemForUpdate(VdencAv1HucBrcUpdateDmem *dmem) const
173     {
174         ENCODE_FUNC_CALL();
175         ENCODE_CHK_NULL_RETURN(dmem);
176 
177         ENCODE_CHK_NULL_RETURN(m_basicFeature);
178         ENCODE_CHK_NULL_RETURN(m_basicFeature->m_av1SeqParams);
179         auto seqParams = m_basicFeature->m_av1SeqParams;
180         ENCODE_CHK_NULL_RETURN(m_basicFeature->m_av1PicParams);
181         auto picParams = m_basicFeature->m_av1PicParams;
182         auto       setting = static_cast<Av1VdencFeatureSettings*>(m_constSettings);
183         ENCODE_CHK_NULL_RETURN(setting);
184 
185         auto brcSettings = setting->brcSettings;
186 
187         // BRC update setting
188         if (m_curTargetFullness > seqParams->VBVBufferSizeInBit && dmem->UPD_PAKPassNum == 0)
189         {
190             dmem->UPD_OverflowFlag = 0x1;
191             m_curTargetFullness -= seqParams->VBVBufferSizeInBit;
192         }
193 
194         dmem->UPD_TARGET_BUF_FULLNESS = (uint32_t)m_curTargetFullness;
195         dmem->UPD_CDF_BufferSize = MOS_ALIGN_CEIL(m_basicFeature->m_cdfMaxNumBytes, CODECHAL_CACHELINE_SIZE);
196         dmem->UPD_FRAMENUM = m_basicFeature->m_frameNum;    // frame number
197         dmem->UPD_HRD_BUFF_FULLNESS = m_delay;
198         dmem->UPD_HRD_BUFF_FULLNESS_LOWER = seqParams->LowerVBVBufferLevelThresholdInBit;
199         dmem->UPD_HRD_BUFF_FULLNESS_UPPER = seqParams->UpperVBVBufferLevelThresholdInBit;
200 
201         auto CalculatedMaxFrame = m_basicFeature->m_frameHeight * m_basicFeature->m_frameWidth;
202         dmem->UPD_UserMaxFrame   = seqParams->UserMaxIFrameSize  > 0 ? MOS_MIN(seqParams->UserMaxIFrameSize, CalculatedMaxFrame) : CalculatedMaxFrame;
203         dmem->UPD_UserMaxFramePB = seqParams->UserMaxPBFrameSize > 0 ? MOS_MIN(seqParams->UserMaxPBFrameSize, CalculatedMaxFrame) : CalculatedMaxFrame;
204 
205         dmem->UPD_CurWidth  = (uint16_t)m_basicFeature->m_oriFrameWidth;
206         dmem->UPD_CurHeight = (uint16_t)m_basicFeature->m_oriFrameHeight;
207         dmem->UPD_Asyn = 0;
208         dmem->UPD_EnableAdaptiveRounding = (m_basicFeature->m_roundingMethod == RoundingMethod::adaptiveRounding);
209 
210         if (seqParams->GopRefDist == 16 && m_rcMode == RATECONTROL_CQL)
211             dmem->UPD_MaxBRCLevel = 4;
212         else if (seqParams->GopRefDist == 8)
213             dmem->UPD_MaxBRCLevel = 3;
214         else if (seqParams->GopRefDist == 4)
215             dmem->UPD_MaxBRCLevel = 2;
216         else if (seqParams->GopRefDist == 2)
217             dmem->UPD_MaxBRCLevel = 1;
218         else
219             dmem->UPD_MaxBRCLevel = 0;
220 
221         bool bAllowedPyramid = seqParams->GopRefDist != 3;
222 
223         if (m_basicFeature->m_pictureCodingType == I_TYPE)
224         {
225             dmem->UPD_CurrFrameType = AV1_BRC_FRAME_TYPE_I;
226         }
227         else if (seqParams->SeqFlags.fields.HierarchicalFlag && bAllowedPyramid)
228         {
229             if (picParams->HierarchLevelPlus1 > 0)
230             {
231                 std::map<int, AV1_BRC_FRAME_TYPE> hierchLevelPlus1_to_brclevel{
232                     {1, AV1_BRC_FRAME_TYPE_P_OR_LB},
233                     {2, AV1_BRC_FRAME_TYPE_B},
234                     {3, AV1_BRC_FRAME_TYPE_B1},
235                     {4, AV1_BRC_FRAME_TYPE_B2},
236                     {5, AV1_BRC_FRAME_TYPE_B3}};
237                 dmem->UPD_CurrFrameType = hierchLevelPlus1_to_brclevel.count(picParams->HierarchLevelPlus1) ? hierchLevelPlus1_to_brclevel[picParams->HierarchLevelPlus1] : AV1_BRC_FRAME_TYPE_INVALID;
238                 //Invalid HierarchLevelPlus1 or LBD frames at level 3 eror check.
239                 if ((dmem->UPD_CurrFrameType == AV1_BRC_FRAME_TYPE_INVALID) ||
240                     (m_basicFeature->m_ref.IsLowDelay() && dmem->UPD_CurrFrameType == AV1_BRC_FRAME_TYPE_B2))
241                 {
242                     ENCODE_VERBOSEMESSAGE("AV1_BRC_FRAME_TYPE_INVALID or LBD picture doesn't support Level 4\n");
243                     dmem->UPD_CurrFrameType = AV1_BRC_FRAME_TYPE_B2;
244                 }
245             }
246             else
247             {
248                 dmem->UPD_CurrFrameType = AV1_BRC_FRAME_TYPE_P_OR_LB;  //No Hierarchical info, treated as flat case
249             }
250         }
251         else
252         {
253             dmem->UPD_CurrFrameType = m_basicFeature->m_ref.IsLowDelay() ? AV1_BRC_FRAME_TYPE_P_OR_LB : AV1_BRC_FRAME_TYPE_B;
254         }
255 
256 #define MEMCPY_CONST(D, S) MOS_SecureMemcpy(dmem->D, sizeof(dmem->D), brcSettings.S.data, brcSettings.S.size);
257         MEMCPY_CONST(UPD_startGAdjFrame, startGlobalAdjustFrame);
258         MEMCPY_CONST(UPD_QPThreshold, QPThresholds);
259         MEMCPY_CONST(UPD_gRateRatioThreshold, globalRateRatioThreshold);
260         MEMCPY_CONST(UPD_gRateRatioThresholdQP, globalRateRatioThresholdQP);
261         MEMCPY_CONST(UPD_startGAdjMult, startGlobalAdjustMult);
262         MEMCPY_CONST(UPD_startGAdjDiv, startGlobalAdjustDiv);
263         MEMCPY_CONST(UPD_DistThreshldI, distortionThresh);
264         MEMCPY_CONST(UPD_DistThreshldP, distortionThresh);
265         MEMCPY_CONST(UPD_DistThreshldB, distortionThreshB);
266         MEMCPY_CONST(UPD_MaxFrameThreshI, maxFrameMultI);
267         MEMCPY_CONST(UPD_MaxFrameThreshP, maxFrameMultP);
268         MEMCPY_CONST(UPD_MaxFrameThreshB, maxFrameMultP);
269 #undef MEMCPY_CONST
270 
271         dmem->UPD_Temporal_Level = m_basicFeature->m_av1PicParams->temporal_id;
272         dmem->UPD_Lowdelay = seqParams->FrameSizeTolerance == EFRAMESIZETOL_EXTREMELY_LOW ? 1 : 0;
273         // To handle ultra-low-delay situation inside driver
274         dmem->UPD_Lowdelay = (dmem->UPD_Lowdelay || seqParams->InitVBVBufferFullnessInBit <= m_inputbitsperframe * 2) ? 1 : 0;
275 
276         dmem->UPD_TR_TargetSize = picParams->TargetFrameSize << 3;
277 
278         if (picParams->TargetFrameSize > 0)
279         {
280             dmem->UPD_TCBRC_SCENARIO = MapTCBRCScenarioInfo(seqParams->ScenarioInfo);
281         }
282 
283         dmem->UPD_LA_TargetFULNESS = 0;
284         dmem->UPD_Delta = 0;
285         dmem->UPD_LALength = 0;
286 
287         //SLBB related fields.
288         dmem->UPD_SLBBSize = m_slbData.slbSize;
289         dmem->UPD_AVPPiCStateCmdNum = m_slbData.avpPicStateCmdNum;
290         dmem->UPD_AVPSegmentStateOffset = m_slbData.avpSegmentStateOffset;
291         dmem->UPD_AVPInloopFilterStateOffset = m_slbData.avpInloopFilterStateOffset;
292         dmem->UPD_VDEncCmd1Offset = m_slbData.vdencCmd1Offset;
293         dmem->UPD_VDEncCmd2Offset = m_slbData.vdencCmd2Offset;
294         dmem->UPD_AVPPicStateOffset = m_slbData.avpPicStateOffset;
295         dmem->UPD_VDEncTileSliceStateOffset = m_slbData.vdencTileSliceStateOffset;
296         dmem->UPD_TileNum = m_slbData.tileNum;
297 
298         // BA start
299         dmem->UPD_LoopFilterParamsBitOffset      = (uint16_t)m_basicFeature->m_av1PicParams->LoopFilterParamsBitOffset;
300         dmem->UPD_QIndexBitOffset                = (uint16_t)m_basicFeature->m_av1PicParams->QIndexBitOffset;
301         dmem->UPD_SegmentationBitOffset          = (uint16_t)m_basicFeature->m_av1PicParams->SegmentationBitOffset; // after SegOn flag bit.
302         dmem->UPD_FrameHdrOBUSizeInBits          = (uint16_t)m_basicFeature->m_av1PicParams->FrameHdrOBUSizeInBits; // excluding frame_header_obu's trailing_bits() and frame_obu's byte_alignment()
303         dmem->UPD_FrameHdrOBUSizeInBytes         = (uint16_t)((m_basicFeature->m_av1PicParams->FrameHdrOBUSizeInBits + 7) >> 3);
304         dmem->UPD_FrameHdrOBUSizeByteOffset      = (uint16_t)(m_basicFeature->m_av1PicParams->FrameHdrOBUSizeByteOffset - m_basicFeature->GetAppHdrSizeInBytes(true));
305         dmem->UPD_FrameType                      = 0;
306         dmem->UPD_ErrorResilientMode             = m_basicFeature->m_av1PicParams->PicFlags.fields.error_resilient_mode;
307         dmem->UPD_IntraOnly                      = 0;
308         dmem->UPD_PrimaryRefFrame                = 0;
309         dmem->UPD_SegOn                          = m_basicFeature->m_av1PicParams->stAV1Segments.SegmentFlags.fields.segmentation_enabled;
310         dmem->UPD_SegMapUpdate                   = 0;
311         dmem->UPD_SegTemporalUpdate              = 0;
312         dmem->UPD_SegUpdateData                  = 0;
313         dmem->UPD_IsFrameOBU                     = m_basicFeature->m_av1PicParams->PicFlags.fields.EnableFrameOBU;
314         dmem->UPD_EnableCDEFUpdate               = m_basicFeature->m_av1SeqParams->CodingToolFlags.fields.enable_cdef;
315         dmem->UPD_CDEFParamsBitOffset            = (uint16_t)m_basicFeature->m_av1PicParams->CDEFParamsBitOffset;
316         dmem->UPD_CDEFParamsSizeInBits           = (uint16_t)m_basicFeature->m_av1PicParams->CDEFParamsSizeInBits;
317         dmem->UPD_EnableLFUpdate                 = 1;
318         dmem->UPD_DisableCdfUpdate               = (m_basicFeature->m_av1PicParams->primary_ref_frame != av1PrimaryRefNone);
319         dmem->UPD_EnableDMAForCdf                = 1;
320         dmem->UPD_AdditionalHrdSizeByteCount     = 0 - m_basicFeature->m_av1PicParams->FrameSizeReducedInBytes;
321         dmem->UPD_PaletteOn                      = m_basicFeature->m_av1PicParams->PicFlags.fields.PaletteModeEnable;
322 
323         if (dmem->UPD_PAKPassNum == 1)
324             m_curTargetFullness += m_inputbitsperframe;
325 
326         if (picParams->PicFlags.fields.allow_intrabc && AV1_KEY_OR_INRA_FRAME(picParams->PicFlags.fields.frame_type))
327         {
328             dmem->UPD_EnableCDEFUpdate = 0;
329             dmem->UPD_EnableLFUpdate   = 0;
330         }
331 
332         return MOS_STATUS_SUCCESS;
333     }
334 
SetConstForUpdate(VdencAv1HucBrcConstantData * params) const335     MOS_STATUS Av1Brc::SetConstForUpdate(VdencAv1HucBrcConstantData *params) const
336     {
337         ENCODE_FUNC_CALL();
338         ENCODE_CHK_NULL_RETURN(params);
339         auto constData = (VdencAv1HucBrcConstantData *)params;
340 
341         auto setting = static_cast<Av1VdencFeatureSettings *>(m_constSettings);
342         ENCODE_CHK_NULL_RETURN(setting);
343 
344         auto brcSettings = setting->brcSettings;
345 
346 #define MEMCPY_CONST(D, S) MOS_SecureMemcpy(constData->D, sizeof(constData->D), brcSettings.S.data, brcSettings.S.size);
347         MEMCPY_CONST(CONST_QPAdjTabI, av1DeltaQpI);
348         MEMCPY_CONST(CONST_QPAdjTabP, av1DeltaQpP);
349         MEMCPY_CONST(CONST_QPAdjTabB, av1DeltaQpP);
350         MEMCPY_CONST(CONST_DistQPAdjTabI, av1DistortionsDeltaQpI);
351         MEMCPY_CONST(CONST_DistQPAdjTabP, av1DistortionsDeltaQpP);
352         MEMCPY_CONST(CONST_DistQPAdjTabB, av1DistortionsDeltaQpP);
353         MEMCPY_CONST(CONST_LoopFilterLevelTabLuma, loopFilterLevelTabLuma);
354         MEMCPY_CONST(CONST_LoopFilterLevelTabChroma, loopFilterLevelTabChroma);
355 
356         // ModeCosts depends on frame type
357         if (m_basicFeature->m_pictureCodingType == I_TYPE)
358         {
359             MEMCPY_CONST(CONST_ModeCosts, hucModeCostsIFrame);
360         }
361         else
362         {
363             MEMCPY_CONST(CONST_ModeCosts, hucModeCostsPFrame);
364         }
365 #undef MEMCPY_CONST
366         return MOS_STATUS_SUCCESS;
367     }
368 
SwitchFlag(uint8_t rc)369     inline uint16_t SwitchFlag(uint8_t rc)
370     {
371         uint16_t brcFlag = 0;
372         switch (rc)
373         {
374         case RATECONTROL_CBR:
375             brcFlag = 0x10; // BRC flag 0: ACQP, 0x10: CBR, 0x20: VBR, 0x40: AVBR, 0x80: CQL
376             break;
377         case RATECONTROL_VBR:
378             brcFlag = 0x20;
379             break;
380         case RATECONTROL_CQP:
381             brcFlag = 0;
382             break;
383         case RATECONTROL_CQL:
384             brcFlag = 0x80;
385             break;
386         default:
387             ENCODE_ASSERTMESSAGE("BRC mode not supported!");
388             break;
389         }
390         return brcFlag;
391     }
392 
CalculateNormalizedDenominator(FRAMERATE * frameRates,uint16_t numberOfLayers,uint32_t normalizedDenominator)393     static uint32_t CalculateNormalizedDenominator(FRAMERATE* frameRates, uint16_t numberOfLayers, uint32_t normalizedDenominator)
394     {
395         ENCODE_FUNC_CALL();
396 
397         // If pointer to the list of FrameRates is null, return the current Normalized Denominator.
398         if (!frameRates)
399         {
400             return normalizedDenominator;
401         }
402 
403         if (numberOfLayers == 0)
404         {
405             return normalizedDenominator;
406         }
407 
408         normalizedDenominator = normalizedDenominator * frameRates[numberOfLayers - 1].Denominator / MosUtilities::MosGCD(normalizedDenominator, frameRates[numberOfLayers - 1].Denominator);
409 
410         return CalculateNormalizedDenominator(frameRates, numberOfLayers - 1, normalizedDenominator);
411     }
412 
GetProfileLevelMaxFrameSize(uint32_t width,uint32_t height,uint32_t userMaxFrameSize)413     inline uint32_t GetProfileLevelMaxFrameSize(uint32_t width, uint32_t height, uint32_t userMaxFrameSize)
414     {
415         ENCODE_FUNC_CALL();
416         uint32_t profileLevelMaxFrame = 0;
417 
418         // Might need calculate max frame size base on profile and level, confirm with arch.
419 
420         profileLevelMaxFrame = width * height;
421         if (userMaxFrameSize > 0)
422         {
423             profileLevelMaxFrame = (uint32_t)MOS_MIN(userMaxFrameSize, profileLevelMaxFrame);
424         }
425 
426         return profileLevelMaxFrame;
427     }
428 
ComputeVDEncInitQPI(uint32_t width,uint32_t height,FRAMERATE frameRate,uint32_t targetBitRate,uint16_t gopPicSize,bool is10Bit,uint16_t n_p)429     inline int32_t ComputeVDEncInitQPI(uint32_t width, uint32_t height, FRAMERATE frameRate, uint32_t targetBitRate, uint16_t gopPicSize, bool is10Bit, uint16_t n_p)
430     {
431         ENCODE_FUNC_CALL();
432 
433         uint32_t frameSize = ((width * height * 3) >> 1);
434         if (is10Bit)
435         {
436             frameSize = (frameSize * 10) >> 3;
437         }
438 
439         const float x0 = 0, y0 = 1.19f, x1 = 1.75f, y1 = 1.75f;
440 
441         int32_t qpP = (int32_t)(1. / 1.2 * pow(10.0, (log10(frameSize * 2. / 3. * ((float)frameRate.Numerator) / ((float)targetBitRate * BRC_KBPS * frameRate.Denominator)) - x0) * (y1 - y0) / (x1 - x0) + y0) + 0.5);
442         qpP = (int32_t)((float)qpP * (5.0));
443         qpP -= 20;
444         qpP = MOS_CLAMP_MIN_MAX(qpP, 1, 200);
445 
446         int32_t  qpI = (qpP > 4) ? (qpP - 4) : qpP;
447         int16_t  qiboost = n_p / 30 - 1;
448         qiboost = MOS_CLAMP_MIN_MAX(qiboost, 10, 20);
449 
450         qpI -= qiboost;
451         qpI = MOS_CLAMP_MIN_MAX(qpI, 1, 200);
452 
453         return qpI;
454     }
455 
GetFrameRate(CODEC_AV1_ENCODE_SEQUENCE_PARAMS const & seqParams)456     static std::tuple<uint32_t, uint32_t> GetFrameRate(CODEC_AV1_ENCODE_SEQUENCE_PARAMS const &seqParams)
457     {
458         if ((seqParams.FrameRate->Numerator != 0) && (seqParams.FrameRate->Denominator != 0))
459         {
460             return std::make_tuple(seqParams.FrameRate->Numerator, seqParams.FrameRate->Denominator);
461         }
462         else
463         {
464             return std::make_tuple(30, 1);
465         }
466     }
467 
SetDmemForInit(VdencAv1HucBrcInitDmem * dmem) const468     MOS_STATUS Av1Brc::SetDmemForInit(VdencAv1HucBrcInitDmem *dmem) const
469     {
470         ENCODE_FUNC_CALL();
471         ENCODE_CHK_NULL_RETURN(dmem);
472         ENCODE_CHK_NULL_RETURN(m_basicFeature);
473 
474         auto setting = static_cast<Av1VdencFeatureSettings*>(m_constSettings);
475         ENCODE_CHK_NULL_RETURN(setting);
476 
477         auto brcSettings = setting->brcSettings;
478 
479         auto seqParams = m_basicFeature->m_av1SeqParams;
480         ENCODE_CHK_NULL_RETURN(seqParams);
481 
482         dmem->BRCFunc = IsBRCResetRequired() ? 2 : 0;
483         dmem->INIT_ProfileLevelMaxFrame = GetProfileLevelMaxFrameSize(m_basicFeature->m_frameWidth, m_basicFeature->m_frameHeight, seqParams->UserMaxIFrameSize);
484         dmem->INIT_TargetBitrate = seqParams->TargetBitRate[seqParams->NumTemporalLayersMinus1] * BRC_KBPS;
485         dmem->INIT_MaxRate = seqParams->MaxBitRate * BRC_KBPS;
486         dmem->INIT_MinRate = seqParams->MinBitRate * BRC_KBPS;
487 
488         std::tie(dmem->INIT_FrameRateM, dmem->INIT_FrameRateD) = GetFrameRate(*seqParams);
489 
490         dmem->INIT_InitBufFullness = MOS_MIN(seqParams->InitVBVBufferFullnessInBit, seqParams->VBVBufferSizeInBit);
491         dmem->INIT_BufSize = m_vbvSize;
492         dmem->INIT_BRCFlag = SwitchFlag(seqParams->RateControlMethod);
493         m_curTargetFullness = seqParams->InitVBVBufferFullnessInBit;
494 
495         auto BGOPSize = seqParams->GopRefDist;
496         int32_t intraPeriod = seqParams->GopPicSize - 1;
497 
498         if (BGOPSize > 1)
499         {
500             if (intraPeriod > 0)
501             {
502                 intraPeriod = ((intraPeriod + (BGOPSize - 1)) / BGOPSize) * BGOPSize;
503             }
504             if (intraPeriod != -1)
505             {
506                 dmem->INIT_GopP  = intraPeriod / BGOPSize;
507                 dmem->INIT_GopB  = intraPeriod / BGOPSize;
508                 dmem->INIT_GopB1 = (dmem->INIT_GopP + dmem->INIT_GopB == intraPeriod)? 0 : dmem->INIT_GopP * 2;
509                 dmem->INIT_GopB2 = intraPeriod - dmem->INIT_GopP - dmem->INIT_GopB - dmem->INIT_GopB1;
510                 if (m_rcMode == RATECONTROL_CQL && seqParams->GopRefDist == 16)
511                 {
512                     dmem->INIT_GopB2 = (dmem->INIT_GopP + dmem->INIT_GopB + dmem->INIT_GopB1 == intraPeriod) ? 0 : dmem->INIT_GopB1 * 2;
513                     dmem->INIT_GopB3 = intraPeriod - dmem->INIT_GopP - dmem->INIT_GopB - dmem->INIT_GopB1 - dmem->INIT_GopB2;
514                 }
515             }
516             else
517             {
518                 dmem->INIT_GopP = 9999;
519                 dmem->INIT_GopB = 9999;
520             }
521         }
522         else
523         {
524             dmem->INIT_GopP = seqParams->GopPicSize - 1;
525             dmem->INIT_GopB = 0;
526         }
527 
528         dmem->INIT_FrameWidth = (uint16_t)m_basicFeature->m_oriFrameWidth;
529         dmem->INIT_FrameHeight = (uint16_t)m_basicFeature->m_oriFrameHeight;
530         dmem->INIT_MinQP = m_basicFeature->m_av1PicParams->MinBaseQIndex;
531         dmem->INIT_MaxQP = m_basicFeature->m_av1PicParams->MaxBaseQIndex == 0 ? 255 : m_basicFeature->m_av1PicParams->MaxBaseQIndex;
532         dmem->INIT_LevelQP = seqParams->ICQQualityFactor;
533         dmem->INIT_GoldenFrameInterval = 14;
534         dmem->INIT_EnableScaling = false;
535         dmem->INIT_OvershootCBR_pct = 0; //sliding window related.
536 
537 #define MEMCPY_CONST(D, S) MOS_SecureMemcpy(dmem->D, sizeof(dmem->D), brcSettings.S.data, brcSettings.S.size);
538         MEMCPY_CONST(INIT_InstRateThreshI0, instRateThresholdI);
539         MEMCPY_CONST(INIT_InstRateThreshP0, instRateThresholdP);
540 #undef MEMCPY_CONST
541 
542         if (dmem->INIT_FrameRateM == 0)
543         {
544             return MOS_STATUS_INVALID_PARAMETER;
545         }
546         double inputBitsPerFrame = ((double)dmem->INIT_MaxRate * (double)dmem->INIT_FrameRateD) / (double)dmem->INIT_FrameRateM;
547         double bpsRatio = inputBitsPerFrame / ((double)dmem->INIT_BufSize / brcSettings.devStdFPS);
548         bpsRatio = MOS_CLAMP_MIN_MAX(bpsRatio, brcSettings.bpsRatioLow, brcSettings.bpsRatioHigh);
549         for (uint32_t i = 0; i < brcSettings.numDevThreshlds / 2; i++)
550         {
551             dmem->INIT_DevThreshPB0[i] = (int8_t)(brcSettings.negMultPB * pow(((double *)(brcSettings.devThresholdFpNegPB.data))[i], bpsRatio));
552             dmem->INIT_DevThreshPB0[i + brcSettings.numDevThreshlds / 2] = (int8_t)(brcSettings.postMultPB * pow(((double *)(brcSettings.devThresholdFpPosPB.data))[i], bpsRatio));
553 
554             dmem->INIT_DevThreshI0[i] = (int8_t)(brcSettings.negMultPB * pow(((double *)(brcSettings.devThresholdFpNegI.data))[i], bpsRatio));
555             dmem->INIT_DevThreshI0[i + brcSettings.numDevThreshlds / 2] = (int8_t)(brcSettings.postMultPB * pow(((double *)(brcSettings.devThresholdFpPosI.data))[i], bpsRatio));
556 
557             dmem->INIT_DevThreshVBR0[i] = (int8_t)(brcSettings.negMultVBR * pow(((double *)(brcSettings.devThresholdVbrNeg.data))[i], bpsRatio));
558             dmem->INIT_DevThreshVBR0[i + brcSettings.numDevThreshlds / 2] = (int8_t)(brcSettings.posMultVBR * pow(((double *)(brcSettings.devThresholdVbrPos.data))[i], bpsRatio));
559         }
560 
561         int32_t qpI = 0, qpP = 0;
562         qpI = ComputeVDEncInitQPI(
563                 m_basicFeature->m_oriFrameWidth,
564                 m_basicFeature->m_oriFrameHeight,
565                 m_basicFeature->m_av1SeqParams->FrameRate[0],
566                 m_basicFeature->m_av1SeqParams->TargetBitRate[0],
567                 m_basicFeature->m_av1SeqParams->GopPicSize,
568                 m_basicFeature->m_is10Bit,
569                 dmem->INIT_GopP);
570 
571         qpP = qpI + 20;
572 
573         dmem->INIT_InitQPI = (uint8_t)qpI;
574         dmem->INIT_InitQPP = (uint8_t)qpP;
575 
576         dmem->INIT_SegMapGenerating = false;
577         dmem->INIT_Total_Level = seqParams->NumTemporalLayersMinus1 + 1;
578         if (dmem->INIT_Total_Level > 1)
579         {
580             return MOS_STATUS_INVALID_PARAMETER;
581         }
582 
583         dmem->INIT_SLIDINGWINDOW_ENABLE = seqParams->SlidingWindowSize != 0;
584         dmem->INIT_SLIDINGWINDOW_SIZE = (uint8_t)seqParams->SlidingWindowSize;
585         if (dmem->INIT_SLIDINGWINDOW_ENABLE && seqParams->TargetBitRate[0] > 0)
586         {
587             dmem->INIT_OvershootCBR_pct = (uint16_t)(seqParams->MaxBitRatePerSlidingWindow * 100 / seqParams->TargetBitRate[0]);
588         }
589         return MOS_STATUS_SUCCESS;
590     }
591 
SetSequenceStructs()592     MOS_STATUS Av1Brc::SetSequenceStructs()
593     {
594         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
595 
596         ENCODE_FUNC_CALL();
597 
598         if (m_basicFeature->m_av1SeqParams->RateControlMethod == RATECONTROL_CQL)
599         {
600             const uint8_t ICQFactorLookup[52] = {
601                 0,  1,  1,  1,  1,  2,  3,  4,  6,  7,  9,  11, 13, 16, 18, 23,
602                 26, 30, 34, 39, 46, 52, 59, 68, 77, 87, 98, 104,112,120,127,134,
603                 142,149,157,164,171,178,186,193,200,207,213,219,225,230,235,240,
604                 245,249,252,255
605             };
606 
607             uint32_t TargetBitRate                                     = m_basicFeature->m_frameWidth * m_basicFeature->m_frameHeight * 8 / 1000;
608             m_basicFeature->m_av1SeqParams->ICQQualityFactor           = ICQFactorLookup[m_basicFeature->m_av1SeqParams->ICQQualityFactor];
609             m_basicFeature->m_av1SeqParams->TargetBitRate[0]           = TargetBitRate;
610             m_basicFeature->m_av1SeqParams->MaxBitRate                 = (TargetBitRate << 4) / 10;
611             m_basicFeature->m_av1SeqParams->MinBitRate                 = 0;
612             m_basicFeature->m_av1SeqParams->InitVBVBufferFullnessInBit = 8000 * (TargetBitRate << 3) / 10;
613             m_basicFeature->m_av1SeqParams->VBVBufferSizeInBit         = 8000 * (TargetBitRate << 1);
614         }
615 
616         m_brcEnabled = IsRateControlBrc(m_basicFeature->m_av1SeqParams->RateControlMethod);
617 
618         m_brcInit = m_brcEnabled && m_basicFeature->m_resolutionChanged;
619 
620         m_rcMode = m_brcEnabled? m_basicFeature->m_av1SeqParams->RateControlMethod : 0;
621 
622         if (m_rcMode == RATECONTROL_CQL || m_rcMode == RATECONTROL_QVBR)
623         {
624             if (m_basicFeature->m_av1SeqParams->ICQQualityFactor > ENCODE_AV1_MAX_ICQ_QUALITYFACTOR)
625             {
626                 ENCODE_ASSERTMESSAGE("Invalid ICQ Quality Factor input (%d)\n", m_basicFeature->m_av1SeqParams->ICQQualityFactor);
627                 eStatus = MOS_STATUS_INVALID_PARAMETER;
628                 return eStatus;
629             }
630         }
631 
632         m_brcReset = m_basicFeature->m_av1SeqParams->SeqFlags.fields.ResetBRC;
633 
634         if (m_brcReset &&
635             (!m_brcEnabled ||
636              m_rcMode == RATECONTROL_CQL))
637         {
638             ENCODE_ASSERTMESSAGE("BRC Reset cannot be trigerred in CQP/ICQ modes - invalid BRC parameters.");
639             m_brcReset = false;
640         }
641 
642         if (IsBRCInitRequired())
643         {
644             auto seqParams = m_basicFeature->m_av1SeqParams;
645             ENCODE_CHK_NULL_RETURN(seqParams);
646 
647             m_delay                   = seqParams->InitVBVBufferFullnessInBit;
648             m_vbvSize                 = seqParams->VBVBufferSizeInBit;
649 
650             uint32_t nom = 0;
651             uint32_t denom = 1;
652             std::tie(nom, denom) = GetFrameRate(*seqParams);
653 
654             if (denom == 0)
655             {
656                 denom = 1;
657             }
658 
659             m_frameRate = (int32_t)((double)nom * 100. / (double)denom);
660 
661             //average frame size in bits based on bit rate and frame rate.
662             const uint32_t maxBitrate      = seqParams->MaxBitRate * BRC_KBPS;
663             m_inputbitsperframe = maxBitrate * 100. / m_frameRate;
664 
665             //make sure the buffer size can contain at least 4 frames in average
666             if (m_vbvSize < (int32_t)(m_inputbitsperframe * 4))
667             {
668                 m_vbvSize = (int32_t)(m_inputbitsperframe * 4);
669             }
670             //make sure the initial buffer size is larger than 2 average frames and smaller than the max buffer size.
671             if (m_delay == 0)
672                 m_delay = 7 * m_vbvSize / 8;
673             if (m_delay < (int32_t)(m_inputbitsperframe * 2))
674                 m_delay = (int32_t)(m_inputbitsperframe * 2);
675             if (m_delay > m_vbvSize)
676                 m_delay = m_vbvSize;
677         }
678 
679         return eStatus;
680     }
681 
FreeBrcResources()682     MOS_STATUS Av1Brc::FreeBrcResources()
683     {
684         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
685 
686         ENCODE_FUNC_CALL();
687         ENCODE_CHK_NULL_RETURN(m_hwInterface);
688 
689         for (auto j = 0; j < CODECHAL_ENCODE_RECYCLED_BUFFER_NUM; j++)
690         {
691             eStatus = Mhw_FreeBb(m_hwInterface->GetOsInterface(), &m_vdenc2ndLevelBatchBuffer[j], nullptr);
692             ENCODE_ASSERT(eStatus == MOS_STATUS_SUCCESS);
693             eStatus = Mhw_FreeBb(m_hwInterface->GetOsInterface(), &m_pakInsertOutputBatchBuffer[j], nullptr);
694             ENCODE_ASSERT(eStatus == MOS_STATUS_SUCCESS);
695         }
696 
697         return eStatus;
698     }
699 
MHW_SETPAR_DECL_SRC(HUC_DMEM_STATE,Av1Brc)700     MHW_SETPAR_DECL_SRC(HUC_DMEM_STATE, Av1Brc)
701     {
702         ENCODE_CHK_NULL_RETURN(params.hucDataSource);
703 
704         switch (params.function)
705         {
706         case BRC_INIT: {
707             auto dmem = (VdencAv1HucBrcInitDmem *)m_allocator->LockResourceForWrite(params.hucDataSource);
708 
709             ENCODE_CHK_NULL_RETURN(dmem);
710             MOS_ZeroMemory(dmem, sizeof(VdencAv1HucBrcInitDmem));
711 
712             SetDmemForInit(dmem);
713 
714             ENCODE_CHK_STATUS_RETURN(m_allocator->UnLock(params.hucDataSource));
715             break;
716         }
717         case BRC_UPDATE: {
718             auto dmem = (VdencAv1HucBrcUpdateDmem *)m_allocator->LockResourceForWrite(params.hucDataSource);
719 
720             ENCODE_CHK_NULL_RETURN(dmem);
721             MOS_ZeroMemory(dmem, sizeof(VdencAv1HucBrcUpdateDmem));
722 
723             dmem->UPD_MaxNumPAKs = params.passNum;
724             dmem->UPD_PAKPassNum = params.currentPass;
725             dmem->UPD_SegMapGenerating = 0;
726 
727             SetDmemForUpdate(dmem);
728 
729             ENCODE_CHK_STATUS_RETURN(m_allocator->UnLock(params.hucDataSource));
730 
731             break;
732         }
733         case PAK_INTEGRATE: {
734             // nothing need to be done within brc feature for pak int
735             break;
736         }
737         default:
738             ENCODE_ASSERTMESSAGE("AV1 BRC feature supports only PAK_INTEGRATE, BRC_INIT and BRC_UPDATE HUC functions");
739             return MOS_STATUS_INVALID_PARAMETER;
740         }
741 
742         return MOS_STATUS_SUCCESS;
743     }
744 
MHW_SETPAR_DECL_SRC(HUC_VIRTUAL_ADDR_STATE,Av1Brc)745     MHW_SETPAR_DECL_SRC(HUC_VIRTUAL_ADDR_STATE, Av1Brc)
746     {
747         if (params.function == BRC_UPDATE)
748         {
749             const PMOS_RESOURCE brcConstDataBuffer = params.regionParams[5].presRegion;
750 
751             auto hucConstData = (VdencAv1HucBrcConstantData *)m_allocator->LockResourceForWrite(brcConstDataBuffer);
752             ENCODE_CHK_NULL_RETURN(hucConstData);
753 
754             SetConstForUpdate(hucConstData);
755 
756             m_allocator->UnLock(brcConstDataBuffer);
757         }
758 
759         return MOS_STATUS_SUCCESS;
760     }
761 
MHW_SETPAR_DECL_SRC(VDENC_PIPE_MODE_SELECT,Av1Brc)762     MHW_SETPAR_DECL_SRC(VDENC_PIPE_MODE_SELECT, Av1Brc)
763     {
764         if (m_brcEnabled)
765         {
766             params.frameStatisticsStreamOut = true;
767         }
768 
769         return MOS_STATUS_SUCCESS;
770     }
771 
772 }  // namespace encode
773