利用FFmpeg和管道(pipe),解決非URL和非文件的輸入形式函數
問題描述:利用FFmpeg來解碼,可是輸入方式不是URL,也不是文件系統中的文件,而是內存中的buffer。線程
解決此問題有兩個思路,首先明確一點,libavformat中有幾個類,有URLProtocol(雖然叫URLxxx,可是不單單是URL的,它但是掌管了全部的輸入方式),AVOutputFormat(有muxer也有demuxer),AVInputFormat(有muxer也有demuxer)。設計
它們對應實例能夠舉幾個例子:指針
URLProtocol::ff_pipe_protocol、ff_http_protocol、ff_file_protocol。。。orm
AVOutputFormat:ff_mpegts_demuxer、ff_mp3_demuxer。。。接口
AVInputFormat:ff_mpegts_demuxer、ff_mp3_demuxer。。。ip
而後來講int avformat_open_input(AVFormatContext **ps, const char *filename, AVInputFormat *fmt, AVDictionary **options);函數,它的filename參數只接受URL或者文件名,可是對於問題中所說的狀況,就不適合了,因此咱們能夠用第一個簡單的辦法來解決。內存
下面舉實例說明。get
如今假如是要用mpegts流的數據來源,每次咱們都能調用某個接口(例如:get_ts_packet(fd, ts_buf, 188);)來得到一個完整的188字節的ts包存入buf裏面,如何傳給FFmpeg呢?input
假設線程1是主線程,線程2是獲取ts包的線程,不斷調用get_ts_packet接口,線程3來調用FFmpeg。思路是
線程1:利用mkfifo新建一個命名管道(MY_FIFO_PIPE);
線程2:不斷去得到ts包,而後就轉存到MY_FIFO_PIPE裏面;
線程3:設計爲FFmpeg,直接調用avformat_open_input(&avfmtctx, MY_FIFO_PIPE, NULL, NULL);
這樣在不修改FFmpeg的前提下使用FFmpeg來進行解複用解碼。
還有另外一種思路,就是修改URLProtocol中的某一個實例(好比file.c中的ff_file_protocol),或者新建一個URLProtocol的實例(ff_xxx_protocol),而後實現下列幾個函數指針:open、read、seek(如不須要seek可不用實現),以此來適配相應的數據來源方式,最終達到使用ffmpeg標準流程來編解碼的目的。