Upload
wen-liao
View
1.386
Download
3
Embed Size (px)
DESCRIPTION
Change log: May/13/2014: Revise description for PAUSE state
Citation preview
GStreamerApplication Development Manual 導讀
第一章到第十章
Wen Liao
目標
了解GStreamer是什麼
注意
● 只包含手冊第一章到第十章● 可能有誤,請自行斟酌對照手冊● 請留意囉唆的程式碼變數顏色
my_var = my_func();
my_hash(my_var);
Outline
● Backgrounds● Overview● Demo● References
Background
● Framework○ Longman:
■ the main supporting parts of a building, vehicle, or object● http://www.ldoceonline.com/dictionary/framework
● Software framework○ 一般性,可重複使用的軟體平台○ 用於降降低開發軟體的成本
Multimedia Framework
● 一種Software framework● 專門來處理多媒體相關應用程式
○ 多媒體播放器○ 多媒體格式轉換○ 多媒體編輯器○ Video conference○ ….
GStreamer
● 一種Multimedia framework● 以基於C語言開發的GObject發展● 支援多平台● LGPL
Element and Pipeline in GStreamer:Series of Producer - Consumer
http://en.wikipedia.org/wiki/GStreamer#Technical_overviewPAD
兩邊有協定溝通決定要傳送那些資料
兩邊有協定溝通決定要傳送那些資料
Plugin
● 一種Element● 大部分以static library形式● 種類
○ codec○ container formats○ IO driver
http://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/chapter-gstreamer.html
Outline
● Backgrounds● Overview ● Demo● References
前情提要
http://en.wikipedia.org/wiki/GStreamer#Technical_overviewPAD
兩邊有協定溝通決定要傳送那些資料
兩邊有協定溝通決定要傳送那些資料
Overview
● Element● Pad● Bin and pipeline● Communication
Element
● 提供基本功能的元件。可以透過Pad和其他Element組合。○ 播放聲音○ 讀取檔案○ 透過網路取得多媒體內容○ 多媒體解碼○ …
● 分類○ Source element○ 一般element○ Sink element
Source Element
● 從檔案或是音效卡讀出資料用
http://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/chapter-elements.html
一般Element
● 有輸入有輸出● 應用:
○ Filters○ convertors○ demuxers○ muxers○ codecs
http://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/chapter-elements.html
Sink Element
● 單純Consume資料,通常就是Render或是音效卡
http://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/chapter-elements.html
產生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
產生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
Element
● gst-inspect指令可以顯示系統可用的element資訊
● GstElement資料結構繼承自GObject○ 可用GObject的屬性○ 可用GObject的signal及對應的callback○ GObject資訊
■ https://developer.gnome.org/gobject/stable/rn01.html
Element和Factory
● GstElementFactory○ Framework maintain所有系統上可以用的plugin
(element)資訊(metadata)■ ex:
● gst_element_factory_get_metadata (factory, GST_ELEMENT_METADATA_DESCRIPTION))
○ 這些metadata可以用來確認目前element和element之間是否可以互相連接
連接Elements
1. 產生pipeline2. 決定並產生elements3. 把elements打包成bin
a. (要記得pipeline是bin的一種)
4. 建立link
http://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/section-elements-link.html
範例
/* 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
接關
/* 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
Element內部狀態
● GST_STATE_NULL○ 建立時預設狀態○ 內部沒有分配任何資源○ 狀態被設成NULL framework會自動清除資源○ 當reference count為零時必須要在該狀態
● GST_STATE_READY○ 資源已配置或是被reset掉
Element內部狀態
● GST_STATE_PAUSED○ 資源已分配並可以執行,但是偏不去處理資料○ 此時可以趁機更動控制資料以達到trick play的目的○ 必須假設馬上就會被play的情況
● GST_STATE_PLAYING○ 和PAUSE差別就是會去處理資料○ 精確的說法,是clock有沒有在run的差別
■ 在這邊有解釋clock● http://gstreamer.freedesktop.
org/data/doc/gstreamer/head/manual/html/chapter-clocks.
html#section-clock-time-types
關於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 statechange
Downward state change
Overview
● Element● Pad● Bin and pipeline● Communication
Pad
● Element的input/output部份○ Sink: Input○ Source: Output
● Element之間的連結方式● GStreamer允許element之間透過negociate
決定link以及資料傳輸方式○ GstCaps
■ GStreamer capabilities of an element● 想像螢幕可以顯示HDMI或是VGA訊號,這些
信號線就是PAD
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
Capabilities
● 支援的屬性稱為property○ Key: 字串○ Value:
■ 基本type如int, float■ Range: 如1~100■ List
● 多個基本type■ Array
● 多個相同的基本type
Capabilities
● 想像Mimetype● 用途
○ PnP○ 檢查相容性○ 提供Metadata○ Filter,限制處理的資料特性
取得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
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);
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
建立Ghost Pad
● 產生element和bin● 把element打包到bin● link element內部● 產生Ghost Pad
範例
/* 產生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
Overview
● Element● Pad● Bin and pipeline● Communication
Bin
● Bin○ 一組透過pad連接起來的elements○ GStreamer提供針對bin的操作。只要操作bin,
GStreamer幫你搞定裏面的element。■ 設定狀態■ 傳送錯誤通知■ …
Bin
http://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/chapter-bins.html
● 精確的來說,Bin是一個container element○ 所有對element/GObject的操作都可以apply到bin
Pipeline
● Pipeline○ 一種bin○ 最高層的bin,和一般bin的差別是他提供介面給應用程
式控制○ 實作上面,每個pipe都是單獨的thread
http://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/section-intro-basics-bins.html
使用bin
● 產生pipeline給應用程式使用● 產生bin● 產生element處理實體資料● 打包成bin● 告訴pipeline處理bin● 連連看● 開工
範例
/* 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
範例
/* 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
Overview
● Element● Pad● Bin and pipeline● Communication
○ bus and message○ buffer
Bus
● 用來傳遞GStreamer framework和應用程式之間的訊息
Communication
● 對象:Pipeline、element、應用程式● 方式
○ buffer object■ 對象:element之間■ 用於傳送Streaming需要的資料■ 單向的從source 到 sink
○ event object■ 對象:
● Element之間● 應用程式到element
■ 雙向■ source 到 sink的event可支援和streaming 同步
Communication
● 對象:Pipeline、element、應用程式● 方式
○ message object■ 對象:element到應用程式■ 支援同步或非同步方式■ Thread safe
○ Queries object■ 對象:
● 應用程式到pipeline● Element之間
■ 用來讓應用程式查詢狀態如已播放時間等
■ 為同步傳輸。表示應用程式送出query要等到
pipeline回應才能繼續執行。
圖示
http://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/section-intro-basics-communication.html
➀
➁
➂
➃
Overview
● Element● Pad● Bin and pipeline● Communication
○ bus and message○ buffer
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
使用GLib/Gtk+ main loop 處理message (1)
● 撰寫callback,撈想看的event● 應用程式中
○ 告訴main loop要聽bus event,前面的callback為參數○ 啟動main loop
範例
/* 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
範例
/* 以下都在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
使用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
Messages
● 格式○ message source
■ 從哪個element送出○ message type○ timestamp
● 分類○ 錯誤或警告通知○ 播放結束通知 (EOS)○ Tag:和metadata 相關○ 狀態改變,如從PLAYING轉換到PAUSE○ 緩衝相關○ Element自訂訊息
Overview
● Element● Pad● Bin and pipeline● Communication
○ bus and message○ buffer
More about Buffer
● GStreamer element之間實際傳送的多媒體資料
● GStreamer幫你弄buffer 機制● 包含
○ 指標○ timestamp○ reference count。減到零自動GG○ flag
典型Buffer生命週期
● Source element: 新增分配、分配記憶體空間、放資料、傳給Sink element
● Sink element: 從buffer讀資料、處理資料、unreference buffer、framework發現reference count變為0所以釋放相關資源
Outline
● Backgrounds● Overview ● Demo● References
Environment
● Ubuntu 12.04.4 64-bit
Element Information
● gst-inspect oggdemux○ Class hierarchy○ Details
手冊Hello World範例程式
● 程式說明● 編譯● Demo
程式描述
● 出處:○ 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
架構 Recap
http://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/chapter-helloworld.html
ogg為一個container。可放audio/video等資料
vorbis為一種聲音格式需要把解出來的資料轉成音效卡支援的格式
元件
Elements
Pads
http://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/chapter-helloworld.html
程式架構
● Element訊息處理Callback● 處理pad add event● 主程式
○ 準備■ 分配資源
● elements● GLib mainloop協助處理message
■ 把element打包成pipeline■ 連連看■ 設定通訊及相關callback
○ 開始執行○ 結束、清場
很囉唆的細節,請自行斟酌
/* 1. Element訊息處理Callback */bus_call (...){ GMainLoop *loop = (GMainLoop *) data;
switch (GST_MESSAGE_TYPE (msg)) { case GST_MESSAGE_EOS:
g_main_loop_quit (loop);break;
... }}
播放結束處理
很囉唆的細節,請自行斟酌
/* 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
很囉唆的細節,請自行斟酌
main(...) {... /* 3. 初始化 GStreamer和GLib mainloop */ gst_init (&argc, &argv);
loop = g_main_loop_new (NULL, FALSE);…. /* 接下頁 */
很囉唆的細節,請自行斟酌
/* 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");
很囉唆的細節,請自行斟酌
/* 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
很囉唆的細節,請自行斟酌
/* 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
前面的callbackcallback吃的參數
很囉唆的細節,請自行斟酌
/* 10. 將pipeline內的elements狀態設為可以播放 */ gst_element_set_state (pipeline, GST_STATE_PLAYING);
/* 11. 開工 */ g_main_loop_run (loop);
很囉唆的細節,請自行斟酌
/* 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)就會到這邊
手冊Hello World範例程式
● 程式說明● 編譯● Demo
編譯參數
● 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
手冊Hello World範例程式
● 程式說明● 編譯● Demo
Outline
● Backgrounds● Terminology ● Demo● References
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/