FFmpeg av_find_input_format函數剖析

AVInputFormat結構體
AVInputFormat 每種碼流輸入格式(例如h264,FLV, MKV, MP4, AVI)對應一個結構體,用來保存視音頻的解碼參數,目前以h264碼流格式爲例,描述結構體成員:
name:封裝格式名稱簡寫(short_name)[h264]
long_name:碼流輸入格式的長名稱[raw H.264 video]
extensions:碼流輸入格式的擴展名[h26l,h264,264,avc]
raw_codec_id:碼流輸入格式ID[28]
read_packet:avformat-57.dll!0x000007fee101ca90 (加載符號以獲取其他信息)
read_header:avformat-57.dll!0x000007fee101cb70 (加載符號以獲取其他信息)

關鍵函數:int (*read_packet)(struct AVFormatContext *, AVPacket *pkt);
read_packet函數讀取一個AVPacket,然後放在pkt,這個函數在進行分幀
av_read_frame函數的裏面會被調用到,調用相應的解碼器獲取一幀的完整數據


問題:各種碼流輸入格式是什麼時候被加載的?
回答:當第一次調用av_register_all的時候就會註冊複用器,其中就包含了各種碼流的輸入格式的處理函數

查看調用關係
av_register_all
    register_all
        REGISTER_MUXDEMUX(H264,             h264);
            #define REGISTER_MUXDEMUX(X, x) REGISTER_MUXER(X, x); REGISTER_DEMUXER(X, x)

#define REGISTER_MUXER(X, x)                                            \
    {                                                                   \
        extern AVOutputFormat ff_##x##_muxer;                           \
        if (CONFIG_##X##_MUXER)                                         \
            av_register_output_format(&ff_##x##_muxer);                 \
    }

#define REGISTER_DEMUXER(X, x)                                          \
    {                                                                   \
        extern AVInputFormat ff_##x##_demuxer;                          \
        if (CONFIG_##X##_DEMUXER)                                       \
            av_register_input_format(&ff_##x##_demuxer);                \
    }

看看註冊碼流輸入格式的函數
void av_register_input_format(AVInputFormat *format)
{
    AVInputFormat **p = last_iformat;

    // Note, format could be added after the first 2 checks but that implies that *p is no longer NULL
    while(p != &format->next && !format->next && avpriv_atomic_ptr_cas((void * volatile *)p, NULL, format))
        p = &(*p)->next;

    if (!format->next)
        last_iformat = &format->next;
}
其中關鍵的全局變量是
static AVInputFormat *first_iformat = NULL;
static AVInputFormat **last_iformat = &first_iformat;
保存了所有碼流格式

AVInputFormat *av_iformat_next(const AVInputFormat *f)
{
    if (f)
        return f->next;
    else
        return first_iformat;
}

AVInputFormat *av_find_input_format(const char *short_name)
{
    AVInputFormat *fmt = NULL;
    while ((fmt = av_iformat_next(fmt)))//獲取解碼器的鏈表指針,
        if (av_match_name(short_name, fmt->name))//根據輸入的碼流格式簡寫,輪詢鏈表查找解碼器
            return fmt;
    return NULL;
}

在avformat_open_input函數優化篇就直接指定碼流的輸入格式,從而減少了探測碼流格式的時間

參考
http://blog.csdn.net/leixiaohua1020/article/details/12677129
http://blog.csdn.net/neustar1/article/details/38231937

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