从学龄前开始解读FFMPEG代码 之 AVDictionary结构体以及av_dict_set相关函数
开始AVDictionary以及相关函数学习前想说的一些话
首先声明源码是我在github上直接clone并checkout到了4.2的版本。关于这个结构体以及后续的相关函数的说明可能会进行多次添加修改(在阅读源码的整体学习过程中真的随时都有可能更新自己的认知)
从AVDictionary开始
AVDictionary结构体其实是FFmpeg提供的用于存储键值对的结构体,使用该结构体可以用于设置在打开视频文件/视频码流的时候所需要的各项参数,比如probesize(探测读入大小),max_delay(最大时延)等等参数。
该结构体的定义文件在libavutil/dict.h 以及dict.c中。
首先在dict.h中,头文件上来的备注中就指出了AVdictionary的缺点,主要作用以及相关的用法:
/**
* @file
* Public dictionary API.
* @deprecated
* AVDictionary is provided for compatibility with libav. It is both in
* implementation as well as API inefficient. It does not scale and is
* extremely slow with large dictionaries.
* It is recommended that new code uses our tree container from tree.c/h
* where applicable, which uses AVL trees to achieve O(log n) performance.
*/
/*
* @{
* 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.
*/
AVDictionary主要是为了服务libav相关文件的,在接口以及实现上来说AVDictionary其实效率很低,不提供缩放功能且在大型的字典存储中非常缓慢,所以建议新的代码使用tree.c/h中的存储方式,使用AVL(二叉查找树,一种高度平衡树,任意节点的子树高度差不会超过1)提供了logn级别的查找速度。(tree.c/h中确实提供了一种更好的存储方式AVTreeNode,对于大型字典存储非常好用。
不过对于普通应用场景,其实并不需要太多的参数,所以AVDictionary完全够用。
AVDictianary用于存储 key:value的键值对,创建键值对也可以直接用一个NULL指针传入。如果需要的时候,NULL也可以作为一个空的dictionary。*(用法类似于AVDictionary d = NULL 之后 直接 av_dict_set(&d, “aa”,“bb”,0) )
AVDictianary结构体由一个int类型和一个AVDictianaryEntry指针(数组)类型组成,定义代码在dict.c中:
struct AVDictionary {
int count;
AVDictionaryEntry *elems;
};
count是用于计数的变量,而AVDictionaryEntry定义则是在dict.h文件中,包含两个字符串(char*类型),这是真正用于存储键值对的结构体
typedef struct AVDictionaryEntry {
char *key;
char *value;
} AVDictionaryEntry;
从变量名就能看出来,key和value就是键值对的键名和键值,AVDictionary内就存放管理着AVDictionaryEntry
在需要创建并存储一个键值对时,就可以通过av_dict_set方法来将键值对写入到AVDictionary字典当中。
av_dict_set()是干啥的
av_dict_set函数定义在dict.c中,代码如下:
int av_dict_set(AVDictionary **pm, const char *key, const char *value,
int flags)
{
AVDictionary *m = *pm;
AVDictionaryEntry *tag = NULL;
char *oldval = NULL, *copy_key = NULL, *copy_value = NULL;
if (!(flags & AV_DICT_MULTIKEY)) {
tag = av_dict_get(m, key, NULL, flags);
}
if (flags & AV_DICT_DONT_STRDUP_KEY)
copy_key = (void *)key;
else
copy_key =