ffmpeg簡單分析字典參數AVDictionary的小祕密
- 我們在使用ffmpeg接口時發現有些接口是可以傳遞其他一些參數(AVDictionary)設置的,但這個AVDictionary究竟可以傳遞什麼值,卻是不得而知
- 比如這個接口,最後一個參數就是AVDictionary類型的
int avformat_open_input(AVFormatContext **ps, const char *url, ff_const59 AVInputFormat *fmt, AVDictionary **options);
-
那麼我們究竟可以傳什麼值呢,ffmpeg並沒有明確告訴你,開發者看到這個接口肯定也是一臉懵,而且由於它是可空的,因此基本上會被使用者置空了,但我們在網上搜索一些例子時,確實發現可以有一些參數設置的,而且這些參數設置確實能解決遇到的問題,因此不得不對這個AVDictionary進行研究下
-
網上經過一番搜索,發現源代碼中有兩個文件裏的內容似乎與AVDictionary有關係,我們可以在線瞧一瞧
- 這是關於avformat的參數
- https://www.ffmpeg.org/doxygen/trunk/libavformat_2options__table_8h-source.html
- 這是關於avcodec的參數
- http://www.ffmpeg.org/doxygen/trunk/libavcodec_2options__table_8h_source.html
-
從這兩個文件來看似乎找到AVDictionary可以設置的值了,就是類型爲AVOption的值,但後面發現這兩個文件裏包含的並非ffmpeg支持的全部參數
-
偶然的機會看到了rtsp.c源代碼,發現裏面也有AVOption,這時就猜測這些參數可能分散在各個文件中,如果使用rtsp協議,那麼可以使用rtsp.c文件裏的AVOption去設置AVDictionary,如果是mov,那麼在movenc.c源代碼中就聲明瞭可用的AVOption,等等
-
我們需要根據具體使用的情況去查找(也終於明白了爲啥ffmpeg對這個AVDictionary描述如此含糊的原因,因爲這個本身就不好描述)
AVOption
- AVOption定義在libavutil/opt.h
中
243 /**
244 * AVOption
245 */
246 typedef struct AVOption {
247 const char *name;
248
249 /**
250 * short English help text
251 * @todo What about other languages?
252 */
253 const char *help;
254
255 /**
256 * The offset relative to the context structure where the option
257 * value is stored. It should be 0 for named constants.
258 */
259 int offset;
260 enum AVOptionType type;
261
262 /**
263 * the default value for scalar options
264 */
265 union {
266 int64_t i64;
267 double dbl;
268 const char *str;
269 /* TODO those are unused now */
270 AVRational q;
271 } default_val;
272 double min; ///< minimum valid value for the option
273 double max; ///< maximum valid value for the option
274
275 int flags;
276 #define AV_OPT_FLAG_ENCODING_PARAM 1 ///< a generic parameter which can be set by the user for muxing or encoding
277 #define AV_OPT_FLAG_DECODING_PARAM 2 ///< a generic parameter which can be set by the user for demuxing or decoding
278 #define AV_OPT_FLAG_AUDIO_PARAM 8
279 #define AV_OPT_FLAG_VIDEO_PARAM 16
280 #define AV_OPT_FLAG_SUBTITLE_PARAM 32
281 /**
282 * The option is intended for exporting values to the caller.
283 */
284 #define AV_OPT_FLAG_EXPORT 64
285 /**
286 * The option may not be set through the AVOptions API, only read.
287 * This flag only makes sense when AV_OPT_FLAG_EXPORT is also set.
288 */
289 #define AV_OPT_FLAG_READONLY 128
290 #define AV_OPT_FLAG_BSF_PARAM (1<<8) ///< a generic parameter which can be set by the user for bit stream filtering
291 #define AV_OPT_FLAG_RUNTIME_PARAM (1<<15) ///< a generic parameter which can be set by the user at runtime
292 #define AV_OPT_FLAG_FILTERING_PARAM (1<<16) ///< a generic parameter which can be set by the user for filtering
293 #define AV_OPT_FLAG_DEPRECATED (1<<17) ///< set if option is deprecated, users should refer to AVOption.help text for more information
294 //FIXME think about enc-audio, ... style flags
295
296 /**
297 * The logical unit to which the option belongs. Non-constant
298 * options and corresponding named constants share the same
299 * unit. May be NULL.
300 */
301 const char *unit;
302 } AVOption;
已知的AVOption
- 這裏記錄下筆者已經發現的AVOption
- 需要注意的是,這些參數你都可以設置,但ffmpeg只會挑那些符合當前環境的參數去使用,例如你確實是在使用rtsp,那麼關於rtsp的參數則會生效
avformat
- https://www.ffmpeg.org/doxygen/trunk/libavformat_2options__table_8h-source.html
avcodec
- http://www.ffmpeg.org/doxygen/trunk/libavcodec_2options__table_8h_source.html
- 這個實在太多了就不截圖了
rtsp
mov
示例
- 以下這個例子演示了AVDictionary在avformat_open_input裏的使用,我們可以看到,AVDictionary可以設置好多個,但最終用哪些完全取決於ffmpeg,也就是說不是你設置什麼就生效什麼,萬一你亂來呢,因此ffmpeg只會根據當前情況選擇哪些符合的參數進行使用,最後可以通過AVDictionaryEntry 看看哪些參數是ffmpeg沒用到的
AVDictionary* options = NULL;
av_dict_set(&options, "buffer_size", "1048576", 0);//設置緩存大小,1080p可將值調大,比如1MB; 524288=512KB 1048576=1MB
av_dict_set(&options, "aaa", "1048576", 0);//aaa純粹是自己隨便定的,因此ffmpeg不會識別它,會直接返回給我們
av_dict_set(&options, "bbb", "1048576", 0);//bbb也是亂寫的
//打開網絡流或文件流
if (avformat_open_input(&pFormatCtx, "rtsp://...", NULL, &options) != 0)
{
printf("Couldn't open input stream.\n");
return;
}
//打印出那些未被消費的參數,以下會打印出aaa,bbb
AVDictionaryEntry *entry=NULL;
while (entry = av_dict_get(options, "", entry, AV_DICT_IGNORE_SUFFIX)) {
log(AV_LOG_INFO, "Option %s not recognized by the demuxer,and the count is %d \n", entry->key, av_dict_count(options));
}
//最後釋放掉
av_dict_free(&options);
參考
- FFmpeg接口-AVDictionary的使用介紹和源碼分析 - 簡書 https://www.jianshu.com/p/89f2da631e16