2016-02-29 16 views
0

我可以運行這樣的命令行非常簡單的管道下水:某些GStreamer管道不被認爲是垃圾箱?

gst-launch-1.0 videotestsrc ! ximagesink 

,並從gst-inspect-1.0ximagesink似乎支持GstVideoOverlay接口,這樣我可以把它綁定到特定的Gtk部件。

但是,當從一些代碼中嘗試做到這一點時,我碰巧找到了網絡,看起來流水線不被認爲是一個bin(因此,widget 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(),它應該給我一個管道是一個箱的特殊情況下,如每here(後固定殘暴語法):

返回成功的新元素,NULL失敗。如果管道描述指定了多個頂層元素,則將所有元素放入GstPipeline,然後返回。

我敢肯定,videotestsrcximagesink是兩個獨立的頂級元素,但是,當我添加以下代碼,在檢查後爲srcnull

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的問題。

我在這裏錯過了什麼?這兩種管道之間會有什麼不同會導致不同的行爲?

回答

1

好的,事實證明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,而不是試圖從源代碼中取出。這在我的情況下工作,因爲我只有一個視頻流(箱)每個實例。如果你有倍數,可能會更困難一些。

要做到這一點,你首先要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; 
}