AVDictionary是FFmpeg中非常常见的类型,在代码中,通常使用它来传递参数或信息。
这里所谓的 “dictionary”,不是指普通的字典,而是指编程语言中,常见的一种 pair 结构,如C++中的map,Python中的字典,json中的键值对指的都是类似的意思。
FFmpeg中的 AVDictionary 是 AVDictionaryEntry 的集合,而 AVDictionaryEntry 则是包含两个字符串字段的结构体(entry:条目,项的意思):
typedef struct AVDictionaryEntry {
char *key;
char *value;
} AVDictionaryEntry;
当我们需要创建一个新的 AVDictionary 时,仅需要将一个值为 NULL 的 AVDictionary 指针地址传入 av_dict_set() 即可。当我们将 NULL 传递给一个 AVDictionary 类型的实参时,它表示一个空的 dictionary。
使用 av_dict_get() 可以获取 dictionary 中的条目,或者遍历其中所有的条目,然后需要使用 av_dict_free() 函数来释放 dictionary 以及其中的内容。
示例代码如下:
AVDictionary *d = NULL; // "create" an empty dictionary
AVDictionaryEntry *t = NULL;
av_dict_set(&d, "foo", "bar", 0); // add an entry
char *k = av_strdup("key"); // if your strings are already allocated,
char *v = av_strdup("value"); // you can avoid copying them like this
av_dict_set(&d, k, v, AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL);
while (t = av_dict_get(d, "", t, AV_DICT_IGNORE_SUFFIX)) {
<....> // iterate over all entries in d
}
av_dict_free(&d);
在操作AVDictionary时,常常需要用到相关的Flag(如示例中所示),其详情如下:
//仅在key完全匹配时才能获取entry,仅用于 av_dict_get()
#define AV_DICT_MATCH_CASE 1
//仅需条目中key开始的部分和传入的 key 相同即可,忽略其后续的部分,仅用于 av_dict_get()
#define AV_DICT_IGNORE_SUFFIX 2
//接管保存在已分配在内存中的 key 的所有权,在后续中负责释放该内存
#define AV_DICT_DONT_STRDUP_KEY 4
//接管保存在已分配在内存中的 value 的所有权,在后续中负责释放该内存
#define AV_DICT_DONT_STRDUP_VAL 8
//不要覆盖已存在的同名entry,即如果没有,则添加,如果有,则不作任何事
#define AV_DICT_DONT_OVERWRITE 16
//如果entry已经存在,追加 value,注意,不添加分隔符,仅仅是简单的追加而已
#define AV_DICT_APPEND 32
//允许存储多个相同的 key
#define AV_DICT_MULTIKEY 64
知道了上述内容之后,那么对AVDictionary的操作也就好理解了,其API有:
AVDictionaryEntry *av_dict_get(const AVDictionary *m, const char *key,
const AVDictionaryEntry *prev, int flags);
/*
获取符合指定 key 的 entry。
注意:返回的 entry 中的 key 和 value,不能被修改,否则可能会导致错误。
如果想要遍历所有的 entry,那么我们将 key 设置为 “”,然后将 flags 设置为 AV_DICT_IGNORE_SUFFIX。
参数 prev:上一个符合条件的 entry,这样就不会重复返回这个以及之前的符合条件的 entry 了。
如果传入NULL,则表示需要返回第一个符合条件的 entry。
*/
int av_dict_count(const AVDictionary *m);
/*
返回 dict 中 entry 的数量。
*/
int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags);
/*
添加一个 entry 到 dict,或者覆盖已存在的同名 entry。
注意:如果指定了 AV_DICT_DONT_STRDUP_KEY 或 AV_DICT_DONT_STRDUP_VAL,本函数发生错误时,会对它们进行 free 操作。
注意:对一个 dict 进行 add 操作,那么从该 dict 之前返回的所有 entry 都将作废,不能再使用。
返回值:成功时大于等于0,失败时返回一个负的错误值。
*/
int av_dict_set_int(AVDictionary **pm, const char *key, int64_t value, int flags);
/*
针对 int 类型的 value,av_dict_set() 函数的方便版函数。
*/
int av_dict_parse_string(AVDictionary **pm, const char *str,
const char *key_val_sep, const char *pairs_sep,
int flags);
/*
从 str 解析 key/value 对,然后将解析成功的 entry 加入到 pm。其中 pairs_sep 指定 pair 之间的分割符号,key_value_sep 指定 key 和 value 之间的分割符号。
注意:即使解析失败,pm中仍然存有已经解析成功并加入的entry,此时需要我们手动free这个dict。
注意:flags会忽略 AV_DICT_DONT_STRDUP_KEY 和 AV_DICT_DONT_STRDUP_VAL,因为在这个函数中,所有加入entry的key和value都是被分配空间然后拷贝的,会自动采用这两个flag。
*/
int av_dict_copy(AVDictionary **dst, const AVDictionary *src, int flags);
/*
将 src 中的entry拷贝到 dst中。
对于 dst 来说,这个操作如同 add 操作,flags指定 add 操作时的行为。
*/
void av_dict_free(AVDictionary **m);
/*
释放 dict。
*/
总结一下:AVDirctionary 是一个存储字符串键值对的数据结构,我们可以通过相关的接口来操作它。