Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Guide to GStreamer Application Development Manual: CH1 to CH10

Guide to GStreamer Application Development Manual: CH1 to CH10

Wen_Liao

June 06, 2014
Tweet

More Decks by Wen_Liao

Other Decks in Technology

Transcript

  1. Background • Framework ◦ Longman: ▪ the main supporting parts

    of a building, vehicle, or object • http://www.ldoceonline.com/dictionary/framework • Software framework ◦ 一般性,可重複使用的軟體平台 ◦ 用於降降低開發軟體的成本
  2. Element and Pipeline in GStreamer: Series of Producer - Consumer

    http://en.wikipedia.org/wiki/GStreamer#Technical_overview PAD 兩邊有協定溝 通決定要傳送 那些資料 兩邊有協定溝 通決定要傳送 那些資料
  3. 一般Element • 有輸入有輸出 • 應用: ◦ Filters ◦ convertors ◦

    demuxers ◦ muxers ◦ codecs http://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/chapter-elements.html
  4. 產生Element 方法一:懶人法 /* 建立 */ element = gst_element_factory_make ("fakesrc", "source");

    ... /* 宰掉 */ gst_object_unref (GST_OBJECT (element)); Factory name 自己給的名稱 Factory name GST會內部maintain reference counter,每次unref 就遞減。減到0就deallocate http://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/chapter-elements.html
  5. 產生Element 方法二:非懶人法 /* 建立 */ factory = gst_element_factory_find ("fakesrc"); element

    = gst_element_factory_create (factory, "source"); ... /* 宰掉 */ gst_object_unref (GST_OBJECT (element)); Factory name 自己給的名稱 Factory name GST會內部maintain reference counter,每次unref 就遞減。減到0就deallocate http://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/chapter-elements.html
  6. Element和Factory • GstElementFactory ◦ Framework maintain所有系統上可以用的plugin (element)資訊(metadata) ▪ ex: •

    gst_element_factory_get_metadata (factory, GST_ELEMENT_METADATA_DESCRIPTION)) ◦ 這些metadata可以用來確認目前element和element之 間是否可以互相連接
  7. 連接Elements 1. 產生pipeline 2. 決定並產生elements 3. 把elements打包成bin a. (要記得pipeline是bin的一種) 4.

    建立link http://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/section-elements-link.html
  8. 範例 /* 1.產生 pipeline */ pipeline = gst_pipeline_new ("my-pipeline"); /*

    2. 產生elements */ source = gst_element_factory_make ("fakesrc", "source"); filter = gst_element_factory_make ("identity", "filter"); sink = gst_element_factory_make ("fakesink", "sink"); /* 3. 打包 */ gst_bin_add_many (GST_BIN (pipeline), source, filter, sink, NULL); http://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/chapter-elements.html
  9. 接關 /* 4. 連連看 */ if (!gst_element_link_many (source, filter, sink,

    NULL)) { g_warning ("Failed to link elements!"); } http://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/chapter-elements.html
  10. Element內部狀態 • GST_STATE_NULL ◦ 建立時預設狀態 ◦ 內部沒有分配任何資源 ◦ 狀態被設成NULL framework會自動清除資源

    ◦ 當reference count為零時必須要在該狀態 • GST_STATE_READY ◦ 資源已配置或是被reset掉
  11. Element內部狀態 • GST_STATE_PAUSED ◦ 資源已分配並可以執行,但是偏不去處理資料 ◦ 此時可以趁機更動控制資料以達到trick play的目的 ◦ 因為隨時都有可能從暫停狀態切換到播放狀態,

    Element需要想辦法降低狀態切換所需時間。 • GST_STATE_PLAYING ◦ 和PAUSE差別就是會去處理資料 ◦ 精確的說法,是clock有沒有在run的差別 ▪ 在這邊有解釋clock • http://gstreamer.freedesktop. org/data/doc/gstreamer/head/manual/html/chapter-clocks.
  12. 關於Element狀態 • 透過下面API更改 ◦ gst_element_set_state (GstElement *element, GstState state); NULL

    READY PAUSE PLAYING http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer/html/GstElement.html#GstState NULL READY PAUSE PLAYING Upward state change Downward state change
  13. Pad • Element的input/output部份 ◦ Sink: Input ◦ Source: Output •

    Element之間的連結方式 • GStreamer允許element之間透過negociate 決定link以及資料傳輸方式 ◦ GstCaps ▪ GStreamer capabilities of an element • 想像螢幕可以顯示HDMI或是VGA訊號,這些 信號線就是PAD
  14. More about Pad • 主要組成 ◦ 資料傳輸方向 ▪ Source ▪

    Sink ◦ Availability ▪ Always ▪ Sometimes (Dynamic) • 應用程式可以透過監聽pad-added event處理對應行為 • gst-inspect指令會列出支援的events ▪ On request • element夠過下面API產生Pad ◦ gst_element_get_request_pad ◦ gst_element_get_compatible_pad
  15. Capabilities • 支援的屬性稱為property ◦ Key: 字串 ◦ Value: ▪ 基本type如int,

    float ▪ Range: 如1~100 ▪ List • 多個基本type ▪ Array • 多個相同的基本type
  16. Capabilities • 想像Mimetype • 用途 ◦ PnP ◦ 檢查相容性 ◦

    提供Metadata ◦ Filter,限制處理的資料特性
  17. 取得Capabilities metadata範例 cap_str = gst_caps_get_structure (caps, 0); if (!gst_structure_get_int (cap_str,

    "width", &width) || !gst_structure_get_int (cap_str, "height", &height)) { g_print ("No width/height available\n"); return; } http://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/section-caps-api.html
  18. Capabilities 作為filter應用方式 • 設定elements兩邊link滿足條件(下面方式擇一) ◦ filter_cap = gst_caps_new_full(..); ◦ filter_cap

    = gst_caps_new_simple(..); • link兩個element,前面的條件作為參數帶入 ◦ gst_element_link_filtered (ele1, ele2, filter_cap);
  19. 範例 /* 產生element和bin */ sink = gst_element_factory_make ("fakesink", "sink"); bin

    = gst_bin_new ("mybin"); gst_bin_add (GST_BIN (bin), sink); /* 產生ghost pad */ pad = gst_element_get_static_pad (sink, "sink"); gst_element_add_pad (bin, gst_ghost_pad_new ("sink", pad)); gst_object_unref (GST_OBJECT (pad)); 把element的pad 轉給ghost pad
  20. 範例 /* 1. 產生pipeline給應用程式使用 */ pipeline = gst_pipeline_new ("my_pipeline"); /*

    2. 產生bin */ bin = gst_bin_new ("my_bin"); /* 3. 產生element處理實體資料 */ source = gst_element_factory_make ("fakesrc", "source"); sink = gst_element_factory_make ("fakesink", "sink"); http://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/section-bin-create.html
  21. 範例 /* 4. 打包成bin */ gst_bin_add_many (GST_BIN (bin), source, sink,

    NULL); /* 5. 告訴pipeline處理bin */ gst_bin_add (GST_BIN (pipeline), bin); /* 6. 連連看 */ gst_element_link (source, sink); http://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/section-bin-create.html
  22. Overview • Element • Pad • Bin and pipeline •

    Communication ◦ bus and message ◦ buffer
  23. Communication • 對象:Pipeline、element、應用程式 • 方式 ◦ buffer object ▪ 對象:element之間

    ▪ 用於傳送Streaming需要的資料 ▪ 單向的從source 到 sink ◦ event object ▪ 對象: • Element之間 • 應用程式到element ▪ 雙向 ▪ source 到 sink的event可支援和streaming 同步
  24. Communication • 對象:Pipeline、element、應用程式 • 方式 ◦ message object ▪ 對象:element到應用程式

    ▪ 支援同步或非同步方式 ▪ Thread safe ◦ Queries object ▪ 對象: • 應用程式到pipeline • Element之間 ▪ 用來讓應用程式查詢狀態如已播放時間等 ▪ 為同步傳輸。表示應用程式送出query要等到 pipeline回應才能繼續執行。
  25. Overview • Element • Pad • Bin and pipeline •

    Communication ◦ bus and message ◦ buffer
  26. More about Bus and Message • Pipeline產生時就會自動分配Bus資源 • 使用方式 ◦

    使用GLib/Gtk+ main loop去 i. 告訴loop要聽bus event,從對應的callback參數中 去撈event如 • GST_MESSAGE_EOS • GST_MESSAGE_ERROR • .. ii. polling
  27. 使用GLib/Gtk+ main loop 處理message (1) • 撰寫callback,撈想看的event • 應用程式中 ◦

    告訴main loop要聽bus event,前面的callback為參數 ◦ 啟動main loop
  28. 範例 /* 1. 寫callback */ my_bus_callback (...) { ... switch

    (GST_MESSAGE_TYPE (message)) { case GST_MESSAGE_ERROR: … } } http://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/chapter-bus.html
  29. 範例 /* 以下都在main() 裏面 */ /* 2. 我要從main loop 聽GStreamer

    bus event */ bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); bus_watch_id = gst_bus_add_watch (bus, my_bus_callback, NULL); gst_object_unref (bus); /* 3. 開工 */ loop = g_main_loop_new (NULL, FALSE); g_main_loop_run (loop); …. http://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/chapter-bus.html 上頁callback function
  30. 使用GLib/Gtk+ main loop 處理message (2) • 直接註冊signal callback bus =

    gst_pipeline_get_bus (GST_PIPELINE (pipeline); gst_bus_add_signal_watch (bus); g_signal_connect (bus, "message::error", G_CALLBACK (cb_message_error), NULL); g_signal_connect (bus, "message::eos", G_CALLBACK (cb_message_eos), NULL); Callback function for events
  31. Messages • 格式 ◦ message source ▪ 從哪個element送出 ◦ message

    type ◦ timestamp • 分類 ◦ 錯誤或警告通知 ◦ 播放結束通知 (EOS) ◦ Tag:和metadata 相關 ◦ 狀態改變,如從PLAYING轉換到PAUSE ◦ 緩衝相關 ◦ Element自訂訊息
  32. Overview • Element • Pad • Bin and pipeline •

    Communication ◦ bus and message ◦ buffer
  33. More about Buffer • GStreamer element之間實際傳送的多媒體資 料 • GStreamer幫你弄buffer 機制

    • 包含 ◦ 指標 ◦ timestamp ◦ reference count。減到零自動GG ◦ flag
  34. 典型Buffer生命週期 • Source element: 新增分配、分配記憶體空間、 放資料、傳給Sink element • Sink element:

    從buffer讀資料、處理資料、 unreference buffer、framework發現reference count變為0所以釋放相關資源
  35. 程式架構 • Element訊息處理Callback • 處理pad add event • 主程式 ◦

    準備 ▪ 分配資源 • elements • GLib mainloop協助處理message ▪ 把element打包成pipeline ▪ 連連看 ▪ 設定通訊及相關callback ◦ 開始執行 ◦ 結束、清場
  36. 很囉唆的細節,請自行斟酌 /* 1. Element訊息處理Callback */ bus_call (...) { GMainLoop *loop

    = (GMainLoop *) data; switch (GST_MESSAGE_TYPE (msg)) { case GST_MESSAGE_EOS: g_main_loop_quit (loop); break; ... } } 播放結束處理
  37. 很囉唆的細節,請自行斟酌 /* 2. 處理pad add event */ on_pad_added(..., GstPad *pad,

    gpointer data) { GstPad *sinkpad; GstElement *decoder = (GstElement *) data; …. sinkpad = gst_element_get_static_pad (decoder, "sink"); gst_pad_link (pad, sinkpad); gst_object_unref (sinkpad); } oggdemux動態產 生pad,所以產生 時才link decoder
  38. 很囉唆的細節,請自行斟酌 main(...) { ... /* 3. 初始化 GStreamer和GLib mainloop */

    gst_init (&argc, &argv); loop = g_main_loop_new (NULL, FALSE); …. /* 接下頁 */
  39. 很囉唆的細節,請自行斟酌 /* 4. 分配資源 */ pipeline = gst_pipeline_new ("audio-player"); source

    = gst_element_factory_make ("filesrc", "file-source"); demuxer = gst_element_factory_make ("oggdemux", "ogg-demuxer"); decoder = gst_element_factory_make ("vorbisdec", "vorbis-decoder"); conv = gst_element_factory_make ("audioconvert", "converter"); sink = gst_element_factory_make ("autoaudiosink", "audio-output");
  40. 很囉唆的細節,請自行斟酌 /* 5. 告訴程式開哪個檔案 */ g_object_set (G_OBJECT (source), "location", argv[1],

    NULL); /* 6. 叫mainloop聽GStreamer bus */ bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); bus_watch_id = gst_bus_add_watch (bus, bus_call, loop); gst_object_unref (bus); 前面的callback
  41. 很囉唆的細節,請自行斟酌 /* 7. 打包 */ gst_bin_add_many (GST_BIN (pipeline), source, demuxer,

    decoder, conv, sink, NULL); /* 8. 連連看 */ gst_element_link (source, demuxer); gst_element_link_many (decoder, conv, sink, NULL); /* 9. 註冊要處理的event */ g_signal_connect (demuxer, "pad-added", G_CALLBACK (on_pad_added), decoder); oggdemux動態產 生pad,所以產生 時才link decoder 前面的callback callback 吃的參數
  42. 很囉唆的細節,請自行斟酌 /* 12. 收工 */ gst_element_set_state (pipeline, GST_STATE_NULL); gst_object_unref (GST_OBJECT

    (pipeline)); g_source_remove (bus_watch_id); g_main_loop_unref (loop); } 狀態設成null, element要自行釋 放資源 bus_call() 中呼叫g_main_loop_quit (loop)就會到這邊
  43. 編譯參數 • gcc -Wall helloworld.c -o helloworld $(pkg- config --cflags

    --libs gstreamer-1.0) $ echo $(pkg-config --cflags --libs gstreamer-0.10) -pthread -I/usr/include/gstreamer-0.10 - I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0 /include -I/usr/include/libxml2 -pthread -lgstreamer-0.10 -lgobject-2.0 -lgmodule-2.0 -lgthread-2.0 -lrt -lxml2 - lglib-2.0 Ubuntu 12.04.4使 用0.10
  44. References • GStreamer - Wikipedia ◦ http://en.wikipedia.org/wiki/GStreamer • Overview of

    the design of GStreamer ◦ http://cgit.freedesktop. org/gstreamer/gstreamer/plain/docs/design/part- overview.txt • Application Development Manual ◦ http://gstreamer.freedesktop.org/documentation/