ffmpeg一般情況下支援打開一個本地檔案,例如“c:\test.avi”
或者是一個流媒體協定的url,例如“rtmp://222.31.64.208/vod/test.flv”
其打開檔案的函數是avformat_open_input(),直接将檔案路徑或者流媒體url的字元串傳遞給該函數就可以了。
但其是否支援從記憶體中讀取資料呢?這個問題困擾了我很長時間。當時在做項目的時候,通過winpcap抓取網絡上的rtp包,打算直接送給ffmpeg進行解碼。一直沒能找到合适的方法。因為抓取的資料包是存在記憶體中的,是以無法傳遞給avformat_open_input()函數其路徑(根本沒有路徑=
=)。當然也可以将抓取的資料報存成檔案,然後用ffmpeg打開這個檔案,但是這樣的話,程式的就太難控制了。
後來經過分析ffmpeg的源代碼,發現其竟然是可以從記憶體中讀取資料的,代碼很簡單,如下所示:
關鍵要在avformat_open_input()之前初始化一個aviocontext,而且将原本的avformatcontext的指針pb(aviocontext類型)指向這個自行初始化aviocontext。當自行指定了aviocontext之後,avformat_open_input()裡面的url參數就不起作用了。示例代碼開辟了一塊空間iobuffer作為aviocontext的緩存。
此外buffer就是期望讀取資料的記憶體,fill_iobuffer則是讀取buffer資料至iobuffer的回調函數。fill_iobuffer()形式(參數,傳回值)是固定的,是一個回調函數,如下所示(隻是個例子,具體怎麼讀取資料可以自行設計)。