GStreamer(一)
http://antkillerfarm.github.io/
概況
當(dāng)前GStreamer主要有兩個(gè)大的版本分支:
1)0.10.x系列。這個(gè)版本系列的歷史較久,相關(guān)資源比較豐富。但目前官方已經(jīng)不再發(fā)展和支持該版本。該系列有中文版的用戶手冊。
2)1.x系列。2012年以來發(fā)布的版本系列,也是官方推薦的版本系列。只有英文的用戶手冊,但手冊的內(nèi)容與0.10.x相差不大,盡管API已經(jīng)不再兼容舊版本。以下的描述以1.x系列為準(zhǔn)。1.x系列被設(shè)計(jì)為可以和0.10.x系列在系統(tǒng)中共存,因此在同一臺電腦上,同時(shí)安裝0.10.x系列和1.x系列是完全沒有沖突的。
GStreamer插件
插件分類
GStreamer本質(zhì)上只是一個(gè)多媒體應(yīng)用框架,具體的多媒體播放功能由插件來完成。
http://gstreamer.freedesktop.org/documentation/plugins.html
這個(gè)網(wǎng)頁就是gstreamer的插件列表。表中列出的插件,分屬4個(gè)不同的插件集:
gst-plugins-base。這類插件格式規(guī)范,維護(hù)的也很好。
gst-plugins-good。這類插件有高質(zhì)量的代碼(但格式未必規(guī)范),而且許可證也符合要求(LGPL或與LGPL兼容的許可證)。
gst-plugins-ugly。這類插件有高質(zhì)量的代碼,但許可證方面有問題。
gst-plugins-bad。這類插件尚不成熟,需要更多文檔、測試和應(yīng)用。
插件安裝方法,以gst-plugins-base為例。
sudo apt-get install gstreamer1.0-plugins-base
除了上面列出的插件之外,目前的做法,更傾向于使用ffmpeg作為后端編解碼庫,尤其是編解碼更復(fù)雜的視頻文件。因此在0.10.x時(shí)代,提供了gstreamer0.10-ffmpeg插件,而1.x時(shí)代,則有g(shù)streamer1.0-libav提供對avcodec、avformat等ffmpeg庫的支持。
核心插件
核心插件又稱gst-plugins-core,目前已經(jīng)集成到gstreamer代碼中,沒有獨(dú)立的庫。
和上面提到的四類插件不同。它不提供具體的多媒體編解碼功能,而是配合框架,搭建完整的多媒體流水線。核心插件無須選擇(也不能選擇),默認(rèn)已經(jīng)集成到gstreamer的插件庫中,它的相關(guān)資料參見:
http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer-plugins/html/
這里僅對其中一部分插件的功能描述如下:
fakesink:一個(gè)數(shù)據(jù)只進(jìn)不出的“黑洞”。例如,一個(gè)視頻文件一般包括視頻流和音頻流。如果設(shè)備只能播放音頻(例如音箱),那么視頻流對于設(shè)備來說,就是沒有意義的東西。這時(shí)可以用fakesink插件將之吃掉。否則,由于GStreamer會在視頻流和音頻流之間進(jìn)行同步,如果視頻流沒有被消耗,音頻流也無法向前進(jìn)。
tee:1路分成N路的分路器。與之相對應(yīng)的是funnel:N路合成1路的合路器。
萬能插件
GStreamer除了那些完成具體功能的插件以外,還有一些抽象的高級插件,如playbin插件。該插件使用了GStreamer的自動(dòng)加載(Auto plugging)機(jī)制,可以自動(dòng)根據(jù)媒體類型,選擇不同的管道播放,相當(dāng)于是個(gè)萬能播放插件。對于GStreamer應(yīng)用開發(fā)人員來說,是個(gè)相當(dāng)好用的東西。
playbin插件負(fù)責(zé)媒體播放的全過程,還有其他一些只負(fù)責(zé)某個(gè)步驟的全能插件:
decodebin:解碼插件。
autoaudiosink:音頻播放插件
autovideosink:視頻播放插件
GStreamer應(yīng)用
相關(guān)工具軟件
GStreamer提供了一個(gè)工具軟件集——gstreamer-tools。其安裝方法如下:
sudo apt-get install gstreamer-tools gstreamer1.0-tools
它包括以下工具:
gst-launch:創(chuàng)建GStreamer管道的原型驗(yàn)證工具。它是其中用的最廣泛的工具——網(wǎng)上關(guān)于GStreamer的問題討論,多數(shù)并不貼出代碼,而是給出gst-launch形式的命令。
下面是一個(gè)播放mp3文件的示例:
gst-launch filesrc location=1.mp3 ! mad ! audioconvert ! autoaudiosink
需要注意的是上面的命令中,!兩邊都要留空格,不然命令會執(zhí)行錯(cuò)誤。
gst-inspect:用于查詢GStreamer插件的相關(guān)信息,也非常常用。比如,如果某個(gè)媒體文件無法播放,首先使用gst-inspect查詢一下相關(guān)插件是否正確安裝。
其他的還有g(shù)st-typefind、gst-xmllaunch、gst-feedback。
注意1.x系列的工具名和0.10.x系列的略有不同,例如gst-launch在1.x系列中叫做gst-launch-1.0。
播放視頻
播放視頻也可以使用playbin插件。這里主要存在以下幾個(gè)問題:
1)不支持0.10.x系列。由于視頻解碼主要由ffmpeg來實(shí)現(xiàn),而在Ubuntu14.04以后,官方已經(jīng)移除了gstreamer0.10-ffmpeg插件,因此很多視頻流已經(jīng)無法處理。
2)xvimagesink錯(cuò)誤問題。playbin插件默認(rèn)使用autovideosink作為視頻播放插件,而autovideosink優(yōu)先使用xvimagesink插件。這個(gè)插件的優(yōu)點(diǎn)是使用了硬件加速的功能,缺點(diǎn)是需要顯卡驅(qū)動(dòng)的支持。因此,無論在真實(shí)機(jī)器還是虛擬機(jī)上,都有顯卡驅(qū)動(dòng)不匹配,從而導(dǎo)致錯(cuò)誤的問題。
這時(shí)可以換個(gè)思路,自己構(gòu)建播放視頻的管道,其核心是使用ximagesink替代xvimagesink。ximagesink是一個(gè)兼容性較好的videosink,缺點(diǎn)是速度沒有xvimagesink快。
以下是一個(gè)播放視頻文件的示例:
gst-launch-1.0 filesrc location=1.avi ! decodebin name=dmux dmux. ! queue ! audioconvert ! autoaudiosink dmux. ! queue ! videoconvert ! ximagesink
示例中的dmux是個(gè)用于定位的標(biāo)記,兩個(gè)dmux.實(shí)際上都指向同一個(gè)位置,這樣就可以在一個(gè)線性的字符串中,表示若干個(gè)流水管道。這種表示法多用于多媒體流的分路和合路處理。標(biāo)記的名稱是無所謂的,將dmux改為其他字符串,并不影響管道的實(shí)際含義。
插件裁剪
這里以播放mp3文件為例,說明插件裁剪的相關(guān)原則。插件裁剪問題在嵌入式設(shè)備上遇到的比較多。受限于有限的存儲空間,我們一般不可能將所有的插件都集成進(jìn)設(shè)備中,而只能根據(jù)產(chǎn)品需求,將必要的插件集成進(jìn)去。這時(shí)就遇到一個(gè)問題:我們該如何選擇被集成的插件集合呢?
1.上層的應(yīng)用程序一般都是通過playbin插件播放音頻文件。因此playbin必選。
2.解碼器根據(jù)音頻格式的不同而不同。例如mp3文件可選用mad作為解碼插件。
3.播放也需要相應(yīng)的插件,比如Linux上最常用的alsasink。
4.由于playbin采用了Auto plugging機(jī)制,因此類似autodetect、audioconvert之類的auto插件也是必選,否則會導(dǎo)致playbin的工作異常。
此外,當(dāng)播放某種文件格式失敗的時(shí)候,可以嘗試使用gst-launch命令播放,這時(shí)的log會比平時(shí)多一些,有助于確認(rèn)問題所在。
播放ape文件
1.ape文件的播放主要依賴于ffmpeg,因此需要添加gst1-libav庫,作為ffmpeg和Gstreamer之間的橋梁。
Openwrt默認(rèn)的gst1-libav庫,并沒有開啟ape格式的支持,需要手動(dòng)修改相關(guān)文件,具體方法可參考已有的ac3格式的實(shí)現(xiàn)。
2.運(yùn)行過程中會出現(xiàn)如下錯(cuò)誤:
No decoder available for type 'application/x-apetag'
這個(gè)錯(cuò)誤的原因是:typefind的時(shí)候,application/x-ape的優(yōu)先級沒有application/x-apetag的高。而前者才是ffmpeg庫播放ape文件時(shí)的MIME。
修改辦法:在gst-plugins-base/gst/typefind/gsttypefindfunctions.c中,將application/x-ape和application/x-apetag交換一下優(yōu)先級。
這里需要修改兩處地方:
1)gst_type_find_suggest函數(shù)的參數(shù)。
2)TYPE_FIND_REGISTER宏。
播放wav文件
wav文件雖然是最簡單的一類音頻文件,但仍然不可以直接播放,能夠直接被ALSA識別的是PCM流。播放wav的插件是wavparse。
處理播放列表(Playlist)
常用的播放列表文件格式包括.m3u/.m3u8、.pls、.xspf等。詳細(xì)列表參見:
https://en.wikipedia.org/wiki/Playlist
可以在rhythmbox中,生成一個(gè)播放列表,然后保存成文件。rhythmbox支持.m3u、.pls、.xspf格式的輸出。
但是rhythmbox畢竟只是播放軟件,一些高階的播放列表功能,比如批量生成、修改TAG之類的還是力有未逮。這時(shí)就需要專門的Tag Editor了。
這里推薦EasyTag,但它只支持生成.m3u文件。它的安裝方法:
sudo apt-get install easytag
GStreamer本身不能處理播放列表文件。官方的插件庫中也沒有處理播放列表文件的插件。
從實(shí)現(xiàn)角度看,處理播放列表主要有兩種方式:
1.編寫GStreamer插件,在GStreamer層解決問題。這方面的例子參見:
https://github.com/mopidy/mopidy/pull/460
2.在應(yīng)用層處理播放列表。比如Totem。
我比較認(rèn)可第2種方法。從程序設(shè)計(jì)的角度看,播放列表更多是一種應(yīng)用層的呈現(xiàn)方式,而非GStreamer所擅長的流處理。從設(shè)計(jì)原則來看,GStreamer作為底層庫,應(yīng)提供“機(jī)制”,而非“方法”。據(jù)說GStreamer官方也對這個(gè)問題爭議了很久,但最終還是不打算支持對播放列表的處理。
Totem Playlist Parser
Totem中處理播放列表的代碼,被單獨(dú)抽離出來,形成了Totem Playlist Parser庫。其官網(wǎng)為:
https://developer.gnome.org/totem-pl-parser
安裝方法:
sudo apt-get install libtotem-plparser-dev
代碼示例參見:
https://github.com/antkillerfarm/antkillerfarm_crazy/tree/master/gstreamer/tutorials/step1
Totem Playlist Parser的openwrt移植
安裝依賴軟件包
Totem Playlist Parser除了依賴常見的glib2、libxml、libsoup之外,還依賴gmime和quvi。其中后者不是必須的,如果不打算網(wǎng)上下載視頻的話,可以不裝。(quvi包主要是一堆lua腳本,用于解析類似youtube、foxnews之類的媒體網(wǎng)站的內(nèi)容。)
完成上面的操作之后,編譯階段基本就沒有什么大問題了。然而,上板調(diào)試,卻出現(xiàn)解析失敗的現(xiàn)象。
安裝MIME解析文件
Totem Playlist Parser最重要的函數(shù)是plparse/totem-pl-parser.c: totem_pl_parser_parse_internal。這個(gè)函數(shù)的主要思路是在special_types和dual_types數(shù)組中,根據(jù)MIME查找相關(guān)的處理函數(shù)。其代碼片段如下:
static PlaylistTypes special_types[] = {PLAYLIST_TYPE ("audio/x-mpegurl", totem_pl_parser_add_m3u, NULL, FALSE),PLAYLIST_TYPE ("video/vnd.mpegurl", totem_pl_parser_add_m4u, NULL, FALSE),PLAYLIST_TYPE ("audio/x-scpls", totem_pl_parser_add_pls, NULL, FALSE),... };從這里可以看出,找到正確的MIME才是開始解析的關(guān)鍵。這里使用了glib提供的g_content_type_guess函數(shù)判斷文件的MIME。
判斷MIME的方式有兩種:
1.根據(jù)文件名判斷。
這種方式的主要函數(shù)是glib/gio/xdgmime.c: xdg_mime_get_mime_types_from_file_name。
2.根據(jù)文件的內(nèi)容(主要是magic number)判斷。
這種方式的主要函數(shù)是glib/gio/xdgmime.c: xdg_mime_get_mime_type_for_data。
無論何種方式,這里實(shí)際上都需要有一個(gè)MIME解析文件提供給程序,用以確定文件的MIME類型。
這里以文件名方式為例,講一下MIME解析文件的基本知識。
1.存儲路徑
通常在/usr/share/mime下,其他可能的路徑,可在代碼中查到。
2.格式類型
主要有三種:
1)XML型。這種類型的解析文件功能和可閱讀性都很強(qiáng),但所占空間較大。
2)glob型。分為glob和glob2兩種格式。功能一般,可閱讀,占用空間一般。
3)cache型。二進(jìn)制文件,不可閱讀,空間最小,效率最高。
我這里采用glob2文件,既方便修改,其占用空間也在可接受的范圍內(nèi)。
總結(jié)
以上是生活随笔為你收集整理的GStreamer(一)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ALSA(一)
- 下一篇: GStreamer(二)