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-2.0)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM