Я пытаюсь создать собственный плагин аудио приемника для 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
Вы можете найти примеры написания своего собственного плагина в репозитории: 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
Оказывается, что большая часть моих неприятностей была вызвана обрезкой и вставкой
это в класс 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 ++ регистрируется?
См. Ваш местный /usr/include/gstreamermm-1.0/gstreamermm/register.h для реализации
Glib :: ObjectBase (typeid (MyAudioSink)) не требуется в моем случае, так как я не использую множественное наследование. Однако это важно в других приложениях, которые делают. Смотри например Реализация пользовательской модели дерева gtkmm