Custon Bin plugin problems

troels troels at newtec.dk
Wed Feb 6 08:56:11 UTC 2019


Hi,

I am trying to make a simple bin plugin using the  gst-template
<https://gitlab.freedesktop.org/gstreamer/gst-template>  . By simple I mean
just using elements already available in the official gstreamer plugins.
However, I am having trouble doing so. Following the tutorials about
creating  bin plugins
<https://gstreamer.freedesktop.org/documentation/plugin-development/element-types/manager.html>  
it seems I should be able to do so primarily in the *_init()* function. Now
I've done it very similar to writing a gstreamer pipeline in an application,
in the hopes that I don't have to care too much about the underlying data
flow of an element/bin. 

So far, so good. I have added ghostpads and the bin is able to compile and
be used as an element in a pipeline. However, when I try to run it using:

*gst-launch-1.0 audiotestsrc ! dizzy ! pulsesink -v
*
 it gives me the following error:

Deinterleave pad
Interleave pad
Ghost pad added: Sink
Ghost pad added: Src
degree: 0.000000
Left=1.000000 Right=0.000000
Setting pipeline to PAUSED ...
Pipeline is PREROLLING ...
/GstPipeline:pipeline0/GstAudioTestSrc:audiotestsrc0.GstPad:src: caps =
audio/x-raw, format=(string)S16LE, layout=(string)interleaved,
rate=(int)44100, channels=(int)2
/GstPipeline:pipeline0/Gstdizzy:dizzy0.GstPad:src: caps = audio/x-raw,
format=(string)S16LE, layout=(string)interleaved, rate=(int)44100,
channels=(int)2
Redistribute latency...
/GstPipeline:pipeline0/GstPulseSink:pulsesink0.GstPad:sink: caps =
audio/x-raw, format=(string)S16LE, layout=(string)interleaved,
rate=(int)44100, channels=(int)2
/GstPipeline:pipeline0/Gstdizzy:dizzy0.GstPad:sink: caps = audio/x-raw,
format=(string)S16LE, layout=(string)interleaved, rate=(int)44100,
channels=(int)2

*(gst-launch-1.0:113107): GStreamer-CRITICAL **: 09:34:52.799: chain on pad
dizzy0:sink but it has no chainfunction*
ERROR: from element /GstPipeline:pipeline0/GstAudioTestSrc:audiotestsrc0:
Internal data stream error.
Additional debug info:
gstbasesrc.c(3055): gst_base_src_loop ():
/GstPipeline:pipeline0/GstAudioTestSrc:audiotestsrc0:
streaming stopped, reason not-supported (-6)
ERROR: pipeline doesn't want to preroll.
Setting pipeline to NULL ...
Freeing pipeline ...

I've focused on the "chain on pad dizzy0:sink but it has no chainfunction",
since I don't really understand that. I understand the purpose of the chain
function, but not why I am required to use it in my case. Also when I look
at the source code of other plugins, most of them don't even have a chain
function and in the tutorials I can't remember seeing an example without a
chain function and how that works.
If I add the chain function from the generated template, it seems all the
data is not entering my bin, but simply flowing through my plugin, since it
just pushes the buffer to the next element in the pipeline. In that case the
plugin "works", but it doesn't serve a purpose, since it isn't doing
anything with the data. 
The template chain function (when not commented):
static void
 gst_dizzy_chain(GstPad *pad, GstObject *parent, GstBuffer *buf) {
   Gstdizzy *filter;

   filter = GST_DIZZY(parent);

   /* just push out the incoming buffer without touching it */
   return gst_pad_push(filter->srcpad, buf);
}

Do I have to push the buffer into my bin somehow in the chain function?

My *_init()* function with really just a simple bin and some ghostpads added
to the sink and source.

static void
gst_dizzy_init(Gstdizzy *filter) {
  filter->sinkpad = gst_pad_new_from_static_template(&sink_factory, "sink");
  filter->srcpad = gst_pad_new_from_static_template(&src_factory, "src");

  // Create Bin
  filter->bin = gst_bin_new("3dsound");

  GST_PAD_SET_PROXY_CAPS(filter->sinkpad);
  GST_PAD_SET_PROXY_CAPS(filter->srcpad);

  // filter->elements.alsasrc = gst_element_factory_make("alsasrc", "src");
  filter->elements.deinterleave = gst_element_factory_make("deinterleave",
"split");
  filter->elements.amplify = gst_element_factory_make("audioamplify",
"sink");
  filter->elements.queue_1 = gst_element_factory_make("queue", "queue1");
  filter->elements.queue_2 = gst_element_factory_make("queue", "queue2");
  filter->elements.volume = gst_element_factory_make("volume", "volume1");
  filter->elements.audio_panorama_1 =
gst_element_factory_make("audiopanorama", "panorama1");
  filter->elements.audio_panorama_2 =
gst_element_factory_make("audiopanorama", "panorama2");
  filter->elements.phaseshift_1 = gst_element_factory_make("audioinvert",
"phaseshift1");
  filter->elements.phaseshift_2 = gst_element_factory_make("audioinvert",
"phaseshift2");
  filter->elements.audio_convert_1_1 =
gst_element_factory_make("audioconvert", "convert1_1");
  filter->elements.audio_convert_1_2 =
gst_element_factory_make("audioconvert", "convert1_2");
  filter->elements.audio_convert_2_1 =
gst_element_factory_make("audioconvert", "convert2_1");
  filter->elements.audio_convert_2_2 =
gst_element_factory_make("audioconvert", "convert2_2");
  filter->elements.interleave = gst_element_factory_make("interleave",
"combine");
  filter->elements.sink_1 = gst_element_factory_make("pulsesink", "sink1");
  filter->elements.sink_2 = gst_element_factory_make("pulsesink", "sink2");
  filter->elements.alsasink = gst_element_factory_make("alsasink",
"alsasink");

  filter->elements.adder = gst_element_factory_make("adder", "add");
  // Ghost Pads
  GstPad *sinkpad = gst_element_get_static_pad(filter->elements.amplify,
"sink");
  GstPad *srcpad = gst_element_get_static_pad(filter->elements.interleave,
"src");

  filter->bin = GST_BIN(gst_pipeline_new("Stereopicture"));

  filter->elements.caps = gst_caps_new_simple("audio/x-raw", "channels",
G_TYPE_INT, 4, NULL);

  // Amplifier
  g_object_set(filter->elements.amplify, "amplification", 12.0, NULL);

  // Deinterleave
  g_object_set(filter->elements.deinterleave, "keep-positions", TRUE, NULL);
  g_object_set(filter->elements.interleave, "channel-positions-from-input",
FALSE, NULL);

  // Volumes
  g_object_set(filter->elements.volume, "volume", 1.0, NULL);

  // Panoramas
  g_object_set(filter->elements.audio_panorama_1, "panorama", 1.0, NULL);
  g_object_set(filter->elements.audio_panorama_2, "panorama", -1.0, NULL);

  gst_bin_add_many(GST_BIN_CAST(filter->bin),
                   gst_object_ref (filter->elements.amplify),
                   gst_object_ref (filter->elements.deinterleave),
                   gst_object_ref (filter->elements.queue_1),
                   gst_object_ref (filter->elements.queue_2),
                   gst_object_ref (filter->elements.volume),
                   gst_object_ref (filter->elements.audio_panorama_1),
                   gst_object_ref (filter->elements.audio_panorama_2),
                   gst_object_ref (filter->elements.phaseshift_1),
                   gst_object_ref (filter->elements.phaseshift_2),
                   gst_object_ref (filter->elements.audio_convert_1_1),
                   gst_object_ref (filter->elements.audio_convert_1_2),
                   gst_object_ref (filter->elements.audio_convert_2_1),
                   gst_object_ref (filter->elements.audio_convert_2_2),
                   gst_object_ref (filter->elements.interleave),
                   gst_object_ref (filter->elements.sink_1),
                   gst_object_ref (filter->elements.sink_2),
                   NULL);

  gst_element_link_filtered(filter->elements.amplify,
filter->elements.deinterleave, filter->elements.caps);
  gst_element_link_pads_full(filter->elements.amplify, "src",
filter->elements.deinterleave, "sink", GST_PAD_LINK_CHECK_NOTHING);

  printf("Deinterleave pad\n");
  gst_element_link_pads_full(filter->elements.deinterleave, "src_3",
filter->elements.queue_1, "sink",GST_PAD_LINK_CHECK_CAPS);
  gst_element_link_pads_full(filter->elements.deinterleave, "src_0",
filter->elements.queue_2, "sink",GST_PAD_LINK_CHECK_CAPS);

  // // Channel 1
  gst_element_link_pads_full(filter->elements.queue_1, "src",
filter->elements.audio_panorama_1, "sink", GST_PAD_LINK_CHECK_CAPS);
  gst_element_link_pads_full(filter->elements.audio_panorama_1, "src",
filter->elements.audio_convert_1_1, "sink", GST_PAD_LINK_CHECK_CAPS);
  gst_element_link_pads_full(filter->elements.audio_convert_1_1, "src",
filter->elements.phaseshift_1, "sink", GST_PAD_LINK_CHECK_CAPS);
  gst_element_link_pads_full(filter->elements.phaseshift_1, "src",
filter->elements.interleave, "sink_0", GST_PAD_LINK_CHECK_CAPS);


  // // Channel 2
  gst_element_link_pads_full(filter->elements.queue_2, "src",
filter->elements.audio_panorama_2, "sink", GST_PAD_LINK_CHECK_CAPS);
  gst_element_link_pads_full(filter->elements.audio_panorama_2, "src",
filter->elements.audio_convert_2_1, "sink", GST_PAD_LINK_CHECK_CAPS);
  gst_element_link_pads_full(filter->elements.audio_convert_2_1, "src",
filter->elements.phaseshift_2, "sink", GST_PAD_LINK_CHECK_CAPS);
  gst_element_link_pads_full(filter->elements.phaseshift_2, "src",
filter->elements.interleave, "sink_1", GST_PAD_LINK_CHECK_CAPS);

  GstPad *ghost_sinkpad = gst_ghost_pad_new("sink", sinkpad);
  GstPad *ghost_srcpad = gst_ghost_pad_new("src", srcpad);

  if(gst_element_add_pad(filter, filter->sinkpad)) {
    printf("Ghost pad added: Sink\n");
  } else {
    printf("Ghost pad could not be added: Sink\n");
  }
  if(gst_element_add_pad(filter, filter->srcpad)) {
    printf("Ghost pad added: Src\n");
  } else {
    printf("Ghost pad could not be added: Src\n");
  }

}

Maybe there is some good example on how to create a bin like this or I just
don't understand how to do it, but I find  writing a manager
<https://gstreamer.freedesktop.org/documentation/plugin-development/element-types/manager.html>  
a little sparse and can't find anybody here with the same chain function
problem.
Yesterday I found  this post
<http://gstreamer-devel.966125.n4.nabble.com/Creating-a-gstreamer-bin-element-td4676819.html#a4676822> 
, which from a higher perspective seems to try and achieve the same as me,
but also has problems doing so due to lack of clear examples/documentation
on the subject.

Any help is very much appreciated. Am I on the right track and is is
possible to do what I am trying to do, or should I go a whole other route?



--
Sent from: http://gstreamer-devel.966125.n4.nabble.com/


More information about the gstreamer-devel mailing list