現在位置 : ホーム > PIXELA Technical Expertise > GStreamer > 便利な Bin を使ったサンプル

便利な Bin を使ったサンプル

公開日:2023年1月5日

GStreamer には、いくつかの Element を組み合わせて、よくある操作をまとめて行ってくれる Bin が用意されています。これらの Bin が利用できる場合には、目的に沿った Pipeline の構築を簡単に行うことができます。この記事では Playback Components で紹介されている、便利な Bin を使ったアプリケーションのサンプルを紹介します。

Decodebin

decodebin は、入力をデマルチプレクスしてデコードした結果を pad-added イベントで通知します。ここで紹介するサンプルでは

decodebin

のような 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" である場合に padaudio_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.oggfile:///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 として機能して、下記のような模様が再生状況に応じて変化します。

audio visualiser

アプリケーション全体のソースコードは 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

のように、ビルドと実行を行います。

まとめ

この記事では

について紹介しました。

文中に記載されている各種名称、会社名、商品名などは各社の商標もしくは登録商標です。

PIXELA Technical Expertise

当社が技術学習するための情報を体系的に整理したものです。多くのエンジニアの一助になればと考え公開しています。

GStreamer 記事一覧