[Cogl] [PATCH 3/3] cogl-basic-video-player: Allow passing a GStreamer pipeline

Robert Bragg robert at sixbynine.org
Thu Jan 30 16:16:43 PST 2014


Nice feature!

This looks good to land to me:

Reviewed-by: Robert Bragg <robert at linux.intel.com>

Thanks,
Robert

On Tue, Jan 21, 2014 at 5:33 PM, Neil Roberts <neil at linux.intel.com> wrote:
> If the URI argument given on the command line doesn't look like a URI
> then the basic video player will now try to parse it as a GStreamer
> pipeline description. The pipeline must contain a coglsink element
> which the player will look for. This can be used to test Cogl GST. For
> example, to test NV12 this can be used:
>
> ./cogl-basic-video-player 'videotestsrc !
>                            video/x-raw,format=(string)NV12 !
>                            coglsink'
> ---
>  examples/cogl-basic-video-player.c | 134 +++++++++++++++++++++++++++++++++----
>  1 file changed, 122 insertions(+), 12 deletions(-)
>
> diff --git a/examples/cogl-basic-video-player.c b/examples/cogl-basic-video-player.c
> index 552298a..34678f3 100644
> --- a/examples/cogl-basic-video-player.c
> +++ b/examples/cogl-basic-video-player.c
> @@ -1,5 +1,6 @@
>  #include <stdbool.h>
>  #include <string.h>
> +#include <stdlib.h>
>
>  #include <cogl/cogl.h>
>  #include <cogl-gst/cogl-gst.h>
> @@ -234,6 +235,120 @@ _set_up_pipeline (gpointer instance,
>    g_signal_connect (data->sink, "new-frame", G_CALLBACK (_new_frame_cb), data);
>  }
>
> +static CoglBool
> +is_uri (const char *str)
> +{
> +  const char *p = str;
> +
> +  while (g_ascii_isalpha (*p))
> +    p++;
> +
> +  return p > str && g_str_has_prefix (p, "://");
> +}
> +
> +static CoglGstVideoSink *
> +find_cogl_gst_video_sink (GstElement *element)
> +{
> +  GstElement *sink_element = NULL;
> +  GstIterator *iterator;
> +  GstElement *iterator_value;
> +  GValue value;
> +
> +  if (!GST_IS_BIN (element))
> +    return NULL;
> +
> +  iterator = gst_bin_iterate_recurse (GST_BIN (element));
> +
> +  g_value_init (&value, GST_TYPE_ELEMENT);
> +
> +  while (gst_iterator_next (iterator, &value) == GST_ITERATOR_OK)
> +    {
> +      iterator_value = g_value_get_object (&value);
> +
> +      g_value_reset (&value);
> +
> +      if (COGL_GST_IS_VIDEO_SINK (iterator_value))
> +        {
> +          sink_element = iterator_value;
> +          break;
> +        }
> +    }
> +
> +  g_value_unset (&value);
> +
> +  gst_iterator_free (iterator);
> +
> +  return COGL_GST_VIDEO_SINK (sink_element);
> +}
> +
> +
> +static CoglBool
> +make_pipeline_for_uri (CoglContext *ctx,
> +                       const char *uri,
> +                       GstElement **pipeline_out,
> +                       CoglGstVideoSink **sink_out,
> +                       GError **error)
> +{
> +  GstElement *pipeline;
> +  GstElement *bin;
> +  CoglGstVideoSink *sink;
> +  GError *tmp_error = NULL;
> +
> +  if (is_uri (uri))
> +    {
> +      pipeline = gst_pipeline_new ("gst-player");
> +      bin = gst_element_factory_make ("playbin", "bin");
> +
> +      sink = cogl_gst_video_sink_new (ctx);
> +
> +      g_object_set (G_OBJECT (bin),
> +                    "video-sink",
> +                    GST_ELEMENT (sink),
> +                    NULL);
> +
> +      gst_bin_add (GST_BIN (pipeline), bin);
> +
> +      g_object_set (G_OBJECT (bin), "uri", uri, NULL);
> +    }
> +  else
> +    {
> +      pipeline = gst_parse_launch (uri, &tmp_error);
> +
> +      if (tmp_error)
> +        {
> +          if (pipeline)
> +            g_object_unref (pipeline);
> +
> +          g_propagate_error (error, tmp_error);
> +
> +          return FALSE;
> +        }
> +
> +      sink = find_cogl_gst_video_sink (pipeline);
> +
> +      if (sink == NULL)
> +        {
> +          g_set_error (error,
> +                       GST_STREAM_ERROR,
> +                       GST_STREAM_ERROR_FAILED,
> +                       "The pipeline does not contain a CoglGstVideoSink. "
> +                       "Make sure you add a 'coglsink' element somewhere in "
> +                       "the pipeline");
> +          g_object_unref (pipeline);
> +          return FALSE;
> +        }
> +
> +      g_object_ref (sink);
> +
> +      cogl_gst_video_sink_set_context (sink, ctx);
> +    }
> +
> +  *pipeline_out = pipeline;
> +  *sink_out = sink;
> +
> +  return TRUE;
> +}
> +
>  int
>  main (int argc,
>        char **argv)
> @@ -242,10 +357,10 @@ main (int argc,
>    CoglContext *ctx;
>    CoglOnscreen *onscreen;
>    GstElement *pipeline;
> -  GstElement *bin;
>    GSource *cogl_source;
>    GstBus *bus;
>    char *uri;
> +  GError *error = NULL;
>
>    memset (&data, 0, sizeof (Data));
>
> @@ -279,22 +394,17 @@ main (int argc,
>       context with cogl_gst_video_sink_set_context.
>    */
>
> -  data.sink = cogl_gst_video_sink_new (ctx);
> -
> -  pipeline = gst_pipeline_new ("gst-player");
> -  bin = gst_element_factory_make ("playbin", "bin");
> -
>    if (argc < 2)
>      uri = "http://docs.gstreamer.com/media/sintel_trailer-480p.webm";
>    else
>      uri = argv[1];
>
> -  g_object_set (G_OBJECT (bin), "video-sink", GST_ELEMENT (data.sink), NULL);
> -
> -
> -  gst_bin_add (GST_BIN (pipeline), bin);
> -
> -  g_object_set (G_OBJECT (bin), "uri", uri, NULL);
> +  if (!make_pipeline_for_uri (ctx, uri, &pipeline, &data.sink, &error))
> +    {
> +      g_print ("Error creating pipeline: %s\n", error->message);
> +      g_clear_error (&error);
> +      return EXIT_FAILURE;
> +    }
>
>    gst_element_set_state (pipeline, GST_STATE_PLAYING);
>    bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
> --
> 1.8.4.2
>
> _______________________________________________
> Cogl mailing list
> Cogl at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/cogl


More information about the Cogl mailing list