Slide 1

Slide 1 text

GStreamer Application Development Manual 導讀 第一章到第十章 Wen Liao

Slide 2

Slide 2 text

目標 了解GStreamer是什麼

Slide 3

Slide 3 text

注意 ● 只包含手冊第一章到第十章 ● 可能有誤,請自行斟酌對照手冊 ● 請留意囉唆的程式碼變數顏色 my_var = my_func(); my_hash(my_var);

Slide 4

Slide 4 text

Outline ● Backgrounds ● Overview ● Demo ● References

Slide 5

Slide 5 text

Background ● Framework ○ Longman: ■ the main supporting parts of a building, vehicle, or object ● http://www.ldoceonline.com/dictionary/framework ● Software framework ○ 一般性,可重複使用的軟體平台 ○ 用於降降低開發軟體的成本

Slide 6

Slide 6 text

Multimedia Framework ● 一種Software framework ● 專門來處理多媒體相關應用程式 ○ 多媒體播放器 ○ 多媒體格式轉換 ○ 多媒體編輯器 ○ Video conference ○ ….

Slide 7

Slide 7 text

GStreamer ● 一種Multimedia framework ● 以基於C語言開發的GObject發展 ● 支援多平台 ● LGPL

Slide 8

Slide 8 text

Element and Pipeline in GStreamer: Series of Producer - Consumer http://en.wikipedia.org/wiki/GStreamer#Technical_overview PAD 兩邊有協定溝 通決定要傳送 那些資料 兩邊有協定溝 通決定要傳送 那些資料

Slide 9

Slide 9 text

Plugin ● 一種Element ● 大部分以static library形式 ● 種類 ○ codec ○ container formats ○ IO driver

Slide 10

Slide 10 text

http://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/chapter-gstreamer.html

Slide 11

Slide 11 text

Outline ● Backgrounds ● Overview ● Demo ● References

Slide 12

Slide 12 text

前情提要 http://en.wikipedia.org/wiki/GStreamer#Technical_overview PAD 兩邊有協定溝 通決定要傳送 那些資料 兩邊有協定溝 通決定要傳送 那些資料

Slide 13

Slide 13 text

Overview ● Element ● Pad ● Bin and pipeline ● Communication

Slide 14

Slide 14 text

Element ● 提供基本功能的元件。可以透過Pad和其他 Element組合。 ○ 播放聲音 ○ 讀取檔案 ○ 透過網路取得多媒體內容 ○ 多媒體解碼 ○ … ● 分類 ○ Source element ○ 一般element ○ Sink element

Slide 15

Slide 15 text

Source Element ● 從檔案或是音效卡讀出資料用 http://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/chapter-elements.html

Slide 16

Slide 16 text

一般Element ● 有輸入有輸出 ● 應用: ○ Filters ○ convertors ○ demuxers ○ muxers ○ codecs http://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/chapter-elements.html

Slide 17

Slide 17 text

Sink Element ● 單純Consume資料,通常就是Render或是音 效卡 http://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/chapter-elements.html

Slide 18

Slide 18 text

產生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

Slide 19

Slide 19 text

產生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

Slide 20

Slide 20 text

Element ● gst-inspect指令可以顯示系統可用的element 資訊 ● GstElement資料結構繼承自GObject ○ 可用GObject的屬性 ○ 可用GObject的signal及對應的callback ○ GObject資訊 ■ https://developer.gnome.org/gobject/stable/rn01. html

Slide 21

Slide 21 text

Element和Factory ● GstElementFactory ○ Framework maintain所有系統上可以用的plugin (element)資訊(metadata) ■ ex: ● gst_element_factory_get_metadata (factory, GST_ELEMENT_METADATA_DESCRIPTION)) ○ 這些metadata可以用來確認目前element和element之 間是否可以互相連接

Slide 22

Slide 22 text

連接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

Slide 23

Slide 23 text

範例 /* 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

Slide 24

Slide 24 text

接關 /* 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

Slide 25

Slide 25 text

Element內部狀態 ● GST_STATE_NULL ○ 建立時預設狀態 ○ 內部沒有分配任何資源 ○ 狀態被設成NULL framework會自動清除資源 ○ 當reference count為零時必須要在該狀態 ● GST_STATE_READY ○ 資源已配置或是被reset掉

Slide 26

Slide 26 text

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.

Slide 27

Slide 27 text

關於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

Slide 28

Slide 28 text

Overview ● Element ● Pad ● Bin and pipeline ● Communication

Slide 29

Slide 29 text

Pad ● Element的input/output部份 ○ Sink: Input ○ Source: Output ● Element之間的連結方式 ● GStreamer允許element之間透過negociate 決定link以及資料傳輸方式 ○ GstCaps ■ GStreamer capabilities of an element ● 想像螢幕可以顯示HDMI或是VGA訊號,這些 信號線就是PAD

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

Capabilities ● 支援的屬性稱為property ○ Key: 字串 ○ Value: ■ 基本type如int, float ■ Range: 如1~100 ■ List ● 多個基本type ■ Array ● 多個相同的基本type

Slide 32

Slide 32 text

Capabilities ● 想像Mimetype ● 用途 ○ PnP ○ 檢查相容性 ○ 提供Metadata ○ Filter,限制處理的資料特性

Slide 33

Slide 33 text

取得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

Slide 34

Slide 34 text

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);

Slide 35

Slide 35 text

Ghost Pad ● 用於處理bin的pad問題。因為bin沒有pad,並 且實際上處理pad的仍然是element ● 想法:Unix下的symbolic link http://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/section-pads-ghost.html 做一個假的 bin本身沒有pad

Slide 36

Slide 36 text

建立Ghost Pad ● 產生element和bin ● 把element打包到bin ● link element內部 ● 產生Ghost Pad

Slide 37

Slide 37 text

範例 /* 產生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

Slide 38

Slide 38 text

Overview ● Element ● Pad ● Bin and pipeline ● Communication

Slide 39

Slide 39 text

Bin ● Bin ○ 一組透過pad連接起來的elements ○ GStreamer提供針對bin的操作。只要操作bin, GStreamer幫你搞定裏面的element。 ■ 設定狀態 ■ 傳送錯誤通知 ■ …

Slide 40

Slide 40 text

Bin http://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/chapter-bins.html ● 精確的來說,Bin是一個container element ○ 所有對element/GObject的操作都可以apply到bin

Slide 41

Slide 41 text

Pipeline ● Pipeline ○ 一種bin ○ 最高層的bin,和一般bin的差別是他提供介面給應用程 式控制 ○ 實作上面,每個pipe都是單獨的thread http://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/section-intro-basics-bins.html

Slide 42

Slide 42 text

使用bin ● 產生pipeline給應用程式使用 ● 產生bin ● 產生element處理實體資料 ● 打包成bin ● 告訴pipeline處理bin ● 連連看 ● 開工

Slide 43

Slide 43 text

範例 /* 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

Slide 44

Slide 44 text

範例 /* 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

Slide 45

Slide 45 text

Overview ● Element ● Pad ● Bin and pipeline ● Communication ○ bus and message ○ buffer

Slide 46

Slide 46 text

Bus ● 用來傳遞GStreamer framework和應用程式 之間的訊息

Slide 47

Slide 47 text

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

Slide 48

Slide 48 text

Communication ● 對象:Pipeline、element、應用程式 ● 方式 ○ message object ■ 對象:element到應用程式 ■ 支援同步或非同步方式 ■ Thread safe ○ Queries object ■ 對象: ● 應用程式到pipeline ● Element之間 ■ 用來讓應用程式查詢狀態如已播放時間等 ■ 為同步傳輸。表示應用程式送出query要等到 pipeline回應才能繼續執行。

Slide 49

Slide 49 text

圖示 http://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/section-intro-basics-communication.html ➀ ➁ ➂ ➃

Slide 50

Slide 50 text

Overview ● Element ● Pad ● Bin and pipeline ● Communication ○ bus and message ○ buffer

Slide 51

Slide 51 text

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

Slide 52

Slide 52 text

使用GLib/Gtk+ main loop 處理message (1) ● 撰寫callback,撈想看的event ● 應用程式中 ○ 告訴main loop要聽bus event,前面的callback為參數 ○ 啟動main loop

Slide 53

Slide 53 text

範例 /* 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

Slide 54

Slide 54 text

範例 /* 以下都在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

Slide 55

Slide 55 text

使用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

Slide 56

Slide 56 text

Messages ● 格式 ○ message source ■ 從哪個element送出 ○ message type ○ timestamp ● 分類 ○ 錯誤或警告通知 ○ 播放結束通知 (EOS) ○ Tag:和metadata 相關 ○ 狀態改變,如從PLAYING轉換到PAUSE ○ 緩衝相關 ○ Element自訂訊息

Slide 57

Slide 57 text

Overview ● Element ● Pad ● Bin and pipeline ● Communication ○ bus and message ○ buffer

Slide 58

Slide 58 text

More about Buffer ● GStreamer element之間實際傳送的多媒體資 料 ● GStreamer幫你弄buffer 機制 ● 包含 ○ 指標 ○ timestamp ○ reference count。減到零自動GG ○ flag

Slide 59

Slide 59 text

典型Buffer生命週期 ● Source element: 新增分配、分配記憶體空間、 放資料、傳給Sink element ● Sink element: 從buffer讀資料、處理資料、 unreference buffer、framework發現reference count變為0所以釋放相關資源

Slide 60

Slide 60 text

Outline ● Backgrounds ● Overview ● Demo ● References

Slide 61

Slide 61 text

Environment ● Ubuntu 12.04.4 64-bit

Slide 62

Slide 62 text

Element Information ● gst-inspect oggdemux ○ Class hierarchy ○ Details

Slide 63

Slide 63 text

手冊Hello World範例程式 ● 程式說明 ● 編譯 ● Demo

Slide 64

Slide 64 text

程式描述 ● 出處: ○ http://gstreamer.freedesktop. org/data/doc/gstreamer/head/manual/html/chapter-helloworld.html#section- helloworld ● 目的:從檔案播放 Ogg影片中Vorbis格式的聲音 http://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/chapter-helloworld.html

Slide 65

Slide 65 text

架構 Recap http://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/chapter-helloworld.html ogg為一個container。 可放audio/video等資料 vorbis為一種聲音格式 需要把解出來的資料轉 成音效卡支援的格式

Slide 66

Slide 66 text

元件 Elements Pads http://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/chapter-helloworld.html

Slide 67

Slide 67 text

程式架構 ● Element訊息處理Callback ● 處理pad add event ● 主程式 ○ 準備 ■ 分配資源 ● elements ● GLib mainloop協助處理message ■ 把element打包成pipeline ■ 連連看 ■ 設定通訊及相關callback ○ 開始執行 ○ 結束、清場

Slide 68

Slide 68 text

很囉唆的細節,請自行斟酌 /* 1. Element訊息處理Callback */ bus_call (...) { GMainLoop *loop = (GMainLoop *) data; switch (GST_MESSAGE_TYPE (msg)) { case GST_MESSAGE_EOS: g_main_loop_quit (loop); break; ... } } 播放結束處理

Slide 69

Slide 69 text

很囉唆的細節,請自行斟酌 /* 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

Slide 70

Slide 70 text

很囉唆的細節,請自行斟酌 main(...) { ... /* 3. 初始化 GStreamer和GLib mainloop */ gst_init (&argc, &argv); loop = g_main_loop_new (NULL, FALSE); …. /* 接下頁 */

Slide 71

Slide 71 text

很囉唆的細節,請自行斟酌 /* 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");

Slide 72

Slide 72 text

很囉唆的細節,請自行斟酌 /* 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

Slide 73

Slide 73 text

很囉唆的細節,請自行斟酌 /* 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 吃的參數

Slide 74

Slide 74 text

很囉唆的細節,請自行斟酌 /* 10. 將pipeline內的elements狀態設為可以播放 */ gst_element_set_state (pipeline, GST_STATE_PLAYING); /* 11. 開工 */ g_main_loop_run (loop);

Slide 75

Slide 75 text

很囉唆的細節,請自行斟酌 /* 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)就會到這邊

Slide 76

Slide 76 text

手冊Hello World範例程式 ● 程式說明 ● 編譯 ● Demo

Slide 77

Slide 77 text

編譯參數 ● 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

Slide 78

Slide 78 text

手冊Hello World範例程式 ● 程式說明 ● 編譯 ● Demo

Slide 79

Slide 79 text

Outline ● Backgrounds ● Terminology ● Demo ● References

Slide 80

Slide 80 text

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/