# Attempting to dynamically switch between input sources
# GdkX11 to get access to xid, GstVideo to get access to set_window_handle
-import gi, signal
+import gi, signal, time
gi.require_version('Gtk', '3.0')
gi.require_version('Gst', '1.0')
gi.require_version('GstVideo', '1.0')
from gi.repository import Gtk, Gst, GdkX11, GstVideo
+stream1="rtmp://matuku.hig.no/live/planet.stream"
+
class Main:
def __init__(self):
# Some capabilities we want to share between different elements
jpegcaps = Gst.Caps.from_string("image/jpeg,width=1280,height=720,framerate=30/1")
+ xrawcaps = Gst.Caps.from_string("video/x-raw,width=1280,height=720,framerate=30/1")
# Set up the pipeline
self.pipeline = Gst.Pipeline()
# src1
self.src1 = Gst.ElementFactory.make("v4l2src", "src1")
- self.src1.set_property("device", "/dev/video1")
-
- # src1 capsfilter
+ self.src1.set_property("device", "/dev/video0")
self.src1caps = Gst.ElementFactory.make("capsfilter", "src1caps")
self.src1caps.set_property("caps", jpegcaps)
-
- # src1jpegdec
- self.src1jpegdec = Gst.ElementFactory.make("jpegdec", "src1jpegdec")
-
- # src1videoconvert
- self.src1videoconvert = Gst.ElementFactory.make("videoconvert", "src1videoconvert")
+ self.src1dec = Gst.ElementFactory.make("decodebin", "src1dec")
# src2
- self.src2 = Gst.ElementFactory.make("v4l2src", "src2")
- self.src2.set_property("device", "/dev/video0")
-
- # src2 capsfilter
+ self.src2 = Gst.ElementFactory.make("videotestsrc", "src2")
+ self.src2.set_property("pattern", "ball")
self.src2caps = Gst.ElementFactory.make("capsfilter", "src2caps")
- self.src2caps.set_property("caps", jpegcaps)
-
- # src2jpegdec
- self.src2jpegdec = Gst.ElementFactory.make("jpegdec", "src2jpegdec")
-
- # src2videoconvert
- self.src2videoconvert = Gst.ElementFactory.make("videoconvert", "src2videoconvert")
+ self.src2caps.set_property("caps", xrawcaps)
+ self.src2dec = Gst.ElementFactory.make("decodebin", "src2dec")
+
+ # src3
+ self.src3 = Gst.ElementFactory.make("rtmpsrc", "src3")
+ self.src3.set_property("location", stream1)
+ self.src3caps = Gst.ElementFactory.make("capsfilter", "src3caps")
+ self.src3caps.set_property("caps", xrawcaps)
+ self.src3dec = Gst.ElementFactory.make("decodebin", "src3dec")
+ self.src3crop = Gst.ElementFactory.make("aspectratiocrop", "src3crop")
+ self.src3crop.set_property("aspect-ratio", Gst.Fraction(16, 9))
+ self.src3crop.set_property("message-forward", True)
+ self.src3croppad = self.src3crop.get_static_pad("sink")
+ self.src3scale = Gst.ElementFactory.make("videoscale")
+ self.src3scalecaps = Gst.ElementFactory.make("capsfilter", "src3scalecaps")
+ self.src3scalecaps.set_property("caps", Gst.Caps.from_string("width=1280,height=720"))
# Video mix
self.videomix = Gst.ElementFactory.make("videomixer", "videomix")
self.src1pad = self.videomix.get_request_pad("sink_1")
- self.src1pad.set_property("zorder", 2)
+ self.src1pad.set_property("zorder", 3)
self.src2pad = self.videomix.get_request_pad("sink_2")
- self.src2pad.set_property("zorder", 1)
+ self.src2pad.set_property("zorder", 2)
+ self.src3pad = self.videomix.get_request_pad("sink_3")
+ self.src3pad.set_property("zorder", 1)
# Add main videosink
- self.videosink = Gst.ElementFactory.make("autovideosink", "videosink")
+ self.videosink = Gst.ElementFactory.make("xvimagesink", "videosink")
self.videosink.set_property("sync", False)
# Add initial elements to the pipeline
self.pipeline.add(self.src1)
self.pipeline.add(self.src1caps)
- self.pipeline.add(self.src1jpegdec)
- self.pipeline.add(self.src1videoconvert)
+ self.pipeline.add(self.src1dec)
+ self.src1dec.connect("pad-added", self.OnPadAdded, self.src1pad, self.videomix)
self.pipeline.add(self.src2)
self.pipeline.add(self.src2caps)
- self.pipeline.add(self.src2jpegdec)
- self.pipeline.add(self.src2videoconvert)
+ self.pipeline.add(self.src2dec)
+ self.src2dec.connect("pad-added", self.OnPadAdded, self.src2pad, self.videomix)
+
+ self.pipeline.add(self.src3)
+ self.pipeline.add(self.src3dec)
+ self.src3dec.connect("pad-added", self.OnPadAdded, self.src3croppad, self.src3crop)
+ self.pipeline.add(self.src3crop)
+ self.pipeline.add(self.src3scale)
+ self.pipeline.add(self.src3scalecaps)
self.pipeline.add(self.videomix)
self.pipeline.add(self.videosink)
# Link the initial pipeline
- self.src1.link(self.src1caps)
- self.src1caps.link(self.src1jpegdec)
- self.src1jpegdec.link(self.src1videoconvert)
- self.src1videoconvert.link(self.videomix)
-
- self.src2.link(self.src2caps)
- self.src2caps.link(self.src2jpegdec)
- self.src2jpegdec.link(self.src2videoconvert)
- self.src2videoconvert.link(self.videomix)
-
- self.videomix.link(self.videosink)
+ if not self.src1.link(self.src1caps):
+ print("Failed to link src1 to src1caps")
+ if not self.src1caps.link(self.src1dec):
+ print("Failed to link src1caps to src1dec")
+ if not self.videomix.link(self.videosink):
+ print("Failed to link videomix to videosink")
+
+ if not self.src2.link(self.src2caps):
+ print("Failed to link src2 to src2caps")
+ if not self.src2caps.link(self.src2dec):
+ print("Failed to link src2caps to src2dec")
+
+ if not self.src3.link(self.src3dec):
+ print("Failed to link src3 to src3dec")
+ if not self.src3crop.link(self.src3scale):
+ print("Failed to link src3crop to src3scale")
+ if not self.src3scale.link(self.src3scalecaps):
+ print("Failed to link src3scale to src3scalecaps")
+ if not self.src3scalecaps.link_pads("src", self.videomix, "sink_3"):
+ print("Failed to link src3scalecaps to videomix")
# Set up a bus to our pipeline to get notified when the video is ready
self.bus = self.pipeline.get_bus()
self.win_id = self.mainwindow.get_object("viewport_main").get_window().get_xid()
# Play!
- self.pipeline.set_state(Gst.State.PLAYING)
+ print(self.pipeline.set_state(Gst.State.READY))
+ print(self.pipeline.set_state(Gst.State.PLAYING))
+ self.pipeline.get_state
# When we get a message that video is ready to display, set the
print("prepare-window-handle")
message.src.set_window_handle(self.win_id)
+ def OnPadAdded(self, element, pad, sink, target):
+ print("Dynamic pad for " + element.name + " added, linking to " + target.name)
+ print(sink.name)
+ pad.link(sink)
+ element.link(target)
+
def SetInput1(self, widget):
print("Switch to input 1")
- self.src1pad.set_property("zorder", 2)
- self.src2pad.set_property("zorder", 1)
+ self.src1pad.set_property("zorder", 3)
+ self.src2pad.set_property("zorder", 2)
+ self.src3pad.set_property("zorder", 1)
def SetInput2(self, widget):
print("Switch to input 2")
- self.src1pad.set_property("zorder", 1)
- self.src2pad.set_property("zorder", 2)
+ self.src1pad.set_property("zorder", 2)
+ self.src2pad.set_property("zorder", 3)
+ self.src3pad.set_property("zorder", 1)
def SetInput3(self, widget):
print("Switch to input 3")
+ self.src1pad.set_property("zorder", 1)
+ self.src2pad.set_property("zorder", 2)
+ self.src3pad.set_property("zorder", 3)
def SetInput4(self, widget):
print("Switch to input 4")