這是 GStreamer 的入門使用教學,播放網路影片串流的 Hello World 程式。
GStreamer 是 GNOME 桌面環境之下用來建立多媒體串流應用的架構(framework),可以簡化影音相關應用程式的開發流程,支援各種常用的多媒體影音格式,如 mp3、ogg、mpeg1、mpeg2、avi、quicktime 等。
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 參數,在呼叫 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()
釋放管線本身的記憶體。
在 Linux 系統中使用 gcc
編譯這個程式碼:
gcc basic-tutorial-1.c -o basic-tutorial-1 `pkg-config --cflags --libs gstreamer-0.10`
編譯完成之後,會產生一個 basic-tutorial-1
執行檔,執行它之後就會開始播放網路上的影片串流:
./basic-tutorial-1
這是播放的視窗: