FFmpeg中AVDictionary介绍
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 <string.h>
#include <iostream>
#include <string>
#include <memory>
#include <vector>#ifdef __cplusplus
extern "C" {
#endif#include <libavutil/dict.h>
#include <libavformat/avformat.h>
#include <libavdevice/avdevice.h>#ifdef __cplusplus
}
#endifint 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.htmlAVDictionary* d = nullptr; // "create" an empty dictionaryAVDictionaryEntry* t = nullptr;av_dict_set(&d, "foo", "bar", 0); // add an entrychar* k = av_strdup("key"); // if your strings are already allocated, you can avoid copying them like thischar* 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_VERconst char* input_format_name = "vfwcap";const char* url = "";
#elseconst 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);
#endifAVInputFormat* 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
總結
以上是生活随笔為你收集整理的FFmpeg中AVDictionary介绍的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: FFmpeg通过摄像头实现对视频流进行解
- 下一篇: 开源库libuuid简介及使用