GStreamer を使って cat
コマンドのようなプログラムを作成するには? gst-launch
を使うと、こんな感じでしょうか。
echo hello > a.txt gst-launch-1.0 filesrc location=a.txt ! fdsink hello
C で書いても簡単で、こんな感じです。
#include <gst/gst.h> | |
int main(int argc, char *argv[]) | |
{ | |
GMainLoop *mainloop; | |
GstElement *pipeline; | |
GError *error = NULL; | |
gst_init(&argc, &argv); | |
mainloop = g_main_loop_new(NULL, FALSE); | |
pipeline = gst_parse_launch("filesrc location=a.txt ! fdsink", &error); | |
gst_element_set_state(pipeline, GST_STATE_PLAYING); | |
g_main_loop_run(mainloop); | |
return 0; | |
} |
これを 前回のプログラムと比較してみると、文字列部分を filesrc
と fdsink
に変更しているだけだということが分ります。
しかし、このままでは 「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 から抜けるように指示します。
#include <gst/gst.h> | |
gboolean on_message(GstBus *bus, GstMessage *message, gpointer p) | |
{ | |
GMainLoop *mainloop = p; | |
(void)bus; | |
if ((GST_MESSAGE_TYPE(message) & GST_MESSAGE_EOS)) | |
g_main_loop_quit(mainloop); | |
return TRUE; | |
} | |
int main(int argc, char *argv[]) | |
{ | |
GMainLoop *mainloop; | |
GstElement *pipeline; | |
GError *error = NULL; | |
GstBus *bus; | |
gst_init(&argc, &argv); | |
mainloop = g_main_loop_new(NULL, FALSE); | |
pipeline = gst_parse_launch("filesrc location=a.txt ! fdsink", &error); | |
bus = gst_element_get_bus(pipeline); | |
gst_bus_add_watch(bus, on_message, mainloop); | |
gst_element_set_state(pipeline, GST_STATE_PLAYING); | |
g_main_loop_run(mainloop); | |
return 0; | |
} |
これで、hello と表示した後にプログラムが終了するようになります。
本物の cat
は、複数のファイルを引数に取って concat するコマンドですが、 filesrc
では複数のファイルを扱えません。 multifilesrc
や splitfilesrc
というエレメントもありますが、若干挙動が異なります。 cat
と同じよう動作をさせる方法は、また今度紹介します。
No comments:
Post a Comment