目標
對於一個軟件庫來說,沒有比在屏幕上打印出Hello World更近直觀的第一印象了。因爲我們是在和一個多媒體的framework打交道,所以我們準備播放一段視頻來代替Hello World。不要被下面的代碼嚇唬住了——真正起作用的也就四行而已。剩下的都是資源管理的代碼,C語言嘛,就是有這個麻煩。不多說了,準備你的第一個GStreamer應用吧……
Hello World
把下面的代碼copy到一個文本文件,並改名爲basic-tutorial-1.c
- #include <gst/gst.h>
-
- int main(int argc, char *argv[]) {
- GstElement *pipeline;
- GstBus *bus;
- GstMessage *msg;
-
- /* Initialize GStreamer */
- gst_init (&argc, &argv);
-
- /* Build the pipeline */
- pipeline = gst_parse_launch ("playbin2 uri=http://docs.gstreamer.com/media/sintel_trailer-480p.webm", NULL);
-
- /* Start playing */
- 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);
-
- /* Free resources */
- 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;
- }
編譯方面根據你的平臺也有介紹,linux平臺http://docs.gstreamer.com/display/GstSDK/Installing+on+Linux,Mac平臺http://docs.gstreamer.com/display/GstSDK/Installing+on+Mac+OS+X,windows下是http://docs.gstreamer.com/display/GstSDK/Installing+on+Windows。如果編譯出錯的話請檢查一下報錯地方的語句,如果編譯通過,那麼可以運行了,會彈出一個窗口,播放網絡上的一個視頻。恭喜你,第一步成功了!
代碼分析
我們看一下代碼,分析一下工作流程。
- /* Initialize GStreamer */
- gst_init (&argc, &argv);
這是所有GStreamer應用的第一句,在gst_init裏面做了
+初始化所有內部數據結構
+檢查所有可用的插件
+運行所有的命令行選項
如果你把argc和argv傳入gst_init,在處理命令行上是由好處的(在GStreamer工具裏面還會講到這個方面)。
- /* Build the pipeline */
- pipeline = gst_parse_launch ("playbin2 uri=http://docs.gstreamer.com/media/sintel_trailer-480p.webm", NULL);
這一行是這個教程最重要的部分,裏面有兩個非常重要的點:gst_parse_launch和playbin2
gst_parse_launch
GStreamer是設計來處理多媒體流的框架。媒體流經過一系列的中間element,從source element流到sink element。這些相互作用的element構成了一整個的pipeline。
使用GStreamer時你常常需要使用獨立的elements來手動搭建一個pipeline,但是,在比較簡單的情況下,我們也可以使用gst_parse_launch()。這個函數原本是描述一個pipeline的,但也可以很方便的用來建立一個pipeline。
playbin2
我們讓gst_parse_launch()函數建立了一個怎麼樣的pipeline呢?這就是playbin2的用處了,我們建立了一個只包含playbin2的element的pipeline。
playbin2是一個特殊的element,它既是一個source也是一個sink,同時也能處理整個pipeline的事務。在內部,他創建和鏈接了所有播放你的媒體所必須的elements,你完全不必擔心。
這個element相對於純手工搭建的pipeline來說,控制粒度沒有那麼好,但也有足夠的可定製了。
在這個例子中,我們僅僅解析了playbin2得一個參數——我們希望播放的URI。試試其他的地址,比如http://或者file://開頭的URI,playbin2都能良好的工作。
如果你鍵入了錯誤的URI,或者URI不存在,或者你漏掉了某個插件,GStreamer提供了一些通知機制,但我們這個例子僅僅實現在出錯時退出,所以就不展開了。
- /* Start playing */
- gst_element_set_state (pipeline, GST_STATE_PLAYING);
這一行代碼展示了另一個需要關注的點:狀態。每一個GStreamer的element有一個狀態,你可以理解成常見的DVD播放器上得播放/暫停按鈕。播放器必須設置pipeline爲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);
這幾行是在等待發生一個錯誤或者流已經播放結束。gst_element_get_bus()會得到pipeline的總線,然後gst_bus_timed_pop_filtered()會阻塞直到你遇到一個錯誤或者流播放結束。這一點在下一講還會繼續介紹,這裏先介紹這麼多。
就這樣了,GStreamer處理了所有的事情,這個例子會在流播放結束或播放出錯時停止,當然,任何時候你都可以用Ctrl+C來終止。
清理
在應用終止前,我們還有一些事情要做
- /* Free resources */
- 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()會返回一個message,這個需要調用gst_message_unref()來釋放(下一講會繼續介紹)。
gst_element_get_bus()會對總線增加一個引用,所以也需要調用get_object_unref()來釋放。設置pipeline爲NULL狀態會讓它釋放掉所有的資源,最後,釋放掉pipeline自身。