[FFmpeg-trac] #9201(ffmpeg:new): -c:v mpeg2video ignoring -qmin+qmax
FFmpeg
trac at avcodec.org
Mon Apr 26 21:45:31 EEST 2021
#9201: -c:v mpeg2video ignoring -qmin+qmax
-------------------------------------+-------------------------------------
Reporter: Warren | Type: defect
Young |
Status: new | Priority: normal
Component: ffmpeg | Version: 4.2.4
Keywords: mpeg2video | Blocked By:
qscale |
Blocking: | Reproduced by developer: 0
Analyzed by developer: 0 |
-------------------------------------+-------------------------------------
I'm trying to get around a problem where setting a too-low -q:v with -f
mpeg2video results in "rc buffer underflow" errors when setting -maxrate.
I realize that -q is a constant-quality mode and that this allows bit rate
to go arbitrarily high, potentially hitting my -maxrate ceiling. The
problem then is, what to do about it?
1. Increase -q, reducing quality for all files, even though they mostly
don't hit the ceiling, just to account for the fact that occasionally I do
get a file that does hit the ceiling, resulting in an encoding failure
with these settings. This works, but results in bad quality across the
board, just to cover the worst-case conditions.
2. Give up on constant-quality mode, letting Q vary between 2 and 31 per
the encoder's defaults. This works, but unless I use 2-pass encoding, it
gives worse quality than an optimally-chosen -q value.
3. Try to use -qmin and -qmax together to achieve both desires: -qmin set
to my prior fixed -q value, plus -qmax set to the largest value I ever see
a need for in testing, which is well under the default, 31.
The problem when I take route 3 is that ffmpeg appears to ignore it. This
despite the fact that I'm just doing what ffmpeg itself suggests: "max
bitrate possibly too small or try trellis with large lmax or increase
qmax". Currently, giving -q + -qmax + -maxrate doesn't change anything.
Reproduction command line:
{{{
ffmpeg -i in.mp4 -f mpegts -c:v mpeg2video -maxrate 18M -bufsize 9M
-qmin:v 8 -qmax:v 20 ... -y out.ts
}}}
The 18M maxrate value is from the ATSC/QAM limitations for broadcast
video, which is why I'm using MPEG-TS as a container here. I ''have'' to
get in under this limit or I'll overrun my hardware MPEG-2 decoders'
buffers.
(The hard limit from the spec is more like 19.4 Mbit/sec, but I also need
space for audio + mux overhead. Pathological cases aside, 18 should be
plenty, even for 1080p at 29.97 MPEG-2 video.)
You don't need any particular input file to show the problem. Although
only certain inputs will give the "rc buffer overflow" symptom, you can
see with ''any'' input that the output isn't constrained as the command
line specifies. With ffmpeg 4.4 (current Homebrew build), I see output
lines like this:
{{{
frame= 360 fps=132 q=31.0 Lsize= 4332kB time=00:00:11.97
bitrate=2962.5kbits/s speed= 4.4x
}}}
It mostly shows q=31 with occasional flickers to q=24.8. Why those two
values, and how can it get to them anyway when they're both above qmax?
Why doesn't it ever go down to 8, even though in the line above, it shows
that it's achieved 3 Mbps, well under my 18 Mbps max?
I realize that you can't combine a constant-quality mode in ffmpeg with
2-pass encoding, but with the above combination of 3 bitrate control
options (qmin+qmax+maxrate) I'd expect it to try qmin, then if that blew
the maxrate budget, try qmax, and error out if that also fails. If
encoding at qmax instead succeeds, try a binary search to find the highest
q value that does fit inside the maxrate limit.
I'm expecting it to repeat this algorithm over each "chunk" of video,
presumably set based on my -bufsize value, though possibly based on other
limits, such as GOP size.
There would have to be a maximum number of iterations, but it should be
able to find a near-optimal Q value for each chunk of video with a small
number of tries:
* 2 steps: just try qmax if qmin fails, oscillating between the two as
necessary
* 3 steps: try `qmin+(qmax-qmin)/2` if qmin fails but qmax succeeds
* 4-5 steps: also try the quarter steps; only 4 steps if `qmin+(qmax-
qmin)/4` succeeds, but 5 if that fails, since you then need to try the ¾
step: `qmin+(3*((qmax-qmin)/4))`
* 9 steps: same algorithm as above, but for eighth-interval steps
For easy-to-encode video, Q should ride along at qmin, giving the effect
of a constant-quality mode (-q=qmin) but by giving -qmax, I'm allowing the
encoder to retry at lower qualities to get the video under my -maxrate
limit.
I've seen this behavior on versions from 4.2.1 to 4.4. I've chosen the
lowest value available in your Version drop-down.
--
Ticket URL: <https://trac.ffmpeg.org/ticket/9201>
FFmpeg <https://ffmpeg.org>
FFmpeg issue tracker
More information about the FFmpeg-trac
mailing list