理解gstreamer架構

來源:互聯網
上載者:User

本文給出了Gstreamer的總體設計。通過閱讀本文可以瞭解Gstreamer的內部工作原理。本文編譯自gstreamer源碼中的文檔,原文在源碼中的位置是/gstreamer/docs/design/part-overview.txt。

概述

Gstreamer是一個libraries和plugins的集合,用於協助實現各種類型的多媒體應用程式,比如播放器,轉碼工具,多媒體伺服器等。

利用Gstreamer編寫多媒體應用程式,就是利用elements構建一個pipeline。element是一個對多媒體流進行處理的object,比如如下的處理:

  • 讀取檔案。
  • 不同格式的編解碼。
  • 從硬體採集裝置上採集資料。
  • 在硬體裝置上播放多媒體。
  • 多個流的複用。


elements的輸入叫做sink pads,輸出叫做source
pads。應用程式通過pad把element串連起來構成pipeline,如所示,其中順著流的方向為downstream,相反方向是upstream。

 

 

 

 

 

 


應用程式會收到來自pipeline的訊息和通知,比如EOS等。

總體設計

Gstreamer的設計目標如下:

  • 快速處理大規模資料。
  • 對多執行緒的完全支援。
  • 能處理各種格式的流媒體。
  • 不同資料流的同步。
  • 處理多種裝置的能力。


基於Gstreamer的應用程式能夠具備的處理能力依賴於系統中安裝的不同種類功能的elements的數量。

Gstreamer核心不具備處理具體的media的功能,但是element處理media時需要具備的特性很多是由Gstreamer的核心提供的。

elements

element是pipeline的最小組成部分。element提供了多個pads,或者為sink,或者為source。一個element有四種可
能的狀態,分別是NULL,READY,PAUSED,PLAYING。NULL和READY狀態下,element不對資料做任何處理,PLAYING
狀態對資料進行處理,PAUSE狀態介於兩者之間,對資料進行preroll。應用程式通過函數調用控制pipeline在不同狀態之間進行轉換。

element的狀態變換不能跳過中間狀態,比如不能從READY狀態直接變換到PLAYING狀態,必須經過中間的PAUSE狀態。

element的狀態轉換成PAUSE會啟用element的pad。首先是source pad被啟用,然後是sink
pad。pad被啟用後會調用activate函數,有一些pad會啟動一個Task。

PAUSE狀態下,pipeline會進行資料的preroll,目的是為後續的PLAYING狀態準備好資料,使得PLAYING啟動的速度更快。一些element需接收到足夠的資料才能完成向PAUSE狀態的轉變,sink
pad只有在接收到第一個資料才能實現向PAUSE的狀態轉變。

通常情況下,element的狀態轉變需要協調一致。

可對element進行如下分類:

  • source,只提供資料來源。
  • sink,比如播放裝置。
  • transform
  • demuxer
  • muxer


Bin

bin是由多個element構成的特殊的element,用圖來說明:

Pipeline

pipeline是具備如下特性的特殊的bin:

  • 選擇並管理一個全域的時鐘。
  • 基於選定的時鐘管理running_time。running_time用於同步,指的是pipeline在PLAYING狀態下花費的時間。
  • 管理pipeline的延遲。
  • 通過GstBus提供element與應用程式間的通訊方式。
  • 管理elements的全域狀態,比如EOS,Error等。


Dataflow and buffers

Gstreamer支援兩種類型的資料流,分別是push模式和pull模式。在push模式下,upstream的element通過調用downstream的sink
pads的函數實現資料的傳送。在pull模式下,downstream的element通過調用upstream的source
pads的函數實現對資料的請求。

push模式是常用的模式,pull模式一般用於demuxer或者低延遲的音頻應用等。

在pads之間傳送的資料封裝在Buffer裡,Buffer中有一個指向實際資料的指標以及一些metadata。metadata的內容包括:

  • timestamp
  • offset
  • duration
  • media type
  • 其它


在push模式下,element通過調用gst_pad_push()函數把buffer傳送給對應的pad。在pull模式下,element通過調用gst_pad_pull_range()函數把pull過來。

element在push
buffer之前需要確認對應的element具備處理buffer中的資料類型的能力。在傳說紅之前首先查詢對應的element能夠處理的格式的種類,並從中選擇合適的格式,通過gst_buffer_set_caps()函數對buffer進行設定,然後才傳送資料。

收到一個buffer後,element要首先對buffer進行檢查以確認是否能夠處理。

可以調用gst_buffer_new()函數建立一個新的buffer,也可以調用gst_pad_alloc_buffer()函數申請一個可用的
buffer。採用第二種方法接收資料的buffer可以設定接收其它類型的資料,這是通過對buffer的caps進行設定來實現的。

選擇媒體類型並對buffer進行設定的處理過程叫做caps negotianation。

Caps

Caps,也就是媒體類型,採用key/value對的列表來描述。key是一個字串類型,value的類型可能是int/float/string類型的single/list/range。

Data flow and events

除了資料流,還有events流。與資料流不同,events的傳送方向既有downstream的,也有upstream的。

events用於傳遞EOS,flushing,seeking等訊息。

有的events必須和data
flow一起進行serialized。serialized的events比如TAG,非serialized的events比如FLUSH。

Pipeline construction

gst_pipeline_create()函數用於建立一個pipeline,gst_bin_add()函數用於向pipeline中添加
element,gst_bin_remove()函數用於從pipeline中移除element。gst_element_get_pad()函數用
於檢索pipeline中的element。gst_pad_link()函數用於把pads串連在一起。

有的element會在資料流開始傳送的時候建立新的pads,通過調用函數g_signal_connect()函數,能在新的pads被建立的時候接收到訊息。

由於處理的資料互相不相容,有的elements是不能被串連到一起的。gst_pad_get_caps()函數查詢element能夠處理的資料類型。

Pipeline clock

Pipeline的一個重要功能是為pipeline中的所有elements選擇一個全域時鐘。

時鐘的作用是提供一個每秒為GST_SECOND的單調遞增的時鐘,單位是納秒。element利用這個時鐘時間來播放資料。

在pipeline被設為PLAYING之前,pipeline查詢每一個element是否能提供clock,並按照如下次序來選擇clock:

  • 應用程式選擇了一個clock。
  • 如果source element提供了clock。
  • 其它任何提供了clock的element。
  • 選擇一個預設的系統clock。


也有特殊的情況,比如存在音頻sink提供了clock,那麼就選擇其提供的clock。

Pipeline states

完成了pads的連結和signals的連結,就可以設定pipeline為PAUSED狀態啟動資料流的處理。當bin(這裡指的是pipeline)進行狀態轉換的時候要轉換所有的children的狀態,轉換的次序是從sink
element開始到source element結束,這樣做的目的是為了確保upstream
element提供資料的時候,downstream element已經準備好。



Pipeline status

Pipeline會通過bus嚮應用程式通報發生的events。bus是由pipeline提供的一個object,可以通過gst_pipeline_get_bus()函數取得。

bus分布到加入pipeline的每一個element。element利用bus來發布messages。有各種不同類型的messages,比如ERRORS,WARNINGS,EOS,STATE_CHANGED等。

pipeline以特殊的方式處理接收到的EOS message,只有當所有的sink element發送了EOS
message的時候,pipeline才會把EOS發送給應用程式。

也可以通過gst_element_query()函數擷取pipeline status,比如擷取當前的位置或者播放的時間。

Pipeline EOS

當source
filter遇上了流結束,會沿著downstream的方向向下一個element發送一個EOS的event,這個event依次傳送給每一個element,接收到EOS
event的element不再接收資料。

啟動了線程的element發送了EOS event後就不再發送資料。

EOS event最終會到達sink element。sink
element會發送一個EOS訊息,通告流結束。pipeline在接收到EOS訊息以後,把訊息發送給應用程式。只有在PLAYING狀態下會把EOS的訊息傳送給應用程式。

發送了EOS以後,pipeline保持PLAYING狀態,等待應用程式把pipeline的狀態置為PAUSE或者READY。應用程式也可以進行seek操作。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.