How to run a 2-to-1 element

iron_guitarist1987 jtrinidadperez at gmail.com
Wed May 23 07:32:52 PDT 2012


I have [finally] created a 2-to-1 simple element. My question now is how to
run it (an example gst-launch using 2 videotestsrc and 1 autosink). Here is
the code:



// gst_ntoone.c - Notes on creating a ntoone

/**
 * SECTION:element-plugin
 *
 * This plugin serves as a base template and a learning tool
 * for creating chain elements. All it does is to 
 *
 * <refsect2>
 * <title>Example launch line</title>
 * |[
 * gst-launch -v -m videontoonesrc pattern=snow ! ntoone ! autovideosink
 * ]|
 * </refsect2>
 */

#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

#include <gst/gst.h>
#include "gstntoone.h"
#include <opencv/cv.h>
#include <opencv/highgui.h>

GST_DEBUG_CATEGORY_STATIC (gst_ntoone_debug);
#define GST_CAT_DEFAULT gst_ntoone_debug

enum
{
  PROP_0,
  PROP_SILENT,
  LINE_COLOR
};

/* the capabilities of the inputs and outputs.
 *
 * describe the real formats here.
 */

//Creates a template for the pads. In the _init() function, you can create
//as many pads you want from these templates.
static GstStaticPadTemplate video_sink_factory = GST_STATIC_PAD_TEMPLATE
("video_sink",
    GST_PAD_SINK,
    GST_PAD_ALWAYS,
    GST_STATIC_CAPS ("ANY")
    );

static GstStaticPadTemplate klv_sink_factory = GST_STATIC_PAD_TEMPLATE
("klv_sink",
    GST_PAD_SINK,
    GST_PAD_ALWAYS,
    GST_STATIC_CAPS ("ANY")
    );

static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
    GST_PAD_SRC,
    GST_PAD_ALWAYS,
    GST_STATIC_CAPS ("ANY")
    );

GST_BOILERPLATE (GstNtoone, gst_ntoone, GstElement,
    GST_TYPE_ELEMENT);

//function prototypes
static void gst_ntoone_set_property (GObject * object, guint prop_id,
    const GValue * value, GParamSpec * pspec);
static void gst_ntoone_get_property (GObject * object, guint prop_id,
    GValue * value, GParamSpec * pspec);
static gboolean gst_ntoone_set_caps (GstPad * pad, GstCaps * caps);
static GstFlowReturn gst_ntoone_collected (GstCollectPads * pads, GstNtoone
* filter);

/* GObject vmethod implementations */
static void
gst_ntoone_base_init (gpointer gclass)
{
  GstElementClass *element_class = GST_ELEMENT_CLASS (gclass);

  //Describe the element's details
  //    Plugin name
  //    Plugin type
  //    A brief description
  //    Author and email (email is optional)
  gst_element_class_set_details_simple(element_class,
    "Plugin Template",
    "Ntoone",
    "Generic Chain Element",
    "Jason Trinidad jtrinidad at eoir.com");

  
  //Register the tamplates. They can be used
  //in the init() function to create pads
  gst_element_class_add_pad_template (element_class,
      gst_static_pad_template_get (&src_factory));
  gst_element_class_add_pad_template (element_class,
      gst_static_pad_template_get (&video_sink_factory));
  gst_element_class_add_pad_template (element_class,
      gst_static_pad_template_get (&klv_sink_factory));
}

/* initialize the plugin's class */
static void
gst_ntoone_class_init (GstNtooneClass * klass)
{
  GObjectClass *gobject_class;
  GstElementClass *gstelement_class;

  gobject_class = (GObjectClass *) klass;
  gstelement_class = (GstElementClass *) klass;

  gobject_class->set_property = gst_ntoone_set_property;
  gobject_class->get_property = gst_ntoone_get_property;

  g_object_class_install_property (gobject_class, PROP_SILENT, 
	  g_param_spec_boolean ("silent", "Silent", "Produce verbose output
?",FALSE, G_PARAM_READWRITE));
  

  g_object_class_install_property (gobject_class, LINE_COLOR, 
	  g_param_spec_string ("line_color", "Line_color", "Chenge the color of the
line", "red", G_PARAM_READWRITE));

}

/* initialize the new element
 * instantiate pads and add them to element
 */
static void
gst_ntoone_init (GstNtoone * filter,
    GstNtooneClass * gclass)
{
  filter->srcpad = gst_pad_new_from_static_template (&src_factory, "src");
  gst_pad_set_getcaps_function (filter->srcpad,
                                GST_DEBUG_FUNCPTR(gst_pad_proxy_getcaps));
  
  filter->sinkpad1 = gst_pad_new_from_static_template (&video_sink_factory,
"video_sink");
  gst_pad_set_setcaps_function (filter->sinkpad1,
                                GST_DEBUG_FUNCPTR(gst_ntoone_set_caps));
  gst_pad_set_getcaps_function (filter->sinkpad1,
                                GST_DEBUG_FUNCPTR(gst_pad_proxy_getcaps));
  
  filter->sinkpad2 = gst_pad_new_from_static_template (&klv_sink_factory,
"klv_sink");
  gst_pad_set_setcaps_function (filter->sinkpad2,
                                GST_DEBUG_FUNCPTR(gst_ntoone_set_caps));
  gst_pad_set_getcaps_function (filter->sinkpad2,
                                GST_DEBUG_FUNCPTR(gst_pad_proxy_getcaps));
  

  filter->collect = gst_collect_pads_new ();
  gst_collect_pads_set_function (filter->collect,
      (GstCollectPadsFunction) gst_ntoone_collected, filter);
  
  gst_collect_pads_add_pad (filter->collect, filter->sinkpad1, sizeof
(GstCollectData));
  gst_collect_pads_add_pad (filter->collect, filter->sinkpad2, sizeof
(GstCollectData));
  
  gst_element_add_pad (GST_ELEMENT (filter), filter->sinkpad1);
  gst_element_add_pad (GST_ELEMENT (filter), filter->sinkpad2);
  gst_element_add_pad (GST_ELEMENT (filter), filter->srcpad);
  filter->silent = FALSE;
  
}

/*-------------------------------------------------------------------
 * _set_property() is used to set arguments in the element.
 * they can be used when running a pipelin by just typing the
 * property name and the value right next to the plugin
 * e.g. gst-launch -v -m videontoonesrc pattern=snow ! ntoone
line_color=green ! autovideosink
 * where pattern and line_color are properties
 -------------------------------------------------------------------*/
static void
gst_ntoone_set_property (GObject * object, guint prop_id,
    const GValue * value, GParamSpec * pspec)
{
  GstNtoone *filter = GST_NTOONE (object);
   
  switch (prop_id) {
    case PROP_SILENT:
      filter->silent = g_value_get_boolean (value);
      break;
    case LINE_COLOR:
      g_free (filter->line_color); 
      filter->line_color = g_value_dup_string (value); 
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}

static void
gst_ntoone_get_property (GObject * object, guint prop_id,
    GValue * value, GParamSpec * pspec)
{
  GstNtoone *filter = GST_NTOONE (object);

 
  switch (prop_id) {
    case PROP_SILENT:
      g_value_set_boolean (value, filter->silent);
      break;
    case LINE_COLOR:
      g_value_set_string (value, filter->line_color);
      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_ntoone_set_caps (GstPad * pad, GstCaps * caps)
{
  GstStructure *structure = gst_caps_get_structure(caps,0);
  GstNtoone *filter;
  GstPad *otherpad;

  filter = GST_NTOONE (gst_pad_get_parent (pad));
  
  gst_structure_get_int (structure, "rate", &filter->srcpad);
  otherpad = (pad == filter->srcpad) ? filter->sinkpad1 : filter->srcpad;
  gst_object_unref (filter);

  
  return gst_pad_set_caps (otherpad, caps);
}


static GstFlowReturn
gst_ntoone_collected (GstCollectPads * pads, GstNtoone * filter)
{
  guint size;
  GstCollectData *cdata;
  GstBuffer *outbuf, *sink1buf, *sink2buf;
  GstFlowReturn ret = GST_FLOW_OK;
  GSList *collected;
  guint nsamples;
  guint ncollected = 0;
  gboolean empty = TRUE;
  
  size = gst_collect_pads_available (pads); //Query how much bytes can be
read from each queued buffer. 
					     //This means that the result of this call is the maximum 
					     //number of bytes that can be read from each of the pads.
  
  GST_DEBUG_OBJECT (filter, "Starting to collect %u bytes", size);
  
  collected = pads->data;
  cdata = (GstCollectData *) collected->data;
  sink1buf = gst_collect_pads_take_buffer (pads, cdata, size);
  
  collected = collected->next;
  cdata = (GstCollectData *) collected->data;
  sink2buf = gst_collect_pads_take_buffer (pads, cdata, size);
  
  gst_pad_push(filter->srcpad,sink1buf);
  
  return ret;
  
  goto eos;
 
eos:
  {
    GST_DEBUG_OBJECT (filter, "no data available, must be EOS");
    gst_buffer_unref (outbuf);
    gst_pad_push_event (filter->srcpad, gst_event_new_eos ());
    return -3;
  }
  
}


/* entry point to initialize the plug-in
 * initialize the plug-in itself
 * register the element factories and other features
 */
static gboolean
plugin_init (GstPlugin * plugin)
{
  /* debug category for filtering log messages
   *
   * exchange the string 'Ntoone plugin' with your description
   */
  GST_DEBUG_CATEGORY_INIT (gst_ntoone_debug, "ntoone",
      0, "Template plugin");

  return gst_element_register (plugin, "ntoone", GST_RANK_NONE,
      GST_TYPE_NTOONE);
}

/* 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 "pluginntoone"
#endif

/* gstreamer looks for this structure to register plugins
 *
 * exchange the string 'Template plugin' with your plugin description
 */
GST_PLUGIN_DEFINE (
    GST_VERSION_MAJOR,
    GST_VERSION_MINOR,
    "ntoone",
    "Template Example",
    plugin_init,
    "0.10.28",
    "GPL",
    "GStreamer",
    "http://gstreamer.net/"
)

Thanks

--
View this message in context: http://gstreamer-devel.966125.n4.nabble.com/How-to-run-a-2-to-1-element-tp4651655.html
Sent from the GStreamer-devel mailing list archive at Nabble.com.


More information about the gstreamer-devel mailing list