Question

I have created a 2-to-1 simple element called ntoone. My question now is how to run it (an example gst-launch using 2 videotestsrc and 1 autosink). It has two static "any" sink pads called video_sink and klv_sink and are added to a collection. Here is the code:

#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@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); 
} 

#ifndef PACKAGE 
#define PACKAGE "pluginntoone" 
#endif 

GST_PLUGIN_DEFINE ( 
    GST_VERSION_MAJOR, 
    GST_VERSION_MINOR, 
    "ntoone", 
    "Template Example", 
    plugin_init, 
    "0.10.28", 
    "GPL", 
    "GStreamer", 
    "http://gstreamer.net/" 
) 

Thanks

Was it helpful?

Solution

First check that your element shows up in gst-inspect.

Then you can use it using gst-launch as below:

gst-launch videotestsrc ! ntoone name=mix ! autovideosink videotestsrc ! ntoone.

You can also specify the pads directly

gst-launch ntoone name=mix ! autovideosink videotestsrc ! ntoone.video_sink videotestsrc ! ntoone.klv_sink

When there is no '!' a new branch of the media graph is started.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top