AVOptions详解

时间:2023-02-18 11:58:33

在前面的文章 《​​如何设置解复用器参数​​​》跟《​​如何设置编码器参数​​​》中,我们学习了如何用 ​​AVDictionary​​ 来设置解复用器,编码器的参数。

但是还有另一种方法也可以设置各种数据结构的参数,那就是用 ​​AVOptions​​ 的方式。

​AVOptions​​ 相关的 API 函数,都在 ​​libavutil/opt.h​​ 里面,本文会选取一部分 API 函数来做讲解。


本文的代码下载地址:​​GitHub​​,编译环境是 Qt 5.15.2 跟 MSVC2019_64bit 。

AVOptions详解

上图中,我设置了两个属性 ​​flags​​ 跟 ​​preset​​,对比 《​​如何设置编码器参数​​》中 ​​AVDictionary​​ 的方法,可以发现,用 ​​AVOptions​​ 会稍微麻烦一点,你需要分清楚这个属性是公共的,还是私有的,然后传递不同的指针给 ​​av_opt_set()​​ 函数。

​AVDictionary​​ 的方法如下:

AVOptions详解

​AVDictionary​​ 可以不用管是公共还是私有,全部丢在一起就行了。

补充:​​AVDictionary​​ 传参,内部的实现也是先设置私有属性,然后再设置公共属性。


​av_opt_set()​​ 函数一旦返回值小于 0 ,代表设置属性失败,通常是因为写错参数名称,写错参数会返回 ​​AVERROR_OPTION_NOT_FOUND​​,这个宏的值是 ​​-22​

​av_opt_set()​​ 是当 value 是字符串的时候用的,如果 ​​value​​ 是一个数字,那可以用 ​​av_opt_set_int()​​ 来设置编码器的参数,如果 value 是浮点数,可以用 ​​av_opt_set_double()​​。

更多设置属性相关的函数如下:

/**
* @defgroup opt_set_funcs Option setting functions
* @{
* Those functions set the field of obj with the given name to value.
*
* @param[in] obj A struct whose first element is a pointer to an AVClass.
* @param[in] name the name of the field to set
* @param[in] val The value to set. In case of av_opt_set() if the field is not
* of a string type, then the given string is parsed.
* SI postfixes and some named scalars are supported.
* If the field is of a numeric type, it has to be a numeric or named
* scalar. Behavior with more than one scalar and +- infix operators
* is undefined.
* If the field is of a flags type, it has to be a sequence of numeric
* scalars or named flags separated by '+' or '-'. Prefixing a flag
* with '+' causes it to be set without affecting the other flags;
* similarly, '-' unsets a flag.
* If the field is of a dictionary type, it has to be a ':' separated list of
* key=value parameters. Values containing ':' special characters must be
* escaped.
* @param search_flags flags passed to av_opt_find2. I.e. if AV_OPT_SEARCH_CHILDREN
* is passed here, then the option may be set on a child of obj.
*
* @return 0 if the value has been set, or an AVERROR code in case of
* error:
* AVERROR_OPTION_NOT_FOUND if no matching option exists
* AVERROR(ERANGE) if the value is out of range
* AVERROR(EINVAL) if the value is not valid
*/
int av_opt_set (void *obj, const char *name, const char *val, int search_flags);
int av_opt_set_int (void *obj, const char *name, int64_t val, int search_flags);
int av_opt_set_double (void *obj, const char *name, double val, int search_flags);
int av_opt_set_q (void *obj, const char *name, AVRational val, int search_flags);
int av_opt_set_bin (void *obj, const char *name, const uint8_t *val, int size, int search_flags);
int av_opt_set_image_size(void *obj, const char *name, int w, int h, int search_flags);
int av_opt_set_pixel_fmt (void *obj, const char *name, enum AVPixelFormat fmt, int search_flags);
int av_opt_set_sample_fmt(void *obj, const char *name, enum AVSampleFormat fmt, int search_flags);
int av_opt_set_video_rate(void *obj, const char *name, AVRational val, int search_flags);
int av_opt_set_channel_layout(void *obj, const char *name, int64_t ch_layout, int search_flags);

可以看到,头文件的注释非常全,看他注释基本就知道怎么使用了。

​av_opt_set()​​​ 是一个通用的函数,不仅仅可以设置编码器的属性参数,也可以设置解码器,​​demuxer​​ ,​​muxer​​,重采样(音频),​​scale​​(图片处理),等等数据结构的属性。


​libavutil/opt.h​​ 文件里面有一个非常重要的函数,就是 ​​av_opt_set_defaults()​​,这个函数是用来设置默认的属性的。

在 ​​avcodec_alloc_context3()​​ 函数调用的时候就会设置好编码器的默认函数,调用流程如下:

AVOptions详解


用 ​​AVOptions​​ 的方式设置编码器参数的方法讲解完毕了。

补充一个知识点,​​ffmpeg​​ 有非常多有用的音视频相关的函数,例如 ​​xxxx​​,基本上你碰到一个需求,如果需要写几十行代码,那你就要想一下 ​​ffmpeg​​ 的 ​​libavutil​​ 库里面有没有类似的函数可以直接用。