GStreamer 入門使用教學(一):播放網路影片串流(Streaming)Hello World 程式

這是 GStreamer 的入門使用教學,播放網路影片串流的 Hello World 程式。

gstreamer-logo

GStreamer 是 GNOME 桌面環境之下用來建立多媒體串流應用的架構(framework),可以簡化影音相關應用程式的開發流程,支援各種常用的多媒體影音格式,如 mp3、ogg、mpeg1、mpeg2、avi、quicktime 等。


下面這段 C 語言程式碼是使用 GStreamer 函式庫,播放網路上的串流影片,請將這段程式碼儲存為 basic-tutorial-1.c

#include <gst/gst.h>
int main(int argc, char *argv[]) {
  /* 基本變數宣告 */
  GstElement *pipeline;
  GstBus *bus;
  GstMessage *msg;

  /* 初始化 GStreamer */
  gst_init (&argc, &argv);

  /* 建立 pipeline */
  pipeline = gst_parse_launch ("playbin2 uri=http://docs.gstreamer.com/media/sintel_trailer-480p.webm", NULL);

  /* 開始撥放影片 */
  gst_element_set_state (pipeline, GST_STATE_PLAYING);

  /* Wait until error or EOS */
  bus = gst_element_get_bus (pipeline);
  msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE, GST_MESSAGE_ERROR | GST_MESSAGE_EOS);

  /* 釋放記憶體資源 */
  if (msg != NULL)
    gst_message_unref (msg);
  gst_object_unref (bus);
  gst_element_set_state (pipeline, GST_STATE_NULL);
  gst_object_unref (pipeline);
  return 0;
}

整個程式的執行流程可以分為以下幾個部分:

Part 1

/* 初始化 GStreamer */
gst_init (&argc, &argv);

程式一開始會先呼叫 gst_init() 進行初始化,只要是有使用到 GStreamer 的程式,一開始都要先呼這個函數,它的作用主要有:

  • 初始化 GStreamer 內部的資料結構。
  • 檢查所有可用的附加元件(plugins)。
  • 解析與執行從命令列所傳入的 GStreamer 參數。

當然如果想要讓程式可以解析與執行從命令列所傳入的 GStreamer 參數,在呼叫 gst_init() 時就記得要傳入 &argc&argv 兩個變數。

Part 2

/* 建立 pipeline */
pipeline = gst_parse_launch ("playbin2 uri=http://docs.gstreamer.com/media/sintel_trailer-480p.webm", NULL);

接著就是呼叫 gst_parse_launch() 建立播放影片的管線(pipeline),這個部分是整個程式最重要的地方。

gst_parse_launch()

GStreamer 是專門設計用來處理多媒體資料流的一個架構,所有的多媒體資料流都是從來源端(source)開始,流向目的端(sink),中間經過一連串的各種影音處理,而這樣的架構就稱為管線(pipeline)。

在 GStreamer 的程式中,程式設計者可以依照自己的需求選取不同的影音處理元件,打造出適合自己的管線來處理多媒體資料,而如果這個管線非常簡單的時候,您可以直接呼叫 gst_parse_launch() 來直接建立並執行這個管線。

gst_parse_launch() 是一個非常好用的函數,他可以直接解析輸入的文字管線描述,建立一個真正可以處理資料的管線,而 GStreamer 中有一個 gst-launch 測試工具就是直接使用這個函數來建立管線的,這個工具在開發與測試比較複雜的管線時會非常有用,您可以參考 gst-launch 指令的相關使用方式

playbin2

在呼叫 gst_parse_launch() 時,還要指定管線的內容,這裡我們只使用 playbin2 這個影片撥放用的元件,也就是說這個管線只有這個元件而已。

playbin2 是一個特殊的元件,它同時是資料的來源端與目的端,單獨一個元件即可作為一個完整的管線,它在內部會自動連接必要的元件去撥放這裡指定的多媒體串流,開發者可以不需要煩惱這個問題,雖然它不向一般自建的管線那樣可以自行調整許多細部的參數,不過對於簡單的教學與應用而言,算是很夠用了。

在這個範例中,我們只有傳入一個 URI 參數給 playbin2,指定多媒體的來源網址,您也可以任意更改這個網址,放入自己的影片檔試試看,而通訊協定不論是網頁的 http:// 或是本機的 file://playbin2 在內部都會自動連接適合的元件來處理。

Part 3

/* 開始撥放影片 */
gst_element_set_state (pipeline, GST_STATE_PLAYING);

呼叫 gst_element_set_state() 將管線(只包含一個元件)的狀態設定為 GST_STATE_PLAYING,開始撥放影片串流。

在 GStreamer 的管線中,每個元件都有一個狀態,就好像影片撥放器的播放與停止一樣,我們必須把狀態設定為撥放(GST_STATE_PLAYING),他才會真正開始處理資料。

Part 4

/* Wait until error or EOS */
bus = gst_element_get_bus (pipeline);
msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE, GST_MESSAGE_ERROR | GST_MESSAGE_EOS);

接著呼叫 gst_element_get_bus() 取得管線的 bus,然後呼叫 gst_bus_timed_pop_filtered(),程式會一直 block 在這裡,直到有 ERROR 或是 EOS(End-Of-Stream)出現之後才會離開。

程式執行到這裡之後,GStreamer 會負責剩下的所有多媒體串流與撥放工作,開發者就不用管了。而 GStreamer 的 bus 我們在後面的教學會有詳細的介紹,目前可以暫時不用管它。

如果您所指定的 URI 有問題,或是某些 GStreamer 附加元件找不到(沒有安裝)時,GStreamer 提供了很多錯誤回報的方式,不過在這個範例中,我們沒有加入太複雜的錯誤處理機制,只是讓程式在錯誤出現時就直接離開。

Part 5

/* 釋放記憶體資源 */
if (msg != NULL)
  gst_message_unref (msg);
gst_object_unref (bus);
gst_element_set_state (pipeline, GST_STATE_NULL);
gst_object_unref (pipeline);

程式的最後還要記得將配置的記憶體回收,在這個範例中,gst_bus_timed_pop_filtered() 所傳回的 msg 在使用完之後要呼叫 gst_message_unref() 釋放記憶體,而 gst_element_get_bus() 所傳回的 bus 則需要呼叫 gst_object_unref() 來釋放。

將管線的狀態設定為 GST_STATE_NULL 可以確保管線釋放所有它所使用的記憶體,最後再使用 gst_object_unref() 釋放管線本身的記憶體。

編譯 GStreamer 程式

在 Linux 系統中使用 gcc 編譯這個程式碼:

gcc basic-tutorial-1.c -o basic-tutorial-1 `pkg-config --cflags --libs gstreamer-0.10`

編譯完成之後,會產生一個 basic-tutorial-1 執行檔,執行它之後就會開始播放網路上的影片串流:

./basic-tutorial-1

這是播放的視窗:

gstreamer-tutorial-1

參考資料:GStreamer SDK Basic tutorials

程式設計

1 Comment

  1. Robert Kan

    我姓简,是windowsxp,vista 正版用家,氣愤微軟不支援它們。裝了ubuntu,能上網,但播不了DvD,請赐教。

Leave a Reply