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