FFmpeg中的AVDictionary是一个结构体,简单的key/value存储,经常使用AVDictionary设置或读取内部参数,声明如下,具体实现在libavutil模块中的dict.c/h,提供此结构体是为了与libav兼容,但它实现效率低下,在FFmpeg 4.1.3版本中已弃用(deprecated),推荐使用libavutil模块中的tree.c/h来替代,但是在一些代码中或API中还是会使用到AVDictionary,包括FFmpeg中的examples,因此这里整理介绍下AVDictionary用法。
typedef struct AVDictionaryEntry {
char *key;
char *value;
} AVDictionaryEntry;
struct AVDictionary {
int count;
AVDictionaryEntry *elems;
};
1. 一个空字典:AVDictionary* dict = nullptr;
2. 由指定的key获取一个字典条目(dictionary entry):av_dict_get
3. 获取字典条目数:av_dict_count
4. 设置一个字典条目,value为const char*:av_dict_set
5. 设置一个字典条目,value为int:av_dict_set_init,此函数内部会将int转为char*,然后再调用av_dict_set
6. 解析key/value对列表,并将解析的条目添加到字典中:av_dict_parse_string
7. 将条目从一个字典拷贝到另一个字典:av_dict_copy
8. 释放为AVDictonary结构分配的内存以及所有的key/value:av_dict_free
9. 以字符串形式获取一个字典条目:av_dict_get_string
10. av_dict_*中有些接口的最后一个参数为int flags,此参数可接受的有效值为在dict.h文件中定义的宏:
(1). AV_DICT_MATCH_CASE:设置字典中检索的key区分大小写,默认不区分大小写
(2). AV_DICT_IGNORE_SUFFIX:忽略字典中指定条目key的后缀
(3). AV_DICT_DONT_STRDUP_KEY:若key已分配,则不进行复制
(4). AV_DICT_DONT_STRDUP_VAL:若value已分配,则不进行复制
(5). AV_DICT_DONT_OVERWRITE:若指定key在字典中已存在,则不进行覆盖
(6). AV_DICT_APPEND:若指定key在字典中已存在,则value直接拼接到已存在value值的后面
(7). AV_DICT_MULTIKE:允许在字典中存储多个相同的key
FFmpeg中有些API都是通过AVDictionary来设置/读取内部参数的,如avformat_open_input,可设置video size、input format等,其使用可参见https://blog.csdn.net/fengbingchun/article/details/93975844
libavformat模块的options_table.h文件中列出了AVFormatContext支持的options选项;libavcodec模块的options_table.h文件中列出了AVCodecContext支持的options选项。
注:有时设置的参数会无效。
测试代码如下(test_ffmpeg_libavutil.cpp):
#include "funset.hpp"
#include
#include
#include
#include
#include
#ifdef __cplusplus
extern "C" {
#endif
#include
#include
#include
#ifdef __cplusplus
}
#endif
int test_ffmpeg_libavutil_avdictionary()
{
{
AVFormatContext* format_ctx = avformat_alloc_context();
const char* url = "rtsp://184.72.239.149/vod/mp4://BigBuckBunny_175k.mov";
int ret = -1;
AVDictionary* dict = nullptr;
av_dict_set(&dict, "max_delay", "100", 0);
ret = avformat_open_input(&format_ctx, url, nullptr, &dict);
if (ret != 0) {
fprintf(stderr, "fail to open url: %s, return value: %d\n", url, ret);
return -1;
}
fprintf(stdout, "dictionary count: %d\n", av_dict_count(format_ctx->metadata));
AVDictionaryEntry* entry = nullptr;
while ((entry = av_dict_get(format_ctx->metadata, "", entry, AV_DICT_IGNORE_SUFFIX))) {
fprintf(stdout, "key: %s, value: %s\n", entry->key, entry->value);
}
avformat_free_context(format_ctx);
av_dict_free(&dict);
}
{ // reference: https://ffmpeg.org/doxygen/4.1/group__lavu__dict.html
AVDictionary* d = nullptr; // "create" an empty dictionary
AVDictionaryEntry* t = nullptr;
av_dict_set(&d, "foo", "bar", 0); // add an entry
char* k = av_strdup("key"); // if your strings are already allocated, you can avoid copying them like this
char* v = av_strdup("value");
av_dict_set(&d, k, v, AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL);
fprintf(stdout, "dictionary count: %d\n", av_dict_count(d));
while (t = av_dict_get(d, "", t, AV_DICT_IGNORE_SUFFIX)) {
fprintf(stdout, "key: %s, value: %s\n", t->key, t->value); // iterate over all entries in d
}
av_dict_free(&d);
}
{
avdevice_register_all();
AVDictionary* options = nullptr;
#ifdef _MSC_VER
const char* input_format_name = "vfwcap";
const char* url = "";
#else
const char* input_format_name = "video4linux2";
const char* url = "/dev/video0";
av_dict_set(&options, "video_size", "640x480", 0);
av_dict_set(&options, "input_format", "mjpeg", 0);
#endif
AVInputFormat* input_fmt = av_find_input_format(input_format_name);
AVFormatContext* format_ctx = avformat_alloc_context();
int ret = avformat_open_input(&format_ctx, url, input_fmt, &options);
if (ret != 0) {
fprintf(stderr, "fail to open url: %s, return value: %d\n", url, ret);
return -1;
}
fprintf(stdout, "dictionary count: %d\n", av_dict_count(format_ctx->metadata));
AVDictionaryEntry* entry = nullptr;
while ((entry = av_dict_get(format_ctx->metadata, "", entry, AV_DICT_IGNORE_SUFFIX))) {
fprintf(stdout, "key: %s, value: %s\n", entry->key, entry->value);
}
av_dict_free(&options);
avformat_close_input(&format_ctx);
}
return 0;
}
执行结果如下:
GitHub:https://github.com//fengbingchun/OpenCV_Test