1. 程式人生 > >GStreamer基礎教程01——Hello World

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自身。