Faster example using videomixer
[python-gstreamer-examples] / example5.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("example5.glade")
18
19 signals = {
20 "on_input1_clicked" : self.SetInput1,
21 "on_input2_clicked" : self.SetInput2,
22 "on_input3_clicked" : self.SetInput3,
23 "on_input4_clicked" : self.SetInput4,
24 "on_input5_clicked" : self.SetInput5,
25 "on_input6_clicked" : self.SetInput6,
26 "on_quit_clicked" : self.OnQuit,
27 }
28
29 self.mainwindow.connect_signals(signals)
30
31 # Create GStreamer bits and bobs
32
33 # Initiate Gstreamer
34 Gst.init(None)
35
36 # Some capabilities we want to share between different elements
37 jpegcaps = Gst.Caps.from_string("image/jpeg,width=1280,height=720,framerate=30/1")
38
39 # Set up the pipeline
40 self.pipeline = Gst.Pipeline()
41
42 # Add elements
43
44 # src1
45 self.src1 = Gst.ElementFactory.make("v4l2src", "src1")
46 self.src1.set_property("device", "/dev/video1")
47
48 # src1 capsfilter
49 self.src1caps = Gst.ElementFactory.make("capsfilter", "src1caps")
50 self.src1caps.set_property("caps", jpegcaps)
51
52 # src1jpegdec
53 self.src1jpegdec = Gst.ElementFactory.make("jpegdec", "src1jpegdec")
54
55 # src1videoconvert
56 self.src1videoconvert = Gst.ElementFactory.make("videoconvert", "src1videoconvert")
57
58 # src2
59 self.src2 = Gst.ElementFactory.make("v4l2src", "src2")
60 self.src2.set_property("device", "/dev/video0")
61
62 # src2 capsfilter
63 self.src2caps = Gst.ElementFactory.make("capsfilter", "src2caps")
64 self.src2caps.set_property("caps", jpegcaps)
65
66 # src2jpegdec
67 self.src2jpegdec = Gst.ElementFactory.make("jpegdec", "src2jpegdec")
68
69 # src2videoconvert
70 self.src2videoconvert = Gst.ElementFactory.make("videoconvert", "src2videoconvert")
71
72 # Video mix
73 self.videomix = Gst.ElementFactory.make("videomixer", "videomix")
74 self.src1pad = self.videomix.get_request_pad("sink_1")
75 self.src1pad.set_property("zorder", 2)
76 self.src2pad = self.videomix.get_request_pad("sink_2")
77 self.src2pad.set_property("zorder", 1)
78
79 # Add main videosink
80 self.videosink = Gst.ElementFactory.make("autovideosink", "videosink")
81 self.videosink.set_property("sync", False)
82
83 # Add initial elements to the pipeline
84 self.pipeline.add(self.src1)
85 self.pipeline.add(self.src1caps)
86 self.pipeline.add(self.src1jpegdec)
87 self.pipeline.add(self.src1videoconvert)
88
89 self.pipeline.add(self.src2)
90 self.pipeline.add(self.src2caps)
91 self.pipeline.add(self.src2jpegdec)
92 self.pipeline.add(self.src2videoconvert)
93
94 self.pipeline.add(self.videomix)
95 self.pipeline.add(self.videosink)
96
97 # Link the initial pipeline
98 self.src1.link(self.src1caps)
99 self.src1caps.link(self.src1jpegdec)
100 self.src1jpegdec.link(self.src1videoconvert)
101 self.src1videoconvert.link(self.videomix)
102
103 self.src2.link(self.src2caps)
104 self.src2caps.link(self.src2jpegdec)
105 self.src2jpegdec.link(self.src2videoconvert)
106 self.src2videoconvert.link(self.videomix)
107
108 self.videomix.link(self.videosink)
109
110 # Set up a bus to our pipeline to get notified when the video is ready
111 self.bus = self.pipeline.get_bus()
112 self.bus.enable_sync_message_emission()
113 self.bus.connect("sync-message::element", self.OnSyncElement)
114
115 # Summon the window and connect the window's close button to quit
116 self.window = self.mainwindow.get_object("mainwindow")
117 self.window.connect("delete-event", Gtk.main_quit)
118 self.window.show_all()
119
120 # Get window ID of the viewport widget from the GUI
121 self.win_id = self.mainwindow.get_object("viewport_main").get_window().get_xid()
122
123 # Play!
124 self.pipeline.set_state(Gst.State.PLAYING)
125
126
127 # When we get a message that video is ready to display, set the
128 # correct window id to hook it to our viewport
129 def OnSyncElement(self, bus, message):
130 if message.get_structure().get_name() == "prepare-window-handle":
131 print("prepare-window-handle")
132 message.src.set_window_handle(self.win_id)
133
134 def SetInput1(self, widget):
135 print("Switch to input 1")
136 self.src1pad.set_property("zorder", 2)
137 self.src2pad.set_property("zorder", 1)
138
139 def SetInput2(self, widget):
140 print("Switch to input 2")
141 self.src1pad.set_property("zorder", 1)
142 self.src2pad.set_property("zorder", 2)
143
144 def SetInput3(self, widget):
145 print("Switch to input 3")
146
147 def SetInput4(self, widget):
148 print("Switch to input 4")
149
150 def SetInput5(self, widget):
151 print("Switch to input 5")
152
153 def SetInput6(self, widget):
154 print("Switch to input 6")
155
156 def OnQuit(self, widget):
157 print("quit")
158 Gtk.main_quit()
159
160 # Workaround to get Ctrl+C to terminate from command line
161 # ref: https://bugzilla.gnome.org/show_bug.cgi?id=622084#c12
162 signal.signal(signal.SIGINT, signal.SIG_DFL)
163
164 start = Main()
165 Gtk.main()