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