首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用C++接口弹出

用C++接口弹出
EN

Stack Overflow用户
提问于 2018-04-23 17:30:35
回答 2查看 975关注 0票数 0

我正在尝试使用Gst::AudioSink作为基类为gstreamer创建一个自定义音频接收器插件。对我来说,这涉及到多个学习曲线,因为我对gstreamer、gstreamermm和gobject还不熟悉。此外,我对gtkmm没有背景或真正的兴趣,因为我目前不从事GUI代码的工作。

我正试图创建一个类似于以下内容的类:

代码语言:javascript
复制
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语言中,我们会做这样的事情:

代码语言:javascript
复制
  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之类的事情):

代码语言:javascript
复制
   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 +

EN

回答 2

Stack Overflow用户

发布于 2018-04-24 09:13:58

您可以在存储库中找到编写自己的插件的示例:https://git.gnome.org/browse/gstreamermm/tree/tests/plugins/derivedfrombasetransform.h

一般来说,头看起来很好,完整的实现应该看起来(或多或少)是这样的:

代码语言:javascript
复制
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

票数 0
EN

Stack Overflow用户

发布于 2018-04-24 16:00:33

事实证明,我的许多麻烦都是由于将其剪切并粘贴到MyAudioSink类中而引起的:

代码语言:javascript
复制
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++类是如何注册自己的呢?

  • Gst::ElementFactory::register_element() -用gstreamer注册类
  • Gst::register_mm_type -记录继承关系

有关实现,请参见本地/usr/include/gstreamermm-1.0/gstreamermm/register.h

Glib::ObjectBase(typeid (MyAudioSink))在我的例子中不是必需的,因为我没有使用多重继承。然而,它在其他应用程序中是非常关键的。参见例如实现自定义gtkmm树模型

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49986814

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档