便利な Bin を使ったサンプル
公開日:2023年1月5日
GStreamer には、いくつかの Element を組み合わせて、よくある操作をまとめて行ってくれる Bin が用意されています。これらの Bin が利用できる場合には、目的に沿った Pipeline の構築を簡単に行うことができます。この記事では Playback Components で紹介されている、便利な Bin を使ったアプリケーションのサンプルを紹介します。
Decodebin
decodebin は、入力をデマルチプレクスしてデコードした結果を pad-added イベントで通知します。ここで紹介するサンプルでは
のような Pipeline を構築してオーディオを再生します。入力に含まれるオーディオは pad-added のイベントで通知されて audiobin と接続し、それ以外のコンポーネントに対しては何もしません。
decodebin の作成は gst_element_factory_make の第一引数 factoryname に decodebin という名前を指定します。 pad-added のイベントを処理するコールバック関数を登録し filesrc と decodebin を pipeline に追加し、両者を接続します。
src = gst_element_factory_make("filesrc", "source");
g_object_set(G_OBJECT(src), "location", argv[1], NULL);
dec = gst_element_factory_make("decodebin", "decoder");
g_signal_connect(dec, "pad-added", G_CALLBACK(cb_newpad), NULL);
gst_bin_add_many(GST_BIN(pipeline), src, dec, NULL);
gst_element_link(src, dec);
pad-added のイベントを処理するコールバック関数 cb_newpad では pad の caps を調べて、名前が "audio" である場合に pad と audio_pad (audio の sink pad であり audio は後述するコードの audiobin で audio sink の機能を持ちます) の sink pad を接続します。video などの他のコンポーネントも処理したい場合は、ここで "video" などの名前を持つ pad に対して、対応する sink pad を接続します。なお、このコード片では audio は宣言されていませんが、別の部分で global 変数として宣言されて、あらかじめ設定されています。
static void
cb_newpad(
GstElement* decodebin,
GstPad* pad,
gpointer data
)
{
GstCaps* caps;
GstStructure* str;
GstPad* audio_pad;
/* only link once */
audio_pad = gst_element_get_static_pad(audio, "sink");
if (GST_PAD_IS_LINKED(audio_pad)) {
g_object_unref(audio_pad);
return;
}
/* check media type */
caps = gst_pad_query_caps(pad, NULL);
str = gst_caps_get_structure(caps, 0);
if (!g_strrstr(gst_structure_get_name(str), "audio")) {
gst_caps_unref(caps);
gst_object_unref(audio_pad);
return;
}
gst_caps_unref(caps);
/* link'n'play */
gst_pad_link(pad, audio_pad);
g_object_unref(audio_pad);
}
このサンプルでは audioconvert と alsasink (audio sink) を audiobin という一つの Bin にまとめています。Bin を作成しただけでは Pad を持ちませんが audioconvert の sink をそのまま Bin の sink にすればよさそうです。実際に GStreamer には ghostpad という仕組みがあり audioconvert の sink を Bin の sink として透過的に扱うことができます。
audio = gst_bin_new("audiobin");
conv = gst_element_factory_make("audioconvert", "aconv");
audio_pad = gst_element_get_static_pad(conv, "sink");
sink = gst_element_factory_make("alsasink", "sink");
gst_bin_add_many(GST_BIN(audio), conv, sink, NULL);
gst_element_link(conv, sink);
gst_element_add_pad(
audio,
gst_ghost_pad_new("sink", audio_pad)
);
gst_object_unref(audio_pad);
gst_bin_add(GST_BIN(pipeline), audio);
上記のコードで
- audioconvert と alsasink を接続して内部に含む
- sink として audioconvert の sink を利用する
という 2 つの機能を持つ audiobin を作成して pipeline に追加しています。
アプリケーション全体のソースコードは decodebin.c をご覧ください。
# ビルド
$ gcc -Wall decodebin.c -o decodebin $(pkg-config --cflags --libs gstreamer-1.0)
# 実行
$ ./decodebin ./song.ogg
のように、ビルドと実行を行います。
URIDecodebin
先の例の decodebin はローカルファイルの再生を行うサンプルでした。 GStreamer には uri で指定できる src と decodebin の機能をあわせ持つ uridecodebin という Bin があります。 decodebin のサンプルコードでは filesrc と decodebin を別々に設定しましたが、これらの機能を uridecodebin 一つで担います。他の Bin の作成と同様に gst_element_factory_make を利用して、第一引数に uridecodebin を与えます。
主な変更点は
- src = gst_element_factory_make("filesrc", "source");
- g_object_set(G_OBJECT(src), "location", argv[1], NULL);
- dec = gst_element_factory_make("decodebin", "decoder");
- g_signal_connect(dec, "pad-added", G_CALLBACK(cb_newpad), NULL);
- gst_bin_add_many(GST_BIN(pipeline), src, dec, NULL);
- gst_element_link(src, dec);
+ uridec = gst_element_factory_make("uridecodebin", "decoder");
+ g_object_set(G_OBJECT(uridec), "uri", argv[1], NULL);
+ g_signal_connect(uridec, "pad-added", G_CALLBACK(cb_newpad), NULL);
+ gst_bin_add_many(GST_BIN(pipeline), uridec, NULL);
となります。入力を設定するプロパティ名が "location" から "uri" に変わっています。
アプリケーション全体のソースコードは uridecodebin.c をご覧ください。
# ビルド
$ gcc -Wall uridecodebin.c -o uridecodebin $(pkg-config --cflags --libs gstreamer-1.0)
# 実行 (local file)
$ ./uridecodebin file:///path/to/song.ogg
# 実行 (network file)
$ ./uridecodebin http://www.example.com/song.ogg
のように、ビルドと実行を行います。
Playbin
Playbin は、ファイル再生を行う Bin で、 Playbin 単体で Pipeline としてふるまいます。 Playbin は、与えられたファイルの種別を判別して、対応する Decoder や Sink を自動的に追加するため、再生対象のコンテンツを指定するだけで利用できます。
Playbin を作成するには、他の Bin の作成と同様に gst_element_factory_make を利用して、第一引数に playbin を与えます。
再生対象のファイルは Playbin のメソッド g_object_set に対して、第二引数でプロパティ名として uri を与え、第三引数で値を URI 形式で与えます。例えば http://www.example.com/song.ogg や file:///path/to/song.ogg といった文字列を与えます。
以前に紹介した Your first application の helloworld アプリケーションの Pipeline 構築部分が
GstElement* play = NULL;
play = gst_element_factory_make("playbin", "play");
g_object_set(G_OBJECT(play), "uri", argv[1], NULL);
だけで済みます。アプリケーション全体のソースコードは playbin.c をご覧ください。
# ビルド
$ gcc -Wall playbin.c -o playbin $(pkg-config --cflags --libs gstreamer-1.0)
# 実行 (local file)
$ ./playbin file:///path/to/song.ogg
# 実行 (network file)
$ ./playbin http://www.example.com/song.ogg
のように、ビルドと実行を行います。
Playsink
最後に高機能な sink である playsink を紹介します。この sink は audio, video, text などの複数のコンポーネントを受け付けることができます。 padd-added イベント発生時のコールバック関数で、コンポーネントの種類に応じた pad を playsink に要求して接続することで、複数のコンポーネントに対処しています。
playsink に対して flags プロパティを設定することで、 playsink の挙動を制御することができます。このプロパティは名前の通りフラグになっており、指定したものが有効化されます。有効にするフラグ名は文字列で指定し、複数のフラグを有効にする場合はフラグ名を + でつなぎます。利用可能なフラグの一覧は GstPlayFlags をご覧ください。面白いフラグを一つ紹介します。 vis はビデオがない場合に audio の visualizer として機能して、下記のような模様が再生状況に応じて変化します。
アプリケーション全体のソースコードは playsink.c をご覧ください。
# ビルド
$ gcc -Wall playsink.c -o playsink $(pkg-config --cflags --libs gstreamer-1.0)
# 実行 (local file)
$ ./playsink file:///path/to/song.ogg
# 実行 (network file)
$ ./playsink http://www.example.com/song.ogg
のように、ビルドと実行を行います。
まとめ
この記事では
について紹介しました。
※文中に記載されている各種名称、会社名、商品名などは各社の商標もしくは登録商標です。