ffmpeg簡單分析字典參數AVDictionary的小祕密

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

  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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章