FFmpeg庖丁解牛系列之dict模块

关于dict模块

由于C语言不像C++和JAVA,没有key/value键值对的高级实现,所以FFmpeg专门写了一个dict模块(AVDictionary字典)用于简单的key/value存储。dict模块相对比较简单,其代码实现主要位于如下两个文件:

libavutil/dict.c
libavutil/dict.h

我们还是按照套路先分析头文件dict.h的内容。文件开头注释部分首先介绍了AVDictionary是个什么模块:

brief Simple key:value store
Dictionaries are used for storing key:value pairs. To create
an AVDictionary, simply pass an address of a NULL pointer to
av_dict_set(). NULL can be used as an empty dictionary wherever
a pointer to an AVDictionary is required.
Use av_dict_get() to retrieve an entry or iterate over all
entries and finally av_dict_free() to free the dictionary
and all its contents.

简言之,就是key:value对存储的。最简单的创建AVDictionary的方式就是给av_dict_set()传递NULL指针,默认创建一个空的字典,通过 av_dict_get()函数 取得字典,通过av_dict_free()函数释放字典。为此,还举了一个例子:

   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);

整个例子十分简洁,先定义两个字典相关的结构体,然后直接通过av_dict_set()函数将key/value对设置进去即可。av_strdup()函数是复制字符串的意思,即av_strdup()函数内部需要分配内存并拷贝字符串内容,以方便存储到字典中。AV_DICT_DONT_STRDUP_KEYAV_DICT_DONT_STRDUP_VAL的意思,顾名思义,不需要字典内部复制字符串key/value,这些内存由字典调用者分配,而不是字典自己去分配。内存的使用一定要记得谁负责分配,又由谁负责释放,以免造成内存泄漏。

主要结构定义

首先是几个宏定义,

#define AV_DICT_MATCH_CASE      1   /*只返回完全匹配key的entry结构*/
#define AV_DICT_IGNORE_SUFFIX   2   /*返回第一个匹配key的entry,忽略key的相关前缀 */
#define AV_DICT_DONT_STRDUP_KEY 4   /*不复制key字符串*/
#define AV_DICT_DONT_STRDUP_VAL 8   /*不复制value字符串*/
#define AV_DICT_DONT_OVERWRITE 16   /*不覆盖已经存在的entry*/
#define AV_DICT_APPEND         32   /*如果entry已经存在,直接附加在后面,并且不添加任何分隔符*/
#define AV_DICT_MULTIKEY       64   /*允许在字典内存储多个相同key的值*/

接下来是结构体,其中AVDictionary的定义在dict.c中,

struct AVDictionary {
    int count;
    AVDictionaryEntry *elems;
};

typedef struct AVDictionaryEntry {
    char *key;
    char *value;
} AVDictionaryEntry;

typedef struct AVDictionary AVDictionary;

上述结构体也很好理解,AVDictionaryEntry就相当于一个key/value对,而AVDictionary则包括了多个key/value而已。这就类似于C++的std::pair,JAVAmap,当然这里要注意AVDictionary的key/value都是字符串类型。

接口函数

AVDictionaryEntry *av_dict_get(const AVDictionary *m, const char *key,
                               const AVDictionaryEntry *prev, int flags);

通过此函数获取一个key/value的键值对。如果要遍历整个字典,可以设置key为空字符串“”,并且设置flags标记为AV_DICT_IGNORE_SUFFIXprev设置为前一个匹配的键值对,如果设置为NULL,那么函数则返回第一个匹配的键值对。

int av_dict_count(const AVDictionary *m);

此函数返回字典内键值对的总数。

int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags);

此函数完成key/value键值对设置到字典中,如果存在相同key的键值对,会覆盖。

int av_dict_set_int(AVDictionary **pm, const char *key, int64_t value, int flags);

此函数也是完成键值对的存储,但是value变成了整形。可是明明我们前面说了字典只能存储字符串啊?原来,在这个函数的内部实现里,通过snprintf将整数转成了字符串并通过av_dict_set()函数进行了存储。

int av_dict_parse_string(AVDictionary **pm, const char *str,
                         const char *key_val_sep, const char *pairs_sep,
                         int flags);

这个函数其实也是完成key/value对键值存储到字典中,但是key/value对是以字符串的形式传递到str中,并以key_val_sep和pairs_sep来做分隔符,分隔符的定义可以参考我们在option章节里的讲解(https://blog.csdn.net/ericbar/article/details/79872779)。

int av_dict_copy(AVDictionary **dst, const AVDictionary *src, int flags);

完成字典的拷贝,从src到dst。需要注意的是,如果dst是NULL,函数内部会主动分配内存并返回给dst。

void av_dict_free(AVDictionary **m);

此函数完成释放字典空间。

int av_dict_get_string(const AVDictionary *m, char **buffer,
                       const char key_val_sep, const char pairs_sep);

这个函数把字典里所有的键值对,以字符串形式(类似于JSON啦)组合存储到buffer指针内,同样的,key_val_seppairs_sep是建议的分隔符。需要注意的是,buffer的内存是由函数内部分配的,释放需要由调用者来完成。

总结

AVDictionary的代码实现,我们同样不做深入分析了,暂时只了解它的使用方法,遇到问题再深入探讨。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值