某些 GStreamer 管道不被视为垃圾箱?
Certain GStreamer pipelines not considered to be a bin?
我可以从命令行 运行 一个非常简单的启动管道:
gst-launch-1.0 videotestsrc ! ximagesink
并且,从 gst-inspect-1.0
开始,ximagesink
似乎支持 GstVideoOverlay
接口,因此我可以将它绑定到特定的 Gtk 小部件。
但是,当我尝试从网上偶然发现的一些代码中执行此操作时,管道似乎不被视为垃圾箱(因此,未将小部件 ID 提供给它)。
代码如下,首先创建管道并设置它来捕获总线消息:
Gst.Element playbin = Gst.Parse.Launch("videotestsrc ! ximagesink");
Gst.Bus bus = playbin.Bus;
bus.AddSignalWatch();
bus.Message += MsgCallback;
然后实际处理总线消息:
private void MsgCallback(object o, MessageArgs args) {
// Only care about window ID binding requests.
Gst.Message msg = args.Message;
if (! Gst.Video.Global.IsVideoOverlayPrepareWindowHandleMessage(msg))
return;
// Get source of message.
Gst.Element src = msg.Src as Gst.Element;
if (src == null)
return;
// Find element supporting interface and notify it to bind.
Gst.Element ov = null;
if (src is Gst.Bin) {
ov = ((Gst.Bin) src).GetByInterface(VideoOverlayAdapter.GType);
VideoOverlayAdapter ad = new VideoOverlayAdapter(ov.Handle);
ad.WindowHandle = windowXId;
}
}
现在,出于某种原因,src is Gst.Bin
为假,这意味着 windowXId
(我之前设置的小部件 ID)永远不会与 GStreamer 通信。
但是,如果我提供一个 playbin
管道(playbin uri=XYZZY videosink='videoconvert ! videoflip method=none ! videoconvert ! autovideosink'
,如果你有兴趣),它工作正常。
据我从 Gst.Parse.Launch()
的文档中可以看出,它应该给我一个管道,它是 bin 的一个特例,按照 here(在修复了残暴的语法之后) :
Returns a new element on success, NULL
on failure. If more than one top level element is specified by the pipeline description , all elements are put into a GstPipeline
, which is then returned.
我很确定 videotestsrc
和 ximagesink
是两个独立的顶级元素,但是,当我添加以下代码时,在检查 src
为 null
:
Console.WriteLine("is bin " + (src is Gst.Bin));
Console.WriteLine("is element " + (src is Gst.Element));
Console.WriteLine("is pipeline " + (src is Gst.Pipeline));
Console.WriteLine(type is " + src.GetType());
我明白了:
is bin False
is element True
is pipeline False
type is Gst.Element
对于有问题的 videotestsrc
管道和以下对于好的 playbin
一个:
is bin True
is element True
is pipeline False
type is Gst.Bin
所以一切都指向有问题的那个给出了一个元素而不是一个 bin,尽管文档是这样说的。
我在这里错过了什么?导致不同行为的两条管道有什么区别?
好吧,原来Gst.Parse.Launch
函数是实际上返回的是一个管道。如果您在创建 bin 后立即复制这些检查语句,可以看到这一点:
Gst.Element playbin = Gst.Parse.Launch("videotestsrc ! ximagesink");
Console.WriteLine("is bin " + (playbin is Gst.Bin));
Console.WriteLine("is element " + (playbin is Gst.Element));
Console.WriteLine("is pipeline " + (playbin is Gst.Pipeline));
Console.WriteLine(type is " + playbin.GetType());
你会看到:
is bin True
is element True
is pipeline True
type is Gst.Pipeline
只是,当我们在回调中获取消息时,源似乎改为设置为元素。我实际上还没有弄清楚 为什么 消息源作为一个元素(甚至是哪个元素)通过,但我至少有一个解决方法,部分归功于我的高级智能但是主要是为了偷偷摸摸地看看 Banshee 的做法:-)
事实证明,回调可以直接访问 bin 而不是试图从源中获取它。这适用于我的情况,因为我每个实例只有一个视频流 (bin)。如果你有倍数,可能会有点困难。
要实现这一点,您首先要使 playbin
成为一个成员变量(如果它还没有的话),然后您可以这样修改回调:
private void MsgCallback(object o, MessageArgs args) {
// Only care about window ID binding requests.
Gst.Message msg = args.Message;
if (! Gst.Video.Global.IsVideoOverlayPrepareWindowHandleMessage(msg))
return;
// Get instance bin, interface element, then notify it to bind.
Gst.Bin src = (Gst.Bin)(this.playbin);
if (src == null) return;
Gst.Element ov = src.GetByInterface(VideoOverlayAdapter.GType);
if (ov == null) return;
VideoOverlayAdapter ad = new VideoOverlayAdapter(ov.Handle);
if (ad == null) return;
ad.WindowHandle = windowXId;
}
我可以从命令行 运行 一个非常简单的启动管道:
gst-launch-1.0 videotestsrc ! ximagesink
并且,从 gst-inspect-1.0
开始,ximagesink
似乎支持 GstVideoOverlay
接口,因此我可以将它绑定到特定的 Gtk 小部件。
但是,当我尝试从网上偶然发现的一些代码中执行此操作时,管道似乎不被视为垃圾箱(因此,未将小部件 ID 提供给它)。
代码如下,首先创建管道并设置它来捕获总线消息:
Gst.Element playbin = Gst.Parse.Launch("videotestsrc ! ximagesink");
Gst.Bus bus = playbin.Bus;
bus.AddSignalWatch();
bus.Message += MsgCallback;
然后实际处理总线消息:
private void MsgCallback(object o, MessageArgs args) {
// Only care about window ID binding requests.
Gst.Message msg = args.Message;
if (! Gst.Video.Global.IsVideoOverlayPrepareWindowHandleMessage(msg))
return;
// Get source of message.
Gst.Element src = msg.Src as Gst.Element;
if (src == null)
return;
// Find element supporting interface and notify it to bind.
Gst.Element ov = null;
if (src is Gst.Bin) {
ov = ((Gst.Bin) src).GetByInterface(VideoOverlayAdapter.GType);
VideoOverlayAdapter ad = new VideoOverlayAdapter(ov.Handle);
ad.WindowHandle = windowXId;
}
}
现在,出于某种原因,src is Gst.Bin
为假,这意味着 windowXId
(我之前设置的小部件 ID)永远不会与 GStreamer 通信。
但是,如果我提供一个 playbin
管道(playbin uri=XYZZY videosink='videoconvert ! videoflip method=none ! videoconvert ! autovideosink'
,如果你有兴趣),它工作正常。
据我从 Gst.Parse.Launch()
的文档中可以看出,它应该给我一个管道,它是 bin 的一个特例,按照 here(在修复了残暴的语法之后) :
Returns a new element on success,
NULL
on failure. If more than one top level element is specified by the pipeline description , all elements are put into aGstPipeline
, which is then returned.
我很确定 videotestsrc
和 ximagesink
是两个独立的顶级元素,但是,当我添加以下代码时,在检查 src
为 null
:
Console.WriteLine("is bin " + (src is Gst.Bin));
Console.WriteLine("is element " + (src is Gst.Element));
Console.WriteLine("is pipeline " + (src is Gst.Pipeline));
Console.WriteLine(type is " + src.GetType());
我明白了:
is bin False
is element True
is pipeline False
type is Gst.Element
对于有问题的 videotestsrc
管道和以下对于好的 playbin
一个:
is bin True
is element True
is pipeline False
type is Gst.Bin
所以一切都指向有问题的那个给出了一个元素而不是一个 bin,尽管文档是这样说的。
我在这里错过了什么?导致不同行为的两条管道有什么区别?
好吧,原来Gst.Parse.Launch
函数是实际上返回的是一个管道。如果您在创建 bin 后立即复制这些检查语句,可以看到这一点:
Gst.Element playbin = Gst.Parse.Launch("videotestsrc ! ximagesink");
Console.WriteLine("is bin " + (playbin is Gst.Bin));
Console.WriteLine("is element " + (playbin is Gst.Element));
Console.WriteLine("is pipeline " + (playbin is Gst.Pipeline));
Console.WriteLine(type is " + playbin.GetType());
你会看到:
is bin True
is element True
is pipeline True
type is Gst.Pipeline
只是,当我们在回调中获取消息时,源似乎改为设置为元素。我实际上还没有弄清楚 为什么 消息源作为一个元素(甚至是哪个元素)通过,但我至少有一个解决方法,部分归功于我的高级智能但是主要是为了偷偷摸摸地看看 Banshee 的做法:-)
事实证明,回调可以直接访问 bin 而不是试图从源中获取它。这适用于我的情况,因为我每个实例只有一个视频流 (bin)。如果你有倍数,可能会有点困难。
要实现这一点,您首先要使 playbin
成为一个成员变量(如果它还没有的话),然后您可以这样修改回调:
private void MsgCallback(object o, MessageArgs args) {
// Only care about window ID binding requests.
Gst.Message msg = args.Message;
if (! Gst.Video.Global.IsVideoOverlayPrepareWindowHandleMessage(msg))
return;
// Get instance bin, interface element, then notify it to bind.
Gst.Bin src = (Gst.Bin)(this.playbin);
if (src == null) return;
Gst.Element ov = src.GetByInterface(VideoOverlayAdapter.GType);
if (ov == null) return;
VideoOverlayAdapter ad = new VideoOverlayAdapter(ov.Handle);
if (ad == null) return;
ad.WindowHandle = windowXId;
}