歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux綜合 >> Linux資訊 >> 更多Linux >> 用 GStreamer 簡化 Linux 多媒體開發

用 GStreamer 簡化 Linux 多媒體開發

日期:2017/2/27 14:23:15   编辑:更多Linux
  GStreamer 是 GNOME 桌面環境下用來構建流媒體應用的編程框架(framework),其目標是要簡化音/視頻應用程序的開發,目前已經能夠被用來處理像 mp3、Ogg、MPEG1、MPEG2、AVI、Quicktime 等多種格式的多媒體數據。     一、基本概念   GStreamer 作為 GNOME 桌面環境推薦的流媒體應用框架,采用了基於插件(plugin)和管道(pipeline)的體系結構,框架中的所有的功能模塊都被實現成可以插拔的組件(component), 並且在需要的時候能夠很方便地安裝到任意一個管道上,由於所有插件都通過管道機制進行統一的數據交換,因此很容易利用已有的各種插件“組裝”出一個功能完善的多媒體應用程序。     1.1 元件處理   對於需要應用 GStreamer 框架的程序員來講,GstElement 是一個必須理解的概念,因為它是組成管道的基本構件,也是框架中所有可用組件的基礎,這也難怪 GStreamer 框架中的大部分函數都會涉及到對 GstElement 對象的操作。從 GStreamer 自身的觀點來看,GstElement 可以描述為一個具有特定屬性的黑盒子,它通過連接點(link point)與外界進行交互,向框架中的其余部分表征自己的特性或者功能。     按照各自功能上的差異,GStreamer 又將 GstElement 細分成如下幾類:   - Source Element 數據源元件 只有輸出端,它僅能用來產生供管道消費的數據,而不能對數據做任何處理。一個典型的數據源元件的例子是音頻捕獲單元,它負責從聲卡讀取原始的音頻數據,然後作為數據源提供給其它模塊使用。   - Filter Element 過濾器元件 既有輸入端又有輸出端,它從輸入端獲得相應的數據,並在經過特殊處理之後傳遞給輸出端。一個典型的過濾器元件的例子是音頻編碼單元,它首先從外界獲得音頻數據,然後根據特定的壓縮算法對其進行編碼,最後再將編碼後的結果提供給其它模塊使用。   - Sink Element 接收器元件 只有輸入端,它僅具有消費數據的能力,是整條媒體管道的終端。一個典型的接收器元件的例子是音頻回放單元,它負責將接收到的數據寫到聲卡上,通常這也是音頻處理過程中的最後一個環節。     圖1將有助於你更好地理解數據源元件、過濾器元件和接收器元件三者的區別,同時也不難看出它們是如何相互配合形成管道的:     圖1     需要注意的是,過濾器元件的具體形式是非常靈活的,GStreamer 並沒有嚴格規定輸入端和輸出端的數目,事實上它們都可以是一個或者多個。圖2 是一個 AVI 分離器的基本結構,它能夠將輸入數據分離成單獨的音頻信息和視頻信息,用於實現該功能的過濾器元件很明顯只具有一個輸入端,但卻需要有兩個輸出端。     圖2      要想在應用程序中創建 GstElement 對象,唯一的辦法是借助於工廠對象 GstElementFactory。由於 GStreamer 框架提供了多種類型的 GstElement 對象,因此對應地提供了多種類型的 GstElementFactory 對象,它們是通過特定的工廠名稱來進行區分的。例如,下面的代碼通過 gst_element_factory_find() 函數獲得了一個名為 mad 的工廠對象,它之後可以用來創建與之對應的 MP3 解碼器元件:     GstElementFactory *factory; factory = gst_element_factory_find ("mad");     成功獲得工廠對象之後,接下來就可以通過 gst_element_factory_create() 函數來創建特定的 GstElement 對象了,該函數在調用時有兩個參數,分別是需要用到的工廠對象,以及即將創建的元件名稱。元件名稱可以用查詢的辦法獲得,也可以通過傳入空指針(NULL)來生成工廠對象的默認元件。下面的代碼示范了如何利用已經獲得的工廠對象,來創建名為 decoder 的 MP3 解碼器元件:     GstElement *element; element = gst_element_factory_create (factory, "decoder");     當創建的 GstElement 不再使用的時候,還必須調用 gst_element_unref() 函數釋放其占用的內存資源:     gst_element_unref (element);     GStreamer 使用了與 GObject 相同的機制來對屬性(property)進行管理,包括查詢(query)、設置(set)和讀取(get)等。所有的 GstElement 對象都需要從其父對象 GstObject 那裡繼承名稱(name)這一最基本的屬性,這是因為像 gst_element_factory_make() 和 gst_element_factory_create() 這樣的函數在創建工廠對象和元件對象時都會用到名稱屬性,通過調用 gst_object_set_name() 和 gst_object_get_name() 函數可以設置和讀取 GstElement 對象的名稱屬性。     1.2 襯墊處理   襯墊(pad)是 GStreamer 框架引入的另外一個基本概念,它指的是元件(element)與外界的連接通道,對於框架中的某個特定元件來說,其能夠處理的媒體類型正是通過襯墊暴露給其它元件的。成功創建 GstElement 對象之後,可以通過 gst_element_get_pad() 獲得該元件的指定襯墊。例如,下面的代碼將返回 element 元件中名為 src 的襯墊:     GstPad *srcpad; srcpad = gst_element_get_pad (element, "src");     如果需要的話也可以通過 gst_element_get_pad_list() 函數,來查詢指定元件中的所有襯墊。例如,下面的代碼將輸出 element 元件中所有襯墊的名稱:     GList *pads; pads = gst_element_get_pad_list (element); while (pads) {  GstPad *pad = GST_PAD (pads->data);  g_print ("pad name is: %sn", gst_pad_get_name (pad));  pads = g_list_next (pads); }     與元件一樣,襯墊的名稱也能夠動態設置或者讀取,這是通過調用 gst_pad_get_name () 和 gst_pad_set_name() 函數來完成的。所有元件的襯墊都可以細分成輸入襯墊和輸出襯墊兩種,其中輸入襯墊只能接收數據但不能產生數據,而輸出襯墊則正好相反,只能產生數據但不能接收數據,利用函數 gst_pad_get_direction() 可以獲得指定襯墊的類型。GStreamer 框架中的所有襯墊都必然依附於某個元件之上,調用 gst_pad_get_parent() 可以獲得指定襯墊所屬的元件,該函數的返回值是一個指向 GstElement 的指針。 襯墊從某種程度上可以看成是元件的代言人,因為它要負責向外界描述該元件所具有的能力。GStreamer 框架提供了統一的機制來讓襯墊描述元件所具有的能力(capability),這是借助數據結構 _GstCaps 來實現的:     strUCt _GstCaps {  gchar *name; /* the name of this caps */  guint16 id; /* type id (major type) */  guint refcount; /* caps are refcounted */  GstProps *properties; /* properties for this capability */  GstCaps *next; /* caps can be chained together */ };     以下是對 mad 元件的能力描述,不難看出該元件中實際包含 sink 和 src 兩個襯墊,並且每個襯墊都帶有特定的功能信息。名為sink的襯墊是 mad 元件的輸入端,它能夠接受 MIME 類型為 audio/mp3 的媒體數據,此外還具有 layer、bitrate 和 framed 三種屬性。名為 src 的襯墊是 mad 元件的輸出端,它負責產生 MIME 類型為 audio/raw 媒體數據,此外還具有 format、depth、rate 和 channels 等多種屬性。     Pads:  SINK template: ’sink’   Availability: Always   Capabilities:   ’mad_sink’:    MIME type: ’audio/mp3’:  SRC template: ’src’   Availability: Always   Capabilities:    ’mad_src’:     MIME type: ’audio/raw’:     format: String: int     endianness: Integer: 1234     width: Integer: 16     depth: Integer: 16     channels: Integer range: 1 - 2     law: Integer: 0     signed: Boolean: TRUE     rate: Integer range: 11025 - 48000     准確地說,GStreamer 框架中的每個襯墊都可能對應於多個能力描述,它們能夠通過函數 gst_pad_get_caps() 來獲得。例如,下面的代碼將輸出pad襯墊中所有能力描述的名稱及其 MIME 類型:     GstCaps *caps; caps = gst_pad_get_caps (pad); g_print ("pad name is: %sn", gst_pad_get_name (pad)); while (caps) {  g_print (" Capability name is %s, MIME type is %sn",  gst_caps_get_name (cap),  gst_caps_get_mime (cap));  caps = caps->next; }     1.3 箱櫃   箱櫃(bin)是 GStreamer 框架中的容器元件,它通常被用來容納其它的元件對象,但由於其自身也是一個 GstElement 對象,因此實際上也能夠被用來容納其它的箱櫃對象。利用箱櫃可以將需要處理的多個元件組合成一個邏輯元件,由於不再需要對箱櫃中的元件逐個進行操作,因此能夠很容易地利用它來構造更加復雜的管道。在 GStreamer 框架中使用箱櫃還有另外一個優點,那就是它會試著對數據流進行優化,這對於多媒體應用來講是很具吸引力的。     圖3描述了箱櫃在 GStreamer 框架中的典型結構:     圖3     在 GStreamer 應用程序中使用的箱櫃主要有兩種類型:   - GstPipeline 管道是最常用到的容器,對於一個 GStreamer 應用程序來講,其頂層箱櫃必須是一條管道。   - GstThread 線程的作用在於能夠提供同步處理能力,如果 GStreamer 應用程序需要進行嚴格的音視頻同步,一般都需要用到這種類型的箱櫃。     GStreamer 框架提供了兩種方法來創建箱櫃:一種是借助工廠方法,另一種則是使用特定的函數。下




Copyright © Linux教程網 All Rights Reserved