1 /******************************************************************************\
2 Copyright (c) 2005-2019, Intel Corporation
3 All rights reserved.
4 
5 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
6 
7 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
8 
9 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
10 
11 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
12 
13 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14 
15 This sample was distributed or derived from the Intel's Media Samples package.
16 The original version of this sample may be obtained from https://software.intel.com/en-us/intel-media-server-studio
17 or https://software.intel.com/en-us/media-client-solutions-support.
18 \**********************************************************************************/
19 
20 
21 #include "brc_routines.h"
22 #include "math.h"
23 #include "mfxdefs.h"
24 #include <algorithm>
25 
26 #ifndef MFX_VERSION
27 #error MFX_VERSION not defined
28 #endif
29 
30 #if (MFX_VERSION >= 1024)
31 #define BRC_SCENE_CHANGE_RATIO1 20.0
32 #define BRC_SCENE_CHANGE_RATIO2 5.0
33 
Hevc_GetExtBuffer(mfxExtBuffer ** extBuf,mfxU32 numExtBuf,mfxU32 id)34 mfxExtBuffer* Hevc_GetExtBuffer(mfxExtBuffer** extBuf, mfxU32 numExtBuf, mfxU32 id)
35 {
36     if (extBuf != 0)
37     {
38         for (mfxU16 i = 0; i < numExtBuf; i++)
39         {
40             if (extBuf[i] != 0 && extBuf[i]->BufferId == id) // assuming aligned buffers
41                 return (extBuf[i]);
42         }
43     }
44 
45     return nullptr;
46 }
47 
Init(mfxVideoParam * par,bool bFielMode)48 mfxStatus cBRCParams::Init(mfxVideoParam* par, bool bFielMode)
49 {
50     printf("Sample BRC is used\n");
51     MFX_CHECK_NULL_PTR1(par);
52     MFX_CHECK(par->mfx.RateControlMethod == MFX_RATECONTROL_CBR ||
53               par->mfx.RateControlMethod == MFX_RATECONTROL_VBR,
54               MFX_ERR_UNDEFINED_BEHAVIOR);
55 
56     mfxU32 k = par->mfx.BRCParamMultiplier == 0 ?  1: par->mfx.BRCParamMultiplier;
57     mfxU32 bpsScale  = (par->mfx.CodecId == MFX_CODEC_AVC) ? 10 : 6;
58 
59     rateControlMethod  = par->mfx.RateControlMethod;
60     targetbps = (((k*par->mfx.TargetKbps*1000) >> bpsScale) << bpsScale);
61     maxbps    = (((k*par->mfx.MaxKbps   *1000) >> bpsScale) << bpsScale);
62 
63     maxbps = (par->mfx.RateControlMethod == MFX_RATECONTROL_CBR) ?
64         targetbps : ((maxbps >= targetbps) ? maxbps : targetbps);
65     mfxExtCodingOption * pExtCO = (mfxExtCodingOption*)Hevc_GetExtBuffer(par->ExtParam, par->NumExtParam, MFX_EXTBUFF_CODING_OPTION);
66 
67     HRDConformance = MFX_BRC_NO_HRD;
68     if (pExtCO)
69     {
70         if ((MFX_CODINGOPTION_OFF != pExtCO->NalHrdConformance) && (MFX_CODINGOPTION_OFF != pExtCO->VuiNalHrdParameters))
71             HRDConformance = MFX_BRC_HRD_STRONG;
72         else if ((MFX_CODINGOPTION_ON == pExtCO->NalHrdConformance) && (MFX_CODINGOPTION_OFF == pExtCO->VuiNalHrdParameters))
73             HRDConformance = MFX_BRC_HRD_WEAK;
74     }
75 
76     if (HRDConformance != MFX_BRC_NO_HRD)
77     {
78         bufferSizeInBytes   = ((k*par->mfx.BufferSizeInKB  *1000) >> 3) << 3;
79         initialDelayInBytes = ((k*par->mfx.InitialDelayInKB*1000) >> 3) << 3;
80         bRec = 1;
81         bPanic = (HRDConformance == MFX_BRC_HRD_STRONG) ? 1 : 0;
82     }
83     MFX_CHECK (par->mfx.FrameInfo.FrameRateExtD != 0 &&
84                par->mfx.FrameInfo.FrameRateExtN != 0,
85                MFX_ERR_UNDEFINED_BEHAVIOR);
86 
87     frameRate = (mfxF64)par->mfx.FrameInfo.FrameRateExtN / (mfxF64)par->mfx.FrameInfo.FrameRateExtD;
88 
89     width  = par->mfx.FrameInfo.Width;
90     height = par->mfx.FrameInfo.Height;
91 
92     chromaFormat = par->mfx.FrameInfo.ChromaFormat == 0 ?  MFX_CHROMAFORMAT_YUV420 : par->mfx.FrameInfo.ChromaFormat ;
93     bitDepthLuma = par->mfx.FrameInfo.BitDepthLuma == 0 ?  8 : par->mfx.FrameInfo.BitDepthLuma;
94     quantOffset  = 6 * (bitDepthLuma - 8);
95 
96     inputBitsPerFrame    = targetbps / frameRate;
97     maxInputBitsPerFrame = maxbps / frameRate;
98     gopPicSize = par->mfx.GopPicSize*(bFielMode ? 2 : 1);
99     gopRefDist = par->mfx.GopRefDist*(bFielMode ? 2 : 1);
100 
101     mfxExtCodingOption2 * pExtCO2 = (mfxExtCodingOption2*)Hevc_GetExtBuffer(par->ExtParam, par->NumExtParam, MFX_EXTBUFF_CODING_OPTION2);
102     bPyr = (pExtCO2 && pExtCO2->BRefType == MFX_B_REF_PYRAMID);
103     maxFrameSizeInBits  = pExtCO2 ? pExtCO2->MaxFrameSize*8 : 0;
104     fAbPeriodLong  = 100;
105     fAbPeriodShort = 5;
106     dqAbPeriod = 100;
107     bAbPeriod = 100;
108 
109     if (maxFrameSizeInBits)
110     {
111         bRec = 1;
112         bPanic = 1;
113     }
114 
115     if (pExtCO2
116         && pExtCO2->MaxQPI <=51 && pExtCO2->MaxQPI > pExtCO2->MinQPI && pExtCO2->MinQPI >=1
117         && pExtCO2->MaxQPP <=51 && pExtCO2->MaxQPP > pExtCO2->MinQPP && pExtCO2->MinQPP >=1
118         && pExtCO2->MaxQPB <=51 && pExtCO2->MaxQPB > pExtCO2->MinQPB && pExtCO2->MinQPB >=1 )
119     {
120         quantMaxI = pExtCO2->MaxQPI + quantOffset;
121         quantMinI = pExtCO2->MinQPI;
122         quantMaxP = pExtCO2->MaxQPP + quantOffset;
123         quantMinP = pExtCO2->MinQPP;
124         quantMaxB = pExtCO2->MaxQPB + quantOffset;
125         quantMinB = pExtCO2->MinQPB;
126     }
127     else
128     {
129         quantMaxI = quantMaxP = quantMaxB = 51 + quantOffset;
130         quantMinI = quantMinP = quantMinB = 1;
131     }
132 
133     mfxExtCodingOption3 * pExtCO3 = (mfxExtCodingOption3*)Hevc_GetExtBuffer(par->ExtParam, par->NumExtParam, MFX_EXTBUFF_CODING_OPTION3);
134     if (pExtCO3)
135     {
136         WinBRCMaxAvgKbps = pExtCO3->WinBRCMaxAvgKbps*par->mfx.BRCParamMultiplier;
137         WinBRCSize = pExtCO3->WinBRCSize;
138     }
139     return MFX_ERR_NONE;
140 }
141 
GetBRCResetType(mfxVideoParam * par,bool bNewSequence,bool & bBRCReset,bool & bSlidingWindowReset)142 mfxStatus   cBRCParams::GetBRCResetType(mfxVideoParam* par, bool bNewSequence, bool &bBRCReset, bool &bSlidingWindowReset)
143 {
144     bBRCReset = false;
145     bSlidingWindowReset = false;
146 
147     if (bNewSequence)
148         return MFX_ERR_NONE;
149 
150     cBRCParams new_par;
151     mfxStatus sts = new_par.Init(par);
152     MFX_CHECK_STS(sts);
153 
154     MFX_CHECK(new_par.rateControlMethod == rateControlMethod, MFX_ERR_INCOMPATIBLE_VIDEO_PARAM) ;
155     MFX_CHECK(new_par.HRDConformance == HRDConformance, MFX_ERR_INCOMPATIBLE_VIDEO_PARAM) ;
156     MFX_CHECK(new_par.frameRate == frameRate, MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
157     MFX_CHECK(new_par.width == width, MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
158     MFX_CHECK(new_par.height == height, MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
159     MFX_CHECK(new_par.chromaFormat == chromaFormat, MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
160     MFX_CHECK(new_par.bitDepthLuma == bitDepthLuma, MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
161 
162     if (HRDConformance == MFX_BRC_HRD_STRONG)
163     {
164         MFX_CHECK(new_par.bufferSizeInBytes   == bufferSizeInBytes, MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
165         MFX_CHECK(new_par.initialDelayInBytes == initialDelayInBytes, MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
166         MFX_CHECK(new_par.targetbps == targetbps, MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
167         MFX_CHECK(new_par.maxbps == maxbps, MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
168     }
169     else if (new_par.targetbps != targetbps || new_par.maxbps != maxbps)
170     {
171         bBRCReset = true;
172     }
173 
174     if (new_par.WinBRCMaxAvgKbps != WinBRCMaxAvgKbps)
175     {
176         bBRCReset = true;
177         bSlidingWindowReset = true;
178     }
179 
180     if (new_par.maxFrameSizeInBits != maxFrameSizeInBits) bBRCReset = true;
181     if (new_par.gopPicSize != gopPicSize) bBRCReset = true;
182     if (new_par.gopRefDist != gopRefDist) bBRCReset = true;
183     if (new_par.bPyr != bPyr) bBRCReset = true;
184     if (new_par.quantMaxI != quantMaxI) bBRCReset = true;
185     if (new_par.quantMinI != quantMinI) bBRCReset = true;
186     if (new_par.quantMaxP != quantMaxP) bBRCReset = true;
187     if (new_par.quantMinP != quantMinP) bBRCReset = true;
188     if (new_par.quantMaxB != quantMaxB) bBRCReset = true;
189     if (new_par.quantMinB != quantMinB) bBRCReset = true;
190 
191     return MFX_ERR_NONE;
192 }
193 
194 
195 
196 enum
197 {
198     MFX_BRC_RECODE_NONE           = 0,
199     MFX_BRC_RECODE_QP             = 1,
200     MFX_BRC_RECODE_PANIC          = 2,
201 };
202 
203    mfxF64 const QSTEP[88] = {
204          0.630,  0.707,  0.794,  0.891,  1.000,   1.122,   1.260,   1.414,   1.587,   1.782,   2.000,   2.245,   2.520,
205          2.828,  3.175,  3.564,  4.000,  4.490,   5.040,   5.657,   6.350,   7.127,   8.000,   8.980,  10.079,  11.314,
206         12.699, 14.254, 16.000, 17.959, 20.159,  22.627,  25.398,  28.509,  32.000,  35.919,  40.317,  45.255,  50.797,
207         57.018, 64.000, 71.838, 80.635, 90.510, 101.594, 114.035, 128.000, 143.675, 161.270, 181.019, 203.187, 228.070,
208         256.000, 287.350, 322.540, 362.039, 406.375, 456.140, 512.000, 574.701, 645.080, 724.077, 812.749, 912.280,
209         1024.000, 1149.401, 1290.159, 1448.155, 1625.499, 1824.561, 2048.000, 2298.802, 2580.318, 2896.309, 3250.997, 3649.121,
210         4096.000, 4597.605, 5160.637, 5792.619, 6501.995, 7298.242, 8192.000, 9195.209, 10321.273, 11585.238, 13003.989, 14596.485
211     };
212 
213 
QStep2QpFloor(mfxF64 qstep,mfxI32 qpoffset=0)214 mfxI32 QStep2QpFloor(mfxF64 qstep, mfxI32 qpoffset = 0) // QSTEP[qp] <= qstep, return 0<=qp<=51+mQuantOffset
215 {
216     mfxU8 qp = mfxU8(std::upper_bound(QSTEP, QSTEP + 51 + qpoffset, qstep) - QSTEP);
217     return qp > 0 ? qp - 1 : 0;
218 }
219 
Qstep2QP(mfxF64 qstep,mfxI32 qpoffset=0)220 mfxI32 Qstep2QP(mfxF64 qstep, mfxI32 qpoffset = 0) // return 0<=qp<=51+mQuantOffset
221 {
222     mfxI32 qp = QStep2QpFloor(qstep, qpoffset);
223 
224     // prevent going QSTEP index out of bounds
225     if (qp >= (mfxI32)(sizeof(QSTEP)/sizeof(mfxF64)) - 1)
226         return 0;
227     return (qp == 51 + qpoffset || qstep < (QSTEP[qp] + QSTEP[qp + 1]) / 2) ? qp : qp + 1;
228 }
QP2Qstep(mfxI32 qp,mfxI32 qpoffset=0)229 mfxF64 QP2Qstep(mfxI32 qp, mfxI32 qpoffset = 0)
230 {
231     return QSTEP[std::min(51 + qpoffset, qp)];
232 }
233 
234 
GetBufferDiviation(mfxU32 targetBitrate)235 mfxF64  cHRD::GetBufferDiviation(mfxU32 targetBitrate)
236 {
237     mfxI64 targetFullness    = std::min(m_delayInBits, m_buffSizeInBits / 2);
238     mfxI64 minTargetFullness = std::min<mfxU32>(m_buffSizeInBits / 2, targetBitrate * 2); // half bufsize or 2 sec
239     targetFullness           = std::max(targetFullness, minTargetFullness);
240 
241     return targetFullness - m_bufFullness;
242 }
243 
UpdateAndCheckHRD(mfxI32 frameBits,mfxI32 recode,mfxI32 minQuant,mfxI32 maxQuant)244 mfxU16 cHRD::UpdateAndCheckHRD(mfxI32 frameBits, mfxI32 recode, mfxI32 minQuant, mfxI32 maxQuant)
245 {
246     mfxU16 brcStatus = MFX_BRC_OK ;
247 
248     if (recode  == 0)
249     {
250         m_prevBufFullness = m_bufFullness;
251         m_underflowQuant = minQuant - 1;
252         m_overflowQuant  = maxQuant + 1;
253     }
254     else
255     { // frame is being recoded - restore buffer state
256         m_bufFullness = m_prevBufFullness;
257         m_frameNum--;
258     }
259 
260     m_maxFrameSize = (mfxI32)(m_bufFullness - 1);
261     m_minFrameSize = (!m_bCBR)? 0 : (mfxI32)(m_bufFullness + 1 + 1 + m_inputBitsPerFrame - m_buffSizeInBits);
262     if (m_minFrameSize < 0)
263         m_minFrameSize = 0;
264 
265    mfxF64  bufFullness = m_bufFullness - frameBits;
266 
267     if (bufFullness < 2)
268     {
269         bufFullness = m_inputBitsPerFrame;
270         brcStatus = MFX_BRC_BIG_FRAME;
271         if (bufFullness > m_buffSizeInBits)
272             bufFullness = m_buffSizeInBits;
273     }
274     else
275     {
276         bufFullness += m_inputBitsPerFrame;
277         if (bufFullness > m_buffSizeInBits - 1)
278         {
279             bufFullness = m_buffSizeInBits - 1;
280             if (m_bCBR)
281                 brcStatus = MFX_BRC_SMALL_FRAME;
282         }
283     }
284     m_frameNum++;
285     if ( MFX_BRC_RECODE_PANIC == recode) // no use in changing QP
286     {
287         if (brcStatus == MFX_BRC_SMALL_FRAME)
288             brcStatus =  MFX_BRC_PANIC_SMALL_FRAME ;
289         if (brcStatus == MFX_BRC_BIG_FRAME)
290             brcStatus =  MFX_BRC_PANIC_BIG_FRAME ;    }
291 
292     m_bufFullness = bufFullness;
293     return brcStatus;
294 }
295 
UpdateMinMaxQPForRec(mfxU32 brcSts,mfxI32 qp)296 mfxStatus cHRD::UpdateMinMaxQPForRec( mfxU32 brcSts, mfxI32 qp)
297 {
298     MFX_CHECK(brcSts == MFX_BRC_BIG_FRAME || brcSts == MFX_BRC_SMALL_FRAME, MFX_ERR_UNDEFINED_BEHAVIOR);
299     if (brcSts == MFX_BRC_BIG_FRAME)
300         m_underflowQuant = qp;
301     else
302         m_overflowQuant = qp;
303     return MFX_ERR_NONE;
304 }
GetTargetSize(mfxU32 brcSts)305 mfxI32 cHRD::GetTargetSize(mfxU32 brcSts)
306 {
307      if (brcSts != MFX_BRC_BIG_FRAME && brcSts != MFX_BRC_SMALL_FRAME) return 0;
308      return (brcSts == MFX_BRC_BIG_FRAME) ? m_maxFrameSize * 3 / 4 : m_minFrameSize * 5 / 4;
309 }
310 
GetNewQP(mfxF64 totalFrameBits,mfxF64 targetFrameSizeInBits,mfxI32 minQP,mfxI32 maxQP,mfxI32 qp,mfxI32 qp_offset,mfxF64 f_pow,bool bStrict=false,bool bLim=true)311 mfxI32 GetNewQP(mfxF64 totalFrameBits, mfxF64 targetFrameSizeInBits, mfxI32 minQP , mfxI32 maxQP, mfxI32 qp , mfxI32 qp_offset, mfxF64 f_pow, bool bStrict = false, bool bLim = true)
312 {
313     mfxF64 qstep = 0, qstep_new = 0;
314     mfxI32 qp_new = qp;
315 
316     qstep = QP2Qstep(qp, qp_offset);
317     qstep_new = qstep * pow(totalFrameBits / targetFrameSizeInBits, f_pow);
318     qp_new = Qstep2QP(qstep_new, qp_offset);
319 
320     if (totalFrameBits < targetFrameSizeInBits) // overflow
321     {
322         if (qp <= minQP)
323         {
324             return qp; // QP change is impossible
325         }
326         if (bLim)
327             qp_new  = std::max(qp_new , (minQP + qp + 1) >> 1);
328         if (bStrict)
329             qp_new  = std::min(qp_new, qp - 1);
330     }
331     else // underflow
332     {
333         if (qp >= maxQP)
334         {
335             return qp; // QP change is impossible
336         }
337         if (bLim)
338             qp_new  = std::min(qp_new , (maxQP + qp + 1) >> 1);
339         if (bStrict)
340             qp_new  = std::max(qp_new, qp + 1);
341     }
342     return mfx::clamp(qp_new, minQP, maxQP);
343 }
344 
345 
346 
347 
Init(mfxU32 buffSizeInBytes,mfxU32 delayInBytes,mfxF64 inputBitsPerFrame,bool bCBR)348 void cHRD::Init(mfxU32 buffSizeInBytes, mfxU32 delayInBytes, mfxF64 inputBitsPerFrame, bool bCBR)
349 {
350     m_bufFullness = m_prevBufFullness= delayInBytes << 3;
351     m_delayInBits = delayInBytes << 3;
352     m_buffSizeInBits = buffSizeInBytes << 3;
353     m_inputBitsPerFrame =inputBitsPerFrame;
354     m_bCBR = bCBR;
355 
356     m_underflowQuant = 0;
357     m_overflowQuant = 999;
358     m_frameNum = 0;
359     m_minFrameSize = 0;
360     m_maxFrameSize = 0;
361 
362 }
363 
UpdateQPParams(mfxI32 qp,mfxU32 type,BRC_Ctx & ctx,mfxU32,mfxI32 minQuant,mfxI32 maxQuant,mfxU32 level)364 void UpdateQPParams(mfxI32 qp, mfxU32 type , BRC_Ctx  &ctx, mfxU32 /* rec_num */, mfxI32 minQuant, mfxI32 maxQuant, mfxU32 level)
365 {
366     ctx.Quant = qp;
367     if (type == MFX_FRAMETYPE_I)
368     {
369         ctx.QuantI = qp;
370         ctx.QuantP = qp + 1;
371         ctx.QuantB = qp + 2;
372     }
373     else if (type == MFX_FRAMETYPE_P)
374     {
375         qp -= level;
376         ctx.QuantI =  qp - 1;
377         ctx.QuantP = qp;
378         ctx.QuantB = qp + 1;
379     }
380     else if (type == MFX_FRAMETYPE_B)
381     {
382         level = level > 0 ? level - 1: 0;
383         qp -= level;
384         ctx.QuantI = qp - 2;
385         ctx.QuantP = qp - 1;
386         ctx.QuantB = qp;
387     }
388     ctx.QuantI = mfx::clamp(ctx.QuantI, minQuant, maxQuant);
389     ctx.QuantP = mfx::clamp(ctx.QuantP, minQuant, maxQuant);
390     ctx.QuantB = mfx::clamp(ctx.QuantB, minQuant, maxQuant);
391     //printf("ctx.QuantI %d, ctx.QuantP %d, ctx.QuantB  %d, level %d\n", ctx.QuantI, ctx.QuantP, ctx.QuantB, level);
392 }
393 
GetRawFrameSize(mfxU32 lumaSize,mfxU16 chromaFormat,mfxU16 bitDepthLuma)394 mfxI32 GetRawFrameSize(mfxU32 lumaSize, mfxU16 chromaFormat, mfxU16 bitDepthLuma)
395 {
396     mfxI32 frameSize = lumaSize;
397 
398   if (chromaFormat == MFX_CHROMAFORMAT_YUV420)
399     frameSize += lumaSize / 2;
400   else if (chromaFormat == MFX_CHROMAFORMAT_YUV422)
401    frameSize += lumaSize;
402   else if (chromaFormat == MFX_CHROMAFORMAT_YUV444)
403     frameSize += lumaSize * 2;
404 
405   frameSize = frameSize * bitDepthLuma / 8;
406   return frameSize*8; //frame size in bits
407 }
408 
Init(mfxVideoParam * par)409 mfxStatus ExtBRC::Init (mfxVideoParam* par)
410 {
411     mfxStatus sts = MFX_ERR_NONE;
412 
413     MFX_CHECK(!m_bInit, MFX_ERR_UNDEFINED_BEHAVIOR);
414     sts = m_par.Init(par);
415     MFX_CHECK_STS(sts);
416 
417     if (m_par.HRDConformance != MFX_BRC_NO_HRD)
418     {
419         m_hrd.Init(m_par.bufferSizeInBytes, m_par.initialDelayInBytes, m_par.maxInputBitsPerFrame, m_par.rateControlMethod == MFX_RATECONTROL_CBR);
420     }
421     memset(&m_ctx, 0, sizeof(m_ctx));
422 
423     m_ctx.fAbLong  = m_par.inputBitsPerFrame;
424     m_ctx.fAbShort = m_par.inputBitsPerFrame;
425     m_ctx.encOrder = mfxU32(-1);
426 
427     mfxI32 rawSize = GetRawFrameSize(m_par.width * m_par.height ,m_par.chromaFormat, m_par.bitDepthLuma);
428     mfxI32 qp = GetNewQP(rawSize, m_par.inputBitsPerFrame, m_par.quantMinI, m_par.quantMaxI, 1 , m_par.quantOffset, 0.5, false, false);
429 
430     UpdateQPParams(qp,MFX_FRAMETYPE_I , m_ctx, 0, m_par.quantMinI, m_par.quantMaxI, 0);
431 
432     m_ctx.dQuantAb = qp > 0 ? 1./qp : 1.0; //kw
433 
434     if (m_par.WinBRCSize)
435     {
436         m_avg.reset(new AVGBitrate(m_par.WinBRCSize, (mfxU32)(m_par.WinBRCMaxAvgKbps*1000.0/m_par.frameRate), (mfxU32)m_par.inputBitsPerFrame) );
437         MFX_CHECK_NULL_PTR1(m_avg.get());
438     }
439 
440     m_bInit = true;
441     return sts;
442 }
443 
GetFrameType(mfxU16 m_frameType,mfxU16 level,mfxU16 gopRegDist)444 mfxU16 GetFrameType(mfxU16 m_frameType, mfxU16 level, mfxU16 gopRegDist)
445 {
446     if (m_frameType & MFX_FRAMETYPE_IDR)
447         return MFX_FRAMETYPE_I;
448     else if (m_frameType & MFX_FRAMETYPE_I)
449         return MFX_FRAMETYPE_I;
450     else if (m_frameType & MFX_FRAMETYPE_P)
451         return MFX_FRAMETYPE_P;
452     else if ((m_frameType & MFX_FRAMETYPE_REF) && (level == 0 || gopRegDist == 1))
453         return MFX_FRAMETYPE_P; //low delay B
454     else
455         return MFX_FRAMETYPE_B;
456 }
457 
458 
isFrameBeforeIntra(mfxU32 order,mfxU32 intraOrder,mfxU32 gopPicSize,mfxU32 gopRefDist)459 bool  isFrameBeforeIntra (mfxU32 order, mfxU32 intraOrder, mfxU32 gopPicSize, mfxU32 gopRefDist)
460 {
461     mfxI32 distance0 = gopPicSize*3/4;
462     mfxI32 distance1 = gopPicSize - gopRefDist*3;
463     return mfxI32(order - intraOrder) > std::max(distance0, distance1);
464 }
465 
SetRecodeParams(mfxU16 brcStatus,mfxI32 qp,mfxI32 qp_new,mfxI32 minQP,mfxI32 maxQP,BRC_Ctx & ctx,mfxBRCFrameStatus * status)466 mfxStatus SetRecodeParams(mfxU16 brcStatus, mfxI32 qp, mfxI32 qp_new, mfxI32 minQP, mfxI32 maxQP, BRC_Ctx &ctx, mfxBRCFrameStatus* status)
467 {
468     ctx.bToRecode = 1;
469 
470     if (brcStatus == MFX_BRC_BIG_FRAME || brcStatus == MFX_BRC_PANIC_BIG_FRAME )
471     {
472          MFX_CHECK(qp_new >= qp, MFX_ERR_UNDEFINED_BEHAVIOR);
473          ctx.Quant = qp_new;
474          ctx.QuantMax = maxQP;
475          if (brcStatus == MFX_BRC_BIG_FRAME && qp_new > qp)
476          {
477             ctx.QuantMin = std::max(qp + 1, minQP); //limit QP range for recoding
478             status->BRCStatus = MFX_BRC_BIG_FRAME;
479 
480          }
481          else
482          {
483              ctx.QuantMin = minQP;
484              ctx.bPanic = 1;
485              status->BRCStatus = MFX_BRC_PANIC_BIG_FRAME;
486          }
487     }
488     else if (brcStatus == MFX_BRC_SMALL_FRAME || brcStatus == MFX_BRC_PANIC_SMALL_FRAME)
489     {
490          MFX_CHECK(qp_new <= qp, MFX_ERR_UNDEFINED_BEHAVIOR);
491 
492          ctx.Quant = qp_new;
493          ctx.QuantMin = minQP; //limit QP range for recoding
494 
495          if (brcStatus == MFX_BRC_SMALL_FRAME && qp_new < qp)
496          {
497             ctx.QuantMax = std::min(qp - 1, maxQP);
498             status->BRCStatus = MFX_BRC_SMALL_FRAME;
499          }
500          else
501          {
502             ctx.QuantMax = maxQP;
503             status->BRCStatus = MFX_BRC_PANIC_SMALL_FRAME;
504             ctx.bPanic = 1;
505          }
506     }
507     //printf("recode %d , qp %d new %d, status %d\n", ctx.encOrder, qp, qp_new, status->BRCStatus);
508     return MFX_ERR_NONE;
509 }
GetNewQPTotal(mfxF64 bo,mfxF64 dQP,mfxI32 minQP,mfxI32 maxQP,mfxI32 qp,bool bPyr,bool bSC)510 mfxI32 GetNewQPTotal(mfxF64 bo, mfxF64 dQP, mfxI32 minQP , mfxI32 maxQP, mfxI32 qp, bool bPyr, bool bSC)
511 {
512     mfxU8 mode = (!bPyr) ;
513 
514     bo  = mfx::clamp(bo, -1.0, 1.0);
515     dQP = mfx::clamp(dQP, 1./maxQP, 1./minQP);
516     dQP = dQP + (1./maxQP - dQP) * bo;
517     dQP = mfx::clamp(dQP, 1./maxQP, 1./minQP);
518     mfxI32 quant_new = (mfxI32) (1. / dQP + 0.5);
519 
520     //printf("   GetNewQPTotal: bo %f, quant %d, quant_new %d, mode %d\n", bo, qp, quant_new, mode);
521     if (!bSC)
522     {
523         if (mode == 0) // low: qp_diff [-2; 2]
524         {
525             if (quant_new >= qp + 5)
526                 quant_new = qp + 2;
527             else if (quant_new > qp + 3)
528                 quant_new = qp + 1;
529             else if (quant_new <= qp - 5)
530                 quant_new = qp - 2;
531             else if (quant_new < qp - 2)
532                 quant_new = qp - 1;
533         }
534         else // (mode == 1) midle: qp_diff [-3; 3]
535         {
536             if (quant_new >= qp + 5)
537                 quant_new = qp + 3;
538             else if (quant_new > qp + 3)
539                 quant_new = qp + 2;
540             else if (quant_new <= qp - 5)
541                 quant_new = qp - 3;
542             else if (quant_new < qp - 2)
543                 quant_new = qp - 2;
544         }
545 
546     }
547     else
548     {
549         quant_new = mfx::clamp(quant_new, qp - 5, qp + 5);
550     }
551     return mfx::clamp(quant_new, minQP, maxQP);
552 }
553 // 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)554 mfxF64 GetAbPeriodCoeff (mfxU32 numInGop, mfxU32 gopPicSize)
555 {
556     const mfxU32 maxForCorrection = 30;
557     const mfxF64 maxValue = 1.5;
558     const mfxF64 minValue = 1.0;
559 
560     mfxU32 numForCorrection = std::min(gopPicSize /2, maxForCorrection);
561     mfxF64 k[maxForCorrection] = {};
562 
563     if (numInGop >= gopPicSize || gopPicSize < 2)
564         return 1.0;
565 
566     for (mfxU32 i = 0; i < numForCorrection; i ++)
567     {
568         k[i] = maxValue - (maxValue - minValue)*i/numForCorrection;
569     }
570     if (numInGop < gopPicSize/2)
571     {
572         return k [numInGop < numForCorrection ? numInGop : numForCorrection - 1];
573     }
574     else
575     {
576         mfxU32 n = gopPicSize - 1 - numInGop;
577         return 1.0/ k[n < numForCorrection ? n : numForCorrection - 1];
578     }
579 
580 }
581 
GetCurQP(mfxU32 type,mfxI32 layer)582 mfxI32 ExtBRC::GetCurQP (mfxU32 type, mfxI32 layer)
583 {
584     mfxI32 qp = 0;
585     if (type == MFX_FRAMETYPE_I)
586     {
587         qp = m_ctx.QuantI;
588         qp = mfx::clamp(qp, m_par.quantMinI, m_par.quantMaxI);
589     }
590     else if (type == MFX_FRAMETYPE_P)
591     {
592         qp = m_ctx.QuantP + layer;
593         qp = mfx::clamp(qp, m_par.quantMinP, m_par.quantMaxP);
594     }
595     else
596     {
597         qp = m_ctx.QuantB + (layer > 0 ? layer - 1 : 0);
598         qp = mfx::clamp(qp, m_par.quantMinB, m_par.quantMaxB);
599     }
600     //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);
601 
602     return qp;
603 }
604 
Update(mfxBRCFrameParam * frame_par,mfxBRCFrameCtrl * frame_ctrl,mfxBRCFrameStatus * status)605 mfxStatus ExtBRC::Update(mfxBRCFrameParam* frame_par, mfxBRCFrameCtrl* frame_ctrl, mfxBRCFrameStatus* status)
606 {
607     mfxStatus sts       = MFX_ERR_NONE;
608 
609     MFX_CHECK_NULL_PTR3(frame_par, frame_ctrl, status);
610     MFX_CHECK(m_bInit, MFX_ERR_NOT_INITIALIZED);
611 
612     mfxU16 &brcSts       = status->BRCStatus;
613     status->MinFrameSize  = 0;
614 
615     //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);
616 
617     mfxI32 bitsEncoded  = frame_par->CodedFrameSize*8;
618     mfxU32 picType      = GetFrameType(frame_par->FrameType, frame_par->PyramidLayer, m_par.gopRefDist);
619     mfxI32 qpY          = frame_ctrl->QpY + m_par.quantOffset;
620     mfxI32 layer        = frame_par->PyramidLayer;
621     mfxF64 qstep        = QP2Qstep(qpY, m_par.quantOffset);
622 
623     mfxF64 fAbLong  = m_ctx.fAbLong   + (bitsEncoded - m_ctx.fAbLong)  / m_par.fAbPeriodLong;
624     mfxF64 fAbShort = m_ctx.fAbShort  + (bitsEncoded - m_ctx.fAbShort) / m_par.fAbPeriodShort;
625     mfxF64 eRate    = bitsEncoded * sqrt(qstep);
626     mfxF64 e2pe     =  0;
627     bool bMaxFrameSizeMode = m_par.maxFrameSizeInBits != 0 &&
628         m_par.rateControlMethod == MFX_RATECONTROL_VBR &&
629         m_par.maxFrameSizeInBits < m_par.inputBitsPerFrame * 2 &&
630         m_ctx.totalDiviation < (-1)*m_par.inputBitsPerFrame*m_par.frameRate;
631 
632     if (picType == MFX_FRAMETYPE_I)
633         e2pe = (m_ctx.eRateSH == 0) ? (BRC_SCENE_CHANGE_RATIO2 + 1) : eRate / m_ctx.eRateSH;
634     else
635         e2pe = (m_ctx.eRate == 0) ? (BRC_SCENE_CHANGE_RATIO2 + 1) : eRate / m_ctx.eRate;
636 
637     mfxU32 frameSizeLim    = 0xfffffff ; // sliding window limitation or external frame size limitation
638 
639     bool  bSHStart = false;
640     bool  bNeedUpdateQP = false;
641 
642     brcSts = MFX_BRC_OK;
643 
644     if (m_par.bRec && m_ctx.bToRecode &&  (m_ctx.encOrder != frame_par->EncodedOrder || frame_par->NumRecode == 0))
645     {
646         //printf("++++++++++++++++++++++++++++++++++\n");
647         // Frame must be recoded, but encoder calls BR for another frame
648         return MFX_ERR_UNDEFINED_BEHAVIOR;
649     }
650     if (frame_par->NumRecode == 0 || m_ctx.encOrder != frame_par->EncodedOrder)
651     {
652         // Set context for new frame
653         if (picType == MFX_FRAMETYPE_I)
654             m_ctx.LastIEncOrder = frame_par->EncodedOrder;
655         m_ctx.encOrder = frame_par->EncodedOrder;
656         m_ctx.poc = frame_par->DisplayOrder;
657         m_ctx.bToRecode = 0;
658         m_ctx.bPanic = 0;
659 
660         if (picType == MFX_FRAMETYPE_I)
661         {
662             m_ctx.QuantMin = m_par.quantMinI;
663             m_ctx.QuantMax = m_par.quantMaxI;
664         }
665         else if (picType == MFX_FRAMETYPE_P)
666         {
667             m_ctx.QuantMin = m_par.quantMinP;
668             m_ctx.QuantMax = m_par.quantMaxP;
669         }
670         else
671         {
672             m_ctx.QuantMin = m_par.quantMinB;
673             m_ctx.QuantMax = m_par.quantMaxB;
674         }
675         m_ctx.Quant = qpY;
676 
677 
678         if (m_ctx.SceneChange && ( m_ctx.poc > m_ctx.SChPoc + 1 || m_ctx.poc == 0))
679             m_ctx.SceneChange &= ~16;
680 
681         bNeedUpdateQP = true;
682 
683         //printf("m_ctx.SceneChange %d, m_ctx.poc %d, m_ctx.SChPoc %d, m_ctx.poc %d \n", m_ctx.SceneChange, m_ctx.poc, m_ctx.SChPoc, m_ctx.poc);
684     }
685     if (e2pe > BRC_SCENE_CHANGE_RATIO2 )
686     {
687       // scene change, resetting BRC statistics
688         fAbLong  = m_ctx.fAbLong  = m_par.inputBitsPerFrame;
689         fAbShort = m_ctx.fAbShort = m_par.inputBitsPerFrame;
690         m_ctx.SceneChange |= 1;
691         if (picType != MFX_FRAMETYPE_B)
692         {
693             bSHStart = true;
694             m_ctx.SceneChange |= 16;
695             m_ctx.eRateSH = eRate;
696             //if ((frame_par->DisplayOrder - m_ctx.SChPoc) >= std::min<mfxU32>(m_par.frameRate, m_par.gopRefDist))
697             {
698                 m_ctx.dQuantAb  = 1./m_ctx.Quant;
699             }
700             m_ctx.SChPoc = frame_par->DisplayOrder;
701             //printf("!!!!!!!!!!!!!!!!!!!!! %d m_ctx.SceneChange %d, order %d\n", frame_par->EncodedOrder, m_ctx.SceneChange, frame_par->DisplayOrder);
702         }
703 
704     }
705     if (m_par.HRDConformance != MFX_BRC_NO_HRD)
706     {
707         //check hrd
708         brcSts = m_hrd.UpdateAndCheckHRD(bitsEncoded,frame_par->NumRecode, m_ctx.QuantMin,m_ctx.QuantMax);
709         //printf("--UpdateAndCheckHRD (%d) brcSts %d, panic %d\n", frame_par->EncodedOrder,brcSts, m_ctx.bPanic);
710         MFX_CHECK(brcSts ==  MFX_BRC_OK || (!m_ctx.bPanic), MFX_ERR_NOT_ENOUGH_BUFFER);
711         if (brcSts == MFX_BRC_BIG_FRAME || brcSts == MFX_BRC_SMALL_FRAME)
712             m_hrd.UpdateMinMaxQPForRec(brcSts, qpY);
713         else
714             bNeedUpdateQP = true;
715         status->MinFrameSize = m_hrd.GetMinFrameSize();
716         //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);
717     }
718     if (m_avg.get())
719     {
720        frameSizeLim = std::min(frameSizeLim, m_avg->GetMaxFrameSize(m_ctx.bPanic, bSHStart || picType == MFX_FRAMETYPE_I, frame_par->NumRecode));
721     }
722     if (m_par.maxFrameSizeInBits)
723     {
724         frameSizeLim = std::min(frameSizeLim, m_par.maxFrameSizeInBits);
725     }
726     //printf("frameSizeLim %d (%d)\n", frameSizeLim, bitsEncoded);
727 
728     if (frame_par->NumRecode < 2)
729     // Check other condions for recoding (update qp is it is needed)
730     {
731         mfxF64 targetFrameSize = std::max<mfxF64>(m_par.inputBitsPerFrame, fAbLong);
732         mfxF64 maxFrameSize = (m_ctx.encOrder == 0 ? 6.0 : (bSHStart || picType == MFX_FRAMETYPE_I) ? 8.0 : 4.0) * targetFrameSize*(m_par.bPyr ? 1.5 : 1.0) ;
733         mfxI32 quantMax = m_ctx.QuantMax;
734         mfxI32 quantMin = m_ctx.QuantMin;
735         mfxI32 quant = qpY;
736 
737         maxFrameSize = std::min<mfxF64>(maxFrameSize, frameSizeLim);
738 
739         if (m_par.HRDConformance != MFX_BRC_NO_HRD)
740         {
741             if (bSHStart || picType == MFX_FRAMETYPE_I)
742                 maxFrameSize = std::min(maxFrameSize, 3.5/9. * m_hrd.GetMaxFrameSize() + 5.5/9. * targetFrameSize);
743             else
744                 maxFrameSize = std::min(maxFrameSize, 2.5/9. * m_hrd.GetMaxFrameSize() + 6.5/9. * targetFrameSize);
745 
746             quantMax = std::min(m_hrd.GetMaxQuant(), quantMax);
747             quantMin = std::max(m_hrd.GetMinQuant(), quantMin);
748         }
749         maxFrameSize = std::max(maxFrameSize, targetFrameSize);
750 
751         if (bitsEncoded >  maxFrameSize && quant < quantMax)
752         {
753 
754             mfxI32 quant_new = GetNewQP(bitsEncoded, (mfxU32)maxFrameSize, quantMin , quantMax, quant ,m_par.quantOffset, 1);
755             if (quant_new > quant )
756             {
757                 bNeedUpdateQP = false;
758                 //printf("    recode 1-0: %d:  k %5f bitsEncoded %d maxFrameSize %d, targetSize %d, fAbLong %f, inputBitsPerFrame %f, qp %d new %d\n",frame_par->EncodedOrder, bitsEncoded/maxFrameSize, (int)bitsEncoded, (int)maxFrameSize,(int)targetFrameSize, fAbLong, m_par.inputBitsPerFrame, quant, quant_new);
759                 if (quant_new > GetCurQP (picType, layer))
760                 {
761                     UpdateQPParams(bMaxFrameSizeMode? quant_new - 1 : quant_new ,picType, m_ctx, 0, quantMin , quantMax, layer);
762                     fAbLong  =  m_ctx.fAbLong  = m_par.inputBitsPerFrame;
763                     fAbShort =  m_ctx.fAbShort = m_par.inputBitsPerFrame;
764                     m_ctx.dQuantAb = 1./quant_new;
765                 }
766 
767                 if (m_par.bRec)
768                 {
769                     SetRecodeParams(MFX_BRC_BIG_FRAME,quant,quant_new, quantMin, quantMax, m_ctx, status);
770                     return sts;
771                 }
772             } //(quant_new > quant)
773         } //bitsEncoded >  maxFrameSize
774 
775         if (bitsEncoded >  maxFrameSize && quant == quantMax &&
776             picType != MFX_FRAMETYPE_I && m_par.bPanic &&
777             (!m_ctx.bPanic) && isFrameBeforeIntra(m_ctx.encOrder, m_ctx.LastIEncOrder, m_par.gopPicSize, m_par.gopRefDist))
778         {
779             //skip frames before intra
780             SetRecodeParams(MFX_BRC_PANIC_BIG_FRAME,quant,quant, quantMin ,quantMax, m_ctx, status);
781             return sts;
782         }
783         if (m_par.HRDConformance != MFX_BRC_NO_HRD && frame_par->NumRecode == 0 && (quant < quantMax))
784         {
785             mfxF64 FAMax = 1./9. * m_hrd.GetMaxFrameSize() + 8./9. * fAbLong;
786 
787             if (fAbShort > FAMax)
788             {
789                 mfxI32 quant_new = GetNewQP(fAbShort, FAMax, quantMin , quantMax, quant ,m_par.quantOffset, 0.5);
790                 //printf("    recode 2-0: %d:  FAMax %f, fAbShort %f, quant_new %d\n",frame_par->EncodedOrder, FAMax, fAbShort, quant_new);
791 
792                 if (quant_new > quant)
793                 {
794                    bNeedUpdateQP = false;
795                    if (quant_new > GetCurQP (picType, layer))
796                    {
797                         UpdateQPParams(quant_new ,picType, m_ctx, 0, quantMin , quantMax, layer);
798                         fAbLong  = m_ctx.fAbLong  = m_par.inputBitsPerFrame;
799                         fAbShort = m_ctx.fAbShort = m_par.inputBitsPerFrame;
800                         m_ctx.dQuantAb = 1./quant_new;
801                     }
802                     if (m_par.bRec)
803                     {
804                         SetRecodeParams(MFX_BRC_BIG_FRAME,quant,quant_new, quantMin, quantMax, m_ctx, status);
805                         return sts;
806                     }
807                 }//quant_new > quant
808             }
809         }//m_par.HRDConformance
810     }
811     if (((m_par.HRDConformance != MFX_BRC_NO_HRD && brcSts != MFX_BRC_OK) || (bitsEncoded > (mfxI32)frameSizeLim)) && m_par.bRec)
812     {
813         mfxI32 quant = m_ctx.Quant;
814         mfxI32 quant_new = quant;
815         if (bitsEncoded > (mfxI32)frameSizeLim)
816         {
817             brcSts = MFX_BRC_BIG_FRAME;
818             quant_new = GetNewQP(bitsEncoded, frameSizeLim, m_ctx.QuantMin , m_ctx.QuantMax,quant,m_par.quantOffset, 1, true);
819         }
820         else if (brcSts == MFX_BRC_BIG_FRAME || brcSts == MFX_BRC_SMALL_FRAME)
821         {
822             quant_new = GetNewQP(bitsEncoded, m_hrd.GetTargetSize(brcSts), m_ctx.QuantMin , m_ctx.QuantMax,quant,m_par.quantOffset, 1, true);
823         }
824         if (quant_new != quant)
825         {
826             if (brcSts == MFX_BRC_SMALL_FRAME)
827             {
828                quant_new = std::max(quant_new, quant-2);
829                brcSts = MFX_BRC_PANIC_SMALL_FRAME;
830             }
831             // Idea is to check a sign mismatch, 'true' if both are negative or positive
832             if ((quant_new - qpY) * (quant_new - GetCurQP (picType, layer)) > 0)
833             {
834                 UpdateQPParams(quant_new ,picType, m_ctx, 0, m_ctx.QuantMin , m_ctx.QuantMax, layer);
835             }
836             bNeedUpdateQP = false;
837         }
838         SetRecodeParams(brcSts,quant,quant_new, m_ctx.QuantMin , m_ctx.QuantMax, m_ctx, status);
839     }
840     else
841     {
842         // no recoding are needed. Save context params
843 
844         mfxF64 k = 1./m_ctx.Quant;
845         mfxF64 dqAbPeriod = m_par.dqAbPeriod;
846         if (m_ctx.bToRecode)
847             dqAbPeriod = (k < m_ctx.dQuantAb)? 16:25;
848 
849         if (bNeedUpdateQP)
850         {
851             m_ctx.dQuantAb += (k - m_ctx.dQuantAb)/dqAbPeriod;
852             m_ctx.dQuantAb = mfx::clamp(m_ctx.dQuantAb, 1./m_ctx.QuantMax , 1./m_ctx.QuantMin);
853 
854             m_ctx.fAbLong  = fAbLong;
855             m_ctx.fAbShort = fAbShort;
856         }
857 
858         bool oldScene = false;
859         if ((m_ctx.SceneChange & 16) && (m_ctx.poc < m_ctx.SChPoc) && (e2pe < .01) && (mfxF64)bitsEncoded < 1.5*fAbLong)
860             oldScene = true;
861         //printf("-- m_ctx.eRate %f,  eRate %f, e2pe %f\n", m_ctx.eRate,  eRate, e2pe );
862 
863         if (picType != MFX_FRAMETYPE_B)
864         {
865             m_ctx.LastNonBFrameSize = bitsEncoded;
866             if (picType == MFX_FRAMETYPE_I)
867                 m_ctx.eRateSH = eRate;
868             else
869                 m_ctx.eRate = eRate;
870 
871         }
872 
873         if (m_avg.get())
874         {
875             m_avg->UpdateSlidingWindow(bitsEncoded, m_ctx.encOrder, m_ctx.bPanic, bSHStart || picType == MFX_FRAMETYPE_I,frame_par->NumRecode);
876         }
877 
878         m_ctx.totalDiviation += ((mfxF64)bitsEncoded - m_par.inputBitsPerFrame);
879 
880         //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.totalDiviation, oldScene , bNeedUpdateQP, m_ctx.Quant,picType);
881 
882         if (!m_ctx.bPanic&& (!oldScene) && bNeedUpdateQP)
883         {
884             mfxI32 quant_new = m_ctx.Quant;
885             //Update QP
886 
887             mfxF64 totDiv = m_ctx.totalDiviation;
888             mfxF64 dequant_new = m_ctx.dQuantAb*pow(m_par.inputBitsPerFrame/m_ctx.fAbLong, 1.2);
889             mfxF64 bAbPreriod = m_par.bAbPeriod;
890 
891             if (m_par.HRDConformance != MFX_BRC_NO_HRD && totDiv > 0 )
892             {
893                 if (m_par.rateControlMethod == MFX_RATECONTROL_VBR)
894                 {
895                     totDiv = std::max(totDiv, m_hrd.GetBufferDiviation(m_par.targetbps));
896                 }
897                 bAbPreriod = (mfxF64)(m_par.bPyr? 4 : 3)*(mfxF64)m_hrd.GetMaxFrameSize() / m_par.inputBitsPerFrame*GetAbPeriodCoeff(m_ctx.encOrder - m_ctx.LastIEncOrder, m_par.gopPicSize) ;
898                 bAbPreriod = mfx::clamp(bAbPreriod , m_par.bAbPeriod/10, m_par.bAbPeriod);
899             }
900             quant_new = GetNewQPTotal(totDiv / bAbPreriod / (mfxF64)m_par.inputBitsPerFrame, dequant_new, m_ctx.QuantMin, m_ctx.QuantMax, m_ctx.Quant, m_par.bPyr && m_par.bRec, bSHStart && m_ctx.bToRecode == 0);
901             //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);
902 
903             if (bMaxFrameSizeMode)
904             {
905                 mfxF64 targetMax = ((mfxF64)m_par.maxFrameSizeInBits*((bSHStart || picType == MFX_FRAMETYPE_I) ? 0.95 : 0.9));
906                 mfxF64 targetMin = ((mfxF64)m_par.maxFrameSizeInBits*((bSHStart || picType == MFX_FRAMETYPE_I) ? 0.9  : 0.8 /*0.75 : 0.5*/));
907                 mfxI32 QuantNewMin = GetNewQP(bitsEncoded, targetMax, m_ctx.QuantMin, m_ctx.QuantMax, m_ctx.Quant, m_par.quantOffset, 1,false, false);
908                 mfxI32 QuantNewMax = GetNewQP(bitsEncoded, targetMin, m_ctx.QuantMin, m_ctx.QuantMax, m_ctx.Quant, m_par.quantOffset, 1,false, false);
909                 mfxI32 quant_corrected = m_ctx.Quant;
910 
911                 if (quant_corrected < QuantNewMin - 3)
912                     quant_corrected += 2;
913                 if (quant_corrected < QuantNewMin)
914                     quant_corrected ++;
915                 else if (quant_corrected > QuantNewMax + 3)
916                     quant_corrected -= 2;
917                 else if (quant_corrected > QuantNewMax)
918                     quant_corrected--;
919 
920                 //printf("   QuantNewMin %d, QuantNewMax %d, m_ctx.Quant %d, new %d (%d)\n", QuantNewMin, QuantNewMax, m_ctx.Quant, quant_corrected, quant_new);
921 
922                 quant_new = mfx::clamp(quant_corrected, m_ctx.QuantMin, m_ctx.QuantMax);
923             }
924             if ((quant_new - m_ctx.Quant)* (quant_new - GetCurQP (picType, layer)) > 0) // this check is actual for async scheme
925             {
926                 //printf("   Update QP %d: totalDiviation %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, totDiv, 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);
927                 UpdateQPParams(quant_new ,picType, m_ctx, 0, m_ctx.QuantMin , m_ctx.QuantMax, layer);
928             }
929         }
930         m_ctx.bToRecode = 0;
931     }
932     return sts;
933 
934 }
935 
GetFrameCtrl(mfxBRCFrameParam * par,mfxBRCFrameCtrl * ctrl)936 mfxStatus ExtBRC::GetFrameCtrl (mfxBRCFrameParam* par, mfxBRCFrameCtrl* ctrl)
937 {
938     MFX_CHECK_NULL_PTR2(par, ctrl);
939     MFX_CHECK(m_bInit, MFX_ERR_NOT_INITIALIZED);
940 
941     mfxI32 qp = 0;
942     if (par->EncodedOrder == m_ctx.encOrder)
943     {
944         qp = m_ctx.Quant;
945     }
946     else
947     {
948         mfxU16 type = GetFrameType(par->FrameType,par->PyramidLayer, m_par.gopRefDist);
949         qp = GetCurQP (type, par->PyramidLayer);
950     }
951     ctrl->QpY = qp - m_par.quantOffset;
952     //printf("ctrl->QpY %d, qp %d quantOffset %d\n", ctrl->QpY , qp , m_par.quantOffset);
953     return MFX_ERR_NONE;
954 }
955 
Reset(mfxVideoParam * par)956 mfxStatus ExtBRC::Reset(mfxVideoParam *par )
957 {
958     mfxStatus sts = MFX_ERR_NONE;
959     MFX_CHECK_NULL_PTR1(par);
960     MFX_CHECK(m_bInit, MFX_ERR_NOT_INITIALIZED);
961 
962     mfxExtEncoderResetOption  * pRO = (mfxExtEncoderResetOption *)Hevc_GetExtBuffer(par->ExtParam, par->NumExtParam, MFX_EXTBUFF_ENCODER_RESET_OPTION);
963     if (pRO && pRO->StartNewSequence == MFX_CODINGOPTION_ON)
964     {
965         Close();
966         sts = Init(par);
967     }
968     else
969     {
970         bool brcReset = false;
971         bool slidingWindowReset = false;
972 
973         sts = m_par.GetBRCResetType(par, false, brcReset, slidingWindowReset);
974         MFX_CHECK_STS(sts);
975 
976         if (brcReset)
977         {
978             sts = m_par.Init(par);
979             MFX_CHECK_STS(sts);
980 
981             m_ctx.Quant = (mfxI32)(1. / m_ctx.dQuantAb * pow(m_ctx.fAbLong / m_par.inputBitsPerFrame, 0.32) + 0.5);
982             m_ctx.Quant = mfx::clamp(m_ctx.Quant, m_par.quantMinI, m_par.quantMaxI);
983 
984             UpdateQPParams(m_ctx.Quant, MFX_FRAMETYPE_I, m_ctx, 0, m_par.quantMinI, m_par.quantMaxI, 0);
985 
986             m_ctx.dQuantAb = 1. / m_ctx.Quant;
987             m_ctx.fAbLong = m_par.inputBitsPerFrame;
988             m_ctx.fAbShort = m_par.inputBitsPerFrame;
989 
990             if (slidingWindowReset)
991             {
992                 m_avg.reset(new AVGBitrate(m_par.WinBRCSize, (mfxU32)(m_par.WinBRCMaxAvgKbps*1000.0 / m_par.frameRate), (mfxU32)m_par.inputBitsPerFrame));
993                 MFX_CHECK_NULL_PTR1(m_avg.get());
994             }
995         }
996     }
997     return sts;
998 }
999 
1000 #endif
1001