problems with caps-negotiating of self-made element

Thiago Sousa Santos thiago.sousa.santos at collabora.com
Tue Dec 20 07:36:01 PST 2011


On Tue, 2011-12-20 at 10:30 +0100, Andreas GST DEV wrote:
> Hello,
> 
> I am working on a image converter, converting images from YUY2 to UYVY.  
> Well, I have some problems with the negotiating of the pads. Without 
> filter-elements between the elements it is working (doing something, but 
> the wrong) and with some filter to force the right media-type it is not 
> working.

You should post the error you are getting. Have you tried looking at
GST_DEBUG yet?

I guess the problem is in using gst_pad_proxy_getcaps, it will get
downstream caps and return that as what your sink pad supports. Which
seems to be false for your case.

> 
> Here is the source-code of my Gst-Element vicimgconv:
> ----------------------------------------------------------------------------------------------------------
> /* GStreamer plugin for converting Images (VICImageConverter)
>   * Copyright (C) 2011 Andreas Buettner
>   *
>   * SECTION:element-vicimgconv
>   *
>   * FIXME:Describe vicimgconv here.
>   *
>   * <refsect2>
>   * <title>Example launch line</title>
>   * |[
>   * gst-launch -v -m fakesrc ! vicimgconv ! fakesink silent=TRUE
>   * ]|
>   * </refsect2>
>   */
> 
> #ifdef HAVE_CONFIG_H
> #  include <config.h>
> #endif
> 
> #include <gst/gst.h>
> #include <gst/video/video.h>
> 
> #include "gstvicimgconv.h"
> 
> GST_DEBUG_CATEGORY_STATIC (gst_vicimgconv_debug);
> #define GST_CAT_DEFAULT gst_vicimgconv_debug
> 
> static const GstElementDetails vicimgconv_details =
>          GST_ELEMENT_DETAILS ("Video Image converter",
>                  "Filter/Converter/Video",
>                  "Converts the colorspace of a videostream",
>                  "ABUE GMBH");
> 
> 
> /* Filter signals and args */
> enum
> {
>      /* FILL ME */
>      LAST_SIGNAL
> };
> 
> enum
> {
>      PROP_0,
>      PROP_SILENT
> };
> 
> /* the capabilities of the inputs and outputs.
>   *
>   * describe the real formats here.
>   */
> static GstStaticPadTemplate vicimgconv_sink_template = 
> GST_STATIC_PAD_TEMPLATE ("sink",
>          GST_PAD_SINK,
>          GST_PAD_ALWAYS,
>          GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("YUY2"))
>          //GST_STATIC_CAPS ("ANY")
>          //GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV("UYVY"))
> );
> 
> static GstStaticPadTemplate vicimgconv_src_template = 
> GST_STATIC_PAD_TEMPLATE ("src",
>          GST_PAD_SRC,
>          GST_PAD_ALWAYS,
>          //GST_STATIC_CAPS ("ANY")
>          //GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV("YUY2"))
>          GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV("UYVY"))
> );
> 
> GST_BOILERPLATE (Gstvicimgconv, gst_vicimgconv, GstElement,
>          GST_TYPE_ELEMENT);
> 
> /*
>   * FUNCTION FORWARD DECLARATION
>   */
> 
> static void gst_vicimgconv_set_property (GObject * object, guint prop_id,
>          const GValue * value, GParamSpec * pspec);
> static void gst_vicimgconv_get_property (GObject * object, guint prop_id,
>          GValue * value, GParamSpec * pspec);
> 
> static gboolean gst_vicimgconv_set_caps (GstPad * pad, GstCaps * caps);
> static GstFlowReturn gst_vicimgconv_chain (GstPad * pad, GstBuffer * buf);
> 
> /* GObject vmethod implementations */
> 
> static void
> gst_vicimgconv_base_init (gpointer gclass)
> {
>      GstElementClass *element_class = GST_ELEMENT_CLASS (gclass);
> 
>      /* set the details of the Element Class */
>      gst_element_class_set_details (element_class, &vicimgconv_details);
> 
>      gst_element_class_add_pad_template (element_class, 
> gst_static_pad_template_get (&vicimgconv_src_template));
>      gst_element_class_add_pad_template (element_class, 
> gst_static_pad_template_get (&vicimgconv_sink_template));
> }
> 
> /* initialize the vicimgconv's class */
> static void
> gst_vicimgconv_class_init (GstvicimgconvClass * klass)
> {
>      GObjectClass *gobject_class;
>      GstElementClass *gstelement_class;
> 
>      gobject_class = (GObjectClass *) klass;
>      gstelement_class = (GstElementClass *) klass;
> 
>      gobject_class->set_property = gst_vicimgconv_set_property;
>      gobject_class->get_property = gst_vicimgconv_get_property;
> 
>      g_object_class_install_property (gobject_class, PROP_SILENT,
>              g_param_spec_boolean ("silent", "Silent", "Produce verbose 
> output ?",
>                      FALSE, G_PARAM_READWRITE));
> 
> }
> 
> /* initialize the new element
>   * instantiate pads and add them to element
>   * set pad calback functions
>   * initialize instance structure
>   */
> static void
> gst_vicimgconv_init (Gstvicimgconv * filter, GstvicimgconvClass * gclass)
> {
>      /* local variables */
>      GstElementClass *klass = GST_ELEMENT_CLASS (gclass);
> 
>      /* pad through which data comes in to the element */
>      //filter->sinkpad = gst_pad_new_from_template 
> (gst_element_class_get_pad_template (klass, "sink"), "sink");
> 
>      filter->sinkpad = gst_pad_new_from_static_template 
> (&vicimgconv_sink_template, "sink");
> 
>      /* set the pointer to the _setcaps() function */
>      //gst_pad_set_setcaps_function (filter->sinkpad, 
> GST_DEBUG_FUNCPTR(gst_vicimgconv_set_caps));
> 
>      /* set the pointer to the _getcaps() function */
>      gst_pad_set_getcaps_function (filter->sinkpad, 
> GST_DEBUG_FUNCPTR(gst_pad_proxy_getcaps));
> 
>      /* set the pointer to the _chain() function */
>      gst_pad_set_chain_function (filter->sinkpad, 
> GST_DEBUG_FUNCPTR(gst_vicimgconv_chain));
> 
> 
>      /* pad through which data goes out of the element */
>      //filter->srcpad = gst_pad_new_from_template 
> (gst_element_class_get_pad_template (klass, "src"), "src");
> 
>      filter->srcpad = gst_pad_new_from_static_template 
> (&vicimgconv_src_template, "src");
> 
>      //gst_pad_set_getcaps_function (filter->srcpad, 
> GST_DEBUG_FUNCPTR(gst_pad_proxy_getcaps));
> 
>      /* add the pads to the element */
>      gst_element_add_pad (GST_ELEMENT (filter), filter->sinkpad);
>      gst_element_add_pad (GST_ELEMENT (filter), filter->srcpad);
>      /* properties initial value */
>      filter->silent = FALSE;
> }
> 
> static void
> gst_vicimgconv_set_property (GObject * object, guint prop_id,
>          const GValue * value, GParamSpec * pspec)
> {
>      Gstvicimgconv *filter = GST_VICIMGCONV (object);
> 
>      /* set the Properties of the Element */
>      switch (prop_id) {
>      case PROP_SILENT:
>          filter->silent = g_value_get_boolean (value);
>          break;
>      default:
>          G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
>          break;
>      }
> }
> 
> static void
> gst_vicimgconv_get_property (GObject * object, guint prop_id,
>          GValue * value, GParamSpec * pspec)
> {
>      Gstvicimgconv *filter = GST_VICIMGCONV (object);
> 
>      /* get the Properties of the Element */
>      switch (prop_id) {
>      case PROP_SILENT:
>          g_value_set_boolean (value, filter->silent);
>          break;
>      default:
>          G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
>          break;
>      }
> }
> 
> /* GstElement vmethod implementations */
> 
> /* this function handles the link with other elements */
> static gboolean gst_vicimgconv_set_caps (GstPad * pad, GstCaps * caps)
> {
>      Gstvicimgconv *filter;
>      //GstPad *otherpad;
>      const GstStructure *structure;
>      const gchar *mime;
> 
>      /* get the strings of the given cap */
>      structure = gst_caps_get_structure(caps, 0);
> 
>      g_return_val_if_fail (structure, FALSE);
> 
>      mime = gst_structure_get_name (structure);
> 
>      /* check if we can handle this mime-type */
>      if (g_strcmp0(mime, "video/x-raw-yuv") != 0)
>      {
>          GST_WARNING("Wrong Mime-Type %s is provided, we only support 
> %s", mime, "video/x-raw-yuv");
>          return FALSE;
>      }
> 
>      /* set the caps of the srcpad of the filter */
>      if (!gst_pad_set_caps (filter->srcpad, caps))
>      {
>          GST_WARNING("Capsnego not successfull");
>          return FALSE;
>      }
> 
> 
>      filter = GST_VICIMGCONV (gst_pad_get_parent (pad));
>      //otherpad = (pad == filter->srcpad) ? filter->sinkpad : 
> filter->srcpad;
> 
> 
>      //gst_object_unref (filter);
> 
>      g_print("gst_vicimgconv_set_caps:return TRUE");
>      //return gst_pad_set_caps (otherpad, caps);
>      return TRUE;
> }
> 
> /* chain function
>   * this function does the actual processing
>   */
> static GstFlowReturn gst_vicimgconv_chain (GstPad * pad, GstBuffer * buf)
> {
>      Gstvicimgconv *filter;
>      GstBuffer *out_buf;
>      guint8 *ptr_in, *ptr_out;
>      guint size;
>      gint i;
> 
>      filter = GST_VICIMGCONV (GST_OBJECT_PARENT (pad));
>      out_buf = gst_buffer_copy (buf);                    /* copy the 
> input buffer */
> 
>      /* call the image conversion function */
>      if(convYUY2toUYVY(GST_BUFFER_DATA(buf), GST_BUFFER_DATA(out_buf), 
> GST_BUFFER_SIZE(buf)) < 0)
>          g_print("Fehler bei der Konvertierung\n");
> 
> 
>      /* add here debug-messages */
>      if (filter->silent == FALSE)
>          //g_print("Have Data of size %u bytes with start-adress %d!\n", 
> size, ptr);
> 
>      /* just push out the incoming buffer without touching it */
>      return gst_pad_push (filter->srcpad, out_buf);
>      //return GST_FLOW_OK;
> }
> 
> 
> /* entry point to initialize the plug-in
>   * initialize the plug-in itself
>   * register the element factories and other features
>   * load here other dependencies
>   * return: TRUE or FALSE
>   */
> static gboolean
> vicimgconv_init (GstPlugin * vicimgconv)
> {
>      /* debug category for fltering log messages
>       *
>       * exchange the string 'Template vicimgconv' with your description
>       */
>      GST_DEBUG_CATEGORY_INIT (gst_vicimgconv_debug, "vicimgconv",
>              0, "Converter for video images");
> 
>      return gst_element_register (vicimgconv, "vicimgconv", GST_RANK_NONE,
>              GST_TYPE_VICIMGCONV);
> }
> 
> /* PACKAGE: this is usually set by autotools depending on some _INIT macro
>   * in configure.ac and then written into and defined in config.h, but 
> we can
>   * just set it ourselves here in case someone doesn't use autotools to
>   * compile this code. GST_PLUGIN_DEFINE needs PACKAGE to be defined.
>   */
> #ifndef PACKAGE
> #define PACKAGE "myfirstvicimgconv"
> #endif
> 
> /* gstreamer looks for this structure to register vicimgconvs
>   *
>   * exchange the string 'Template vicimgconv' with your vicimgconv 
> description
>   */
> GST_PLUGIN_DEFINE (
>          GST_VERSION_MAJOR,
>          GST_VERSION_MINOR,
>          "vicimgconv",
>          "Converter for video images",
>          vicimgconv_init,
>          VERSION,
>          "LGPL",
>          "GStreamer",
>          "http://gstreamer.net/"
> )
> 
> 
> 
> /* Konvertierung vom YUY2 ins UYVY Format --> ByteSwapping */
> int convYUY2toUYVY(unsigned char *source_ptr, unsigned char *result_ptr, 
> unsigned int size)
> {
>      int i;
> 
>      /* Verarbeitung */
>      for (i = 0; i < size; i = i+2)
>      {
>          //printf("Wert %d: 0x%02X\n", i, *source_ptr);
>          *(result_ptr) = *(source_ptr + 1);
>          *(result_ptr + 1) = *(source_ptr);
>          result_ptr = result_ptr + 2;
>          source_ptr = source_ptr + 2;
>      }
> 
>      return 1;
> }
> ----------------------------------------------------------------------------------------------------------
> 
> 
> This is the working application-code:
> ----------------------------------------------------------------------------------------------------------
> /*
>   * vicimgconv_app.c
>   *
>   *  Created on: 20.12.2011
>   *      Author: user
>   */
> 
> /* modules */
> #include <string.h>
> #include <math.h>
> #include <gst/gst.h>
> #include <glib.h>
> #include <glib-object.h>
> 
> /* function declaration */
> 
> 
> 
> /* main */
> int main (int argc, char *argv[])
> {
>    g_debug(G_STRFUNC);
> 
>    /* variables */
>    GstElement *vsrc, *vconv, *vsink;
>    GstElement *pipeline;
>    GMainLoop *loop;
>    gboolean res;
> 
>    /* always init first */
>    gst_init (&argc, &argv);
> 
>    /* the pipeline to hold everything */
>    pipeline = gst_pipeline_new (NULL);
>    g_assert (pipeline);
> 
>    /* creating all videoelements */
>    vsrc = gst_element_factory_make ("videotestsrc","vsrc");
>    g_assert(vsrc);
>    vconv = gst_element_factory_make ("vicimgconv","vicimgconv");
>    g_assert(vconv);
>    vsink = gst_element_factory_make ("xvimagesink","vsink");
>    g_assert(vsink);
> 
>    /* check if all elements are created */
>    if (!pipeline || !vsrc || !vconv || !vsink) {
>      g_printerr ("One element could not be created. Exiting.\n");
>      return -1;
>    }
>    else
>    { g_message("All elements are created.");}
> 
>    /* add all elements to the pipeline */
>    gst_bin_add_many (GST_BIN (pipeline), vsrc, vconv, vsink, NULL);
> 
>      res = gst_element_link_many(vsrc, vconv, vsink,NULL);
>      if (res == FALSE)
>          g_debug("linking error");
> 
>    /* set the pipeline to playing */
>    g_message ("starting sender pipeline\n");
>    gst_element_set_state (pipeline, GST_STATE_PLAYING);
> 
>    /* we need to run a GLib main loop to get the messages */
>    loop = g_main_loop_new (NULL, FALSE);
>    g_main_loop_run (loop);
> 
>    /* set to the pipeline to ending */
>    g_print ("stopping sender pipeline\n");
>    gst_element_set_state (pipeline, GST_STATE_NULL);
> 
> return 0;
> }
> ----------------------------------------------------------------------------------------------------------
> 
> But If I try to use filters between the elements, it is not working:
> ----------------------------------------------------------------------------------------------------------
> 
> /* modules */
> #include <string.h>
> #include <math.h>
> #include <gst/gst.h>
> #include <glib.h>
> #include <glib-object.h>
> 
> /* function declaration */
> 
> 
> 
> /* main */
> int main (int argc, char *argv[])
> {
>    g_debug(G_STRFUNC);
> 
>    /* variables */
>    GstElement *vsrc, *vconv, *vsink;
>    GstElement *pipeline;
>    GMainLoop *loop;
>    gboolean res;
>      GstCaps *caps, *caps2;
> 
>    /* always init first */
>    gst_init (&argc, &argv);
> 
>    /* the pipeline to hold everything */
>    pipeline = gst_pipeline_new (NULL);
>    g_assert (pipeline);
> 
>    /* creating all videoelements */
>    vsrc = gst_element_factory_make ("videotestsrc","vsrc");
>    g_assert(vsrc);
>    vconv = gst_element_factory_make ("vicimgconv","vicimgconv");
>    g_assert(vconv);
>    vsink = gst_element_factory_make ("xvimagesink","vsink");
>    g_assert(vsink);
> 
>    /* check if all elements are created */
>    if (!pipeline || !vsrc || !vconv || !vsink) {
>      g_printerr ("One element could not be created. Exiting.\n");
>      return -1;
>    }
>    else
>    { g_message("All elements are created.");}
> 
> 
>      caps = gst_caps_new_simple ("video/x-raw-yuv" ,
>          "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'),
>          "width", G_TYPE_INT, 320,
>          "height", G_TYPE_INT, 240,
>          "bpp", G_TYPE_INT, 24,
>          NULL );
> 
>      caps2 = gst_caps_new_simple ("video/x-raw-yuv" ,
>                  "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('U', 'Y', 
> 'V', 'Y'),
>                  NULL );
> 
> 
>    /* add all elements to the pipeline */
>    gst_bin_add_many (GST_BIN (pipeline), vsrc, vconv, vsink, NULL);
> 
>      if(!gst_element_link_filtered(vsrc,vconv,caps))
>      {
>              g_print ("1 Failed to link one or more elements!\n");
>              return -1;
>      }
> 
>      if(!gst_element_link_filtered(vconv,vsink,caps2))
>      {
>              g_print ("1 Failed to link one or more elements!\n");
>              return -1;
>      }
> 
>    /* set the pipeline to playing */
>    g_message ("starting sender pipeline\n");
>    gst_element_set_state (pipeline, GST_STATE_PLAYING);
> 
>    /* we need to run a GLib main loop to get the messages */
>    loop = g_main_loop_new (NULL, FALSE);
>    g_main_loop_run (loop);
> 
>    /* set to the pipeline to ending */
>    g_print ("stopping sender pipeline\n");
>    gst_element_set_state (pipeline, GST_STATE_NULL);
> 
> return 0;
> }
> ----------------------------------------------------------------------------------------------------------
> 
> Maybe anybody has a hint for me. I suppose that I have to change 
> something in the Gst-Element vicimgconv or?
> 
> Thanks in advance.
> 
> Andreas

--
Thiago

> 
> 
> _______________________________________________
> gstreamer-devel mailing list
> gstreamer-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/gstreamer-devel




More information about the gstreamer-devel mailing list