當點擊播放文件或者輸入要播放的文件后,vlc會執行一系列的流程。
首先需要了解視頻以及流媒體處理及播放的流程,由鏈接中的描述,視頻以及流媒體處理時,首先要解協議(http,rtmp,rtsp等),然后是解封裝(mp4,mkv,avi等),獲得音頻碼流和視頻碼流,分別解碼后,再根據時間戳進行同步。使用vlc點擊播放后,就是這一系列的流程。
點擊播放支持RTSP協議的攝像頭后,vlc會開啟線程對輸入的文件或者url進行分析(src/playlist/preparser.c),根據視頻源屬性做一些准備工作,包括:
->InputSourceInit()
->input_SplitMRL()分解url
->demux_New()創建分離器,如果是一個mp4文件,則會動態加載libmp4庫,以此類推
->demux_Control()調用libmp4的Control函數,以此類推
......
->InitPrograms()根據文件或url屬性創建解碼器(decoder),創建過程會加載對應模塊
之后就是從網絡或者本地獲取數據,堆棧如下。從堆棧中可以看到,接收線程接收網絡數據時,如果數據有封包格式(如mp4,mkv,ts等),則首先進行的是解封裝,將解封包后的數據組成block(可以理解為是一個結構體,這個結構體可以用來保存壓縮后的圖像數據),放入數據fifo中;解碼線程從數據fifo中取出block來解碼,最后交由其他渲染模塊去顯示。不同的是,攝像頭並沒有封裝視頻格式,而是傳輸的編碼后的裸數據。
同理,播放一個本地mp4文件的堆棧如下。播放本地文件就沒有了解協議的步驟,但是使用了libmp4進行了拆包。
放入數據fifo中的數據還沒有被解碼,另外還有兩個解碼線程(音頻和視頻)不斷的從各自的隊列中取數據解碼,視頻解碼線程的堆棧如下。解碼線程首先從上述數據fifo中取出數據,使用已經根據數據源格式創建好的解碼器解碼,之后將解碼后的數據放到圖像fifo中。
最后是渲染線程的堆棧,渲染線程不斷的從圖像fifo中取出數據渲染到窗體上。
程序的整體框圖如下。當RTSP session建立的時候,程序根據RTSP會話得到的SDP信息創建視頻解碼器和音頻解碼器。RTP數據到來后,經過Demux,分別放入兩個fifo中,然后兩個解碼線程分別從各自的fifo中取出視頻和音頻數據解碼。解碼后的音頻數據直接播放,解碼后的視頻數據放入picture_fifo_t中,由渲染線程負責顯示。
附:
配置好的Windows版vlc工程下載:https://github.com/jiayayao/vlc_2.1.0-vs_2010,下載后使用vs2010可以直接編譯運行,調試學習非常方便。