gstreamer — сопрягаемый объект с переполнением стека

Я пытаюсь создать собственный плагин аудио приемника для gstreamer, используя Gst :: AudioSink в качестве базового класса. Для меня это включает в себя несколько кривых обучения, так как я новичок в gstreamer, gstreamermm и gobject. Кроме того, я не имею никакого опыта или реального интереса к gtkmm, так как в настоящее время я не работаю над кодом GUI.

Я пытаюсь создать класс в соответствии с:

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();
};

Кажется, мне не хватает магии в class_init () функция, которая должна связывать функции базового класса с виртуальными функциями в MyAudioSink.
В C мы бы сделали что-то вроде:

  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);

На самом деле я не получаю привязку C ++ к gobject.
Что эквивалентно для связи с иерархией виртуальных функций C ++?

У меня сложилось впечатление от видео Марцина https://gstconf.ubicast.tv/videos/gstreamermm-c-way-of-doing-gstreamer-based-applications/ что виртуальные функции должны вызываться автоматически.

Я могу создать плагин, который можно использовать наполовину (не поддерживает такие вещи, как EOS), добавив:

   add_pad(sinkpad = Gst::Pad::create(get_pad_template("sink"), "sink"));
sinkpad->set_chain_function(sigc::mem_fun(*this, &MyAudioSink::chain));

Но я не думаю, что у раковины должна быть функция цепи.

Я также задавал этот вопрос в списке рассылки gtkmm. Если я получу ответ, я опубликую его здесь.

Для MyAudioSink я получаю иерархию классов:

GObject + —- GInitiallyUnowned
+ —- GstObject
+ —- GstElement
+ —- myaudiosink

Скорее, чем:

GObject + —- GInitiallyUnowned
+ —- GstObject
+ —- GstElement
+ —- GstBaseAudioSink
+ —- GstAudioSink
+ —- myaudiosink

Я подозреваю, что это суть моей проблемы.

Для примера аудиофильтра Марцин упоминает Вот Я получил классную иерархию:

GObject + —- GInitiallyUnowned
+ —- GstObject
+ —- GstElement
+ —- GstBaseTransform
+ —- GstAudioFilter
+ —- myaudiofilter

0

Решение

Вы можете найти примеры написания своего собственного плагина в репозитории: https://git.gnome.org/browse/gstreamermm/tree/tests/plugins/derivedfrombasetransform.h

В целом, ваш заголовок выглядит нормально, и полная реализация должна выглядеть (более или менее) так:

class MyAudioSink: public Gst::AudioSink
{
public:
explicit MyAudioSink(KantarAudioSink *gobj)
: Glib::ObjectBase(typeid (MyAudioSink)),
Gst::AudioSink(gobj) {}

static void class_init(Gst::ElementClass<MyAudioSink> *klass)
{
// Y
klass->set_metadata("longname", "classification", "description", "author");

klass->add_pad_template(Gst::PadTemplate::create("sink", Gst::PAD_SINK, Gst::PAD_ALWAYS, Gst::Caps::create_any()));
}

virtual int write_vfunc(gpointer data, guint length) override {}
virtual void reset_vfunc() {}
};

Совсем недавно у нас было сообщение об ошибке, когда кто-то опубликовал очень хороший, крошечный пример плагина для аудиофильтра, вы также можете использовать его в качестве примера для своего проекта: https://bug794249.bugzilla-attachments.gnome.org/attachment.cgi?id=369564

Если это не работает, не стесняйтесь сообщать об ошибке здесь: https://bugzilla.gnome.org/enter_bug.cgi?product=gstreamermm

0

Другие решения

Оказывается, что большая часть моих неприятностей была вызвана обрезкой и вставкой
это в класс MyAudioSink:

static GType get_base_type()
{
return Element::get_base_type();
}

Это сказалось на том, что мой класс основан на gstElement что было не так.
Я думал, что это было невинное заклинание, подобное заклинанию.
Это показывает опасности вырезать и вставить, но больше, чем опасности слепого кодирования.
Я также был виновен в упрощении примера кода, который я вставил сюда, так что никто из моих вопросов не показывает проблему.

Это решает мою проблему, но не отвечает на мой вопрос.
Я постараюсь обобщить это ниже.

«Что эквивалентно для связи с иерархией виртуальных функций C ++?»

Чтобы создать обертку для класса gobject, нужно использовать обычный процесс glibmmproc.
Оболочка определяется файлами с расширениями .hg и .ccg, из которых интерфейс C ++ и GObject обертка генерируются.

Например, чтобы обернуть объект класса Foo Вы можете создать Foo.hg и Foo.ccg.
glibmmproc будет генерировать Foo.h и Foo.cc.
Foo.cc включает в себя большую часть вашего определения класса Foo, но с
дополнительная обертка объекта Foo_class.

Foo_class класс gobject, который оборачивает виртуальные функции gobject (vfunc_callbacks) и передает их в Foo
разрешение производным классам Foo использовать наследование C ++ и виртуальные функции C ++.
Образец скрыт, и разработчику C ++ по большей части нужно беспокоиться только об интерфейсе C ++, предоставленном Foo.h

Один из способов понять внутреннее устройство — это собрать gstreamermm из исходного кода и изучить код, сгенерированный glibmmproc.
Для моего случая это будет: gstreamermm / audiosink.cc & gstreamermm / audiosink.h генерируется из
src / audiosink.ccg и src / audiosink.hg

Так как делает сам производный класс C ++ регистрируется?

  • Gst :: ElementFactory :: register_element () — регистрирует класс с помощью gstreamer
  • Gst :: register_mm_type — записывает наследственные отношения

См. Ваш местный /usr/include/gstreamermm-1.0/gstreamermm/register.h для реализации

Glib :: ObjectBase (typeid (MyAudioSink)) не требуется в моем случае, так как я не использую множественное наследование. Однако это важно в других приложениях, которые делают. Смотри например Реализация пользовательской модели дерева gtkmm

0

По вопросам рекламы [email protected]