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