前面我们讲过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 举报,一经查实,本站将立刻删除。