我正在尝试使用Gst::AudioSink作为基类为gstreamer创建一个自定义音频接收器插件。对我来说,这涉及到多个学习曲线,因为我对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++虚拟函数层次结构的等效值是什么?
我从Marcin的视频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 +
而不是:
GObject +
我怀疑这就是我问题的实质。
对于音频过滤的例子,Marcin提到了这里,我得到了一个类级别:
GObject +
发布于 2018-04-24 09:13:58
您可以在存储库中找到编写自己的插件的示例: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。
如果这不起作用,可以在这里提交一个bug:bug.cgi?product=gstreamermm
发布于 2018-04-24 16:00:33
事实证明,我的许多麻烦都是由于将其剪切并粘贴到MyAudioSink类中而引起的:
static GType get_base_type()
{
return Element::get_base_type();
}这样做的效果是告诉gobject我的课是基于gstElement的,这是错误的。我以为是一些无辜的咒语。这显示了剪切和粘贴的危险,但更多的是盲目编码的危险。我还因为过度简化了我粘贴在这里的示例代码而感到内疚,因为我的问题没有人会显示问题。
这解决了我的问题,但没有回答我的问题。我将试着在下面总结一下。
“链接到C++虚拟函数层次结构的等效值是什么?”?
要为gobject类创建一个包装器,通常的过程是使用格列布姆。包装器由扩展名.hg和.ccg的文件定义,从中生成C++接口和gobject包装器。
例如,要包装一个gobject类foo,可以创建Foo.hg和Foo.ccg。然后glibmmproc将生成Foo.h和Foo.cc。Foo.cc包含了Foo类的大部分定义,但附带了一个附加的gobject包装器Foo_class。
Foo_class是一个gobject类,它封装了gobject虚拟函数(vfunc_callbacks)并将它们转发给Foo,允许Foo的派生类使用C++继承和C++虚拟函数。样板是隐藏的,C++开发人员大部分只需要担心Foo.h提供的C++接口。
理解内部机制的一种方法是从源代码构建gstreamermm,并研究glibmmproc生成的代码。就我的情况而言,这将是:从src/audosink.ccg和src/audosink.hg生成的gstreamermm/audosink.cc&gstreamermm/audosink.h。
那么派生的C++类是如何注册自己的呢?
有关实现,请参见本地/usr/include/gstreamermm-1.0/gstreamermm/register.h
Glib::ObjectBase(typeid (MyAudioSink))在我的例子中不是必需的,因为我没有使用多重继承。然而,它在其他应用程序中是非常关键的。参见例如实现自定义gtkmm树模型
https://stackoverflow.com/questions/49986814
复制相似问题