Monday, December 7, 2015

GStreamer でプログラミング 2 (Bus と Message)

GStreamer を使って cat コマンドのようなプログラムを作成するには? gst-launch を使うと、こんな感じでしょうか。

echo hello > a.txt
gst-launch-1.0 filesrc location=a.txt ! fdsink
hello

C で書いても簡単で、こんな感じです。

これを 前回のプログラムと比較してみると、文字列部分を filesrcfdsink に変更しているだけだということが分ります。

しかし、このままでは 「hello」と表示された後、プログラムが終了せずに止ってしまいます。理由は、指定したファイルを最後まで読み出したにもかかわらず、 mainloop から抜けてこないからです。 glib の main loop から抜けるには、 g_main_loop_quit() を使いますが、どうやったら「最後まで読み出した」ということが分るのでしょう?

答は、Bus を見ると分ります。 Bus は、プログラムと pipeline がやりとりを行うためのオブジェクトです。pipeline になにかあったときには、かならず bus にメッセージ(GstMessage) が流れてきます。このメッセージを見てみましょう。

Bus は、 pipeline が持っています。 pipeline から gst_element_get_bus() を使って bus を取り出します。 取り出した bus に、「なにか変化があったらこの関数を呼んで」という gst_bus_add_watch() で、 on_message() を登録しておきます。

on_message() では、届いたメッセージによって適切な処理をさせます。今回のように「ファイルを最後まで読み出した」時、 Bus には End of Stream (EOS) が届くはずですので、EOS が届いたら、 g_main_loop_quit() を呼び mainloop から抜けるように指示します。

これで、hello と表示した後にプログラムが終了するようになります。

本物の cat は、複数のファイルを引数に取って concat するコマンドですが、 filesrc では複数のファイルを扱えません。 multifilesrcsplitfilesrc というエレメントもありますが、若干挙動が異なります。 cat と同じよう動作をさせる方法は、また今度紹介します。

No comments:

Post a Comment