播放器解決了視訊播放的問題。通常來說,解決問題最好的辦好就是大而化小,小而化無。因為整個播放過程是一個複雜的過程,是以播放器也采用分而治之的辦法。
簡單來說,這個大問題可以分解為四個小問題。
1,資料接收;
2,資料解析;
3,資料解碼;
4,資料輸出。
我會對mplayer和vlc這兩個開源播放器的代碼結構來說明這四個問題。
一,資料接收(access)
自然,我們不能無中生有,要處理資料,總要有資料來源才行。但是資料來源的管道有很多種。
可能是硬碟檔案,可能是dvdCD光牒,也可能是http/httplive資料包,也可能是rtp資料包(vod),或者ftp,廣播電視的ts流等等。
是以第一步我們要處理的問題就是如何把不同的資料來源統一一個接口。這需要不同資料包解析器,也就是實作不同的協定來滿足這個需求。
對于mplayer,相關的代碼在strearm,
對于vlc,相關的代碼在/modules/access
檢視代碼目錄,裡面檔案名可以和我們前面說的一些資料來源一一對應。是以如果我們需要實作某種協定,大抵是可以從這裡擷取一些實作思路的。
二,資料解析(demux)
有了資料了,我們還要解析這些資料。
為了友善媒體檔案的傳輸,我們要把音頻,圖像,同步資訊等等一堆資訊放到一起(就是上一篇說的容器),這個過程就是mux(multiplex)。
但是為了友善媒體檔案的處理,我們又需要解複用demux(Demultiplexer)
Container是為了解決的傳輸而誕生的,demux就是為了解析而誕生的。
不同的容器需要不同的解析器,就是不同的demux接口,為了友善程式設計,我們同樣需要統一接口。我們來看看mplayer和vlc是如何做的。
mplayer把相關代碼放在了libmpdemux裡面。
vlc把相關代碼放在/modules/demux裡面。
這兩個代碼統一各種容器的解析方式(就是我們常見的avi,ts,mkv的解析)。
不過需要注意的是,這些代碼很大一部分都是warp的ffmpeg/libavformat裡面的代碼。
三,解碼(decode)
上面那個過程把音視訊資料分離,我們得到的資料可能是mpeg-2/h.264壓縮的視訊,也可能是mp3/aac/ac-3等音頻資料。
但是這些資料都是壓縮過的,我們知道,螢幕是由一個一個的點結成的,這一個一個點又是由rgb來描述的,聲霸卡是處理一個一個音頻幀的。
這個過程我們要解決的問題就是把壓縮過的資料還原出來。如何還原?沒錯,靠我們的解碼器。
上一篇說了不同的解碼标準,現實中的情況是,我們有了一個标準,但是我們可能根據這個标準來實作不同的解碼器。就像我們有一張桌子的草圖,但是我們做的桌子卻有不同的顔色一個。标準有了,實作可以不同。
mplayer把這塊代碼放到libmpcodecs裡
vlc把這塊代碼放到/modules/codec裡。
不過要指出的是,這兩塊代碼同樣大部分是在warp ffmpeg/libavcodec。
ffmpeg真是做為神一樣庫而存在啊。
四,資料輸出(render)
準備好了解碼後的資料,就差最好一步輸出了。
視訊通常會解碼為yuv資料,音頻通常會解碼為pcm資料。然後我們把這些資料分别放到螢幕和聲霸卡裡,播放過程就算完成了。
同樣,資料輸出也有很多管道,也需要統一。
圖像可能會輸出到sdl,x11或者framebuffer,或者directfb,也可能是wingdi。
音頻可能會出到oss,alsa,等等。
為了統一這些,vlc和mplayer同樣warp了一些庫,
mplayer放到libvo與libao