FFmpeg的默认值陷阱

前面我们讲过FFmpeg的参数配置系统:

avformat avcodec等API都用到了搜索子对象配置的功能。比如使用libx264编码器,你可以使用avcodec公共参数来配置码率和线程数,可以使用libx264模块的私有参数配置preset tune。公共参数在option_tables.c里,子对象私有参数在各个模块内部,关键字AVOption。

作者:quink,公众号:Fun With FFmpeg,FFmpeg的参数配置系统

但即使知道了实现原理,很多人对FFmpeg的参数仍然一头雾水。没办法,参数太多了,涉及一堆领域知识,并纠缠着FFmpeg自己的演进历史。没人能熟悉FFmpeg所有参数。有些参数的坑太隐蔽,资深开发者也难免掉进坑里。今天讲讲我踩过的坑。

一、默认的码率

有开发者抱怨,为什么我用FFmpeg videotoolbox编码出来的视频清晰度很差?检查他使用的命令参数,原来是没有设置视频的码率。

为什么不设置视频码率,编码出来的视频是糊的因为libavcodec视频编码默认码率是200 kbps。对于绝大多数应用场景,200 kbps是远远不够的。

#define AV_CODEC_DEFAULT_BITRATE 200*1000

static const AVOption avcodec_options[] = {
{"b", "set bitrate (in bits/s)", OFFSET(bit_rate), AV_OPT_TYPE_INT64, {.i64 = AV_CODEC_DEFAULT_BITRATE }, 0, INT64_MAX, A|V|E},

能不能给FFmpeg提个patch,改改默认的码率呢?NAK:

  • 历史原因,修改默认值影响很大
  • 合理的码率与很多因素有关,没法预设一个合理的定值

也许有细心的同学会问:为什么libx264不设置码率,编码出来的视频清晰度是正常的?因为FFmpeg封装的libx264默认的码控模式是crf( Constant Rate Factor)。

二、默认GOP

FFmpeg videotoolbox编码模糊,第二个原因是默认的GOP不合理。用工具查看输出的码流:

GOP: IPPPPPPPPPPP 12 CLOSED
GOP: IPPPPPPPPPPP 12 CLOSED
GOP: IPPPPPPPPPPP 12 CLOSED
GOP: IPPPPPPPPPPP 12 CLOSED

FFmpeg中的参数描述:

{"g", "set the group of picture (GOP) size", OFFSET(gop_size), AV_OPT_TYPE_INT, {.i64 = 12 }, INT_MIN, INT_MAX, V|E},

默认GOP 12帧,GOP过小,导致压缩效率低,画质损失大。

三、默认qp

当你配置了合理的码率和GOP之后,videotoolbox编码模糊问题解决了。但是,有个更头疼的问题偶尔会冒出来:videotoolbox编码输出的视频码率和你设置的码率不一致,容易出现码率偏高的情况

我花了俩小时找到了问题原因:

1. Rick Kern给videotoolbox加上了qp上下限配置的功能

lavc/videotoolboxenc: support additional options

Added support for more VideoToolbox encoder options:
- qmin and qmax options are now used
- max_slice_bytes: Max number of bytes per H.264 slice
- max_ref_frames: Limit the number of reference frames
- Disable open GOP when the cgop flag is set
- power_efficient: Enable power-efficient mode

2. qp上限默认值反常

{"qmin", "minimum video quantizer scale (VBR)", OFFSET(qmin), AV_OPT_TYPE_INT, {.i64 = 2 }, -1, 69, V|E},
{"qmax", "maximum video quantizer scale (VBR)", OFFSET(qmax), AV_OPT_TYPE_INT, {.i64 = 31 }, -1, 1024, V|E},

qmax默认值31,值过小,容易出现码率过高的情况。

四、默认的tag

这是个老生常谈的问题了:FFmpeg输出的H.265编码mp4封装视频,Apple的系统播放器无法播放。原因是FFmpeg默认用的H.265 tag是hevc,Apple要求hvc1。这是个封装问题,不是编码问题。hvc1在mp4 stsd box里长这样:

                        [stsd: Sample Description Box]
                            position = 1184036
                            size = 2269
                            version = 0
                            flags = 0x000000
                            entry_count = 1
                            [hvc1: Visual Description]
                                position = 1184052
                                size = 2253

关于hvc1和hevc的选择,FFmpeg技术上更正确,hevc要求更宽泛,Apple要求更严格。具体区别见:https://gist.github.com/quink-black/6828ebf722f6a4d35fbc5c5bc2dbaf42

解决方法:指定tag

ffmpeg -i hevc.mp4 -c copy -tag:v hvc1 output.mp4

五、如何解决不合理的编码参数问题?

前面讲的几个不合理默认值导致的编码问题,x264都不存在,为什么?libx264.c重置了libavcodec层的不合理参数:

static const FFCodecDefault x264_defaults[] = {
    { "b",                "0" },
    { "bf",               "-1" },
    { "flags2",           "0" },
    { "g",                "-1" },
    { "i_qfactor",        "-1" },
    { "b_qfactor",        "-1" },
    { "qmin",             "-1" },
    { "qmax",             "-1" },
    { "qdiff",            "-1" },
    { "qblur",            "-1" },
    { "qcomp",            "-1" },
    ……
        const FFCodec ff_libx264_encoder = {
    .p.name           = "libx264",
    CODEC_LONG_NAME("libx264 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10"),
    .p.type           = AVMEDIA_TYPE_VIDEO,
    .p.id             = AV_CODEC_ID_H264,
    ……
    .defaults         = x264_defaults,
    ……

libavcodec/options_table.h里的默认参数不能轻易修改,有历史原因。libavcodec框架提供了机制,能让每个编码器定制它的默认值。

类似x264的处理,FFmpeg 7.1里我已经重置了videotoolbox编码的默认码率和qp上下限。默认GOP的处理还要再考虑下。

经验教训:合理的默认值是软件防呆设计的一环,傻瓜式使用也能满足基本功能。

版权声明:本文内容转自互联网,本文观点仅代表作者本人。本站仅提供信息存储空间服务,所有权归原作者所有。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至1393616908@qq.com 举报,一经查实,本站将立刻删除。

(0)

相关推荐

发表回复

登录后才能评论