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

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

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

Mihai Stoica
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.
_______________________________________________
gstreamer-devel mailing list
[hidden email]
http://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
Reply | Threaded
Open this post in threaded view
|

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

Stefan Sauer
Am 02.05.2011 18:02, schrieb Mihai Stoica:

> 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 ?

I don't see anything obvious right now, but wonder why you are not using
GstDiscoverer instead.

Stefan

>
> 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.
> _______________________________________________
> gstreamer-devel mailing list
> [hidden email]
> http://lists.freedesktop.org/mailman/listinfo/gstreamer-devel

_______________________________________________
gstreamer-devel mailing list
[hidden email]
http://lists.freedesktop.org/mailman/listinfo/gstreamer-devel