FFMPEG打開媒體的的過程開始于avformat_open_input,是以該函數的重要性不可忽視。
在該函數中,FFMPEG完成了:
輸入輸出結構體AVIOContext的初始化;
輸入資料的協定(例如RTMP,或者file)的識别(通過一套評分機制):1判斷檔案名的字尾 2讀取檔案頭的資料進行比對;
使用獲得最高分的檔案協定對應的URLProtocol,通過函數指針的方式,與FFMPEG連接配接(非專業用詞);
剩下的就是調用該URLProtocol的函數進行open,read等操作了
以下是通過eclipse+MinGW調試FFMPEG源代碼獲得的函數調用關系圖
可見最終都調用了URLProtocol結構體中的函數指針。
URLProtocol結構是一大堆函數指針的集合(avio.h檔案)參見第四章資料結構
URLProtocol功能就是完成各種輸入協定的讀寫等操作
但輸入協定種類繁多,它是怎樣做到“大一統”的呢?
原來,每個具體的輸入協定都有自己對應的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等操作了