天天看點

avformat_open_input

FFMPEG打開媒體的的過程開始于avformat_open_input,是以該函數的重要性不可忽視。

在該函數中,FFMPEG完成了:

輸入輸出結構體AVIOContext的初始化;

輸入資料的協定(例如RTMP,或者file)的識别(通過一套評分機制):1判斷檔案名的字尾 2讀取檔案頭的資料進行比對;

使用獲得最高分的檔案協定對應的URLProtocol,通過函數指針的方式,與FFMPEG連接配接(非專業用詞);

剩下的就是調用該URLProtocol的函數進行open,read等操作了

以下是通過eclipse+MinGW調試FFMPEG源代碼獲得的函數調用關系圖

可見最終都調用了URLProtocol結構體中的函數指針。

URLProtocol結構是一大堆函數指針的集合(avio.h檔案)參見第四章資料結構

URLProtocol功能就是完成各種輸入協定的讀寫等操作

但輸入協定種類繁多,它是怎樣做到“大一統”的呢?

avformat_open_input

原來,每個具體的輸入協定都有自己對應的URLProtocol。

比如file協定(FFMPEG把檔案也當做一種特殊的協定)(*file.c檔案)

URLProtocol ff_pipe_protocol = {  

    .name                = "pipe",  

    .url_open            = pipe_open,  

    .url_read            = file_read,  

    .url_write           = file_write,  

    .url_get_file_handle = file_get_handle,  

    .url_check           = file_check,  

};  

或者rtmp協定(此處使用了librtmp)(librtmp.c檔案)

URLProtocol ff_rtmp_protocol = {  

    .name                = "rtmp",  

    .url_open            = rtmp_open,  

    .url_read            = rtmp_read,  

    .url_write           = rtmp_write,  

    .url_close           = rtmp_close,  

    .url_read_pause      = rtmp_read_pause,  

    .url_read_seek       = rtmp_read_seek,  

    .url_get_file_handle = rtmp_get_file_handle,  

    .priv_data_size      = sizeof(RTMP),  

    .flags               = URL_PROTOCOL_FLAG_NETWORK,  

};  

可見它們把各自的函數指針都指派給了URLProtocol結構體的函數指針

是以avformat_open_input隻需調用url_open,url_read這些函數就可以完成各種具體輸入協定的open,read等操作了