Log in

View Full Version : Buffer in x265 and vbv settings


hellgauss
17th May 2026, 10:33
I have some questions about handling vbv in x265. The goal is to split the source video in mutliple GOPs, e.g. with the help of a preliminary test encoding or with a scenecut tool, and then encode them in parallel or without re-encoding the whole video in the case of crashes. Eventually, re-encode some GOPs if vbv shows an underflow. Of course vbv must be OK in the whole video and not only in each GOP.

My idea of the vbv is a pool of #maxsize with an input of #maxrate in which a decoder drains water according to the decoding-timestamp of each frame. As an extra rule, if the buffer fullness is >(#init x #maxsize) at the beginning of a GOP, assume it to be (#init x #maxsize) instead. During playback, the buffer should never be <=0.

1) In this (wrong?) framework, what is the meaning of max and min vbv-fullness? The doc says that they are experimental options, however they default to 80% and 50% instead of 100% and 0% , so they have some meaning.

2) Can a hevc GOP start with a B frame? It should be a "only forward" B frame, ore somewhat a "reversed" P, but in theory there can be up to 16 B before the keyframe. What about x265?

3) Does extra info data (e.g. PPS, VPS, SPS, prefix/suffix SEI) have to be counted in the vbv?

4) Is there any free tool for a-posteriori vbv check of a hevc stream?

Thank you!
HG

rwill
17th May 2026, 11:47
My idea of the vbv is a pool of #maxsize with an input of #maxrate in which a decoder drains water according to the decoding-timestamp of each frame. As an extra rule, if the buffer fullness is >(#init x #maxsize) at the beginning of a GOP, assume it to be (#init x #maxsize) instead. During playback, the buffer should never be <=0.


You seem to mix decoder and encoder sides of the buffer model. I suggest to only look at it from the encoder perspective as it is a bit simpler to understand. For example from the decoder side view the input of #maxrate can only happen if the respective picture has already been encoded at the encoder side, which is only the case if its timestamp is within the video buffer window etc....


1) In this (wrong?) framework, what is the meaning of max and min vbv-fullness? The doc says that they are experimental options, however they default to 80% and 50% instead of 100% and 0% , so they have some meaning.


I guess that fullness thing is just some rate control internal thing. It tries to keep fullness between min and max most of the time and will probably adjust harder if its outside the "happy range".


2) Can a hevc GOP start with a B frame? It should be a "only forward" B frame, ore somewhat a "reversed" P, but in theory there can be up to 16 B before the keyframe. What about x265?


Not in coding order, but in display order. Its a bit inefficient tho and won't help your buffer. As you mentioned splitting at scenecuts its a but of a no-no.


3) Does extra info data (e.g. PPS, VPS, SPS, prefix/suffix SEI) have to be counted in the vbv?


Yes, of course. All data that is transmitted.


4) Is there any free tool for a-posteriori vbv check of a hevc stream?


I know no free one but know not much anyway. Some people I know do this in Microsoft Excel even.

Z2697
17th May 2026, 14:46
x265 doesn't use "unidir-B", so the B frames are always bi-directional.

The max number 16 is just an "arbitrary" choice by developers (of x264?).
https://github.com/Mr-Z-2697/x265-experimental/commits/E-2025-10-04

And again only the "middle" one in a sequence of B frames can be used as reference (a limitation of x264/5) so the beneifts of more B frames are very limited (but still with it's drawbacks).

Z2697
17th May 2026, 17:18
Not sure if I can understand this but it looks like it's making at most "1%" adjustments to try to maintain the fullness

/* Try to get the buffer at least 50% filled, but don't set an impossible goal. */
double finalDur = 1;
if (m_param->rc.bStrictCbr)
{
finalDur = x265_clip3(0.4, 1.0, totalDuration);
}
targetFill = X265_MIN(m_bufferFill + totalDuration * m_vbvMaxRate * 0.5, m_bufferSize * (m_minBufferFill * finalDur));
if (bufferFillCur < targetFill)
{
q *= 1.01;
loopTerminate |= 1;
continue;
}
/* Try to get the buffer not more than 80% filled, but don't set an impossible goal. */

targetFill = x265_clip3(m_bufferSize * (1 - m_maxBufferFill * finalDur), m_bufferSize, m_bufferFill - totalDuration * m_vbvMaxRate * 0.5);
if ((m_isCbr || m_2pass) && bufferFillCur > targetFill && !m_isSceneTransition)
{
q /= 1.01;
loopTerminate |= 2;
continue;
}
break;

rwill
17th May 2026, 17:47
It is doing iterations until the estimated VBV fullness at the end of the lookahead window is between 50% and 80%. It also cancels when it would adjust in one direction but already adjusted in the other direction before.

hellgauss
17th May 2026, 19:34
Thanks for replies!

So I assume that a good scene split can be done by checking IDR frames in a fast test encoding, as long as I set --no-open-gop.

For min/max fullness, it seems from the code that for a crf encoding only min is used. It makes sense, there is no need to give extra bitrate to simple scenes, while in complex scenes it can be reduced to prevent underflow. It seems to me a tweak to qcomp when the buffer start to going too low.

I'll start trying to code a script for vbv-check given (maxrate, bufsize, init).

cubicibo
18th May 2026, 09:00
Do not forget to use the concatenation flag. You may also want to specify matching init and end vbv fullness to each segment to improve VBV compliance of your concatenated file.

I know no free one but know not much anyway. Some people I know do this in Microsoft Excel even.
There's akupenguin vbv.pl script (http://akuvian.org/src/x264/vbv.pl). You merely need a script that dumps the frame size in bytes to a text file, which is straightforward for Annex B output. Of course, this approach only work with CFR content with constant VBV parameters.

So I assume that a good scene split can be done by checking IDR frames in a fast test encoding, as long as I set --no-open-gop.
Yes. Looking at the stat file of a turbo first pass may be sufficient for your needs, without outputting any bitstream.

hellgauss
18th May 2026, 10:12
I do not know perl, but it seems to me that the script, which is based upon mkvinfo, does not consider actual DTS of frames. This could lead to overestimate buffer fullness, e.g. in the first b-frame of a group.

I think I'll do it via ffprobe on raw hevc streams, no need to check concatenation there :)

cubicibo
18th May 2026, 10:55
The input txt file requires the frame to be in coding order. If your stream is in Annex B format then it's the number of bytes between every Access Unit Delimiter, one after the other in the bitstream.