ffmpeg dict 相关的函数
总结
- ffmpeg 的 dict 数据结构本质 动态数组(长度+起始地址) + key-value
- 函数
- av_dict_get: 遍历所有字典获取
- av_dict_set: 字典 elems 最后一个位置添加/更新的 pair,flags 控制各种策略
- av_dict_set_int: int 转 string,然后调 av_dict_set
- av_dict_iterate: elems 首地址+元素索引来获取 next 应该遍历的元素
- av_dict_parse_string: 通过两个分隔符,来获取 key-value,然后 av_dict_set 赋值
- av_dict_get_string: av_dict_iterate 遍历所有 pair,然后拼接分隔符
- av_dict_copy: av_dict_iterate 遍历 src 元素,然后 av_dict_set 赋值给 dst
- av_dict_free: 遍历所有 key-value,释放 pair、elems、AVDictionary
- av_dict_count: 返回 AVDictionary->count
数据结构
- AVDictionary 数据结构,存储字典
struct AVDictionary {
int count; //当前 AVDictionary 键值对数量
AVDictionaryEntry *elems; // elems[]数组
};
typedef struct AVDictionaryEntry {
char *key;
char *value;
} AVDictionaryEntry;
- Dict 匹配模式宏定义
/**< 仅获取键名完全匹配(区分大小写)的条目。仅在 av_dict_get() 中有意义。 */
#define AV_DICT_MATCH_CASE 1
/**< 返回字典中第一个与搜索键前缀匹配的条目,忽略找到的键字符串的后缀部分。仅在 av_dict_get() 中有意义。 */
#define AV_DICT_IGNORE_SUFFIX 2
/**< 接管键的所有权,该键已通过 av_malloc(),或其他内存分配函数分配。避免重新复制字符串。 */
#define AV_DICT_DONT_STRDUP_KEY 4
/**< 接管值的所有权,该值已通过 av_malloc(),或其他内存分配函数分配。避免重新复制字符串。 */
#define AV_DICT_DONT_STRDUP_VAL 8
/**< 不覆盖已存在的条目。如果键已存在,则保持原值不变。 */
#define AV_DICT_DONT_OVERWRITE 16
/**< 如果条目已存在,则将新值附加到旧值后面。注意:不会添加任何分隔符,字符串会直接连接在一起。 */
#define AV_DICT_APPEND 32
/**< 允许在字典中存储多个相同键名的条目。正常情况下相同键会覆盖或附加。 */
#define AV_DICT_MULTIKEY 64
函数
av_dict_get 获取 key 的 value
AVDictionaryEntry *av_dict_get(const AVDictionary *m, const char *key,
const AVDictionaryEntry *prev, int flags)
//eg 找字典 key
av_dict_get(format_opts, "scan_all_pmts", NULL, AV_DICT_MATCH_CASE)
- 通过 av_dict_iterate 遍历所有字典
- flags 决定如何匹配 key 和字典元素(全匹配、忽略大小写-全转大写、匹配前缀)
av_dict_iterate 迭代字典 next 元素
const AVDictionaryEntry *av_dict_iterate(const AVDictionary *m,
const AVDictionaryEntry *prev)
//eg 用于遍历 AVDictionary 元素
while(t = av_dict_iterate(b,t))
- 核心
**<font style="color:#DF2A3F;">return</font>**** ****<font style="color:#DF2A3F;">AVDictionary->elems[ prev - AVDictionary->elems + 1 ]</font>**
- prev 地址是传入的迭代到的地址,即上一个地址(prev == NULL 即是返回第一个元素)
- AVDictionary->elems 是字典首地址
- prev - AVDiconary-> elems 表示之前遍历的元素索引,+1 表示 next 元素索引
av_dict_set 赋值 key 的 value
int av_dict_set(AVDictionary **pm, const char *key, const char *value,int flags)
//eg 字典赋值 string 类型 type
av_dict_set(&format_opts, "scan_all_pmts", "1", AV_DICT_DONT_OVERWRITE)
**<font style="color:#DF2A3F;">*pm == NULL</font>**
空字典- 调用 av_malloc(底层 malloc / posix_memalign / memalign 等分配,根据指令集)分配内存
**<font style="color:#DF2A3F;">flag != AV_DICT_DONT_STRDUP_KEY/VAL</font>**
已给 key/value 分配内存,避免重新分配- av_strdup 重新分配 key/value,不然直接类型转换使用原始 key/value
- **插入新 key **
- av_realloc_array **扩容 +1 elems 数组,存在最后一个位置**
**<font style="color:#DF2A3F;">flag != AV_DICT_MULTIKEY</font>**
不允许多 key- av_dict_get 获取是否已有键
- 字典已有 key
**<font style="color:#DF2A3F;">flag == AV_DICT_DONT_OVERWRITE</font>**
,已有 key,跳过**<font style="color:#DF2A3F;">flag == AV_DICT_APPEND</font>**
原值后拼接新值,需重新给 value 分配内存,然后删除 key_old,最后在 elems 最后一个位置插入 key-value- 否则覆盖旧值,并将当前元素删除,然后再**最后一个位置插入 key-value**
- 若字典中无元素,释放整个字典结构
av_dict_set_int 赋值 int 类型 value
int av_dict_set_int(AVDictionary **pm, const char *key, int64_t value, int flags)
//eg 字典赋值 int 类型 value
av_dict_set(&format_opts, "scan_all_pmts", 1 , AV_DICT_DONT_OVERWRITE)
- 把输入 int 类型的 value,*转换为 char ,然后调用 av_dict_set 进行赋值
- 要把 flag 的 AV_DICT_DONT_STRDUP_VAL 清除,因为需要重新分配字符串内存
av_dict_parse_string 解析多个 key-value 对
int av_dict_parse_string(AVDictionary **pm, const char *str,
const char *key_val_sep, const char *pairs_sep, int flags)
//eg 解析多个 string 类型字典,: 分割多个 key-val对,= 分割 key 和 val
av_dict_parse_string(&dict, "codec=h264:bitrate=1000000", ":", "=", 0);
flags &= ~(AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL)
要求复制字符串- 通过 parse_key_value_pair 去遍历每一个 pair
- av_get_token 提取 key 和 value (通过遍历找到 : 和 = 这两个分隔符)
- av_dict_set 赋值 key-value
av_dict_get_string 返回字典所有 key-vale
int av_dict_get_string(const AVDictionary *m, char **buffer,
const char key_val_sep, const char pairs_sep)
//eg str 获取形如 "key1=value1:key2=value2" 的字典
av_dict_get_string(dict, &str, '=', ':');
av_dict_copy 复制字典
int av_dict_copy(AVDictionary **dst, const AVDictionary *src, int flags)
//eg 将 src 中所有键值对深拷贝到 dst 中
av_dict_copy(&dst, src, 0);
- 底层
**<font style="color:#DF2A3F;">av_dict_iterate + av_dict_set</font>**
**<font style="color:#DF2A3F;">flags & AV_DICT_DONT_STRDUP_KEY / VAL</font>**
可以控制深拷贝和浅拷贝****(浅拷贝需要自己承担悬空指针的风险)
av_dict_free 释放字典
void av_dict_free(AVDictionary **pm)
//eg 释放字典
av_dict_free(&dict)
- 倒序遍历 AVDictionary->elems
- av_freep 释放每一个 key 和 value
- av_freep 释放 elems 本身空间
- av_freep 最后释放 AVDictionary 字典
av_dict_count 返回字典元素数量
int av_dict_count(const AVDictionary *m)
//eg 获取字典元素量
av_dict_count(dict)
- 本质就是
**<font style="color:#DF2A3F;">return AVDictionary->count </font>**
avpriv_dict_set_timestamp 设置字典中时间戳
int avpriv_dict_set_timestamp(AVDictionary **dict, const char *key, int64_t timestamp)
//eg 将当前系统时间(微秒)写入字典中,
//key 为 "creation_time",格式为 ISO 8601(如 2025-05-09T13:45:00Z)。
avpriv_dict_set_timestamp(&dict, "creation_time", av_gettime());
- 传入 int 时间戳,然后转成 iso 格式字符串,微秒级别
- av_dict_set 写入 key-value