將下面代碼copy到一個命名爲basic-tutorial-1.c的文件中。html
#include <gst/gst.h> int main(int argc, char *argv[]) { GstElement *pipeline, *source, *sink; GstBus *bus; GstMessage *msg; GstStateChangeReturn ret; /* Initialize GStreamer */ gst_init (&argc, &argv); /* Create the elements */ source = gst_element_factory_make ("videotestsrc", "source"); sink = gst_element_factory_make ("autovideosink", "sink"); /* Create the empty pipeline */ pipeline = gst_pipeline_new ("test-pipeline"); if (!pipeline || !source || !sink) { g_printerr ("Not all elements could be created.\n"); return -1; } /* Build the pipeline */ gst_bin_add_many (GST_BIN (pipeline), source, sink, NULL); if (gst_element_link (source, sink) != TRUE) { g_printerr ("Elements could not be linked.\n"); gst_object_unref (pipeline); return -1; } /* Modify the source's properties */ g_object_set (source, "pattern", 0, NULL); /* Start playing */ ret = gst_element_set_state (pipeline, GST_STATE_PLAYING); if (ret == GST_STATE_CHANGE_FAILURE) { g_printerr ("Unable to set the pipeline to the playing state.\n"); gst_object_unref (pipeline); return -1; } /* 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); /* Parse message */ if (msg != NULL) { GError *err; gchar *debug_info; switch (GST_MESSAGE_TYPE (msg)) { case GST_MESSAGE_ERROR: gst_message_parse_error (msg, &err, &debug_info); g_printerr ("Error received from element %s: %s\n", GST_OBJECT_NAME (msg->src), err->message); g_printerr ("Debugging information: %s\n", debug_info ? debug_info : "none"); g_clear_error (&err); g_free (debug_info); break; case GST_MESSAGE_EOS: g_print ("End-Of-Stream reached.\n"); break; default: /* We should not reach here because we only asked for ERRORs and EOS */ g_printerr ("Unexpected message received.\n"); break; } gst_message_unref (msg); } /* Free resources */ gst_object_unref (bus); gst_element_set_state (pipeline, GST_STATE_NULL); gst_object_unref (pipeline); return 0; }
GStreamer的基本構造塊爲元素(elements),它向下遊流動從source elements(數據的製做者)向sink elements(數據的消費者),穿過過濾器元件(filter elements)而處理數據。異步
/* Create the elements */ source = gst_element_factory_make ("videotestsrc", "source"); sink = gst_element_factory_make ("autovideosink", "sink");
能夠看出在這段代碼中,新元素能夠用gst_element_factory_make()來建立。第一個參數是元素的建立類型(Basic tutorial 14: Handy elements:顯示了一些常見的類型,以及 Basic tutorial 10: GStreamer tools:展現瞭如何獲取全部可用類型的列表)。第二個參數是咱們想給這個特定實例的名稱。命名你的元素是很是有用之後對它們進行檢索,若是你沒有保持一個指針(和更有意義的調試輸出)。若是你傳遞NULL的名字,然而,,GStreamer將會爲您提供一個惟一的名稱。ide
在本教程中,咱們建立兩個元素:一個 videotestsrc 和 autovideosink。函數
videotestsrc 是源元素(它產生的數據),它建立了一個測試視頻模式。此元素對於調試目的(和教程)是有用的,而不是在實際應用中使用。工具
autovideosink是一個接收元素(它消耗的數據),它在一個窗口中顯示接收到的圖像。存在幾個視頻接收器,根據不一樣的操做系統,具備能力的變化範圍。 autovideosink自動選擇並實例化最好的一個,因此你沒必要擔憂的細節,你的代碼更是平臺無關的。測試
/* Create the empty pipeline */ pipeline = gst_pipeline_new ("test-pipeline");
GStreamer中的全部元素都必須典型地包含在一個管道內才能使用它們,由於它須要一些時鐘和短信功能護理。咱們建立gst_pipeline_new()等的管道。ui
/* Build the pipeline */ gst_bin_add_many (GST_BIN (pipeline), source, sink, NULL); if (gst_element_link (source, sink) != TRUE) { g_printerr ("Elements could not be linked.\n"); gst_object_unref (pipeline); return -1; }
管道是一種特殊類型的bin,這是用來包含其餘元素的元素。所以,適用於bin的全部方法也適用於管道。在咱們的例子中,咱們調用 gst_bin_add_many() 將元素添加到管道(mind the cast)。這個函數接受要添加元素的列表,用NULL結束。單個元素能夠用 gst_bin_add() 進行添加。this
這些元素,可是,沒有相互鏈接的呢。對於這一點,咱們須要使用 gst_element_link() 。它的第一個參數是source,而第二個是destination。順序計數,由於連接必須遵循數據流(這是 from source elements to sink elements)成立。請記住,只有居住在同一個bin的元素能夠彼此連接,因此記得將它們添加到統一管道在試圖連接它們以前!spa
/* Modify the source's properties */ g_object_set (source, "pattern", 0, NULL);
大多數的GStreamer元素具備可定製的屬性:能夠修改來改變元素的行爲(可寫屬性),或者詢問,瞭解元素的內部狀態(可讀屬性)。屬性用 g_object_get() 讀取和用 g_object_set()寫入。操作系統
g_object_set()
accepts a NULL-terminated list of property-name, property-value pairs,這樣多個屬性能夠一次改變(GStreamer的元素都是一種特殊的GObject,這是實體提供物業設施:這就是爲何屬性的處理方法有g_前綴。
以上代碼的行更改 videotestsrc 中的「模式」屬性,該屬性控制測試視頻的類型元素輸出。嘗試不一樣的值!
全部屬性的元素自曝的名稱和可能的值可使用Basic tutorial 10: GStreamer tools中描述的GST-檢驗工具中找到。
在這一點上,咱們有整個管道建造和設置,以及本教程的其他部分是很是類似的前一個,但咱們將增長更多的錯誤檢查:
/* Start playing */ ret = gst_element_set_state (pipeline, GST_STATE_PLAYING); if (ret == GST_STATE_CHANGE_FAILURE) { g_printerr ("Unable to set the pipeline to the playing state.\n"); gst_object_unref (pipeline); return -1; }
咱們稱 gst_element_set_state(),可是這一次咱們檢查它的返回值的錯誤。改變狀態是一個微妙的過程和一些更細節的Basic tutorial 3: Dynamic pipelines中給出。
/* 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); /* Parse message */ if (msg != NULL) { GError *err; gchar *debug_info; switch (GST_MESSAGE_TYPE (msg)) { case GST_MESSAGE_ERROR: gst_message_parse_error (msg, &err, &debug_info); g_printerr ("Error received from element %s: %s\n", GST_OBJECT_NAME (msg->src), err->message); g_printerr ("Debugging information: %s\n", debug_info ? debug_info : "none"); g_clear_error (&err); g_free (debug_info); break; case GST_MESSAGE_EOS: g_print ("End-Of-Stream reached.\n"); break; default: /* We should not reach here because we only asked for ERRORs and EOS */ g_printerr ("Unexpected message received.\n"); break; } gst_message_unref (msg); }
gst_bus_timed_pop_filtered() 執行結束並返回等待一個 GstMessage 這是咱們之前忽略。咱們要求gst_bus_timed_pop_filtered()返回遇到的任何錯誤狀況或EOS,因此咱們須要檢查哪個發生的事情,並在屏幕上打印一條消息(您的應用程序可能要進行更復雜的動做)。
GstMessage
是它幾乎能夠提供任何種類的信息很是靈活的結構。幸運的是,GStreamer中提供了一系列分析功能,爲各種消息的。
在這種狀況下,一旦咱們知道了消息中包含一個錯誤(使用 GST_MESSAGE_TYPE() 宏),咱們可使用 gst_message_parse_error()
,它返回一個GLib的 GError
錯誤信息結構和一個字符串用於調試。檢查代碼,看看它們是如何使用和釋放。
在這一點上是值得正式的介紹一下GStreamer總線。它負責把元素所生成的 GstMessage
s提供給應用程序,爲了與應用程序的線程保持聯繫。最後一點很重要,由於媒體的實際流工做是在另外一個線程而不是應用程序。
消息能夠從總線實時地經過 gst_bus_timed_pop_filtered()和它的兄弟姐妹,或異步,使用信號(在接下來的教程中所示)。您的應用程序應該始終注意錯誤和其餘回放產生的相關問題。
代碼的其他部分是在清理序列,這是相同 Basic tutorial 1: Hello world!。
若是你以爲本身練,試試這個練習:添加source和the sink of this pipeline之間的視頻過濾器元件。使用 vertigotv 會有一個不錯的效果。您將須要建立它,將它添加到管道,並與其餘元素聯繫起來。
根據您的平臺,可用插件時,你可能會獲得一個「談判(negotiation)」的錯誤,由於接收器不明白的過濾器生產(更多關於談判的 Basic tutorial 6: Media formats and Pad Capabilities:媒體格式和墊功能)。在這種狀況下,添加過濾器後,嘗試添加一個被稱爲 ffmpegcolorspace
的元素(這是,創建4個元素的管道,更多關於 ffmpegcolorspace
請參看Basic tutorial 14: Handy elements:方便的元素)。
本教程顯示:
如何用 gst_element_factory_make()
創建元素
如何用 gst_pipeline_new() 創建一個空的管道
如何用 gst_bin_add_many() 將元素添加管道
如何用 gst_element_link()
將元素彼此連接
這樣就完成了最近兩個教程致力於GStreamer的基本概念。
記住,此頁你應該找到本教程的完整源代碼,並創建它所需的任何附件文件。
很高興你能受用這個教程,之後的教程再見!