GStreamer基礎教程01——Hello World
目標
對於一個軟體庫來說,沒有比在螢幕上打印出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; }
程式碼分析
我們看一下程式碼,分析一下工作流程。
/* 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自身。