1

我有一个用于渲染视频流的 C#/Mono 应用程序,直到最近,我一直在使用自己内部开发的 InterOp 绑定。

我现在正从那种方法转向使用 GStreamer# 的​​方法,因为这可能会减少维护工作量,至少对我来说是这样 :-)

由于我需要将独立的视频流绑定到特定的DrawableArea小部件,因此我的方法捕获了 GStreamer 消息,然后使用函数gst_is_video_overlay_prepare_window_handle_message(msg)(a)检查它们。

如果返回 true,然后我会调用 来响应,之前使用 获取的小部件的句柄在gst_video_overlay_set_window_handle(xid)哪里。xidgdk_x11_window_get_xid()

我的问题是:通过 GStreamer# 代码搜索,我找不到执行绑定的等效函数,所以我想知道这是如何完成的。

有人有什么建议或信息可以提供吗?

这两个函数的源代码在里面,gst-plugins-base-1.4.4/gst-libs/gst/video/videooverlay.c所以,在紧要关头,我可以虚拟化我自己的函数来完成这项工作(或者只是坚持我们的绑定,但在我看来,这将被包含在GStreamer# 因为渲染到特定的小部件似乎是一个非常方便的工具。


(a)那些 GStreamer 摇摆不定。他们必须用所有不必要的打字来替换他们的键盘:-)

4

1 回答 1

2

结果证明这些函数可用的,但是在基线 GStreamer 东西的单独库和子命名空间中。

Xid 的获取仍然是通过自制的 InterOp 绑定完成的,也就是说:

[DllImport("libgdk-3", EntryPoint = "gdk_x11_window_get_xid")]
private extern static IntPtr GdkX11WindowGetXid(IntPtr window);

您还拥有 playbin、总线和 X11 窗口 ID 的实例级变量:

private IntPtr windowXid;
private Gst.Element playBin;
private Gst.Bus bus;

然后,在实例化类时,您捕获Realized信号并确保 GStreamer 总线上的所有消息都转到您的回调函数:

this.Realized += OnRealized;
playBin = Gst.ElementFactory.Make('playbin', 'playbin');
bus = playBin.Bus;
bus.AddSignalWatch();
bus.Message += MessageCallback;

在该实现函数中,您保存 Xid 供以后使用(在实例变量中):

void OnRealized(object o, EventArgs args) {
    windowXid = GdkX11WindowGetXid(this.Window.Handle);
}

并且,当 GStreamer 询问时,提供此句柄以响应请求:

private void MessageCallback(object o, MessageArgs args) {
    Gst.Message msg = args.Message;
    if (! Gst.Video.Global.IsVideoOverlayPrepareWindowHandleMessage(msg))
        return;

    Gst.Element src = msg.Src as Gst.Element;
    if (src == null)
        return;

    Gst.Element overlay = null;
    if (src is Gst.Bin)
        overlay = ((Gst.Bin)src).GetByInterface

    Gst.Video.VideoOverlayAdapter = new Gst.Video.VideoOverlayAdapter(overlay.Handle);
    adapter.WindowHandle = windowXid;
}

请注意,我已经完全限定了所有 GStreamer 对象,因此绝对清楚它们可以在哪里找到。如果没有它们(以及使用变量),代码可能会更简洁,var但我想确保所有信息都可用。

于 2016-02-23T01:09:11.517 回答