X-Git-Url: https://git.slaskete.net/python-gstreamer-examples/blobdiff_plain/28384339c30c154d2e55e266d45f2dd52ad4861a..HEAD:/example5.py?ds=sidebyside diff --git a/example5.py b/example5.py index 44ace18..b252a17 100755 --- a/example5.py +++ b/example5.py @@ -2,12 +2,14 @@ # 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): @@ -35,6 +37,7 @@ class Main: # 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() @@ -43,69 +46,87 @@ class Main: # 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() @@ -121,7 +142,9 @@ class Main: 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 @@ -131,18 +154,29 @@ class Main: 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")