gstreamermm, Gst::AudioSink and virtual functions

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

gstreamermm, Gst::AudioSink and virtual functions

Adams, Bruce (KMLWG)

Hi,

     I’m trying to create a custom audio sink plugin for gstreamer using the Gst::AudioSink as a base class. For me this involves multiple learning curves as I’m new to gstreamer, gstreamermm and gobject. Also I have no background or real interest in gtkmm as I’m not working on GUI code at present.

 

I am trying to create a class along the lines of:

 

class MyAudioSink: public Gst::AudioSink

{

public:

    explicit MyAudioSink(KantarAudioSink *gobj);

    virtual ~MyAudioSink();

 

    static void class_init(Gst::ElementClass<MyAudioSink> *klass);

 

    virtual int write_vfunc(gpointer data, guint length) override;

    virtual void reset_vfunc();

};

 

I seem to missing some magic in the class_init() function that should link the base class functions to the virtual functions in MyAudioSink.

In C we would do something like:

 

  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);

  GstAudioSinkClass *audio_sink_class = GST_AUDIO_SINK_CLASS (klass);

  audio_sink_class->write = GST_DEBUG_FUNCPTR (myaudiosink_write);

 

I don’t really grok the C++ binding to gobject.

What is the equivalent for linking to the C++ virtual function hierarchy?

 

I got the impression from Marcin’s video https://gstconf.ubicast.tv/videos/gstreamermm-c-way-of-doing-gstreamer-based-applications/ that the virtual functions should be invoked automatically.

 

I can create a half usable (doesn’t handle things like EOS) plugin by adding:

 

   add_pad(sinkpad = Gst::Pad::create(get_pad_template("sink"), "sink"));

   sinkpad->set_chain_function(sigc::mem_fun(*this, &MyAudioSink::chain));

 

But a sink should not have a chain function.

Also it seems strange that I have to add the sink pad at all. An audio sink should already have one I should just need to refine the capabilities a bit more.

I guess this is an artifact of using gmmproc to create C++ wrappers? I don’t want to use gmmproc myself (I not sure what package its in anyway).

 

I think there should some example elements and more introductory documentation (this is something I may be able to help with as I do this other commitments permitting). The best example transform element I could find was the foo element used in the test code. There is no equivalent for a sink element.

 

It’s also worth mentioning that the generated documentation does not appear online here https://developer.gnome.org/gstreamermm/1.10/

 

Regards,

 

Bruce.



Kantar Disclaimer
_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
Reply | Threaded
Open this post in threaded view
|

Re: gstreamermm, Gst::AudioSink and virtual functions

Marcin Kolny
Hi Bruce,
I think I've already answered your question on stackoverflow: https://stackoverflow.com/questions/49986814/interfacing-gobject-with-c/49997751#49997751

2018-04-23 15:47 GMT+01:00 Adams, Bruce (KMLWG) <[hidden email]>:

Hi,

     I’m trying to create a custom audio sink plugin for gstreamer using the Gst::AudioSink as a base class. For me this involves multiple learning curves as I’m new to gstreamer, gstreamermm and gobject. Also I have no background or real interest in gtkmm as I’m not working on GUI code at present.

 

I am trying to create a class along the lines of:

 

class MyAudioSink: public Gst::AudioSink

{

public:

    explicit MyAudioSink(KantarAudioSink *gobj);

    virtual ~MyAudioSink();

 

    static void class_init(Gst::ElementClass<MyAudioSink> *klass);

 

    virtual int write_vfunc(gpointer data, guint length) override;

    virtual void reset_vfunc();

};

 

I seem to missing some magic in the class_init() function that should link the base class functions to the virtual functions in MyAudioSink.

In C we would do something like:

 

  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);

  GstAudioSinkClass *audio_sink_class = GST_AUDIO_SINK_CLASS (klass);

  audio_sink_class->write = GST_DEBUG_FUNCPTR (myaudiosink_write);

 

I don’t really grok the C++ binding to gobject.

What is the equivalent for linking to the C++ virtual function hierarchy?

 

I got the impression from Marcin’s video https://gstconf.ubicast.tv/videos/gstreamermm-c-way-of-doing-gstreamer-based-applications/ that the virtual functions should be invoked automatically.

 

I can create a half usable (doesn’t handle things like EOS) plugin by adding:

 

   add_pad(sinkpad = Gst::Pad::create(get_pad_template("sink"), "sink"));

   sinkpad->set_chain_function(sigc::mem_fun(*this, &MyAudioSink::chain));

 

But a sink should not have a chain function.

Also it seems strange that I have to add the sink pad at all. An audio sink should already have one I should just need to refine the capabilities a bit more.

I guess this is an artifact of using gmmproc to create C++ wrappers? I don’t want to use gmmproc myself (I not sure what package its in anyway).

 

I think there should some example elements and more introductory documentation (this is something I may be able to help with as I do this other commitments permitting). The best example transform element I could find was the foo element used in the test code. There is no equivalent for a sink element.

 

It’s also worth mentioning that the generated documentation does not appear online here https://developer.gnome.org/gstreamermm/1.10/

 

Regards,

 

Bruce.



Kantar Disclaimer

_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list




--
Pozdrawiam
Marcin Kolny

_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
Reply | Threaded
Open this post in threaded view
|

RE: gstreamermm, Gst::AudioSink and virtual functions

Adams, Bruce (KMLWG)

Hi,

      Thanks for your help so far. I’ve made some progress but I’m still stuck.

I am still trying to create a ‘do nothing’ audiosink upon which I can build.

Is there a clear statement somewhere of what an C++ audiosink class must provide?

I was able to create a a ‘do nothing’ sink using “gst-element-maker mydemosink audiosink”

which seems to work but there is nothing obvious to translate from that code into the C++ version.

 

The latest output is:

 

(gst-launch-1.0:16830): GStreamer-CRITICAL **: gst_object_set_parent: assertion 'GST_IS_OBJECT (object)' failed

 

** (gst-launch-1.0:16830): CRITICAL **: gst_audio_ring_buffer_open_device: assertion 'GST_IS_AUDIO_RING_BUFFER (buf)' failed

 

(gst-launch-1.0:16830): GStreamer-CRITICAL **: gst_object_unparent: assertion 'GST_IS_OBJECT (object)' failed

ERROR: Pipeline doesn't want to pause.

 

I thought the ring buffer was provided by the parent class AudioBaseSink  but it seems not.

 

Note for testing this I’m using:

 

   gst-launch-1.0 -v audiotestsrc blocksize=8000 num-buffers=10 ! audio/x-raw,rate=8000,channels=1 ! myaudiosink

 

The simplest MyAudioSink.hpp to reproduce this:

 

#include <gstreamermm.h>

#include <gstreamermm/audiosink.h>

 

class MyAudioSink: public Gst::AudioSink                     

{

public:

   explicit MyAudioSink(Gst::AudioSink::BaseObjectType* gobj):

      Glib::ObjectBase(typeid (MyAudioSink)), // type must be registered before use

      Gst::AudioSink(gobj)

   {

   }

 

   virtual ~MyAudioSink()

   {

   }

 

   static void class_init(Gst::ElementClass<MyAudioSink> *klass)

   {

      klass->set_metadata("MyAudioSink",

                          "Sink/Audio", "A test audio sink", "author");

      klass->add_pad_template(Gst::PadTemplate::create("sink", Gst::PAD_SINK, Gst::PAD_ALWAYS,

                                                       Gst::Caps::create_from_string("audio/x-raw,format=S16LE,rate=8000,channels=1")));

   }

};

 

 

A C++ myaudiofilter derived from AudioFilter on the other hand seems to just work:

 

gst-launch-1.0 audiotestsrc blocksize=8000 num-buffers=10 ! audio/x-raw,rate=8000,channels=1 ! myaudiofilter ! fakesink

 

Calling create_ring_buffer() in the constructor MyAudioSink causes a seg fault:

 

(gst-inspect-1.0:23564): GStreamer-CRITICAL **: gst_object_set_parent: assertion 'GST_IS_OBJECT (object)' failed

 

(gst-inspect-1.0:23564): GLib-GObject-CRITICAL **: g_object_get_qdata: assertion 'G_IS_OBJECT (object)' failed

 

(gst-inspect-1.0:23564): GLib-GObject-CRITICAL **: g_object_get_qdata: assertion 'G_IS_OBJECT (object)' failed

Segmentation fault (core dumped)

 

#3  fault_handler_sighandler (signum=11) at gst-launch.c:94

#4  <signal handler called>

#5  0x00007eff8272b898 in Glib::wrap_auto(_GObject*, bool) () from /usr/lib/x86_64-linux-gnu/libglibmm-2.4.so.1

#6  0x00007eff82df5bcf in Glib::wrap(_GstAudioRingBuffer*, bool) () from /usr/lib/x86_64-linux-gnu/libgstreamermm-1.0.so.1

#7  0x00007eff82df16c6 in Gst::AudioBaseSink::create_ring_buffer() () from /usr/lib/x86_64-linux-gnu/libgstreamermm-1.0.so.1

#8  0x00007eff830f5eb4 in MyAudioSink::MyAudioSink

 

I tried putting it in some of the vfunc’s like open, reset , write and start instead but none of them are invoked before it starts asserting.

 

Its not immediately obvious where to set a breakpoint to try and track this down

I’m wading through glib and gstreamer source trying to find out without much success so far.

Any tips would be appreciated.

 

Regards,

 

Bruce.


_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
Reply | Threaded
Open this post in threaded view
|

Re: gstreamermm, Gst::AudioSink and virtual functions

Marcin Kolny
Hi Bruce,
Could you post a whole project? It'd help me a lot with investigations.

2018-04-25 13:10 GMT+01:00 Adams, Bruce (KMLWG) <[hidden email]>:

Hi,

      Thanks for your help so far. I’ve made some progress but I’m still stuck.

I am still trying to create a ‘do nothing’ audiosink upon which I can build.

Is there a clear statement somewhere of what an C++ audiosink class must provide?

I was able to create a a ‘do nothing’ sink using “gst-element-maker mydemosink audiosink”

which seems to work but there is nothing obvious to translate from that code into the C++ version.

 

The latest output is:

 

(gst-launch-1.0:16830): GStreamer-CRITICAL **: gst_object_set_parent: assertion 'GST_IS_OBJECT (object)' failed

 

** (gst-launch-1.0:16830): CRITICAL **: gst_audio_ring_buffer_open_device: assertion 'GST_IS_AUDIO_RING_BUFFER (buf)' failed

 

(gst-launch-1.0:16830): GStreamer-CRITICAL **: gst_object_unparent: assertion 'GST_IS_OBJECT (object)' failed

ERROR: Pipeline doesn't want to pause.

 

I thought the ring buffer was provided by the parent class AudioBaseSink  but it seems not.

 

Note for testing this I’m using:

 

   gst-launch-1.0 -v audiotestsrc blocksize=8000 num-buffers=10 ! audio/x-raw,rate=8000,channels=1 ! myaudiosink

 

The simplest MyAudioSink.hpp to reproduce this:

 

#include <gstreamermm.h>

#include <gstreamermm/audiosink.h>

 

class MyAudioSink: public Gst::AudioSink                     

{

public:

   explicit MyAudioSink(Gst::AudioSink::BaseObjectType* gobj):

      Glib::ObjectBase(typeid (MyAudioSink)), // type must be registered before use

      Gst::AudioSink(gobj)

   {

   }

 

   virtual ~MyAudioSink()

   {

   }

 

   static void class_init(Gst::ElementClass<MyAudioSink> *klass)

   {

      klass->set_metadata("MyAudioSink",

                          "Sink/Audio", "A test audio sink", "author");

      klass->add_pad_template(Gst::PadTemplate::create("sink", Gst::PAD_SINK, Gst::PAD_ALWAYS,

                                                       Gst::Caps::create_from_string("audio/x-raw,format=S16LE,rate=8000,channels=1")));

   }

};

 

 

A C++ myaudiofilter derived from AudioFilter on the other hand seems to just work:

 

gst-launch-1.0 audiotestsrc blocksize=8000 num-buffers=10 ! audio/x-raw,rate=8000,channels=1 ! myaudiofilter ! fakesink

 

Calling create_ring_buffer() in the constructor MyAudioSink causes a seg fault:

 

(gst-inspect-1.0:23564): GStreamer-CRITICAL **: gst_object_set_parent: assertion 'GST_IS_OBJECT (object)' failed

 

(gst-inspect-1.0:23564): GLib-GObject-CRITICAL **: g_object_get_qdata: assertion 'G_IS_OBJECT (object)' failed

 

(gst-inspect-1.0:23564): GLib-GObject-CRITICAL **: g_object_get_qdata: assertion 'G_IS_OBJECT (object)' failed

Segmentation fault (core dumped)

 

#3  fault_handler_sighandler (signum=11) at gst-launch.c:94

#4  <signal handler called>

#5  0x00007eff8272b898 in Glib::wrap_auto(_GObject*, bool) () from /usr/lib/x86_64-linux-gnu/libglibmm-2.4.so.1

#6  0x00007eff82df5bcf in Glib::wrap(_GstAudioRingBuffer*, bool) () from /usr/lib/x86_64-linux-gnu/libgstreamermm-1.0.so.1

#7  0x00007eff82df16c6 in Gst::AudioBaseSink::create_ring_buffer() () from /usr/lib/x86_64-linux-gnu/libgstreamermm-1.0.so.1

#8  0x00007eff830f5eb4 in MyAudioSink::MyAudioSink

 

I tried putting it in some of the vfunc’s like open, reset , write and start instead but none of them are invoked before it starts asserting.

 

Its not immediately obvious where to set a breakpoint to try and track this down

I’m wading through glib and gstreamer source trying to find out without much success so far.

Any tips would be appreciated.

 

Regards,

 

Bruce.




--
Pozdrawiam
Marcin Kolny

_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
Reply | Threaded
Open this post in threaded view
|

Re: gstreamermm, Gst::AudioSink and virtual functions

Marcin Kolny
Hi Bruce,
Sorry for late response. I've looked at your example, and turns out that it was a bug in gstreamermm. I've fixed it, and the latest master branch should be ok: https://git.gnome.org/browse/gstreamermm/commit/?id=20090e4db48fa30e193be2637e881add4cb6d3d4

2018-04-30 11:36 GMT+01:00 Adams, Bruce (KMLWG) <[hidden email]>:

Hi,

      The attached is a minimal project that reproduces the issue.

It just adds a main and a CMakeLists.txt the sample code I sent earlier.

 

One other thing that seems dubious to me is that:

 

#include <gstreamermm/private/audiosink_p.h>

 

Is required in order for the register_element() function to compile.

 

Regards,

 

Bruce.

 

 

From: Marcin Kolny [mailto:[hidden email]]
Sent: 29 April 2018 16:49
To: Adams, Bruce (KMLWG)
Cc: [hidden email]
Subject: Re: gstreamermm, Gst::AudioSink and virtual functions

 

Hi Bruce,

Could you post a whole project? It'd help me a lot with investigations.

 

2018-04-25 13:10 GMT+01:00 Adams, Bruce (KMLWG) <[hidden email]>:

Hi,

      Thanks for your help so far. I’ve made some progress but I’m still stuck.

I am still trying to create a ‘do nothing’ audiosink upon which I can build.

Is there a clear statement somewhere of what an C++ audiosink class must provide?

I was able to create a a ‘do nothing’ sink using “gst-element-maker mydemosink audiosink”

which seems to work but there is nothing obvious to translate from that code into the C++ version.

 

The latest output is:

 

(gst-launch-1.0:16830): GStreamer-CRITICAL **: gst_object_set_parent: assertion 'GST_IS_OBJECT (object)' failed

 

** (gst-launch-1.0:16830): CRITICAL **: gst_audio_ring_buffer_open_device: assertion 'GST_IS_AUDIO_RING_BUFFER (buf)' failed

 

(gst-launch-1.0:16830): GStreamer-CRITICAL **: gst_object_unparent: assertion 'GST_IS_OBJECT (object)' failed

ERROR: Pipeline doesn't want to pause.

 

I thought the ring buffer was provided by the parent class AudioBaseSink  but it seems not.

 

Note for testing this I’m using:

 

   gst-launch-1.0 -v audiotestsrc blocksize=8000 num-buffers=10 ! audio/x-raw,rate=8000,channels=1 ! myaudiosink

 

The simplest MyAudioSink.hpp to reproduce this:

 

#include <gstreamermm.h>

#include <gstreamermm/audiosink.h>

 

class MyAudioSink: public Gst::AudioSink                     

{

public:

   explicit MyAudioSink(Gst::AudioSink::BaseObjectType* gobj):

      Glib::ObjectBase(typeid (MyAudioSink)), // type must be registered before use

      Gst::AudioSink(gobj)

   {

   }

 

   virtual ~MyAudioSink()

   {

   }

 

   static void class_init(Gst::ElementClass<MyAudioSink> *klass)

   {

      klass->set_metadata("MyAudioSink",

                          "Sink/Audio", "A test audio sink", "author");

      klass->add_pad_template(Gst::PadTemplate::create("sink", Gst::PAD_SINK, Gst::PAD_ALWAYS,

                                                       Gst::Caps::create_from_string("audio/x-raw,format=S16LE,rate=8000,channels=1")));

   }

};

 

 

A C++ myaudiofilter derived from AudioFilter on the other hand seems to just work:

 

gst-launch-1.0 audiotestsrc blocksize=8000 num-buffers=10 ! audio/x-raw,rate=8000,channels=1 ! myaudiofilter ! fakesink

 

Calling create_ring_buffer() in the constructor MyAudioSink causes a seg fault:

 

(gst-inspect-1.0:23564): GStreamer-CRITICAL **: gst_object_set_parent: assertion 'GST_IS_OBJECT (object)' failed

 

(gst-inspect-1.0:23564): GLib-GObject-CRITICAL **: g_object_get_qdata: assertion 'G_IS_OBJECT (object)' failed

 

(gst-inspect-1.0:23564): GLib-GObject-CRITICAL **: g_object_get_qdata: assertion 'G_IS_OBJECT (object)' failed

Segmentation fault (core dumped)

 

#3  fault_handler_sighandler (signum=11) at gst-launch.c:94

#4  <signal handler called>

#5  0x00007eff8272b898 in Glib::wrap_auto(_GObject*, bool) () from /usr/lib/x86_64-linux-gnu/libglibmm-2.4.so.1

#6  0x00007eff82df5bcf in Glib::wrap(_GstAudioRingBuffer*, bool) () from /usr/lib/x86_64-linux-gnu/libgstreamermm-1.0.so.1

#7  0x00007eff82df16c6 in Gst::AudioBaseSink::create_ring_buffer() () from /usr/lib/x86_64-linux-gnu/libgstreamermm-1.0.so.1

#8  0x00007eff830f5eb4 in MyAudioSink::MyAudioSink

 

I tried putting it in some of the vfunc’s like open, reset , write and start instead but none of them are invoked before it starts asserting.

 

Its not immediately obvious where to set a breakpoint to try and track this down

I’m wading through glib and gstreamer source trying to find out without much success so far.

Any tips would be appreciated.

 

Regards,

 

Bruce.




--

Pozdrawiam
Marcin Kolny




--
Pozdrawiam
Marcin Kolny

_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list