2 # GdkX11 to get access to xid, GstVideo to get access to set_window_handle 
   4 gi
.require_version('Gtk', '3.0') 
   5 gi
.require_version('Gst', '1.0') 
   6 gi
.require_version('GstVideo', '1.0') 
   7 from gi
.repository 
import Gtk
, Gst
, GstVideo
, GdkX11
 
  10 settings 
= Gtk
.Settings
.get_default() 
  11 settings
.props
.gtk_button_images 
= True 
  16         # Create gui bits and bobs 
  18         self
.mainwindow 
= Gtk
.Builder() 
  19         self
.mainwindow
.add_from_file("stream.glade") 
  22             "on_stream_clicked" : self
.OnStream
, 
  23             "on_stop_clicked" : self
.OnStop
, 
  24             "on_quit_clicked" : self
.OnQuit
, 
  27         self
.mainwindow
.connect_signals(signals
) 
  29         # Create GStreamer bits and bobs 
  31         # Initiate the pipeline 
  33         self
.pipeline 
= Gst
.Pipeline("mypipeline") 
  35         # Add our video source, the first v4l2 device we can find 
  36         self
.videosrc 
= Gst
.ElementFactory
.make("v4l2src", "videosource") 
  37         self
.pipeline
.add(self
.videosrc
) 
  39         # Add a jpeg decoder to force the v4l2src to output jpeg data 
  40         self
.jpegdec 
= Gst
.ElementFactory
.make("jpegdec", "jpegdec") 
  41         self
.pipeline
.add(self
.jpegdec
) 
  42         self
.videosrc
.link(self
.jpegdec
) 
  44         # Add some video convert magic 
  45         self
.videoconvert 
= Gst
.ElementFactory
.make("videoconvert", "videoconvert") 
  46         self
.pipeline
.add(self
.videoconvert
) 
  47         self
.jpegdec
.link(self
.videoconvert
) 
  49         # Add a videosink element to the pipeline 
  50         self
.videosink 
= Gst
.ElementFactory
.make("autovideosink", "videosink") 
  51         self
.videosink
.set_property("sync", False) 
  52         self
.pipeline
.add(self
.videosink
) 
  53         self
.videoconvert
.link(self
.videosink
) 
  56         self
.pipeline
.set_state(Gst
.State
.PLAYING
) 
  58         # Set up a bus to our pipeline to get notified when the video is ready 
  59         self
.bus 
= self
.pipeline
.get_bus() 
  60         self
.bus
.enable_sync_message_emission() 
  61         self
.bus
.connect("sync-message::element", self
.OnSyncElement
) 
  63         # Summon the window and connect the window's close button to quit 
  64         self
.window 
= self
.mainwindow
.get_object("mainwindow") 
  65         self
.window
.connect("delete-event", Gtk
.main_quit
) 
  66         self
.window
.show_all() 
  68         # Get window ID of the viewport widget from the GUI 
  69         self
.win_id 
= self
.mainwindow
.get_object("viewport").get_window().get_xid() 
  72     # When we get a message that video is ready to display, set the 
  73     # correct window id to hook it to our viewport 
  74     def OnSyncElement(self
, bus
, message
): 
  75         if message
.get_structure().get_name() == "prepare-window-handle": 
  76             print "prepare-window-handle" 
  77             message
.src
.set_window_handle(self
.win_id
) 
  79     def OnStream(self
, widget
): 
  81         self
.pipeline
.set_state(Gst
.State
.PLAYING
) 
  83     def OnStop(self
, widget
): 
  85         self
.pipeline
.set_state(Gst
.State
.READY
) 
  87     def OnQuit(self
, widget
): 
  91     # Workaround to get Ctrl+C to terminate from command line 
  92     # ref: https://bugzilla.gnome.org/show_bug.cgi?id=622084#c12 
  93     signal
.signal(signal
.SIGINT
, signal
.SIG_DFL
)