AVOptions提供了一个通用的系统来声明任意结构(“对象”)上的选项。
一个选项可以有一个帮助文本,一个类型和一系列可能的值。 然后可以枚举,读取和写入选项。
Implementing AVOptions
本节介绍如何向结构体添加AVOptions功能。
所有AVOptions相关信息都存储在AVClass中。 因此,struct的第一个成员应该是一个指向描述它的AVClass的指针。 AVClass的选项字段必须设置为一个以NULL结尾的AVOptions的静态数组。 每个AVOption必须具有非空名称,类型,默认值和数字类型AVOptions也是允许值的范围。 它还必须从结构的开始处声明一个以字节为单位的偏移量,其中与此AVOption相关联的字段位于该位置。 AVOption结构中的其他字段也应在适用时进行设置,但不是必需的。
以下示例说明了支持AVOptions的结构:
typedef struct test_struct {
const AVClass *class;
int int_opt;
char *str_opt;
uint8_t *bin_opt;
int bin_len;
} test_struct;
static const AVOption test_options[] = {
{ "test_int", "This is a test option of int type.", offsetof(test_struct, int_opt),
AV_OPT_TYPE_INT, { .i64 = -1 }, INT_MIN, INT_MAX },
{ "test_str", "This is a test option of string type.", offsetof(test_struct, str_opt),
AV_OPT_TYPE_STRING },
{ "test_bin", "This is a test option of binary type.", offsetof(test_struct, bin_opt),
AV_OPT_TYPE_BINARY },
{ NULL },
};
static const AVClass test_class = {
.class_name = "test class",
.item_name = av_default_item_name,
.option = test_options,
.version = LIBAVUTIL_VERSION_INT,
};
接下来,分配你的结构时,你必须确保AVClass指针被设置为正确的值。 然后,可以调用av_opt_set_defaults()来初始化默认值。 之后,该结构就可以与AVOptions API一起使用了。
清理时,您可以使用av_opt_free()函数自动释放所有分配的字符串和二进制选项。
继续以上示例:
test_struct *alloc_test_struct(void)
{
test_struct *ret = av_mallocz(sizeof(*ret));
ret->class = &test_class;
av_opt_set_defaults(ret);
return ret;
}
void free_test_struct(test_struct **foo)
{
av_opt_free(*foo);
av_freep(foo);
}
Nesting
可能会发生一个AVOptions启用的结构包含另一个支持AVOptions的结构作为成员(例如,libavcodec中的AVCodecContext导出通用选项,而其priv_data字段导出编解码器特定的选项)。 在这种情况下,可以设置父结构以导出子选项。 要做到这一点,只需在父结构的AVClass中实现AVClass.child_next()和AVClass.child_class_next()。 假设来自上面的test_struct现在还包含一个child_struct字段:
typedef struct child_struct {
AVClass *class;
int flags_opt;
} child_struct;
static const AVOption child_opts[] = {
{ "test_flags", "This is a test option of flags type.",
offsetof(child_struct, flags_opt), AV_OPT_TYPE_FLAGS, { .i64 = 0 }, INT_MIN, INT_MAX },
{ NULL },
};
static const AVClass child_class = {
.class_name = "child class",
.item_name = av_default_item_name,
.option = child_opts,
.version = LIBAVUTIL_VERSION_INT,
};
void *child_next(void *obj, void *prev)
{
test_struct *t = obj;
if (!prev && t->child_struct)
return t->child_struct;
return NULL
}
const AVClass child_class_next(const AVClass *prev)
{
return prev ? NULL : &child_class;
将上面定义的child_next()和child_class_next()放在test_class中,现在可以通过test_struct访问child_struct的选项(再次,在创建之后,需要在child_struct上完成上述的正确设置)。
从上面的例子可能不清楚为什么需要child_next()和child_class_next()。 区别在于child_next()迭代实际存在的对象,而child_class_next()遍历所有可能的子类。 例如。 如果AVCodecContext被初始化为使用具有私有选项的编解码器,那么它的child_next()将返回AVCodecContext.priv_data并完成迭代。 AVCodecContext.av_class上的OTOH child_class_next()将使用私有选项来迭代所有可用的编解码器。
Named constants
可以为选项创建命名常量。 只需将选项的单位字段设置为常量应用于字符串,并将常量自身创建为类型为AV_OPT_TYPE_CONST的选项,其单位字段设置为相同的字符串。 它们的default_val字段应包含命名常量的值。 例如,要为上面的test_flags选项添加一些命名常量,请将以下内容放入child_opts数组中:
{ "test_flags", "This is a test option of flags type.",
offsetof(child_struct, flags_opt), AV_OPT_TYPE_FLAGS, { .i64 = 0 }, INT_MIN, INT_MAX, "test_unit" },
{ "flag1", "This is a flag with value 16", 0, AV_OPT_TYPE_CONST, { .i64 = 16 }, 0, 0, "test_unit" },
Using AVOptions
本节介绍在支持AVOptions的结构中访问选项。 FFmpeg中的这样的结构是例如。 libavcodec中的AVCodecContext或libavformat中的AVFormatContext。
Examining AVOptions
检查选项的基本功能是av_opt_next(),它遍历为一个对象定义的所有选项,av_opt_find()将搜索给定名称的选项。
嵌套情况更复杂。 支持AVOptions的结构可能具有启用AVOptions的子项。 将AV_OPT_SEARCH_CHILDREN标志传递给av_opt_find()将使函数递归地搜索子项。
列举基本上有两种情况。 第一个是当您想要获取结构体及其子代中可能存在的所有选项(例如构建文档时)。 在这种情况下,您应该在父结构的AVClass上递归调用av_opt_child_class_next()。 第二种情况是当你有一个已经初始化的结构与所有的孩子,你想获得所有可以实际写入或读取的选项。 在这种情况下,您应该在每个结果上递归调用av_opt_child_next()(和av_opt_next())。
Reading and writing AVOptions
设置选项时,您通常会直接从用户读取字符串。 在这种情况下,只需将其传递给av_opt_set()即可。 对于非字符串类型选项,av_opt_set()将根据选项类型解析字符串。
类似地,av_opt_get()将读取任何选项类型并将其转换为将被返回的字符串。 不要忘记字符串被分配,所以你必须用av_free()释放它。
在某些情况下,将所有选项放入AVDictionary并调用av_opt_set_dict()可能会更为方便。 一个具体的例子是lavf / lavc中的格式/编解码器打开功能,它使用填充了选项的字典作为参数。 这使得可以设置不能另外设置的一些选项,因为例如 在文件实际打开之前,输入文件格式是不知道的。
一、模块
一)、Evaluating option strings
这组函数可用于评估选项字符串并从中获取数字。
它们与av_opt_set()执行相同的操作,除了将结果写入到调用者提供的指针中。
参数:obj:一个结构体,其第一个元素是指向AVClass的指针。
o:要评估字符串的选项。
val:要评估的字符串。
*_val:字符串的值将写在这里。
返回:0成功,负数为失败。
函数
int | av_opt_eval_flags (void *obj, const AVOption *o, const char *val, int *flags_out) |
int | av_opt_eval_int (void *obj, const AVOption *o, const char *val, int *int_out) |
int | av_opt_eval_int64 (void *obj, const AVOption *o, const char *val, int64_t *int64_out) |
int | av_opt_eval_float (void *obj, const AVOption *o, const char *val, float *float_out) |
int | av_opt_eval_double (void *obj, const AVOption *o, const char *val, double *double_out) |
int | av_opt_eval_q (void *obj, const AVOption *o, const char *val, AVRational *q_out) |
二)、Option setting functions
那些函数将给定名称的obj的字段设置为value。
参数:obj:一个结构,其第一个元素是指向AVClass的指针。
name:要设置的字段的名称
val:要设置的值。 如果av_opt_set()如果字段不是字符串类型,则会解析给定的字符串。 支持SI后缀和一些命名标量。 如果字段是数字类型,则必须是数字或命名标量。 具有多个标量和+ - 中缀运算符的行为未定义。 如果该字段是一个标志类型,它必须是一个数字标量或命名标记的序列,以'+'或' - '分隔。 用'+'替代标志会导致设置不影响其他标志; 同样地,' - '取消标志。
search_flags:标志传递给av_opt_find2。即 如果AV_OPT_SEARCH_CHILDREN被传递到这里,那么可以在obj的子对象上设置该选项。
返回:如果值已设置,则为0,如果出现错误,则为AVERROR代码:AVERROR_OPTION_NOT_FOUND(如果不存在匹配选项)AVERROR(ERANGE)如果值超出范围AVERROR(EINVAL),如果该值无效
宏
#define | av_opt_set_int_list(obj, name, val, term, flags) |
参数:obj:AVClass对象设置选项
name:二进制选项的名称
val:指向整数列表的指针(对于列表的内容,必须具有正确的类型)
term:列表终止符(通常为0或-1)
flags:搜索标志
函数
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) |
int | av_opt_set_dict_val (void *obj, const char *name, const AVDictionary *val, int search_flags) |
三)、Option getting functions
那些函数从对象获取给定名称的选项的值。
参数:obj:一个结构体,其第一个元素是指向AVClass的指针。
name:获取的选项的名称。
search_flags:标志传递给av_opt_find2。即 如果AV_OPT_SEARCH_CHILDREN在这里被传递,那么该选项可能在obj的一个小孩中找到。
out_val:该选项的值将在此处写入
返回:> = 0成功,否则为否定错误代码
函数
int | av_opt_get (void *obj, const char *name, int search_flags, uint8_t **out_val) |
如果av_opt_get中的search_flags中设置了AV_OPT_ALLOW_NULL,并且该选项具有AV_OPT_TYPE_STRING或AV_OPT_TYPE_BINARY,并将其设置为NULL,则out_val将被设置为NULL,而不是分配的空字符串。
int | av_opt_get_int (void *obj, const char *name, int search_flags, int64_t *out_val) |
int | av_opt_get_double (void *obj, const char *name, int search_flags, double *out_val) |
int | av_opt_get_q (void *obj, const char *name, int search_flags, AVRational *out_val) |
int | av_opt_get_image_size (void *obj, const char *name, int search_flags, int *w_out, int *h_out) |
int | av_opt_get_pixel_fmt (void *obj, const char *name, int search_flags, enum AVPixelFormat *out_fmt) |
int | av_opt_get_sample_fmt (void *obj, const char *name, int search_flags, enum AVSampleFormat *out_fmt) |
int | av_opt_get_video_rate (void *obj, const char *name, int search_flags, AVRational *out_val) |
int | av_opt_get_channel_layout (void *obj, const char *name, int search_flags, int64_t *ch_layout) |
int | av_opt_get_dict_val (void *obj, const char *name, int search_flags, AVDictionary **out_val) |
二、数据结构
struct | AVOption{ const char * name; const char * help;// 短英文帮助文本 int offset; //相对于存储选项值的上下文结构的偏移量。 enum AVOptionType type; union { int64_t i64 double dbl const char * str AVRational q } default_val //标量选项的默认值 double min; // 选项的最小有效值 double max; // 选项的最大有效值 int flags; const char * unit;//选项所属的逻辑单位。 } |
struct | AVOptionRange{ const char * str; double value_min;//价值范围。 double value_max; double component_min;//价值的组成范围。 double component_max; int is_range; //范围标志。 } |
struct | AVOptionRanges{ AVOptionRange ** range;//选项范围数组。 int nb_ranges;//每个组件的范围数。 int nb_components;//组件数量 } |
三、宏
#define | AV_OPT_SEARCH_CHILDREN (1 << 0) |
#define | AV_OPT_SEARCH_FAKE_OBJ (1 << 1) |
#define | AV_OPT_ALLOW_NULL (1 << 2) |
#define | AV_OPT_MULTI_COMPONENT_RANGE (1 << 12) |
#define | AV_OPT_SERIALIZE_SKIP_DEFAULTS 0x00000001 |
#define | AV_OPT_SERIALIZE_OPT_FLAGS_EXACT 0x00000002 |
四、枚举
enum | AVOptionType { AV_OPT_TYPE_FLAGS, AV_OPT_TYPE_INT, AV_OPT_TYPE_INT64, AV_OPT_TYPE_DOUBLE, AV_OPT_TYPE_FLOAT, AV_OPT_TYPE_STRING, AV_OPT_TYPE_RATIONAL, AV_OPT_TYPE_BINARY, AV_OPT_TYPE_DICT, AV_OPT_TYPE_UINT64, AV_OPT_TYPE_CONST = 128, AV_OPT_TYPE_IMAGE_SIZE = MKBETAG('S','I','Z','E'), AV_OPT_TYPE_PIXEL_FMT = MKBETAG('P','F','M','T'), AV_OPT_TYPE_SAMPLE_FMT = MKBETAG('S','F','M','T'), AV_OPT_TYPE_VIDEO_RATE = MKBETAG('V','R','A','T'),AV_OPT_TYPE_DURATION = MKBETAG('D','U','R',' '), AV_OPT_TYPE_COLOR = MKBETAG('C','O','L','R'), AV_OPT_TYPE_CHANNEL_LAYOUT = MKBETAG('C','H','L','A'), AV_OPT_TYPE_BOOL = MKBETAG('B','O','O','L') } |
enum | { AV_OPT_FLAG_IMPLICIT_KEY = 1 } |
五、函数
int | av_opt_show2 (void *obj, void *av_log_obj, int req_flags, int rej_flags) |
参数:av_log_obj:用于显示选项的日志上下文
req_flags :请求显示选项的标志。 只显示它的选项 - > flags&req_flags。
rej_flags:拒绝标记的选项显示。 只显示它的选项!(opt-> flags&req_flags)。
void | av_opt_set_defaults (void *s) |
参数:s:一个支持Option的结构(它的第一个成员必须是A类的指针)
void | av_opt_set_defaults2 (void *s, int mask, int flags) |
只有这些AVOption字段(opt-> flags&mask)==标志将其默认值应用于s。
参数:s:一个支持Option的结构(它的第一个成员必须是A类的指针)
mask:AV_OPT_FLAG_ *的组合
flags:AV_OPT_FLAG_ *的组合
int | av_set_options_string (void *ctx, const char *opts, const char *key_val_sep, const char *pairs_sep) |
对于找到的每个键/值对,将值存储在ctx中的字段中,名称类似于键。 ctx必须是AVClass上下文,使用AVOptions进行存储。
参数:opts:选项字符串进行解析,可能为NULL
key_val_sep:一个0个终止的字符列表,用于将值与值分离
pairs_sep:用于将两个对彼此分离的0个字符的字符列表
返回:成功设置密钥/值对的数量,或与错误:AVERROR(EINVAL)相对应的AVERROR代码,如果opts无法解析,则如果密钥/值对不能被解析,则由av_opt_set()发出的错误代码。
int | av_opt_set_from_string (void *ctx, const char *opts, const char *const *shorthand, const char *key_val_sep, const char *pairs_sep) |
对于找到的每个键=值对,设置ctx中相应选项的值。
参数:ctx:AVClass对象设置选项
opts:选项字符串,由分隔符分隔的键值对
shorthand:一个以NULL结尾的快捷方式符号选项名称数组:如果opts中的第一个字段没有关键部分,则该关键字取自速记的第一个元素; 然后再次为第二个等等,直到选择完成,缩写完成或找到命名选项; 之后,所有选项都必须命名
key_val_sep:用于将值与值分隔的0个终止的字符列表,例如'='
pairs_sep:用于将两个对彼此分离的0个字符的列表,例如':'或','
返回:成功设置key = value对的数量,或与错误时的AVERROR代码相对应的负数值:AVERROR(EINVAL)如果opts无法解析,则如果键/值对不能被解析,则由av_set_string3()发出的错误代码。
void | av_opt_free (void *obj) |
int | av_opt_flag_is_set (void *obj, const char *field_name, const char *flag_name) |
参数:field_name:标志字段选项的名称
flag_name:要检查的标志的名称
返回:如果标志设置为非零,如果标志未设置,则为0,不是正确的类型,或者标志字段不存在。
int | av_opt_set_dict (void *obj, struct AVDictionary **options) |
参数:obj:一个结构体,其第一个元素是指向AVClass的指针
options:选择处理。 这个字典将被释放,并被一个新的字体替换,其中包含obj中没有找到的所有选项。 当然这个新的字典需要被av_dict_free()的调用者释放。
返回:0成功,如果在obj中发现某个选项,则为AVIDOR,但无法设置。
int | av_opt_set_dict2 (void *obj, struct AVDictionary **options, int search_flags) |
参数:obj:一个结构体,其第一个元素是指向AVClass的指针
options:选择处理。 这个字典将被释放,并被一个新的字体替换,其中包含obj中没有找到的所有选项。 当然这个新的字典需要被av_dict_free()的调用者释放。
search_flags:AV_OPT_SEARCH_ *的组合。
返回:0成功,如果在obj中发现某个选项,则为AVIDOR,但无法设置。
int | av_opt_get_key_value (const char **ropts, const char *key_val_sep, const char *pairs_sep, unsigned flags, char **rkey, char **rval) |
参数:ropts:指向选项字符串的指针,将被更新为指向其余的字符串(对之一或最后一个NUL)
key_val_sep:用于将值与值分隔的0个终止的字符列表,例如'='
pairs_sep:用于将两个对彼此分离的0个字符的列表,例如':'或','
flags:标志; 请参阅下面的AV_OPT_FLAG_ *值
rkey:解密键,必须使用av_free()
rval:解析值,必须使用av_free()
返回:> = 0表示成功,否则为错误对应于错误代码的负值; 特别是:AVERROR(EINVAL)如果没有键存在
const AVOption * | av_opt_find (void *obj, const char *name, const char *unit, int opt_flags, int search_flags) |
只考虑设置了所有指定标志的选项。
参数:obj:指向结构体的指针,其第一个元素是指向AVClass的指针。 或者,如果设置了AV_OPT_SEARCH_FAKE_OBJ搜索标志,则指向AVClass的双指针。
name:要查找的选项的名称。
uint:当搜索命名常量时,它所属的单位的名称。
opt_flags:仅查找所有指定的标志设置的选项(AV_OPT_FLAG)。
search_flags:AV_OPT_SEARCH_ *的组合。
返回:指向找到的选项的指针,如果没有找到选项,则返回NULL。
注意:使用AV_OPT_SEARCH_CHILDREN标志找到的选项可能无法通过av_opt_set()直接设置。 使用AVDictionary(例如avformat_open_input())选项的特殊调用来设置使用此标志找到的选项。
const AVOption * | av_opt_find2 (void *obj, const char *name, const char *unit, int opt_flags, int search_flags, void **target_obj) |
只考虑设置了所有指定标志的选项。
参数:obj:指向结构体的指针,其第一个元素是指向AVClass的指针。 或者,如果设置了AV_OPT_SEARCH_FAKE_OBJ搜索标志,则指向AVClass的双指针。
name:要查找的选项的名称。
uint:当搜索命名常量时,它所属的单位的名称。
opt_flags:仅查找所有指定的标志设置的选项(AV_OPT_FLAG)。
search_flags:AV_OPT_SEARCH_ *的组合。
target_obj:如果非NULL,则该选项所属的对象将在此处写入。 如果AV_OPT_SEARCH_CHILDREN存在于search_flags中,它可能与obj不同。 如果search_flags包含AV_OPT_SEARCH_FAKE_OBJ,则忽略此参数。
返回:指向找到的选项的指针,如果没有找到选项,则返回NULL。
const AVOption * | av_opt_next (const void *obj, const AVOption *prev) |
参数:obj:一个AVOptions启用的结构体或一个描述它的AVClass的双指针。
prev:先前调用此对象上的av_opt_next()的结果或NULL
返回:下一个AVOption或NULL
void * | av_opt_child_next (void *obj, void *prev) |
参数:prev:以前调用此函数或NULL的结果
返回:下一个启用AVOptions的子项或NULL
const AVClass * | av_opt_child_class_next (const AVClass *parent, const AVClass *prev) |
参数:prev:以前调用此函数或NULL的结果
返回:AVClass对应于下一个潜在的小孩或NULL
void * | av_opt_ptr (const AVClass *avclass, void *obj, const char *name) |
这个函数允许访问一个结构体,即使它的字段被移动或重新命名,因为进行访问的应用程序已被编译,
返回:一个指向该字段的指针,可以将其转换为正确的类型并读取或写入。
void | av_opt_freep_ranges (AVOptionRanges **ranges) |
int | av_opt_query_ranges (AVOptionRanges **, void *obj, const char *key, int flags) |
返回的列表可能取决于obj中的其他字段,例如配置文件。
参数:flags:是一个位掩码的标志,未定义的标志不应该被设置,应该被忽略AV_OPT_SEARCH_FAKE_OBJ表示obj是一个双指针到AVClass而不是一个完整的实例AV_OPT_MULTI_COMPONENT_RANGE表示该函数可能返回多个组件,结果必须使用av_opt_freep_ranges来释放。
返回:成功返回的数量,否则为否定错误代码
int | av_opt_copy (void *dest, const void *src) |
需要内存分配的选项(例如字符串或二进制)在目标对象中被错误地配置。 分配给这些选项的原始内存将被释放,除非src和dest选项都指向同一个内存。
参数:dest:要复制的对象
src:复制的对象
返回:0成功,否定错误
int | av_opt_query_ranges_default (AVOptionRanges **, void *obj, const char *key, int flags) |
此列表是在不使用AVClass.query_ranges()回调的情况下构建的,可用作回调中的回退。
参数:flags:是一个位掩码的标志,未定义的标志不应该被设置,应该被忽略AV_OPT_SEARCH_FAKE_OBJ表示obj是一个双指针到AVClass而不是一个完整的实例AV_OPT_MULTI_COMPONENT_RANGE表示该函数可能返回多个组件,结果必须使用av_opt_free_ranges来释放。
返回:成功返回的数量,否则为否定错误代码
int | av_opt_is_set_to_default (void *obj, const AVOption *o) |
选项o必须属于对象。 不能调用此函数来检查子项的选项状态。
参数:obj:AVClass对象检查选项
o:被检查的选项
返回:> 0,当选项设置为默认值时,0选项未设置为默认值时,错误为<0
int | av_opt_is_set_to_default_by_name (void *obj, const char *name, int search_flags) |
参数:obj:AVClass对象检查选项
name:选项名称
search_flags:组合AV_OPT_SEARCH_ *
返回:> 0,当选项设置为默认值时,0选项未设置为默认值时,错误为<0
int | av_opt_serialize (void *obj, int opt_flags, int flags, char **buffer, const char key_val_sep, const char pairs_sep) |
创建一个包含对象的序列化选项的字符串。 这样的字符串可以传回给av_opt_set_from_string(),以恢复选项值。 序列化值或名称字符串中出现的键/值或对分隔符通过av_escape()函数进行转义。
参数:obj:AVClass对象进行序列化
opt_flags;将所有指定的标志设置为序列化选项(AV_OPT_FLAG)
flags:组合AV_OPT_SERIALIZE_ *标志
buffer:指向缓冲区的指针将分配给包含序列化选项的字符串。 当不再需要时,调用者必须释放缓冲区。
key_val_sep:用于将键与值分离的字符
pairs_sep:用于将两个对彼此分开的字符
返回:> = 0成功,否定错误