Opened 4 years ago
Last modified 4 years ago
#9201 reopened defect
-c:v mpeg2video ignoring -qmin+qmax
Reported by: | Warren Young | Owned by: | |
---|---|---|---|
Priority: | normal | Component: | undetermined |
Version: | unspecified | Keywords: | |
Cc: | Blocked By: | ||
Blocking: | Reproduced by developer: | no | |
Analyzed by developer: | no |
Description
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?
- 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.
- 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.
- 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@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.
Change History (3)
comment:1 by , 4 years ago
Component: | ffmpeg → undetermined |
---|---|
Keywords: | mpeg2video qscale removed |
Version: | 4.2.4 → unspecified |
comment:2 by , 4 years ago
Resolution: | → needs_more_info |
---|---|
Status: | new → closed |
comment:3 by , 4 years ago
Resolution: | needs_more_info |
---|---|
Status: | closed → reopened |
you can either set a bitrate or use a constant quantizer
I've got bitrate graphs that say different. Not only does combining -q/qmin/qmax
with -maxrate
clip the bit rate as requested — to a point — ffmpeg doesn't refuse to encode when you combine these options.
(These graphs were produced by an R script I wrote that wraps ffprobe.)
complete, uncut console output
Here it is, boiled down to the smallest command I can come up with that shows the symptom:
$ ffmpeg -i 5233t.mp4 -c:v mpeg2video -c:a copy -qmax 10 -maxrate 18M -y 5233t.ts ffmpeg version N-102053-g2a623bacc8 Copyright (c) 2000-2021 the FFmpeg developers built with gcc 8 (GCC) configuration: --enable-libvpx --enable-libx264 --enable-gpl libavutil 56. 74.100 / 56. 74.100 libavcodec 58.137.100 / 58.137.100 libavformat 58. 79.100 / 58. 79.100 libavdevice 58. 14.100 / 58. 14.100 libavfilter 7.111.100 / 7.111.100 libswscale 5. 10.100 / 5. 10.100 libswresample 3. 10.100 / 3. 10.100 libpostproc 55. 10.100 / 55. 10.100 Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '5233t.mp4': Metadata: major_brand : mp42 minor_version : 1 compatible_brands: isommp41mp42 creation_time : 2021-04-27T01:07:37.000000Z Duration: 00:00:15.30, start: 0.000000, bitrate: 19516 kb/s Stream #0:0(eng): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709), 1920x1080 [SAR 1:1 DAR 16:9], 17072 kb/s, 28.38 fps, 29.97 tbr, 30k tbn, 60k tbc (default) Metadata: creation_time : 2021-04-27T01:07:37.000000Z handler_name : Core Media Video vendor_id : [0][0][0][0] encoder : AVC Coding Stream #0:1(eng): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 317 kb/s (default) Metadata: creation_time : 2021-04-27T01:07:37.000000Z handler_name : Core Media Audio vendor_id : [0][0][0][0] Stream mapping: Stream #0:0 -> #0:0 (h264 (native) -> mpeg2video (native)) Stream #0:1 -> #0:1 (copy) Press [q] to stop, [?] for help [mpeg2video @ 0x2efbdc0] Automatically choosing VBV buffer size of 268 kbyte Output #0, mpegts, to '5233t.ts': Metadata: major_brand : mp42 minor_version : 1 compatible_brands: isommp41mp42 encoder : Lavf58.79.100 Stream #0:0(eng): Video: mpeg2video (Main), yuv420p(tv, bt709, progressive), 1920x1080 [SAR 1:1 DAR 16:9], q=2-31, 200 kb/s, 29.97 fps, 90k tbn (default) Metadata: creation_time : 2021-04-27T01:07:37.000000Z handler_name : Core Media Video vendor_id : [0][0][0][0] encoder : Lavc58.137.100 mpeg2video Side data: cpb: bitrate max/min/avg: 18000000/0/200000 buffer size: 2195456 vbv_delay: N/A Stream #0:1(eng): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 317 kb/s (default) Metadata: creation_time : 2021-04-27T01:07:37.000000Z handler_name : Core Media Audio vendor_id : [0][0][0][0] [mpeg2video @ 0x2efbdc0] rc buffer underflowime=00:00:05.14 bitrate=13052.9kbits/s speed=4.58x [mpeg2video @ 0x2efbdc0] max bitrate possibly too small or try trellis with large lmax or increase qmax [mpeg2video @ 0x2efbdc0] rc buffer underflowime=00:00:06.99 bitrate=14685.7kbits/s speed=4.28x [mpeg2video @ 0x2efbdc0] max bitrate possibly too small or try trellis with large lmax or increase qmax [mpeg2video @ 0x2efbdc0] rc buffer underflow [mpeg2video @ 0x2efbdc0] max bitrate possibly too small or try trellis with large lmax or increase qmax [mpeg2video @ 0x2efbdc0] rc buffer underflow [mpeg2video @ 0x2efbdc0] max bitrate possibly too small or try trellis with large lmax or increase qmax [mpeg2video @ 0x2efbdc0] rc buffer underflowime=00:00:08.66 bitrate=15496.2kbits/s speed=4.05x [mpeg2video @ 0x2efbdc0] max bitrate possibly too small or try trellis with large lmax or increase qmax frame= 459 fps=127 q=31.0 Lsize= 23842kB time=00:00:15.31 bitrate=12751.1kbits/s speed=4.24x video:22621kB audio:593kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 2.702119%
Points of interest:
- It is showing
q=31.0
despite-qmax 10
. If you add-vstats
to the command, you will find that theq=
value ramps quickly up to 31.0 and stays there most of the time, flickering down to 24.8, as reported above.
- It is not the case that
-qmax
is being ignored, however. This may simply be a display bug, because changing-qmax
to 11 in the above command allows it to succeed.
an input sample if the issue is not reproducible with testsrc2.
That's a bad test source for this sort of problem, since testsrc2
generates a nearly-CBR stream. You need something with some bitrate variability to give -maxrate
something to clip.
Since I couldn't find an official ffmpeg test source with such variability, I've snipped a 15-second section from the particular video I ran into this with, here. (This is the 5233t.mp4
file referenced in the quoted command output above.)
I still believe you could have experienced the same problem with a large number of other videos. All you need is something sufficiently VBR, then set the bitrate control parameters tight enough that the symptom occurs.
If you point me at a suitably-VBR file you trust for testing such things, I'm sure I can make ffmpeg squeal with it, too.
I don't think this is a valid ticket (you can either set a bitrate or use a constant quantizer) but feel free to reopen this ticket if you can test current FFmpeg git head, the only version supported here, and if you can provide the command line you tested together with the complete, uncut console output and an input sample if the issue is not reproducible with
testsrc2
.