1. 程式人生 > >GStreamer流媒體知識介紹

GStreamer流媒體知識介紹

 

 

GStreamer框架

1、GStreamer是什麼?

眾所周知,Microsoft's Windows和Apple's MacOS對多媒體裝置、多媒體創作、播放和實時處理等方面都有很好的支援,而Linux對多媒體應用一直略顯不足,所以為了解決Linux上對多媒體方面的支援,才引進GStreamer。

GStreamer是一個通用的跨平臺的流媒體應用程式框架,基於GObject,以C語言寫成。 GStreamer並不受限於音訊和視訊處理,它能夠處理任意型別的資料流,因此任意一種流媒體應用都可以支援,如:MeidaPlayer、A/V Editor、VOIP、RTSP、A/V Coder等等。 GStreamer框架是基於外掛(plugin)和管道(pipeline)的體系結構,框架中所有功能模組都是可插拔的元件,可隨意安裝到任意管道上,因此造就了大量的GStreamer的共享庫。

 

 

2、 pipeline是什麼?

 

這是個典型的MeidaPlayer的模型。

source —— 資料來源,可能是file、http、rtp等。

demux —— 負責把容器裡的音視訊資料剝離出來,然後分別送給audio/video decoder。

decoder —— 解碼,然後把解完後的資料(pcm/yuv)送給audio/video output輸出。

output —— 負責將decoder過來的資料呈現出來。

如果把資料想象成流水的話,每個模組功能雖然不同,但基本都是接收上個模組過來的資料,然後加工,把加工後的資料送到下一個模組,這些模組通過某種方式連線起來,就形成了一個流水線(pipeline),這個流水線就是一個MediaPlayer。 GStreamer 把每個模組都看做是一個元件(element),然後構建連線和操作這些element的方法,使用者可以通過自己的需求把不同的elements排列組合,形成不同的pipeline。

 

3. element是什麼?

element是一個對多媒體流進行處理的object,也是一個具體的功能模組,是pipeline的最小組成部分。

element分類:source(只提供資料來源),sink(如播放裝置),transform,demuxer,muxer element的輸入為sink pad,輸出為source pad,通過pad把element連線起來構成pipeline 圖中downstream為順流方向,upstream為逆流方向

 

4. pad是什麼?

element的襯墊(pad)對應輸入和輸出介面,對於輸入襯墊為sink pad,對於輸出襯墊為source pad element之間都是通過pad來連結的,順序流向不能錯,也基於pad型別進行分類

pad有處理特殊資料的能力,一個pad能夠限制資料流型別(GstCaps)的通過。 連結成功的條件是:只有在兩個襯墊(pads)允許通過的資料型別一致的時候才被建立,通過caps negotiation方法。 襯墊有三種類型的時效性: 永久型(always)、隨機型(sometimes)、請求型(on request)。 永久型的襯墊一直會存在,隨機型的襯墊只在某種特定的條件下才存在(會隨機消失的襯墊也屬於隨機型), 請求型的襯墊只在應用程式明確發出請求時才出現。

 

5. 四種狀態

element有四種可能的狀態,分別是NULL,READY,PAUSED,PLAYING。

GST_STATE_NULL 預設狀態,該狀態將會回收所有被元件佔用的資源。

GST_STATE_READY 準備狀態,該狀態會得到所需的全域性資源,但資料流並未處理。

GST_STATE_PAUSED 暫停狀態,元件已經對流開始處理,一旦狀態變為 PLAYING,可以重放資料流, 與PLAYING 狀態的區別是:時鐘是禁止執行的,主要對資料進行preroll。

GST_STATE_PLAYING 與 PAUSED 狀態一模一樣,但可以執行時鐘,對資料進行處理。

通過函式gst_element_set_state()可以改變一個元件的狀態,但狀態變換不能跳變,比如不能從READY狀態 直接變換到PLAYING狀態,必須經過中間的PAUSE狀態。

 

6. element流程

element create   

  gstreamer載入時,掃描/usr/lib/gstreamer-1.0目錄下的庫,識別其中的feature,並記錄相關資訊。當使用時,檢查gstreamer core是否支援該功能,如果有,則載入相應庫,獲取資訊,建立相應的element例項。

element link

  element建立後,會新增到pipeline,在link時會通過gst_pad_query_caps(pad, NULL)查詢pad template caps。因為此時尚未開啟裝置、初始化等,所以不知道element真正支援的caps,但只要查詢的caps有交集即可link成功。

NULL->READY

  該狀態下,會初始化裝置,根據相應的class呼叫start()或open()等函式初始化相應的硬體裝置,初始化class的結構引數等。

READY->PAUSED

  進一步申請資源,確定相應的引數設定,同時會啟用pad。然後資料預滾(preroll),當資料到達時,檢查資料時間戳是否在segment內,進行資料同步,最後就是commit,進入PAUSED。

PAUSED->PLAYING

  在這個過程,設定clock時鐘執行,接收到資料時,檢查時間有效性,進行資料同步、處理,push到下游,傳送QOS事件到上游,完成一個迴圈。

 

 

7. bin是什麼?

箱櫃(bin)是由多個element構成的容器,同時bin本身也是一種element,所以能夠像操作普通element一樣操作一個bin,改變bin的狀態可以改變bin內部所有elements的狀態。

bin可以傳送匯流排訊息給它的子集elements ,包括:錯誤訊息(error messages),標籤訊息(tag messages),EOS訊息(EOS messages)。

管道(pipeline)是一個特殊的bin,當設定管道暫停或播放狀態的時候,資料流將開始流動,並且媒體資料處理也開始處理。一旦開始,pipeline將在一個單獨的執行緒中執行,直到被停止或者資料流播放完畢。

data flow:資料流在pads之間傳送,封裝在Buffer裡,Buffer包含指向資料的指標和一些metadata。

event flow:事件流與資料量不同,既有downstream方向,也有upstream,可以捕捉事件訊號,進行回撥處理

pipeline構建過程

gst_pipeline_new()函式:建立一個pipeline

gst_bin_add()函式:向pipeline中新增elements

gst_bin_remove()函式:從pipeline中移除element

gst_element_link()函式:連結pipeline中的elements

 

 

8. 緩衝區

緩衝區是指管道里的資料流,通常一個源元件會建立一個新的緩衝區,同時元件還將會把緩衝區的資料傳遞給下一個元件。使用GStreamer建立管道,不需要自己來處理緩衝區,元件將會自動處理這些緩衝區。

一個緩衝區主要組成:

指向某塊記憶體的指標

記憶體的大小

緩衝區的時間戳

一個引用計數,指出了緩衝區所使用的元件數。沒有元件可引用的時候,這個引用將用於銷燬緩衝區

 

9. message/event/signal

Bus message —— 用於gstreamer和app之間互動的,比如當一個檔案播放結束的時候,gstreamer會發一個EOS的message到GstBus上,如果app有去偵聽(函式gst_bus_add_watch),那麼在處理訊息的callback函式中就可以收到這個訊息。

event —— 用於gstreamer內部element之間(或pad之間)傳遞事件的,比如source element資料已經結束,會發出一個EOS event,順著pipeline依次向downstream方向傳遞,elements得到通知,做一些cleanup工作,當所有sink element都收到並處理之後,gstreamer內部產生一條GSTMessage,並post至GstBus,如果APP有監聽,就能知道當前播放已經結束。

signal —— 屬於GObject體系,用於app和GObject之間互動的一種機制。在gstreamer中,element本身也是gobject,所以通過signal,就可以將app和element聯絡起來。 當element發生了一些事情相讓app知道時,就可以用signal的方式來通知app,比如動態建立了一個Pad。

 

 

10. 初步總結

需要包含標頭檔案gst/gst.h來訪問庫函式。

使用gst_init初始化GStreamer庫和一些必要的引數。

使用gst_element_factory_make建立元件,引數為工廠物件名和新元件名,在bin中可查詢該元件。

使用gst_object_unref釋放元件,元件引用記數減1,任一元件建立時,引用記數為1,當引用記數為0時,元件會被銷燬。

使用gst_bin_new或gst_pipeline_new建立箱櫃。

使用gst_bin_add/remove新增/移除元件,元件所屬箱櫃,銷燬箱櫃,則箱櫃中的元件同樣被銷燬,元件移除則自動銷燬。

使用gst_element_link連結元件

每個管道預設包含一個匯流排,應用程式不需要再建立匯流排,只需在總線上設定一個訊息處理器,匯流排會輪詢訊息處理器是否有新的訊息,當採集到訊息後,匯流排將呼叫相應的回撥函式來處理。使用gst_bus_add_watch或gst_bus_add_signal_watch偵聽回撥,或使用gst_bus_peek/poll主動輪詢訊息。

 

11. 編譯說明

比如之前的helloworld程式

編譯: gcc -Wall helloworld.c -o helloworld $(pkg-config --cflags --libs gstreamer-0.10)

編譯時藉助了pkg-config命令,用於獲得某一個庫/模組的所有編譯相關的資訊。

pkg-config --cflags --libs gstreamer-0.10 會把gstreamer-0.10編譯所依賴的庫路徑和標頭檔案路徑全部找出來,不用再依次寫出,這條命令引數相當於: -pthread -I/usr/include/glib-2.0 -I/usr/lib/i386-linux-gnu/glib-2.0/include -I/usr/include/gstreamer-0.10 -I/usr/include/libxml2 -pthread -L/usr/lib/i386-linux-gnu -lgstreamer-0.10 -lgobject-2.0 -lgmodule-2.0 -lxml2 -lgthread-2.0 -lrt -lglib-