From: Einar Jørgen Haraldseid Date: Sat, 3 Jun 2017 16:58:15 +0000 (+0200) Subject: Example switching between two video sources (but very slow) X-Git-Url: https://git.slaskete.net/python-gstreamer-examples/commitdiff_plain/02565d3145b9c03a575b9c3959ebd4ab61287ba4 Example switching between two video sources (but very slow) --- diff --git a/example4.glade b/example4.glade new file mode 100644 index 0000000..6d7a61a --- /dev/null +++ b/example4.glade @@ -0,0 +1,128 @@ + + + + + + True + False + gtk-orientation-landscape + 3 + + + True + False + gtk-orientation-reverse-landscape + 3 + + + False + GStreamer video test + video-display + + + True + False + + + True + False + 8 + 8 + 8 + + + viewport + 1280 + 720 + True + True + False + True + True + + + + + False + True + 0 + + + + + True + False + 8 + 8 + 8 + 8 + 1 + + + True + False + 8 + True + bottom + center + + + Input 1 + True + True + True + image1 + True + + + + False + True + 0 + + + + + Input 2 + True + True + True + image2 + True + + + + False + True + 1 + + + + + gtk-quit + True + True + True + True + True + + + + False + True + 2 + + + + + + + False + True + 1 + + + + + + diff --git a/example4.py b/example4.py new file mode 100755 index 0000000..7398782 --- /dev/null +++ b/example4.py @@ -0,0 +1,129 @@ +#!/usr/bin/env python +# Attempting to dynamically switch between input sources + +# GdkX11 to get access to xid, GstVideo to get access to set_window_handle +import gi, signal +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 + +class Main: + def __init__(self): + + # Create gui bits and bobs + + self.mainwindow = Gtk.Builder() + self.mainwindow.add_from_file("example4.glade") + + signals = { + "on_input1_clicked" : self.SetInput1, + "on_input2_clicked" : self.SetInput2, + "on_quit_clicked" : self.OnQuit, + } + + self.mainwindow.connect_signals(signals) + + # Create GStreamer bits and bobs + + # Initiate Gstreamer + Gst.init(None) + + # Some capabilities we want to share between different elements + commoncaps = Gst.Caps.from_string("video/x-raw,width=1280,height=720,framerate=30/1") + + # Set up the pipeline + self.pipeline = Gst.Pipeline() + + # Add a videotestsrc element, set it to pattern "ball" and some other properties + self.ball = Gst.ElementFactory.make("videotestsrc", "ball") + self.ball.set_property("pattern", "ball") + self.ball.set_property("flip", True) + + # Add a capsfilter that we want to apply to our ball + self.ballcaps = Gst.ElementFactory.make("capsfilter", "ballcaps") + self.ballcaps.set_property("caps", commoncaps) + + # Webcam source + self.webcam = Gst.ElementFactory.make("v4l2src", "webcam") + self.webcam.set_property("device", "/dev/video0") + + # Webcam capsfilter + self.webcamcaps = Gst.ElementFactory.make("capsfilter", "webcamcaps") + self.webcamcaps.set_property("caps", commoncaps) + + # Add a videosink (where the playback happens) + self.videosink = Gst.ElementFactory.make("autovideosink", "videosink") + self.videosink.set_property("sync", False) + + # Add initial elements to the pipeline + self.pipeline.add(self.ball) + self.pipeline.add(self.ballcaps) + self.pipeline.add(self.videosink) + + # Link the initial pipeline + self.ball.link(self.ballcaps) + self.ballcaps.link(self.videosink) + + # Set up a bus to our pipeline to get notified when the video is ready + self.bus = self.pipeline.get_bus() + self.bus.enable_sync_message_emission() + self.bus.connect("sync-message::element", self.OnSyncElement) + + # Summon the window and connect the window's close button to quit + self.window = self.mainwindow.get_object("mainwindow") + self.window.connect("delete-event", Gtk.main_quit) + self.window.show_all() + + # Get window ID of the viewport widget from the GUI + self.win_id = self.mainwindow.get_object("viewport").get_window().get_xid() + + # Play! + self.pipeline.set_state(Gst.State.PLAYING) + + + # When we get a message that video is ready to display, set the + # correct window id to hook it to our viewport + def OnSyncElement(self, bus, message): + if message.get_structure().get_name() == "prepare-window-handle": + print("prepare-window-handle") + message.src.set_window_handle(self.win_id) + + def SetInput1(self, widget): + print("Switch to input 1") + # Halt current pipeline and tear it down + self.pipeline.set_state(Gst.State.NULL) + self.webcamcaps.unlink(self.videosink) + self.pipeline.remove(self.webcam) + self.pipeline.remove(self.webcamcaps) + # Construct new pipeline + self.pipeline.add(self.ball) + self.pipeline.add(self.ballcaps) + self.ball.link(self.ballcaps) + self.ballcaps.link(self.videosink) + self.pipeline.set_state(Gst.State.PLAYING) + + def SetInput2(self, widget): + print("Switch to input 2") + # Halt current pipeline and tear it down + self.pipeline.set_state(Gst.State.NULL) + self.ballcaps.unlink(self.videosink) + self.pipeline.remove(self.ball) + self.pipeline.remove(self.ballcaps) + # Construct new pipeline + self.pipeline.add(self.webcam) + self.pipeline.add(self.webcamcaps) + self.webcam.link(self.webcamcaps) + self.webcamcaps.link(self.videosink) + self.pipeline.set_state(Gst.State.PLAYING) + + def OnQuit(self, widget): + print("quit") + Gtk.main_quit() + + # Workaround to get Ctrl+C to terminate from command line + # ref: https://bugzilla.gnome.org/show_bug.cgi?id=622084#c12 + signal.signal(signal.SIGINT, signal.SIG_DFL) + +start = Main() +Gtk.main()