Wednesday, December 9, 2015

GStreamer でプログラミング 4 (Bin と Iterator)

もし本当に GStreamer の pipeline に入っているエレメントの名前が分らなかったら?

pipeline は自分が持っているエレメントを知っています。なので、pipeline に問い合わせて、持っているエレメントをイテレーターで貰うことができます。これ、pipeline の親クラスである GstBin の機能なんです。

Ruby のように Internal Iterator (内部イテレータ)かつ、Dynamic Typing (動的型付け) であれば

pipeline.each do |elem|
puts elem.name
end

と書けるのですが、C で実装されている GStreamer では、ちょっと面倒ですね。

  1. Pipelineから外部イテレータを貰い ( gst_bin_iterate_elements() )
  2. 次のエレメントをイテレーターから貰います。( gst_iterator_next() )
  3. 貰ったエレメントは、実は GValue という「なんでも内包できる構造体」なので、これから実際のエレメントを取り出します。 ( g_value_get_object() )
#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;
GstIterator *itr;
GstElement *elem;
GValue val = G_VALUE_INIT;
gboolean done = FALSE;
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);
itr = gst_bin_iterate_elements(GST_BIN(pipeline));
while (!done) {
switch (gst_iterator_next(itr, &val)) {
case GST_ITERATOR_OK:
elem = g_value_get_object(&val);
g_print("name: %s\n", gst_element_get_name(elem));
g_value_unset(&val);
break;
default:
done = TRUE;
break;
}
}
gst_element_set_state(pipeline, GST_STATE_PLAYING);
g_main_loop_run(mainloop);
return 0;
}
view raw element-itr.c hosted with ❤ by GitHub

gst_iterator_foreach() もあるのですが Lambda が使えない C では、関数を指定する必要があります。

GValue は、なんでも入れることができるという点で、「void*」のようなものですが、型情報を持っている点が異なります。型が必須なので必ず使う前に G_VALUE_INIT または g_value_init() で初期化してください。

GValue や GstElement は、Dynamic Typing を持っていない C のために実装された Glib Dynamic Type System を使っています。 GObject が基本クラスです。Ruby C API で言うところの、 VALUE ですね。

他のエレメントを内包できるエレメントは、イテレーターが使えることが多いので、一度やり方を覚えると便利です。お試しあれ。

No comments:

Post a Comment