1 /*############################################################################
2   # Copyright (C) 2005 Intel Corporation
3   #
4   # SPDX-License-Identifier: MIT
5   ############################################################################*/
6 
7 #include "brc_routines.h"
8 
9 #include <math.h>
10 #include <algorithm>
11 
12 #ifndef MFX_VERSION
13     #error MFX_VERSION not defined
14 #endif
15 
16 #define BRC_SCENE_CHANGE_RATIO1 20.0
17 #define BRC_SCENE_CHANGE_RATIO2 5.0
18 
hevcBitRateScale(mfxU32 bitrate)19 static mfxU32 hevcBitRateScale(mfxU32 bitrate) {
20     mfxU32 bit_rate_scale = 0;
21     while (bit_rate_scale < 16 && (bitrate & ((1 << (6 + bit_rate_scale + 1)) - 1)) == 0)
22         bit_rate_scale++;
23     return bit_rate_scale;
24 }
hevcCbpSizeScale(mfxU32 cpbSize)25 static mfxU32 hevcCbpSizeScale(mfxU32 cpbSize) {
26     mfxU32 cpb_size_scale = 2;
27     while (cpb_size_scale < 16 && (cpbSize & ((1 << (4 + cpb_size_scale + 1)) - 1)) == 0)
28         cpb_size_scale++;
29     return cpb_size_scale;
30 }
31 const mfxU32 h264_h265_au_cpb_removal_delay_length_minus1 = 23;
32 const mfxU32 h264_bit_rate_scale                          = 4;
33 const mfxU32 h264_cpb_size_scale                          = 2;
34 
Hevc_GetExtBuffer(mfxExtBuffer ** extBuf,mfxU32 numExtBuf,mfxU32 id)35 mfxExtBuffer* Hevc_GetExtBuffer(mfxExtBuffer** extBuf, mfxU32 numExtBuf, mfxU32 id) {
36     if (extBuf != 0) {
37         for (mfxU16 i = 0; i < numExtBuf; i++) {
38             if (extBuf[i] != 0 && extBuf[i]->BufferId == id) // assuming aligned buffers
39                 return (extBuf[i]);
40         }
41     }
42 
43     return 0;
44 }
45 
Init(mfxVideoParam * par,bool bField)46 mfxStatus cBRCParams::Init(mfxVideoParam* par, bool bField) {
47     printf("Sample BRC is used\n");
48     MFX_CHECK_NULL_PTR1(par);
49     MFX_CHECK(par->mfx.RateControlMethod == MFX_RATECONTROL_CBR ||
50                   par->mfx.RateControlMethod == MFX_RATECONTROL_VBR,
51               MFX_ERR_UNDEFINED_BEHAVIOR);
52     bFieldMode = bField;
53     codecId    = par->mfx.CodecId;
54 
55     mfxU32 k  = par->mfx.BRCParamMultiplier == 0 ? 1 : par->mfx.BRCParamMultiplier;
56     targetbps = k * par->mfx.TargetKbps * 1000;
57     maxbps    = k * par->mfx.MaxKbps * 1000;
58 
59     maxbps = (par->mfx.RateControlMethod == MFX_RATECONTROL_CBR)
60                  ? targetbps
61                  : ((maxbps >= targetbps) ? maxbps : targetbps);
62 
63     mfxU32 bit_rate_scale =
64         (par->mfx.CodecId == MFX_CODEC_AVC) ? h264_bit_rate_scale : hevcBitRateScale(maxbps);
65     mfxU32 cpb_size_scale =
66         (par->mfx.CodecId == MFX_CODEC_AVC) ? h264_cpb_size_scale : hevcCbpSizeScale(maxbps);
67 
68     rateControlMethod = par->mfx.RateControlMethod;
69     maxbps            = ((maxbps >> (6 + bit_rate_scale)) << (6 + bit_rate_scale));
70 
71     mfxExtCodingOption* pExtCO = (mfxExtCodingOption*)Hevc_GetExtBuffer(par->ExtParam,
72                                                                         par->NumExtParam,
73                                                                         MFX_EXTBUFF_CODING_OPTION);
74 
75     HRDConformance = MFX_BRC_NO_HRD;
76     if (pExtCO) {
77         if ((MFX_CODINGOPTION_OFF != pExtCO->NalHrdConformance) &&
78             (MFX_CODINGOPTION_OFF != pExtCO->VuiNalHrdParameters))
79             HRDConformance = MFX_BRC_HRD_STRONG;
80         else if ((MFX_CODINGOPTION_ON == pExtCO->NalHrdConformance) &&
81                  (MFX_CODINGOPTION_OFF == pExtCO->VuiNalHrdParameters))
82             HRDConformance = MFX_BRC_HRD_WEAK;
83     }
84 
85     if (HRDConformance != MFX_BRC_NO_HRD) {
86         bufferSizeInBytes = ((k * par->mfx.BufferSizeInKB * 1000) >> (cpb_size_scale + 1))
87                             << (cpb_size_scale + 1);
88         initialDelayInBytes = ((k * par->mfx.InitialDelayInKB * 1000) >> (cpb_size_scale + 1))
89                               << (cpb_size_scale + 1);
90         bRec   = 1;
91         bPanic = (HRDConformance == MFX_BRC_HRD_STRONG) ? 1 : 0;
92     }
93     MFX_CHECK(par->mfx.FrameInfo.FrameRateExtD != 0 && par->mfx.FrameInfo.FrameRateExtN != 0,
94               MFX_ERR_UNDEFINED_BEHAVIOR);
95 
96     frameRate = (mfxF64)par->mfx.FrameInfo.FrameRateExtN / (mfxF64)par->mfx.FrameInfo.FrameRateExtD;
97 
98     width  = par->mfx.FrameInfo.Width;
99     height = par->mfx.FrameInfo.Height;
100 
101     chromaFormat = par->mfx.FrameInfo.ChromaFormat == 0 ? MFX_CHROMAFORMAT_YUV420
102                                                         : par->mfx.FrameInfo.ChromaFormat;
103     bitDepthLuma = par->mfx.FrameInfo.BitDepthLuma == 0 ? 8 : par->mfx.FrameInfo.BitDepthLuma;
104 
105     quantOffset = 6 * (bitDepthLuma - 8);
106 
107     inputBitsPerFrame    = targetbps / frameRate;
108     maxInputBitsPerFrame = maxbps / frameRate;
109     gopPicSize           = par->mfx.GopPicSize * (bFieldMode ? 2 : 1);
110     gopRefDist           = par->mfx.GopRefDist * (bFieldMode ? 2 : 1);
111 
112     mfxExtCodingOption2* pExtCO2 =
113         (mfxExtCodingOption2*)Hevc_GetExtBuffer(par->ExtParam,
114                                                 par->NumExtParam,
115                                                 MFX_EXTBUFF_CODING_OPTION2);
116     bPyr               = (pExtCO2 && pExtCO2->BRefType == MFX_B_REF_PYRAMID);
117     maxFrameSizeInBits = pExtCO2 ? pExtCO2->MaxFrameSize * 8 : 0;
118 
119     fAbPeriodLong  = 100;
120     fAbPeriodShort = 6;
121     dqAbPeriod     = 100;
122     bAbPeriod      = 100;
123 
124     if (maxFrameSizeInBits) {
125         bRec   = 1;
126         bPanic = 1;
127     }
128 
129     if (pExtCO2 && pExtCO2->MaxQPI <= 51 && pExtCO2->MaxQPI > pExtCO2->MinQPI &&
130         pExtCO2->MinQPI >= 1 && pExtCO2->MaxQPP <= 51 && pExtCO2->MaxQPP > pExtCO2->MinQPP &&
131         pExtCO2->MinQPP >= 1 && pExtCO2->MaxQPB <= 51 && pExtCO2->MaxQPB > pExtCO2->MinQPB &&
132         pExtCO2->MinQPB >= 1) {
133         quantMaxI = pExtCO2->MaxQPI + quantOffset;
134         quantMinI = pExtCO2->MinQPI;
135         quantMaxP = pExtCO2->MaxQPP + quantOffset;
136         quantMinP = pExtCO2->MinQPP;
137         quantMaxB = pExtCO2->MaxQPB + quantOffset;
138         quantMinB = pExtCO2->MinQPB;
139     }
140     else {
141         quantMaxI = quantMaxP = quantMaxB = 51 + quantOffset;
142         quantMinI = quantMinP = quantMinB = 1;
143     }
144 
145     mfxExtCodingOption3* pExtCO3 =
146         (mfxExtCodingOption3*)Hevc_GetExtBuffer(par->ExtParam,
147                                                 par->NumExtParam,
148                                                 MFX_EXTBUFF_CODING_OPTION3);
149     if (pExtCO3) {
150         WinBRCMaxAvgKbps = pExtCO3->WinBRCMaxAvgKbps * par->mfx.BRCParamMultiplier;
151         WinBRCSize       = pExtCO3->WinBRCSize;
152     }
153     mMBBRC = pExtCO3 && (pExtCO3->EnableMBQP == MFX_CODINGOPTION_ON);
154     return MFX_ERR_NONE;
155 }
156 
GetBRCResetType(mfxVideoParam * par,bool bNewSequence,bool & bBRCReset,bool & bSlidingWindowReset)157 mfxStatus cBRCParams::GetBRCResetType(mfxVideoParam* par,
158                                       bool bNewSequence,
159                                       bool& bBRCReset,
160                                       bool& bSlidingWindowReset) {
161     bBRCReset           = false;
162     bSlidingWindowReset = false;
163 
164     if (bNewSequence)
165         return MFX_ERR_NONE;
166 
167     cBRCParams new_par;
168     mfxStatus sts = new_par.Init(par);
169     MFX_CHECK_STS(sts);
170 
171     MFX_CHECK(new_par.rateControlMethod == rateControlMethod, MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
172     MFX_CHECK(new_par.HRDConformance == HRDConformance, MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
173     MFX_CHECK(new_par.frameRate == frameRate, MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
174     MFX_CHECK(new_par.width == width, MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
175     MFX_CHECK(new_par.height == height, MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
176     MFX_CHECK(new_par.chromaFormat == chromaFormat, MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
177     MFX_CHECK(new_par.bitDepthLuma == bitDepthLuma, MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
178 
179     if (HRDConformance == MFX_BRC_HRD_STRONG) {
180         MFX_CHECK(new_par.bufferSizeInBytes == bufferSizeInBytes, MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
181         MFX_CHECK(new_par.initialDelayInBytes == initialDelayInBytes,
182                   MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
183         MFX_CHECK(new_par.targetbps == targetbps, MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
184         MFX_CHECK(new_par.maxbps == maxbps, MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
185     }
186     else if (new_par.targetbps != targetbps || new_par.maxbps != maxbps) {
187         bBRCReset = true;
188     }
189 
190     if (new_par.WinBRCMaxAvgKbps != WinBRCMaxAvgKbps) {
191         bBRCReset           = true;
192         bSlidingWindowReset = true;
193     }
194 
195     if (new_par.maxFrameSizeInBits != maxFrameSizeInBits)
196         bBRCReset = true;
197     if (new_par.gopPicSize != gopPicSize)
198         bBRCReset = true;
199     if (new_par.gopRefDist != gopRefDist)
200         bBRCReset = true;
201     if (new_par.bPyr != bPyr)
202         bBRCReset = true;
203     if (new_par.quantMaxI != quantMaxI)
204         bBRCReset = true;
205     if (new_par.quantMinI != quantMinI)
206         bBRCReset = true;
207     if (new_par.quantMaxP != quantMaxP)
208         bBRCReset = true;
209     if (new_par.quantMinP != quantMinP)
210         bBRCReset = true;
211     if (new_par.quantMaxB != quantMaxB)
212         bBRCReset = true;
213     if (new_par.quantMinB != quantMinB)
214         bBRCReset = true;
215 
216     return MFX_ERR_NONE;
217 }
218 
219 enum {
220     MFX_BRC_RECODE_NONE  = 0,
221     MFX_BRC_RECODE_QP    = 1,
222     MFX_BRC_RECODE_PANIC = 2,
223 };
224 
225 mfxF64 const QSTEP[88] = {
226     0.630,    0.707,    0.794,    0.891,     1.000,     1.122,     1.260,    1.414,    1.587,
227     1.782,    2.000,    2.245,    2.520,     2.828,     3.175,     3.564,    4.000,    4.490,
228     5.040,    5.657,    6.350,    7.127,     8.000,     8.980,     10.079,   11.314,   12.699,
229     14.254,   16.000,   17.959,   20.159,    22.627,    25.398,    28.509,   32.000,   35.919,
230     40.317,   45.255,   50.797,   57.018,    64.000,    71.838,    80.635,   90.510,   101.594,
231     114.035,  128.000,  143.675,  161.270,   181.019,   203.187,   228.070,  256.000,  287.350,
232     322.540,  362.039,  406.375,  456.140,   512.000,   574.701,   645.080,  724.077,  812.749,
233     912.280,  1024.000, 1149.401, 1290.159,  1448.155,  1625.499,  1824.561, 2048.000, 2298.802,
234     2580.318, 2896.309, 3250.997, 3649.121,  4096.000,  4597.605,  5160.637, 5792.619, 6501.995,
235     7298.242, 8192.000, 9195.209, 10321.273, 11585.238, 13003.989, 14596.485
236 };
237 
QStep2QpFloor(mfxF64 qstep,mfxI32 qpoffset=0)238 mfxI32 QStep2QpFloor(mfxF64 qstep,
239                      mfxI32 qpoffset = 0) // QSTEP[qp] <= qstep, return 0<=qp<=51+mQuantOffset
240 {
241     mfxU8 qp = mfxU8(std::upper_bound(QSTEP, QSTEP + 51 + qpoffset, qstep) - QSTEP);
242     return qp > 0 ? qp - 1 : 0;
243 }
244 
Qstep2QP(mfxF64 qstep,mfxI32 qpoffset=0)245 mfxI32 Qstep2QP(mfxF64 qstep, mfxI32 qpoffset = 0) // return 0<=qp<=51+mQuantOffset
246 {
247     mfxI32 qp = QStep2QpFloor(qstep, qpoffset);
248 
249     // prevent going QSTEP index out of bounds
250     if (qp >= (mfxI32)(sizeof(QSTEP) / sizeof(QSTEP[0])) - 1)
251         return 0;
252     return (qp == 51 + qpoffset || qstep < (QSTEP[qp] + QSTEP[qp + 1]) / 2) ? qp : qp + 1;
253 }
QP2Qstep(mfxI32 qp,mfxI32 qpoffset=0)254 mfxF64 QP2Qstep(mfxI32 qp, mfxI32 qpoffset = 0) {
255     return QSTEP[std::min(51 + qpoffset, qp)];
256 }
257 
GetNewQP(mfxF64 totalFrameBits,mfxF64 targetFrameSizeInBits,mfxI32 minQP,mfxI32 maxQP,mfxI32 qp,mfxI32 qp_offset,mfxF64 f_pow,bool bStrict=false,bool bLim=true)258 mfxI32 GetNewQP(mfxF64 totalFrameBits,
259                 mfxF64 targetFrameSizeInBits,
260                 mfxI32 minQP,
261                 mfxI32 maxQP,
262                 mfxI32 qp,
263                 mfxI32 qp_offset,
264                 mfxF64 f_pow,
265                 bool bStrict = false,
266                 bool bLim    = true) {
267     mfxF64 qstep = 0, qstep_new = 0;
268     mfxI32 qp_new = qp;
269 
270     qstep     = QP2Qstep(qp, qp_offset);
271     qstep_new = qstep * pow(totalFrameBits / targetFrameSizeInBits, f_pow);
272     qp_new    = Qstep2QP(qstep_new, qp_offset);
273 
274     if (totalFrameBits < targetFrameSizeInBits) // overflow
275     {
276         if (qp <= minQP) {
277             return qp; // QP change is impossible
278         }
279         if (bLim)
280             qp_new = std::max(qp_new, (minQP + qp + 1) >> 1);
281         if (bStrict)
282             qp_new = std::min(qp_new, qp - 1);
283     }
284     else // underflow
285     {
286         if (qp >= maxQP) {
287             return qp; // QP change is impossible
288         }
289         if (bLim)
290             qp_new = std::min(qp_new, (maxQP + qp + 1) >> 1);
291         if (bStrict)
292             qp_new = std::max(qp_new, qp + 1);
293     }
294     return mfx::clamp(qp_new, minQP, maxQP);
295 }
296 
UpdateQPParams(mfxI32 qp,mfxU32 type,BRC_Ctx & ctx,mfxU32,mfxI32 minQuant,mfxI32 maxQuant,mfxU32 level)297 void UpdateQPParams(mfxI32 qp,
298                     mfxU32 type,
299                     BRC_Ctx& ctx,
300                     mfxU32 /* rec_num */,
301                     mfxI32 minQuant,
302                     mfxI32 maxQuant,
303                     mfxU32 level) {
304     ctx.Quant = qp;
305     if (type == MFX_FRAMETYPE_I) {
306         ctx.QuantI = qp;
307         ctx.QuantP = qp + 1;
308         ctx.QuantB = qp + 2;
309     }
310     else if (type == MFX_FRAMETYPE_P) {
311         qp -= level;
312         ctx.QuantI = qp - 1;
313         ctx.QuantP = qp;
314         ctx.QuantB = qp + 1;
315     }
316     else if (type == MFX_FRAMETYPE_B) {
317         level = level > 0 ? level - 1 : 0;
318         qp -= level;
319         ctx.QuantI = qp - 2;
320         ctx.QuantP = qp - 1;
321         ctx.QuantB = qp;
322     }
323     ctx.QuantI = mfx::clamp(ctx.QuantI, minQuant, maxQuant);
324     ctx.QuantP = mfx::clamp(ctx.QuantP, minQuant, maxQuant);
325     ctx.QuantB = mfx::clamp(ctx.QuantB, minQuant, maxQuant);
326     //printf("ctx.QuantI %d, ctx.QuantP %d, ctx.QuantB  %d, level %d\n", ctx.QuantI, ctx.QuantP, ctx.QuantB, level);
327 }
328 
GetRawFrameSize(mfxU32 lumaSize,mfxU16 chromaFormat,mfxU16 bitDepthLuma)329 mfxI32 GetRawFrameSize(mfxU32 lumaSize, mfxU16 chromaFormat, mfxU16 bitDepthLuma) {
330     mfxI32 frameSize = lumaSize;
331 
332     if (chromaFormat == MFX_CHROMAFORMAT_YUV420)
333         frameSize += lumaSize / 2;
334     else if (chromaFormat == MFX_CHROMAFORMAT_YUV422)
335         frameSize += lumaSize;
336     else if (chromaFormat == MFX_CHROMAFORMAT_YUV444)
337         frameSize += lumaSize * 2;
338 
339     frameSize = frameSize * bitDepthLuma / 8;
340     return frameSize * 8; //frame size in bits
341 }
isFieldMode(mfxVideoParam * par)342 bool isFieldMode(mfxVideoParam* par) {
343     return ((par->mfx.CodecId == MFX_CODEC_HEVC) &&
344             !(par->mfx.FrameInfo.PicStruct & MFX_PICSTRUCT_PROGRESSIVE));
345 }
346 
Init(mfxVideoParam * par)347 mfxStatus ExtBRC::Init(mfxVideoParam* par) {
348     mfxStatus sts = MFX_ERR_NONE;
349 
350     MFX_CHECK(!m_bInit, MFX_ERR_UNDEFINED_BEHAVIOR);
351     sts = m_par.Init(par, isFieldMode(par));
352     MFX_CHECK_STS(sts);
353 
354     if (m_par.HRDConformance != MFX_BRC_NO_HRD) {
355         if (m_par.codecId == MFX_CODEC_AVC)
356             m_hrdSpec.reset(new H264_HRD());
357         else
358             m_hrdSpec.reset(new HEVC_HRD());
359         m_hrdSpec->Init(m_par);
360     }
361     m_ctx = {};
362 
363     m_ctx.fAbLong  = m_par.inputBitsPerFrame;
364     m_ctx.fAbShort = m_par.inputBitsPerFrame;
365     m_ctx.encOrder = mfxU32(-1);
366 
367     mfxI32 rawSize =
368         GetRawFrameSize(m_par.width * m_par.height, m_par.chromaFormat, m_par.bitDepthLuma);
369     mfxI32 qp = GetNewQP(rawSize,
370                          m_par.inputBitsPerFrame,
371                          m_par.quantMinI,
372                          m_par.quantMaxI,
373                          1,
374                          m_par.quantOffset,
375                          0.5,
376                          false,
377                          false);
378 
379     UpdateQPParams(qp, MFX_FRAMETYPE_I, m_ctx, 0, m_par.quantMinI, m_par.quantMaxI, 0);
380 
381     m_ctx.dQuantAb = qp > 0 ? 1. / qp : 1.0; //kw
382 
383     if (m_par.WinBRCSize) {
384         m_avg.reset(new AVGBitrate(m_par.WinBRCSize,
385                                    (mfxU32)(m_par.WinBRCMaxAvgKbps * 1000.0 / m_par.frameRate),
386                                    (mfxU32)m_par.inputBitsPerFrame));
387         MFX_CHECK_NULL_PTR1(m_avg.get());
388     }
389     if (m_par.mMBBRC) {
390         mfxU32 size   = par->AsyncDepth > 1 ? 2 : 1;
391         mfxU16 blSize = 16;
392         mfxU32 wInBlk = (par->mfx.FrameInfo.Width + blSize - 1) / blSize;
393         mfxU32 hInBlk = (par->mfx.FrameInfo.Height + blSize - 1) / blSize;
394 
395         m_MBQPBuff.resize(size * wInBlk * hInBlk);
396         m_MBQP.resize(size);
397         m_ExtBuff.resize(size);
398 
399         for (mfxU32 i = 0; i < size; i++) {
400             m_MBQP[i].Header.BufferId = MFX_EXTBUFF_MBQP;
401             m_MBQP[i].Header.BufferSz = sizeof(mfxExtMBQP);
402             m_MBQP[i].BlockSize       = blSize;
403             m_MBQP[i].NumQPAlloc      = wInBlk * hInBlk;
404             m_MBQP[i].Mode            = MFX_MBQP_MODE_QP_VALUE;
405             m_MBQP[i].QP              = &(m_MBQPBuff[i * wInBlk * hInBlk]);
406             m_ExtBuff[i]              = (mfxExtBuffer*)&(m_MBQP[i]);
407         }
408     }
409     m_bInit = true;
410     return sts;
411 }
412 
GetFrameType(mfxU16 m_frameType,mfxU16 level,mfxU16 gopRegDist)413 mfxU16 GetFrameType(mfxU16 m_frameType, mfxU16 level, mfxU16 gopRegDist) {
414     if (m_frameType & MFX_FRAMETYPE_IDR)
415         return MFX_FRAMETYPE_I;
416     else if (m_frameType & MFX_FRAMETYPE_I)
417         return MFX_FRAMETYPE_I;
418     else if (m_frameType & MFX_FRAMETYPE_P)
419         return MFX_FRAMETYPE_P;
420     else if ((m_frameType & MFX_FRAMETYPE_REF) && (level == 0 || gopRegDist == 1))
421         return MFX_FRAMETYPE_P; //low delay B
422     else
423         return MFX_FRAMETYPE_B;
424 }
425 
isFrameBeforeIntra(mfxU32 order,mfxU32 intraOrder,mfxU32 gopPicSize,mfxU32 gopRefDist)426 bool isFrameBeforeIntra(mfxU32 order, mfxU32 intraOrder, mfxU32 gopPicSize, mfxU32 gopRefDist) {
427     mfxI32 distance0 = gopPicSize * 3 / 4;
428     mfxI32 distance1 = gopPicSize - gopRefDist * 3;
429     return mfxI32(order - intraOrder) > std::max(distance0, distance1);
430 }
431 
SetRecodeParams(mfxU16 brcStatus,mfxI32 qp,mfxI32 qp_new,mfxI32 minQP,mfxI32 maxQP,BRC_Ctx & ctx,mfxBRCFrameStatus * status)432 mfxStatus SetRecodeParams(mfxU16 brcStatus,
433                           mfxI32 qp,
434                           mfxI32 qp_new,
435                           mfxI32 minQP,
436                           mfxI32 maxQP,
437                           BRC_Ctx& ctx,
438                           mfxBRCFrameStatus* status) {
439     ctx.bToRecode = 1;
440 
441     if (brcStatus == MFX_BRC_BIG_FRAME || brcStatus == MFX_BRC_PANIC_BIG_FRAME) {
442         MFX_CHECK(qp_new >= qp, MFX_ERR_UNDEFINED_BEHAVIOR);
443         ctx.Quant    = qp_new;
444         ctx.QuantMax = maxQP;
445         if (brcStatus == MFX_BRC_BIG_FRAME && qp_new > qp) {
446             ctx.QuantMin      = std::max(qp + 1, minQP); //limit QP range for recoding
447             status->BRCStatus = MFX_BRC_BIG_FRAME;
448         }
449         else {
450             ctx.QuantMin      = minQP;
451             ctx.bPanic        = 1;
452             status->BRCStatus = MFX_BRC_PANIC_BIG_FRAME;
453         }
454     }
455     else if (brcStatus == MFX_BRC_SMALL_FRAME || brcStatus == MFX_BRC_PANIC_SMALL_FRAME) {
456         MFX_CHECK(qp_new <= qp, MFX_ERR_UNDEFINED_BEHAVIOR);
457 
458         ctx.Quant    = qp_new;
459         ctx.QuantMin = minQP; //limit QP range for recoding
460 
461         if (brcStatus == MFX_BRC_SMALL_FRAME && qp_new < qp) {
462             ctx.QuantMax      = std::min(qp - 1, maxQP);
463             status->BRCStatus = MFX_BRC_SMALL_FRAME;
464         }
465         else {
466             ctx.QuantMax      = maxQP;
467             status->BRCStatus = MFX_BRC_PANIC_SMALL_FRAME;
468             ctx.bPanic        = 1;
469         }
470     }
471     //printf("recode %d , qp %d new %d, status %d\n", ctx.encOrder, qp, qp_new, status->BRCStatus);
472     return MFX_ERR_NONE;
473 }
474 mfxI32
GetNewQPTotal(mfxF64 bo,mfxF64 dQP,mfxI32 minQP,mfxI32 maxQP,mfxI32 qp,bool bPyr,bool bSC)475 GetNewQPTotal(mfxF64 bo, mfxF64 dQP, mfxI32 minQP, mfxI32 maxQP, mfxI32 qp, bool bPyr, bool bSC) {
476     mfxU8 mode = (!bPyr);
477 
478     bo               = mfx::clamp(bo, -1.0, 1.0);
479     dQP              = mfx::clamp(dQP, 1. / maxQP, 1. / minQP);
480     dQP              = dQP + (1. / maxQP - dQP) * bo;
481     dQP              = mfx::clamp(dQP, 1. / maxQP, 1. / minQP);
482     mfxI32 quant_new = (mfxI32)(1. / dQP + 0.5);
483 
484     //printf("   GetNewQPTotal: bo %f, quant %d, quant_new %d, mode %d\n", bo, qp, quant_new, mode);
485     if (!bSC) {
486         if (mode == 0) // low: qp_diff [-2; 2]
487         {
488             if (quant_new >= qp + 5)
489                 quant_new = qp + 2;
490             else if (quant_new > qp + 3)
491                 quant_new = qp + 1;
492             else if (quant_new <= qp - 5)
493                 quant_new = qp - 2;
494             else if (quant_new < qp - 2)
495                 quant_new = qp - 1;
496         }
497         else // (mode == 1) midle: qp_diff [-3; 3]
498         {
499             if (quant_new >= qp + 5)
500                 quant_new = qp + 3;
501             else if (quant_new > qp + 3)
502                 quant_new = qp + 2;
503             else if (quant_new <= qp - 5)
504                 quant_new = qp - 3;
505             else if (quant_new < qp - 2)
506                 quant_new = qp - 2;
507         }
508     }
509     else {
510         quant_new = mfx::clamp(quant_new, qp - 5, qp + 5);
511     }
512     return mfx::clamp(quant_new, minQP, maxQP);
513 }
514 // Reduce AB period before intra and increase it after intra (to avoid intra frame affect on the bottom of hrd)
GetAbPeriodCoeff(mfxU32 numInGop,mfxU32 gopPicSize)515 mfxF64 GetAbPeriodCoeff(mfxU32 numInGop, mfxU32 gopPicSize) {
516     const mfxU32 maxForCorrection = 30;
517     const mfxF64 maxValue         = 1.5;
518     const mfxF64 minValue         = 1.0;
519 
520     mfxU32 numForCorrection    = std::min(gopPicSize / 2, maxForCorrection);
521     mfxF64 k[maxForCorrection] = {};
522 
523     if (numInGop >= gopPicSize || gopPicSize < 2)
524         return 1.0;
525 
526     for (mfxU32 i = 0; i < numForCorrection; i++) {
527         k[i] = maxValue - (maxValue - minValue) * i / numForCorrection;
528     }
529     if (numInGop < gopPicSize / 2) {
530         return k[numInGop < numForCorrection ? numInGop : numForCorrection - 1];
531     }
532     else {
533         mfxU32 n = gopPicSize - 1 - numInGop;
534         return 1.0 / k[n < numForCorrection ? n : numForCorrection - 1];
535     }
536 }
537 
GetCurQP(mfxU32 type,mfxI32 layer)538 mfxI32 ExtBRC::GetCurQP(mfxU32 type, mfxI32 layer) {
539     mfxI32 qp = 0;
540     if (type == MFX_FRAMETYPE_I) {
541         qp = m_ctx.QuantI;
542         qp = mfx::clamp(qp, m_par.quantMinI, m_par.quantMaxI);
543     }
544     else if (type == MFX_FRAMETYPE_P) {
545         qp = m_ctx.QuantP + layer;
546         qp = mfx::clamp(qp, m_par.quantMinP, m_par.quantMaxP);
547     }
548     else {
549         qp = m_ctx.QuantB + (layer > 0 ? layer - 1 : 0);
550         qp = mfx::clamp(qp, m_par.quantMinB, m_par.quantMaxB);
551     }
552     //printf("GetCurQP I %d P %d B %d, min %d max %d type %d \n", m_ctx.QuantI, m_ctx.QuantP, m_ctx.QuantB, m_par.quantMinI, m_par.quantMaxI, type);
553 
554     return qp;
555 }
556 
CheckHrdAndUpdateQP(HRDCodecSpec & hrd,mfxU32 frameSizeInBits,mfxU32 eo,bool bIdr,mfxI32 currQP)557 inline mfxU16 CheckHrdAndUpdateQP(HRDCodecSpec& hrd,
558                                   mfxU32 frameSizeInBits,
559                                   mfxU32 eo,
560                                   bool bIdr,
561                                   mfxI32 currQP) {
562     if (frameSizeInBits > hrd.GetMaxFrameSizeInBits(eo, bIdr)) {
563         hrd.SetUndeflowQuant(currQP);
564         return MFX_BRC_BIG_FRAME;
565     }
566     else if (frameSizeInBits < hrd.GetMinFrameSizeInBits(eo, bIdr)) {
567         hrd.SetUndeflowQuant(currQP);
568         return MFX_BRC_SMALL_FRAME;
569     }
570     return MFX_BRC_OK;
571 }
GetFrameTargetSize(mfxU32 brcSts,mfxI32 minFrameSize,mfxI32 maxFrameSize)572 mfxI32 GetFrameTargetSize(mfxU32 brcSts, mfxI32 minFrameSize, mfxI32 maxFrameSize) {
573     if (brcSts != MFX_BRC_BIG_FRAME && brcSts != MFX_BRC_SMALL_FRAME)
574         return 0;
575     return (brcSts == MFX_BRC_BIG_FRAME) ? maxFrameSize * 3 / 4 : minFrameSize * 5 / 4;
576 }
Update(mfxBRCFrameParam * frame_par,mfxBRCFrameCtrl * frame_ctrl,mfxBRCFrameStatus * status)577 mfxStatus ExtBRC::Update(mfxBRCFrameParam* frame_par,
578                          mfxBRCFrameCtrl* frame_ctrl,
579                          mfxBRCFrameStatus* status) {
580     mfxStatus sts = MFX_ERR_NONE;
581 
582     MFX_CHECK_NULL_PTR3(frame_par, frame_ctrl, status);
583     MFX_CHECK(m_bInit, MFX_ERR_NOT_INITIALIZED);
584 
585     mfxU16& brcSts       = status->BRCStatus;
586     status->MinFrameSize = 0;
587 
588     //printf("ExtBRC::Update:  m_ctx.encOrder %d , frame_par->EncodedOrder %d, frame_par->NumRecode %d, frame_par->CodedFrameSize %d, qp %d\n", m_ctx.encOrder , frame_par->EncodedOrder, frame_par->NumRecode, frame_par->CodedFrameSize, frame_ctrl->QpY);
589 
590     mfxI32 bitsEncoded = frame_par->CodedFrameSize * 8;
591     mfxU32 picType = GetFrameType(frame_par->FrameType, frame_par->PyramidLayer, m_par.gopRefDist);
592     mfxI32 qpY     = frame_ctrl->QpY + m_par.quantOffset;
593     mfxI32 layer   = frame_par->PyramidLayer;
594     mfxF64 qstep   = QP2Qstep(qpY, m_par.quantOffset);
595 
596     mfxF64 fAbLong  = m_ctx.fAbLong + (bitsEncoded - m_ctx.fAbLong) / m_par.fAbPeriodLong;
597     mfxF64 fAbShort = m_ctx.fAbShort + (bitsEncoded - m_ctx.fAbShort) / m_par.fAbPeriodShort;
598     mfxF64 eRate    = bitsEncoded * sqrt(qstep);
599     mfxF64 e2pe     = 0;
600     bool bMaxFrameSizeMode =
601         m_par.maxFrameSizeInBits != 0 && m_par.rateControlMethod == MFX_RATECONTROL_VBR &&
602         m_par.maxFrameSizeInBits < m_par.inputBitsPerFrame * 2 &&
603         m_ctx.totalDeviation < (-1) * m_par.inputBitsPerFrame * m_par.frameRate;
604 
605     if (picType == MFX_FRAMETYPE_I)
606         e2pe = (m_ctx.eRateSH == 0) ? (BRC_SCENE_CHANGE_RATIO2 + 1) : eRate / m_ctx.eRateSH;
607     else
608         e2pe = (m_ctx.eRate == 0) ? (BRC_SCENE_CHANGE_RATIO2 + 1) : eRate / m_ctx.eRate;
609 
610     mfxU32 frameSizeLim = 0xfffffff; // sliding window limitation or external frame size limitation
611 
612     bool bSHStart      = false;
613     bool bNeedUpdateQP = false;
614 
615     brcSts = MFX_BRC_OK;
616 
617     if (m_par.bRec && m_ctx.bToRecode &&
618         (m_ctx.encOrder != frame_par->EncodedOrder || frame_par->NumRecode == 0)) {
619         // Frame must be recoded, but encoder calls BR for another frame
620         return MFX_ERR_UNDEFINED_BEHAVIOR;
621     }
622     if (frame_par->NumRecode == 0 || m_ctx.encOrder != frame_par->EncodedOrder) {
623         // Set context for new frame
624         if (picType == MFX_FRAMETYPE_I)
625             m_ctx.LastIEncOrder = frame_par->EncodedOrder;
626         m_ctx.encOrder  = frame_par->EncodedOrder;
627         m_ctx.poc       = frame_par->DisplayOrder;
628         m_ctx.bToRecode = 0;
629         m_ctx.bPanic    = 0;
630 
631         if (picType == MFX_FRAMETYPE_I) {
632             m_ctx.QuantMin = m_par.quantMinI;
633             m_ctx.QuantMax = m_par.quantMaxI;
634         }
635         else if (picType == MFX_FRAMETYPE_P) {
636             m_ctx.QuantMin = m_par.quantMinP;
637             m_ctx.QuantMax = m_par.quantMaxP;
638         }
639         else {
640             m_ctx.QuantMin = m_par.quantMinB;
641             m_ctx.QuantMax = m_par.quantMaxB;
642         }
643         m_ctx.Quant = qpY;
644 
645         if (m_ctx.SceneChange && (m_ctx.poc > m_ctx.SChPoc + 1 || m_ctx.poc == 0))
646             m_ctx.SceneChange &= ~16;
647 
648         bNeedUpdateQP = true;
649 
650         if (m_par.HRDConformance != MFX_BRC_NO_HRD) {
651             m_hrdSpec->ResetQuant();
652         }
653         //printf("m_ctx.SceneChange %d, m_ctx.poc %d, m_ctx.SChPoc, m_ctx.poc %d \n", m_ctx.SceneChange, m_ctx.poc, m_ctx.SChPoc, m_ctx.poc);
654     }
655     bool bIntra = picType == MFX_FRAMETYPE_I;
656     if (m_par.HRDConformance != MFX_BRC_NO_HRD) {
657         brcSts = CheckHrdAndUpdateQP(*m_hrdSpec.get(),
658                                      bitsEncoded,
659                                      frame_par->EncodedOrder,
660                                      bIntra,
661                                      qpY);
662 
663         MFX_CHECK(brcSts == MFX_BRC_OK || (!m_ctx.bPanic), MFX_ERR_NOT_ENOUGH_BUFFER);
664         if (brcSts == MFX_BRC_OK && !m_ctx.bPanic)
665             bNeedUpdateQP = true;
666 
667         status->MinFrameSize = m_hrdSpec->GetMinFrameSizeInBits(frame_par->EncodedOrder, bIntra);
668 
669         //printf("%d: poc %d, size %d QP %d (%d %d), HRD sts %d, maxFrameSize %d, type %d \n",frame_par->EncodedOrder, frame_par->DisplayOrder, bitsEncoded, m_ctx.Quant, m_ctx.QuantMin, m_ctx.QuantMax, brcSts,  m_hrd.GetMaxFrameSize(), frame_par->FrameType);
670     }
671     if (e2pe > BRC_SCENE_CHANGE_RATIO2) {
672         // scene change, resetting BRC statistics
673         fAbLong = m_ctx.fAbLong = m_par.inputBitsPerFrame;
674         fAbShort = m_ctx.fAbShort = m_par.inputBitsPerFrame;
675         fAbLong  = m_ctx.fAbLong + (bitsEncoded - m_ctx.fAbLong) / m_par.fAbPeriodLong;
676         fAbShort = m_ctx.fAbShort + (bitsEncoded - m_ctx.fAbShort) / m_par.fAbPeriodShort;
677         m_ctx.SceneChange |= 1;
678         if (picType != MFX_FRAMETYPE_B) {
679             bSHStart = true;
680             m_ctx.SceneChange |= 16;
681             m_ctx.eRateSH = eRate;
682             //if ((frame_par->DisplayOrder - m_ctx.SChPoc) >= std::min((mfxU32)(m_par.frameRate), m_par.gopRefDist))
683             { m_ctx.dQuantAb = 1. / m_ctx.Quant; }
684             m_ctx.SChPoc = frame_par->DisplayOrder;
685             //printf("!!!!!!!!!!!!!!!!!!!!! %d m_ctx.SceneChange %d, order %d\n", frame_par->EncodedOrder, m_ctx.SceneChange, frame_par->DisplayOrder);
686         }
687     }
688 
689     if (m_avg.get()) {
690         frameSizeLim = std::min(
691             frameSizeLim,
692             m_avg->GetMaxFrameSize(m_ctx.bPanic, bSHStart || bIntra, frame_par->NumRecode));
693     }
694     if (m_par.maxFrameSizeInBits) {
695         frameSizeLim = std::min(frameSizeLim, m_par.maxFrameSizeInBits);
696     }
697     //printf("frameSizeLim %d (%d)\n", frameSizeLim, bitsEncoded);
698 
699     if (frame_par->NumRecode < 2)
700     // Check other condions for recoding (update qp is it is needed)
701     {
702         mfxF64 targetFrameSize = std::max<mfxF64>((mfxF64)m_par.inputBitsPerFrame, fAbLong);
703         mfxF64 maxFrameSize =
704             (m_ctx.encOrder == 0 ? 6.0 : (bSHStart || picType == MFX_FRAMETYPE_I) ? 8.0 : 4.0) *
705             targetFrameSize * (m_par.bPyr ? 1.5 : 1.0);
706         mfxI32 quantMax = m_ctx.QuantMax;
707         mfxI32 quantMin = m_ctx.QuantMin;
708         mfxI32 quant    = qpY;
709 
710         maxFrameSize = std::min(maxFrameSize, (mfxF64)frameSizeLim);
711 
712         if (m_par.HRDConformance != MFX_BRC_NO_HRD) {
713             if (bSHStart || bIntra)
714                 maxFrameSize =
715                     std::min(maxFrameSize,
716                              3.5 / 9. * m_hrdSpec->GetMaxFrameSizeInBits(m_ctx.encOrder, bIntra) +
717                                  5.5 / 9. * targetFrameSize);
718             else
719                 maxFrameSize =
720                     std::min(maxFrameSize,
721                              2.5 / 9. * m_hrdSpec->GetMaxFrameSizeInBits(m_ctx.encOrder, bIntra) +
722                                  6.5 / 9. * targetFrameSize);
723 
724             quantMax = std::min(m_hrdSpec->GetMaxQuant(), quantMax);
725             quantMin = std::max(m_hrdSpec->GetMinQuant(), quantMin);
726         }
727         maxFrameSize = std::max(maxFrameSize, targetFrameSize);
728 
729         if (bitsEncoded > maxFrameSize && quant < quantMax) {
730             mfxI32 quant_new = GetNewQP(bitsEncoded,
731                                         (mfxU32)maxFrameSize,
732                                         quantMin,
733                                         quantMax,
734                                         quant,
735                                         m_par.quantOffset,
736                                         1);
737             if (quant_new > quant) {
738                 bNeedUpdateQP = false;
739                 //printf("    recode 1-0: %d:  k %5f bitsEncoded %d maxFrameSize %d, targetSize %d, fAbLong %f, inputBitsPerFrame %d, qp %d new %d\n",frame_par->EncodedOrder, bitsEncoded/maxFrameSize, (int)bitsEncoded, (int)maxFrameSize,(int)targetFrameSize, fAbLong, m_par.inputBitsPerFrame, quant, quant_new);
740                 if (quant_new > GetCurQP(picType, layer)) {
741                     UpdateQPParams(bMaxFrameSizeMode ? quant_new - 1 : quant_new,
742                                    picType,
743                                    m_ctx,
744                                    0,
745                                    quantMin,
746                                    quantMax,
747                                    layer);
748                     fAbLong = m_ctx.fAbLong = m_par.inputBitsPerFrame;
749                     fAbShort = m_ctx.fAbShort = m_par.inputBitsPerFrame;
750                     m_ctx.dQuantAb            = 1. / quant_new;
751                 }
752 
753                 if (m_par.bRec) {
754                     SetRecodeParams(MFX_BRC_BIG_FRAME,
755                                     quant,
756                                     quant_new,
757                                     quantMin,
758                                     quantMax,
759                                     m_ctx,
760                                     status);
761                     return sts;
762                 }
763             } //(quant_new > quant)
764         } //bitsEncoded >  maxFrameSize
765 
766         if (bitsEncoded > maxFrameSize && quant == quantMax && picType != MFX_FRAMETYPE_I &&
767             m_par.bPanic && (!m_ctx.bPanic) &&
768             isFrameBeforeIntra(m_ctx.encOrder,
769                                m_ctx.LastIEncOrder,
770                                m_par.gopPicSize,
771                                m_par.gopRefDist)) {
772             //skip frames before intra
773             SetRecodeParams(MFX_BRC_PANIC_BIG_FRAME,
774                             quant,
775                             quant,
776                             quantMin,
777                             quantMax,
778                             m_ctx,
779                             status);
780             return sts;
781         }
782         if (m_par.HRDConformance != MFX_BRC_NO_HRD && frame_par->NumRecode == 0 &&
783             (quant < quantMax)) {
784             mfxF64 maxFrameSizeHrd =
785                 m_hrdSpec->GetMaxFrameSizeInBits(frame_par->EncodedOrder, bIntra);
786             mfxF64 FAMax = 1. / 9. * maxFrameSizeHrd + 8. / 9. * fAbLong;
787 
788             if (fAbShort > FAMax) {
789                 mfxI32 quant_new =
790                     GetNewQP(fAbShort, FAMax, quantMin, quantMax, quant, m_par.quantOffset, 0.5);
791                 //printf("    recode 2-0: %d:  FAMax %f, fAbShort %f, quant_new %d\n",frame_par->EncodedOrder, FAMax, fAbShort, quant_new);
792 
793                 if (quant_new > quant) {
794                     bNeedUpdateQP = false;
795                     if (quant_new > GetCurQP(picType, layer)) {
796                         UpdateQPParams(quant_new, picType, m_ctx, 0, quantMin, quantMax, layer);
797                         fAbLong = m_ctx.fAbLong = m_par.inputBitsPerFrame;
798                         fAbShort = m_ctx.fAbShort = m_par.inputBitsPerFrame;
799                         m_ctx.dQuantAb            = 1. / quant_new;
800                     }
801                     if (m_par.bRec) {
802                         SetRecodeParams(MFX_BRC_BIG_FRAME,
803                                         quant,
804                                         quant_new,
805                                         quantMin,
806                                         quantMax,
807                                         m_ctx,
808                                         status);
809                         return sts;
810                     }
811                 } //quant_new > quant
812             }
813         } //m_par.HRDConformance
814     }
815     if (((m_par.HRDConformance != MFX_BRC_NO_HRD && brcSts != MFX_BRC_OK) ||
816          (bitsEncoded > (mfxI32)frameSizeLim)) &&
817         m_par.bRec) {
818         mfxI32 quant     = m_ctx.Quant;
819         mfxI32 quant_new = quant;
820         if (bitsEncoded > (mfxI32)frameSizeLim) {
821             brcSts    = MFX_BRC_BIG_FRAME;
822             quant_new = GetNewQP(bitsEncoded,
823                                  frameSizeLim,
824                                  m_ctx.QuantMin,
825                                  m_ctx.QuantMax,
826                                  quant,
827                                  m_par.quantOffset,
828                                  1,
829                                  true);
830         }
831         else if (brcSts == MFX_BRC_BIG_FRAME || brcSts == MFX_BRC_SMALL_FRAME) {
832             mfxF64 targetSize = GetFrameTargetSize(
833                 brcSts,
834                 m_hrdSpec->GetMinFrameSizeInBits(frame_par->EncodedOrder, bIntra),
835                 m_hrdSpec->GetMaxFrameSizeInBits(frame_par->EncodedOrder, bIntra));
836             if (targetSize == 0) {
837                 return MFX_ERR_INVALID_VIDEO_PARAM;
838             }
839 
840             quant_new = GetNewQP(bitsEncoded,
841                                  targetSize,
842                                  m_ctx.QuantMin,
843                                  m_ctx.QuantMax,
844                                  quant,
845                                  m_par.quantOffset,
846                                  1,
847                                  true);
848         }
849         if (quant_new != quant) {
850             if (brcSts == MFX_BRC_SMALL_FRAME) {
851                 quant_new = std::max(quant_new, quant - 2);
852                 brcSts    = MFX_BRC_PANIC_SMALL_FRAME;
853             }
854             // Idea is to check a sign mismatch, 'true' if both are negative or positive
855             if ((quant_new - qpY) * (quant_new - GetCurQP(picType, layer)) > 0) {
856                 UpdateQPParams(quant_new, picType, m_ctx, 0, m_ctx.QuantMin, m_ctx.QuantMax, layer);
857             }
858             bNeedUpdateQP = false;
859         }
860         SetRecodeParams(brcSts, quant, quant_new, m_ctx.QuantMin, m_ctx.QuantMax, m_ctx, status);
861     }
862     else {
863         // no recoding are needed. Save context params
864 
865         mfxF64 k          = 1. / m_ctx.Quant;
866         mfxF64 dqAbPeriod = m_par.dqAbPeriod;
867         if (m_ctx.bToRecode)
868             dqAbPeriod = (k < m_ctx.dQuantAb) ? 16 : 25;
869 
870         if (bNeedUpdateQP) {
871             m_ctx.dQuantAb += (k - m_ctx.dQuantAb) / dqAbPeriod;
872             m_ctx.dQuantAb = mfx::clamp(m_ctx.dQuantAb, 1. / m_ctx.QuantMax, 1. / m_ctx.QuantMin);
873 
874             m_ctx.fAbLong  = fAbLong;
875             m_ctx.fAbShort = fAbShort;
876         }
877 
878         bool oldScene = false;
879         if ((m_ctx.SceneChange & 16) && (m_ctx.poc < m_ctx.SChPoc) && (e2pe < .01) &&
880             (mfxF64)bitsEncoded < 1.5 * fAbLong)
881             oldScene = true;
882         //printf("-- m_ctx.eRate %f,  eRate %f, e2pe %f\n", m_ctx.eRate,  eRate, e2pe );
883 
884         if (picType != MFX_FRAMETYPE_B) {
885             m_ctx.LastNonBFrameSize = bitsEncoded;
886             if (picType == MFX_FRAMETYPE_I)
887                 m_ctx.eRateSH = eRate;
888             else
889                 m_ctx.eRate = eRate;
890         }
891 
892         if (m_avg.get()) {
893             m_avg->UpdateSlidingWindow(bitsEncoded,
894                                        m_ctx.encOrder,
895                                        m_ctx.bPanic,
896                                        bSHStart || picType == MFX_FRAMETYPE_I,
897                                        frame_par->NumRecode);
898         }
899 
900         m_ctx.totalDeviation += ((mfxF64)bitsEncoded - m_par.inputBitsPerFrame);
901 
902         //printf("-- %d (%d)) Total deviation %f, old scene %d, bNeedUpdateQP %d, m_ctx.Quant %d, type %d\n", frame_par->EncodedOrder, frame_par->DisplayOrder,m_ctx.totalDeviation, oldScene , bNeedUpdateQP, m_ctx.Quant,picType);
903 
904         if (!m_ctx.bPanic && (!oldScene) && bNeedUpdateQP) {
905             mfxI32 quant_new = m_ctx.Quant;
906             //Update QP
907 
908             mfxF64 totDev          = m_ctx.totalDeviation;
909             mfxF64 HRDDev          = 0.0;
910             mfxF64 maxFrameSizeHrd = 0.0;
911             if (m_par.HRDConformance != MFX_BRC_NO_HRD) {
912                 HRDDev          = m_hrdSpec->GetBufferDeviation(frame_par->EncodedOrder);
913                 maxFrameSizeHrd = m_hrdSpec->GetMaxFrameSizeInBits(frame_par->EncodedOrder, bIntra);
914                 //printf("HRDDiv %f\n", HRDDiv);
915             }
916             mfxF64 dequant_new = m_ctx.dQuantAb * pow(m_par.inputBitsPerFrame / m_ctx.fAbLong, 1.2);
917             mfxF64 bAbPreriod  = m_par.bAbPeriod;
918 
919             if (m_par.HRDConformance != MFX_BRC_NO_HRD) {
920                 if (m_par.rateControlMethod == MFX_RATECONTROL_VBR &&
921                     m_par.maxbps > m_par.targetbps) {
922                     totDev = std::max(totDev, HRDDev);
923                 }
924                 else {
925                     totDev = HRDDev;
926                 }
927                 if (totDev > 0) {
928                     bAbPreriod =
929                         (mfxF64)(m_par.bPyr ? 4 : 3) * (mfxF64)maxFrameSizeHrd / fAbShort *
930                         GetAbPeriodCoeff(m_ctx.encOrder - m_ctx.LastIEncOrder, m_par.gopPicSize);
931                     bAbPreriod = mfx::clamp(bAbPreriod, m_par.bAbPeriod / 10, m_par.bAbPeriod);
932                 }
933             }
934             quant_new = GetNewQPTotal(totDev / bAbPreriod / (mfxF64)m_par.inputBitsPerFrame,
935                                       dequant_new,
936                                       m_ctx.QuantMin,
937                                       m_ctx.QuantMax,
938                                       m_ctx.Quant,
939                                       m_par.bPyr && m_par.bRec,
940                                       bSHStart && m_ctx.bToRecode == 0);
941             //printf("    ===%d quant old %d quant_new %d, bitsEncoded %d m_ctx.QuantMin %d m_ctx.QuantMax %d\n", frame_par->EncodedOrder, m_ctx.Quant, quant_new, bitsEncoded, m_ctx.QuantMin, m_ctx.QuantMax);
942 
943             if (bMaxFrameSizeMode) {
944                 mfxF64 targetMax = ((mfxF64)m_par.maxFrameSizeInBits *
945                                     ((bSHStart || picType == MFX_FRAMETYPE_I) ? 0.95 : 0.9));
946                 mfxF64 targetMin =
947                     ((mfxF64)m_par.maxFrameSizeInBits *
948                      ((bSHStart || picType == MFX_FRAMETYPE_I) ? 0.9 : 0.8 /*0.75 : 0.5*/));
949                 mfxI32 QuantNewMin     = GetNewQP(bitsEncoded,
950                                               targetMax,
951                                               m_ctx.QuantMin,
952                                               m_ctx.QuantMax,
953                                               m_ctx.Quant,
954                                               m_par.quantOffset,
955                                               1,
956                                               false,
957                                               false);
958                 mfxI32 QuantNewMax     = GetNewQP(bitsEncoded,
959                                               targetMin,
960                                               m_ctx.QuantMin,
961                                               m_ctx.QuantMax,
962                                               m_ctx.Quant,
963                                               m_par.quantOffset,
964                                               1,
965                                               false,
966                                               false);
967                 mfxI32 quant_corrected = m_ctx.Quant;
968 
969                 if (quant_corrected < QuantNewMin - 3)
970                     quant_corrected += 2;
971                 if (quant_corrected < QuantNewMin)
972                     quant_corrected++;
973                 else if (quant_corrected > QuantNewMax + 3)
974                     quant_corrected -= 2;
975                 else if (quant_corrected > QuantNewMax)
976                     quant_corrected--;
977 
978                 //printf("   QuantNewMin %d, QuantNewMax %d, m_ctx.Quant %d, new %d (%d)\n", QuantNewMin, QuantNewMax, m_ctx.Quant, quant_corrected, quant_new);
979 
980                 quant_new = mfx::clamp(quant_corrected, m_ctx.QuantMin, m_ctx.QuantMax);
981             }
982             if ((quant_new - m_ctx.Quant) * (quant_new - GetCurQP(picType, layer)) >
983                 0) // this check is actual for async scheme
984             {
985                 //printf("   Update QP %d: totalDeviation %f, bAbPreriod %f (%f), QP %d (%d %d), qp_new %d (qpY %d), type %d, dequant_new %f (%f) , m_ctx.fAbLong %f, m_par.inputBitsPerFrame %f (%f)\n",frame_par->EncodedOrder,totDev , bAbPreriod, GetAbPeriodCoeff(m_ctx.encOrder - m_ctx.LastIEncOrder, m_par.gopPicSize), m_ctx.Quant, m_ctx.QuantMin, m_ctx.QuantMax,quant_new, qpY, picType, 1.0/dequant_new, 1.0/m_ctx.dQuantAb, m_ctx.fAbLong, m_par.inputBitsPerFrame, m_par.inputBitsPerFrame/m_ctx.fAbLong);
986                 UpdateQPParams(quant_new, picType, m_ctx, 0, m_ctx.QuantMin, m_ctx.QuantMax, layer);
987             }
988         }
989         m_ctx.bToRecode = 0;
990         if (m_par.HRDConformance != MFX_BRC_NO_HRD) {
991             m_hrdSpec->Update(bitsEncoded, frame_par->EncodedOrder, bIntra);
992         }
993     }
994     return sts;
995 }
996 
GetFrameCtrl(mfxBRCFrameParam * par,mfxBRCFrameCtrl * ctrl)997 mfxStatus ExtBRC::GetFrameCtrl(mfxBRCFrameParam* par, mfxBRCFrameCtrl* ctrl) {
998     MFX_CHECK_NULL_PTR2(par, ctrl);
999     MFX_CHECK(m_bInit, MFX_ERR_NOT_INITIALIZED);
1000 
1001     mfxI32 qp = 0;
1002     if (par->EncodedOrder == m_ctx.encOrder) {
1003         qp = m_ctx.Quant;
1004     }
1005     else {
1006         mfxU16 type = GetFrameType(par->FrameType, par->PyramidLayer, m_par.gopRefDist);
1007         qp          = GetCurQP(type, par->PyramidLayer);
1008     }
1009     ctrl->QpY = qp - m_par.quantOffset;
1010     if (m_par.HRDConformance != MFX_BRC_NO_HRD) {
1011         ctrl->InitialCpbRemovalDelay  = m_hrdSpec->GetInitCpbRemovalDelay(par->EncodedOrder);
1012         ctrl->InitialCpbRemovalOffset = m_hrdSpec->GetInitCpbRemovalDelayOffset(par->EncodedOrder);
1013     }
1014     if (m_par.mMBBRC) {
1015         if (ctrl->NumExtParam == 0) {
1016             //attach MBBRC buffer
1017             ctrl->NumExtParam = 1;
1018             ctrl->ExtParam    = &(m_ExtBuff[par->EncodedOrder % m_ExtBuff.size()]);
1019         }
1020         mfxExtMBQP* pExtMBQP =
1021             (mfxExtMBQP*)Hevc_GetExtBuffer(ctrl->ExtParam, ctrl->NumExtParam, MFX_EXTBUFF_MBQP);
1022         if (pExtMBQP) {
1023             //fill QP map
1024             for (size_t i = 0; i < pExtMBQP->NumQPAlloc; i++) {
1025                 pExtMBQP->QP[i] = (mfxU8)(qp + ((qp < 51) ? (i % 2) : 0));
1026             }
1027         }
1028     }
1029     return MFX_ERR_NONE;
1030 }
1031 
Reset(mfxVideoParam * par)1032 mfxStatus ExtBRC::Reset(mfxVideoParam* par) {
1033     mfxStatus sts = MFX_ERR_NONE;
1034     MFX_CHECK_NULL_PTR1(par);
1035     MFX_CHECK(m_bInit, MFX_ERR_NOT_INITIALIZED);
1036 
1037     mfxExtEncoderResetOption* pRO =
1038         (mfxExtEncoderResetOption*)Hevc_GetExtBuffer(par->ExtParam,
1039                                                      par->NumExtParam,
1040                                                      MFX_EXTBUFF_ENCODER_RESET_OPTION);
1041     if (pRO && pRO->StartNewSequence == MFX_CODINGOPTION_ON) {
1042         Close();
1043         sts = Init(par);
1044     }
1045     else {
1046         bool brcReset           = false;
1047         bool slidingWindowReset = false;
1048 
1049         sts = m_par.GetBRCResetType(par, false, brcReset, slidingWindowReset);
1050         MFX_CHECK_STS(sts);
1051 
1052         if (brcReset) {
1053             sts = m_par.Init(par, isFieldMode(par));
1054             MFX_CHECK_STS(sts);
1055 
1056             m_ctx.Quant = (mfxI32)(
1057                 1. / m_ctx.dQuantAb * pow(m_ctx.fAbLong / m_par.inputBitsPerFrame, 0.32) + 0.5);
1058             m_ctx.Quant = mfx::clamp(m_ctx.Quant, m_par.quantMinI, m_par.quantMaxI);
1059 
1060             UpdateQPParams(m_ctx.Quant,
1061                            MFX_FRAMETYPE_I,
1062                            m_ctx,
1063                            0,
1064                            m_par.quantMinI,
1065                            m_par.quantMaxI,
1066                            0);
1067 
1068             m_ctx.dQuantAb = 1. / m_ctx.Quant;
1069             m_ctx.fAbLong  = m_par.inputBitsPerFrame;
1070             m_ctx.fAbShort = m_par.inputBitsPerFrame;
1071 
1072             if (slidingWindowReset) {
1073                 m_avg.reset(
1074                     new AVGBitrate(m_par.WinBRCSize,
1075                                    (mfxU32)(m_par.WinBRCMaxAvgKbps * 1000.0 / m_par.frameRate),
1076                                    (mfxU32)m_par.inputBitsPerFrame));
1077                 MFX_CHECK_NULL_PTR1(m_avg.get());
1078             }
1079         }
1080     }
1081     return sts;
1082 }
1083 
Init(cBRCParams & par)1084 void HEVC_HRD::Init(cBRCParams& par) {
1085     m_hrdInput.Init(par);
1086     m_prevAuCpbRemovalDelayMinus1 = -1;
1087     m_prevAuCpbRemovalDelayMsb    = 0;
1088     m_prevAuFinalArrivalTime      = 0;
1089     m_prevBpAuNominalRemovalTime  = (mfxU32)m_hrdInput.m_initCpbRemovalDelay;
1090     m_prevBpEncOrder              = 0;
1091 }
1092 
Reset(cBRCParams & par)1093 void HEVC_HRD::Reset(cBRCParams& par) {
1094     sHrdInput hrdInput;
1095     hrdInput.Init(par);
1096     m_hrdInput.m_bitrate    = hrdInput.m_bitrate;
1097     m_hrdInput.m_cpbSize90k = hrdInput.m_cpbSize90k;
1098 }
1099 
Update(mfxU32 sizeInbits,mfxU32 eo,bool bSEI)1100 void HEVC_HRD::Update(mfxU32 sizeInbits, mfxU32 eo, bool bSEI) {
1101     mfxF64 auNominalRemovalTime = 0.0;
1102     mfxF64 initCpbRemovalDelay  = GetInitCpbRemovalDelay(eo);
1103     if (eo > 0) {
1104         mfxU32 auCpbRemovalDelayMinus1 = (eo - m_prevBpEncOrder) - 1;
1105         // (D-1)
1106         mfxU32 auCpbRemovalDelayMsb = 0;
1107 
1108         if (!bSEI && (eo - m_prevBpEncOrder) != 1) {
1109             auCpbRemovalDelayMsb =
1110                 ((mfxI32)auCpbRemovalDelayMinus1 <= m_prevAuCpbRemovalDelayMinus1)
1111                     ? m_prevAuCpbRemovalDelayMsb + m_hrdInput.m_maxCpbRemovalDelay
1112                     : m_prevAuCpbRemovalDelayMsb;
1113         }
1114 
1115         m_prevAuCpbRemovalDelayMsb    = auCpbRemovalDelayMsb;
1116         m_prevAuCpbRemovalDelayMinus1 = auCpbRemovalDelayMinus1;
1117 
1118         // (D-2)
1119         mfxU32 auCpbRemovalDelayValMinus1 = auCpbRemovalDelayMsb + auCpbRemovalDelayMinus1;
1120         // (C-10, C-11)
1121         auNominalRemovalTime = m_prevBpAuNominalRemovalTime +
1122                                m_hrdInput.m_clockTick * (auCpbRemovalDelayValMinus1 + 1);
1123     }
1124     else // (C-9)
1125         auNominalRemovalTime = m_hrdInput.m_initCpbRemovalDelay;
1126 
1127     // (C-3)
1128     mfxF64 initArrivalTime = m_prevAuFinalArrivalTime;
1129 
1130     if (!m_hrdInput.m_cbrFlag) {
1131         mfxF64 initArrivalEarliestTime = (bSEI)
1132                                              // (C-7)
1133                                              ? auNominalRemovalTime - initCpbRemovalDelay
1134                                              // (C-6)
1135                                              : auNominalRemovalTime - m_hrdInput.m_cpbSize90k;
1136         // (C-4)
1137         initArrivalTime = std::max<mfxF64>(m_prevAuFinalArrivalTime,
1138                                            initArrivalEarliestTime * m_hrdInput.m_bitrate);
1139     }
1140     // (C-8)
1141     mfxF64 auFinalArrivalTime = initArrivalTime + (mfxF64)sizeInbits * 90000;
1142 
1143     m_prevAuFinalArrivalTime = auFinalArrivalTime;
1144 
1145     if (bSEI) {
1146         m_prevBpAuNominalRemovalTime = auNominalRemovalTime;
1147         m_prevBpEncOrder             = eo;
1148     }
1149 }
1150 
GetInitCpbRemovalDelay(mfxU32 eo) const1151 mfxU32 HEVC_HRD::GetInitCpbRemovalDelay(mfxU32 eo) const {
1152     mfxF64 auNominalRemovalTime;
1153 
1154     if (eo > 0) {
1155         // (D-1)
1156         mfxU32 auCpbRemovalDelayMsb    = 0;
1157         mfxU32 auCpbRemovalDelayMinus1 = eo - m_prevBpEncOrder - 1;
1158 
1159         // (D-2)
1160         mfxU32 auCpbRemovalDelayValMinus1 = auCpbRemovalDelayMsb + auCpbRemovalDelayMinus1;
1161         // (C-10, C-11)
1162         auNominalRemovalTime = m_prevBpAuNominalRemovalTime +
1163                                m_hrdInput.m_clockTick * (auCpbRemovalDelayValMinus1 + 1);
1164 
1165         // (C-17)
1166         mfxF64 deltaTime90k =
1167             auNominalRemovalTime - m_prevAuFinalArrivalTime / m_hrdInput.m_bitrate;
1168 
1169         return (m_hrdInput.m_cbrFlag
1170                     // (C-19)
1171                     ? (mfxU32)(deltaTime90k)
1172                     // (C-18)
1173                     : (mfxU32)std::min(deltaTime90k, m_hrdInput.m_cpbSize90k));
1174     }
1175 
1176     return (mfxU32)m_hrdInput.m_initCpbRemovalDelay;
1177 }
1178 
GetTargetDelay(mfxF64 cpbSize90k,mfxF64 initCpbRemovalDelay,bool bVBR)1179 inline mfxF64 GetTargetDelay(mfxF64 cpbSize90k, mfxF64 initCpbRemovalDelay, bool bVBR) {
1180     return bVBR ? std::max(std::min(3.0 * cpbSize90k / 4.0, initCpbRemovalDelay), cpbSize90k / 2.0)
1181                 : std::min(cpbSize90k / 2.0, initCpbRemovalDelay);
1182 }
GetBufferDeviation(mfxU32 eo) const1183 mfxF64 HEVC_HRD::GetBufferDeviation(mfxU32 eo) const {
1184     mfxU32 delay       = GetInitCpbRemovalDelay(eo);
1185     mfxF64 targetDelay = GetTargetDelay(m_hrdInput.m_cpbSize90k,
1186                                         m_hrdInput.m_initCpbRemovalDelay,
1187                                         !m_hrdInput.m_cbrFlag);
1188     return (targetDelay - delay) / 90000.0 * m_hrdInput.m_bitrate;
1189 }
1190 
GetBufferDeviationFactor(mfxU32 eo) const1191 mfxF64 HEVC_HRD::GetBufferDeviationFactor(mfxU32 eo) const {
1192     mfxU32 delay       = GetInitCpbRemovalDelay(eo);
1193     mfxF64 targetDelay = GetTargetDelay(m_hrdInput.m_cpbSize90k,
1194                                         m_hrdInput.m_initCpbRemovalDelay,
1195                                         !m_hrdInput.m_cbrFlag);
1196     return abs((targetDelay - delay) / targetDelay);
1197 }
1198 
GetMaxFrameSizeInBits(mfxU32 eo,bool) const1199 mfxU32 HEVC_HRD::GetMaxFrameSizeInBits(mfxU32 eo, bool /*bSEI*/) const {
1200     return (mfxU32)(GetInitCpbRemovalDelay(eo) / 90000.0 * m_hrdInput.m_bitrate);
1201 }
1202 
GetMinFrameSizeInBits(mfxU32 eo,bool) const1203 mfxU32 HEVC_HRD::GetMinFrameSizeInBits(mfxU32 eo, bool /*bSEI*/) const {
1204     mfxU32 delay = GetInitCpbRemovalDelay(eo);
1205     if ((!m_hrdInput.m_cbrFlag) ||
1206         ((delay + m_hrdInput.m_clockTick + 16.0) < m_hrdInput.m_cpbSize90k))
1207         return 0;
1208     return (mfxU32)((delay + m_hrdInput.m_clockTick + 16.0 - m_hrdInput.m_cpbSize90k) / 90000.0 *
1209                         m_hrdInput.m_bitrate +
1210                     0.99999);
1211 }
1212 
H264_HRD()1213 H264_HRD::H264_HRD() : m_trn_cur(0), m_taf_prv(0) {}
1214 
Init(cBRCParams & par)1215 void H264_HRD::Init(cBRCParams& par) {
1216     m_hrdInput.Init(par);
1217     m_hrdInput.m_clockTick *= (1.0 / 90000.0);
1218     m_taf_prv = 0.0;
1219     m_trn_cur = m_hrdInput.m_initCpbRemovalDelay / 90000.0;
1220     m_trn_cur = GetInitCpbRemovalDelay(0) / 90000.0;
1221 }
1222 
Reset(cBRCParams & par)1223 void H264_HRD::Reset(cBRCParams& par) {
1224     sHrdInput hrdInput;
1225     hrdInput.Init(par);
1226     m_hrdInput.m_bitrate    = hrdInput.m_bitrate;
1227     m_hrdInput.m_cpbSize90k = hrdInput.m_cpbSize90k;
1228 }
1229 
Update(mfxU32 sizeInbits,mfxU32 eo,bool bSEI)1230 void H264_HRD::Update(mfxU32 sizeInbits, mfxU32 eo, bool bSEI) {
1231     //const bool interlace = false; //BRC is frame level only
1232     mfxU32 initDelay = GetInitCpbRemovalDelay(eo);
1233 
1234     double tai_earliest =
1235         bSEI ? m_trn_cur - (initDelay / 90000.0) : m_trn_cur - (m_hrdInput.m_cpbSize90k / 90000.0);
1236 
1237     double tai_cur = (!m_hrdInput.m_cbrFlag) ? std::max(m_taf_prv, tai_earliest) : m_taf_prv;
1238 
1239     m_taf_prv = tai_cur + (mfxF64)sizeInbits / m_hrdInput.m_bitrate;
1240     m_trn_cur += m_hrdInput.m_clockTick;
1241 }
1242 
GetInitCpbRemovalDelay(mfxU32) const1243 mfxU32 H264_HRD::GetInitCpbRemovalDelay(mfxU32 /* eo */) const {
1244     double delay                  = std::max(0.0, m_trn_cur - m_taf_prv);
1245     mfxU32 initialCpbRemovalDelay = mfxU32(90000 * delay + 0.5);
1246 
1247     return (mfxU32)(initialCpbRemovalDelay == 0
1248                         ? 1 // should not be equal to 0
1249                         : initialCpbRemovalDelay > m_hrdInput.m_cpbSize90k &&
1250                                   (!m_hrdInput.m_cbrFlag)
1251                               ? m_hrdInput.m_cpbSize90k // should not exceed hrd buffer
1252                               : initialCpbRemovalDelay);
1253 }
GetBufferDeviation(mfxU32 eo) const1254 mfxF64 H264_HRD::GetBufferDeviation(mfxU32 eo) const {
1255     mfxU32 delay       = GetInitCpbRemovalDelay(eo);
1256     mfxF64 targetDelay = GetTargetDelay(m_hrdInput.m_cpbSize90k,
1257                                         m_hrdInput.m_initCpbRemovalDelay,
1258                                         !m_hrdInput.m_cbrFlag);
1259     return (targetDelay - delay) / 90000.0 * m_hrdInput.m_bitrate;
1260 }
GetBufferDeviationFactor(mfxU32 eo) const1261 mfxF64 H264_HRD::GetBufferDeviationFactor(mfxU32 eo) const {
1262     mfxU32 delay       = GetInitCpbRemovalDelay(eo);
1263     mfxF64 targetDelay = GetTargetDelay(m_hrdInput.m_cpbSize90k,
1264                                         m_hrdInput.m_initCpbRemovalDelay,
1265                                         !m_hrdInput.m_cbrFlag);
1266     return abs((targetDelay - delay) / targetDelay);
1267 }
1268 
GetInitCpbRemovalDelayOffset(mfxU32 eo) const1269 mfxU32 H264_HRD::GetInitCpbRemovalDelayOffset(mfxU32 eo) const {
1270     // init_cpb_removal_delay + init_cpb_removal_delay_offset should be constant
1271     return mfxU32(m_hrdInput.m_cpbSize90k - GetInitCpbRemovalDelay(eo));
1272 }
GetMinFrameSizeInBits(mfxU32 eo,bool) const1273 mfxU32 H264_HRD::GetMinFrameSizeInBits(mfxU32 eo, bool /*bSEI*/) const {
1274     mfxU32 delay = GetInitCpbRemovalDelay(eo);
1275     if ((!m_hrdInput.m_cbrFlag) ||
1276         ((delay + m_hrdInput.m_clockTick * 90000) < m_hrdInput.m_cpbSize90k))
1277         return 0;
1278 
1279     return (mfxU32)((delay + m_hrdInput.m_clockTick * 90000.0 - m_hrdInput.m_cpbSize90k) / 90000.0 *
1280                     m_hrdInput.m_bitrate) +
1281            16;
1282 }
GetMaxFrameSizeInBits(mfxU32 eo,bool bSEI) const1283 mfxU32 H264_HRD::GetMaxFrameSizeInBits(mfxU32 eo, bool bSEI) const {
1284     mfxU32 initDelay = GetInitCpbRemovalDelay(eo);
1285 
1286     double tai_earliest = (bSEI) ? m_trn_cur - (initDelay / 90000.0)
1287                                  : m_trn_cur - (m_hrdInput.m_cpbSize90k / 90000.0);
1288 
1289     double tai_cur = (!m_hrdInput.m_cbrFlag) ? std::max(m_taf_prv, tai_earliest) : m_taf_prv;
1290 
1291     mfxU32 maxFrameSize = (mfxU32)((m_trn_cur - tai_cur) * m_hrdInput.m_bitrate);
1292 
1293     return maxFrameSize;
1294 }
Init(cBRCParams par)1295 void sHrdInput::Init(cBRCParams par) {
1296     m_cbrFlag             = (par.rateControlMethod == MFX_RATECONTROL_CBR);
1297     m_bitrate             = par.maxbps;
1298     m_maxCpbRemovalDelay  = 1 << (h264_h265_au_cpb_removal_delay_length_minus1 + 1);
1299     m_clockTick           = 90000. / par.frameRate;
1300     m_cpbSize90k          = mfxU32(90000. * par.bufferSizeInBytes * 8.0 / m_bitrate);
1301     m_initCpbRemovalDelay = 90000. * 8. * par.initialDelayInBytes / m_bitrate;
1302 }
1303