Reading of GST tags with explicit pipeline and not decodebin/playbin

Mihai Stoica mihai.stoica at gmail.com
Mon May 2 08:02:31 PDT 2011


Hi,

I have some issues trying to extract GST tags from a mov file.
Because of performance requirements I don't want to use a decoder.. so
the pipeline would be similar to:
gst-launch filesrc location=./movie.mov ! qtdemux ! fakesink --tags,
but written with GStreamer API with C.

If I execute this pipeline in command line I can see all tags being
extracted, but when trying to execute the C code no GST_MESSAGE_TAG is
being received.
If I replace qtdemux with decodebin without doing other changes to the
code... tag messages are being captured without any issues.

Could anyone give me a hint about what am I doing wrong ?

The code would be like this:

static GstElement *
create_decodebin_pipeline (MetadataExtractor *extractor, const gchar *uri)
{
	GstElement *pipeline = NULL;

	GstElement *filesrc  = NULL;
	GstElement *bin      = NULL;

	pipeline = gst_element_factory_make ("pipeline", NULL);
	if (!pipeline) {
		g_warning ("Failed to create GStreamer pipeline");
		return NULL;
	}

	filesrc = gst_element_factory_make ("giosrc", NULL);
	if (!filesrc) {
		g_warning ("Failed to create GStreamer giosrc");
		gst_object_unref (GST_OBJECT (pipeline));
		return NULL;
	}

	bin = gst_element_factory_make ("qtdemux", "qtdemux");
	if (!bin) {
		g_warning ("Failed to create GStreamer qtdemux");
		gst_object_unref (GST_OBJECT (pipeline));
		gst_object_unref (GST_OBJECT (filesrc));
		return NULL;
	}
	
	g_object_set (G_OBJECT (bin), "name", "demux", NULL);

	g_signal_connect (G_OBJECT (bin),
			  "pad-added",
			  G_CALLBACK (dbin_dpad_cb),
			  extractor);

	gst_bin_add (GST_BIN (pipeline), filesrc);
	gst_bin_add (GST_BIN (pipeline), bin);

	if (!gst_element_link_many (filesrc, bin, NULL)) {
		g_warning ("Could not link GStreamer elements");
		gst_object_unref (GST_OBJECT (pipeline));
		return NULL;
	}

	g_object_set (G_OBJECT (filesrc), "location", uri, NULL);

	extractor->bin = bin;

	return pipeline;
}


static void
dbin_dpad_cb (GstElement* e, GstPad* pad, gboolean cont, gpointer data_)
{
	MetadataExtractor *extractor = (MetadataExtractor *)data_;
	GstElement        *fsink;
	GstPad            *fsinkpad;
	GValue             val = {0, };

	fsink = gst_element_factory_make ("fakesink", NULL);

	/* We increase the preroll buffer so we get duration (one frame not enough)*/
	g_value_init (&val, G_TYPE_INT);
	g_value_set_int (&val, 51);
	g_object_set_property (G_OBJECT (fsink), "preroll-queue-len", &val);
	g_value_unset (&val);

	extractor->fsinks = g_list_append (extractor->fsinks, fsink);
	gst_element_set_state (fsink, GST_STATE_PAUSED);

	gst_bin_add (GST_BIN (extractor->pipeline), fsink);
	fsinkpad = gst_element_get_static_pad (fsink, "sink");
	gst_pad_link (pad, fsinkpad);
	gst_object_unref (fsinkpad);
}


static gboolean
poll_for_ready (MetadataExtractor *extractor,
                GstState state, /* GST_STATE_PAUSED */
                gboolean ready_with_state, /* TRUE */
                gboolean ready_with_eos) /* FALSE */
{

	gint64              timeout   = 5 * GST_SECOND;
	GstBus             *bus       = extractor->bus;
	GstTagList         *new_tags;

	gst_element_set_state (extractor->pipeline, state);

	while (TRUE) {
		GstMessage *message;
		GstElement *src;

		message = gst_bus_timed_pop (bus, timeout);

		if (!message) {
			g_warning ("Pipeline timed out");
			return FALSE;
		}

		src = (GstElement*)GST_MESSAGE_SRC (message);

		switch (GST_MESSAGE_TYPE (message)) {
		case GST_MESSAGE_TAG: {

			gst_message_parse_tag (message, &new_tags);
			add_tags (new_tags, extractor);
			gst_tag_list_free (new_tags);
			break;
		}
		default:
			/* Nothing to do here */
			break;
		}

		gst_message_unref (message);
	}

	g_assert_not_reached ();

	return FALSE;
}

Thanks,
Mihai.


More information about the gstreamer-devel mailing list