It sorta works now
[python-gstreamer-examples] / example4.py
1 #!/usr/bin/env python
2 # Attempting to dynamically switch between input sources
3
4 # GdkX11 to get access to xid, GstVideo to get access to set_window_handle
5 import gi, signal
6 gi.require_version('Gtk', '3.0')
7 gi.require_version('Gst', '1.0')
8 gi.require_version('GstVideo', '1.0')
9 from gi.repository import Gtk, Gst, GdkX11, GstVideo
10
11 class Main:
12 def __init__(self):
13
14 # Create gui bits and bobs
15
16 self.mainwindow = Gtk.Builder()
17 self.mainwindow.add_from_file("example4.glade")
18
19 signals = {
20 "on_input1_clicked" : self.SetInput1,
21 "on_input2_clicked" : self.SetInput2,
22 "on_quit_clicked" : self.OnQuit,
23 }
24
25 self.mainwindow.connect_signals(signals)
26
27 # Create GStreamer bits and bobs
28
29 # Initiate Gstreamer
30 Gst.init(None)
31
32 # Some capabilities we want to share between different elements
33 commoncaps = Gst.Caps.from_string("video/x-raw,width=1280,height=720,framerate=30/1")
34
35 # Set up the pipeline
36 self.pipeline = Gst.Pipeline()
37
38 # Add a videotestsrc element, set it to pattern "ball" and some other properties
39 self.ball = Gst.ElementFactory.make("videotestsrc", "ball")
40 self.ball.set_property("pattern", "ball")
41 self.ball.set_property("flip", True)
42
43 # Add a capsfilter that we want to apply to our ball
44 self.ballcaps = Gst.ElementFactory.make("capsfilter", "ballcaps")
45 self.ballcaps.set_property("caps", commoncaps)
46
47 # Webcam source
48 self.webcam = Gst.ElementFactory.make("v4l2src", "webcam")
49 self.webcam.set_property("device", "/dev/video0")
50
51 # Webcam capsfilter
52 self.webcamcaps = Gst.ElementFactory.make("capsfilter", "webcamcaps")
53 self.webcamcaps.set_property("caps", commoncaps)
54
55 # Add a videosink (where the playback happens)
56 self.videosink = Gst.ElementFactory.make("autovideosink", "videosink")
57 self.videosink.set_property("sync", False)
58
59 # Add initial elements to the pipeline
60 self.pipeline.add(self.ball)
61 self.pipeline.add(self.ballcaps)
62 self.pipeline.add(self.videosink)
63
64 # Link the initial pipeline
65 self.ball.link(self.ballcaps)
66 self.ballcaps.link(self.videosink)
67
68 # Set up a bus to our pipeline to get notified when the video is ready
69 self.bus = self.pipeline.get_bus()
70 self.bus.enable_sync_message_emission()
71 self.bus.connect("sync-message::element", self.OnSyncElement)
72
73 # Summon the window and connect the window's close button to quit
74 self.window = self.mainwindow.get_object("mainwindow")
75 self.window.connect("delete-event", Gtk.main_quit)
76 self.window.show_all()
77
78 # Get window ID of the viewport widget from the GUI
79 self.win_id = self.mainwindow.get_object("viewport").get_window().get_xid()
80
81 # Play!
82 self.pipeline.set_state(Gst.State.PLAYING)
83
84
85 # When we get a message that video is ready to display, set the
86 # correct window id to hook it to our viewport
87 def OnSyncElement(self, bus, message):
88 if message.get_structure().get_name() == "prepare-window-handle":
89 print("prepare-window-handle")
90 message.src.set_window_handle(self.win_id)
91
92 def SetInput1(self, widget):
93 print("Switch to input 1")
94 # Halt current pipeline and tear it down
95 self.pipeline.set_state(Gst.State.READY)
96 self.webcamcaps.unlink(self.videosink)
97 self.pipeline.remove(self.webcam)
98 self.pipeline.remove(self.webcamcaps)
99 # Construct new pipeline
100 self.pipeline.add(self.ball)
101 self.pipeline.add(self.ballcaps)
102 self.ball.link(self.ballcaps)
103 self.ballcaps.link(self.videosink)
104 self.pipeline.set_state(Gst.State.PLAYING)
105
106 def SetInput2(self, widget):
107 print("Switch to input 2")
108 # Halt current pipeline and tear it down
109 self.pipeline.set_state(Gst.State.READY)
110 self.ballcaps.unlink(self.videosink)
111 self.pipeline.remove(self.ball)
112 self.pipeline.remove(self.ballcaps)
113 # Construct new pipeline
114 self.pipeline.add(self.webcam)
115 self.pipeline.add(self.webcamcaps)
116 self.webcam.link(self.webcamcaps)
117 self.webcamcaps.link(self.videosink)
118 self.pipeline.set_state(Gst.State.PLAYING)
119
120 def OnQuit(self, widget):
121 print("quit")
122 Gtk.main_quit()
123
124 # Workaround to get Ctrl+C to terminate from command line
125 # ref: https://bugzilla.gnome.org/show_bug.cgi?id=622084#c12
126 signal.signal(signal.SIGINT, signal.SIG_DFL)
127
128 start = Main()
129 Gtk.main()