Permalink
Browse files

Added multi-camera console to repository.

  • Loading branch information...
1 parent 20c839d commit 33c28837cf62f243a2a9a317f16d22e58e2ce3b7 @csete committed Aug 24, 2010
Showing with 207 additions and 0 deletions.
  1. +2 −0 README
  2. +205 −0 multicam.py
View
2 README
@@ -14,4 +14,6 @@ A simple TX+RX simulator that can be used to test without any USRP.
gst-cmd.txt:
Example Gstreamer commands to build the video processing pipelines.
+multicam.py:
+An experimental GUI to switch between different cameras (not very functional yet).
View
@@ -0,0 +1,205 @@
+#!/usr/bin/env python
+# -*- Mode: Python -*-
+# vi:si:et:sw=4:sts=4:ts=4
+#
+# Multi camera console for the simple DVB setup with Gstreamer and GNU Radio.
+# Based on the switch.py example from the gst-python repository
+
+
+import pygtk
+pygtk.require('2.0')
+
+import sys
+
+import gobject
+gobject.threads_init()
+
+import pygst
+pygst.require('0.10')
+import gst
+import gst.interfaces
+import gtk
+gtk.gdk.threads_init()
+
+class SwitchTest:
+ def __init__(self, videowidget):
+ self.playing = False
+ pipestr = ('videotestsrc pattern=0 ! textoverlay text="CAM 1" auto-resize=false halign=left ! sel.sink0 '
+ 'videotestsrc pattern=13 ! textoverlay text="CAM 2" auto-resize=false halign=left ! sel.sink1 '
+ 'videotestsrc pattern=1 ! textoverlay text="CAM 3" auto-resize=false halign=left ! sel.sink2 '
+ 'input-selector name=sel ! video/x-raw-yuv,width=640,height=480,framerate=15/1 ! '
+ 'clockoverlay text="OZ9AEC" auto-resize=false shaded-background=true ! tee name="split" '
+ 'split. ! queue ! autovideosink '
+ 'split. ! queue ! theoraenc ! matroskamux ! filesink location=stream.mkv')
+ self.pipeline = gst.parse_launch(pipestr)
+ self.videowidget = videowidget
+
+ bus = self.pipeline.get_bus()
+ bus.enable_sync_message_emission()
+ bus.add_signal_watch()
+ bus.connect('sync-message::element', self.on_sync_message)
+ bus.connect('message', self.on_message)
+
+ def on_sync_message(self, bus, message):
+ if message.structure is None:
+ return
+ if message.structure.get_name() == 'prepare-xwindow-id':
+ # Sync with the X server before giving the X-id to the sink
+ gtk.gdk.threads_enter()
+ gtk.gdk.display_get_default().sync()
+ self.videowidget.set_sink(message.src)
+ message.src.set_property('force-aspect-ratio', True)
+ gtk.gdk.threads_leave()
+
+ def on_message(self, bus, message):
+ t = message.type
+ if t == gst.MESSAGE_ERROR:
+ err, debug = message.parse_error()
+ print "Error: %s" % err, debug
+ if self.on_eos:
+ self.on_eos()
+ self.playing = False
+ elif t == gst.MESSAGE_EOS:
+ if self.on_eos:
+ self.on_eos()
+ self.playing = False
+
+ def play(self):
+ self.playing = True
+ gst.info("playing player")
+ self.pipeline.set_state(gst.STATE_PLAYING)
+
+ def stop(self):
+ self.pipeline.set_state(gst.STATE_NULL)
+ gst.info("stopped player")
+ self.playing = False
+
+ def get_state(self, timeout=1):
+ return self.pipeline.get_state(timeout=timeout)
+
+ def is_playing(self):
+ return self.playing
+
+ def switch(self, padname):
+ switch = self.pipeline.get_by_name('sel')
+ stop_time = switch.emit('block')
+ newpad = switch.get_static_pad(padname)
+ start_time = newpad.get_property('running-time')
+
+ gst.warning('stop time = %d' % (stop_time,))
+ gst.warning('stop time = %s' % (gst.TIME_ARGS(stop_time),))
+
+ gst.warning('start time = %d' % (start_time,))
+ gst.warning('start time = %s' % (gst.TIME_ARGS(start_time),))
+
+ gst.warning('switching from %r to %r'
+ % (switch.get_property('active-pad'), padname))
+ switch.emit('switch', newpad, stop_time, start_time)
+
+class VideoWidget(gtk.DrawingArea):
+ def __init__(self):
+ gtk.DrawingArea.__init__(self)
+ self.imagesink = None
+ self.unset_flags(gtk.DOUBLE_BUFFERED)
+
+ def do_expose_event(self, event):
+ if self.imagesink:
+ self.imagesink.expose()
+ return False
+ else:
+ return True
+
+ def set_sink(self, sink):
+ assert self.window.xid
+ self.imagesink = sink
+ self.imagesink.set_xwindow_id(self.window.xid)
+
+class SwitchWindow(gtk.Window):
+ UPDATE_INTERVAL = 500
+ def __init__(self):
+ gtk.Window.__init__(self)
+ self.set_default_size(410, 325)
+
+ self.create_ui()
+ self.player = SwitchTest(self.videowidget)
+ self.populate_combobox()
+
+ self.update_id = -1
+ self.changed_id = -1
+ self.seek_timeout_id = -1
+
+ self.p_position = gst.CLOCK_TIME_NONE
+ self.p_duration = gst.CLOCK_TIME_NONE
+
+ def on_delete_event():
+ self.player.stop()
+ gtk.main_quit()
+ self.connect('delete-event', lambda *x: on_delete_event())
+
+ def load_file(self, location):
+ self.player.set_location(location)
+
+ def play(self):
+ self.player.play()
+
+ def populate_combobox(self):
+ switch = self.player.pipeline.get_by_name('sel')
+ for i, pad in enumerate([p for p in switch.pads()
+ if p.get_direction() == gst.PAD_SINK]):
+ # the switch.py example used sink0 and sink1 pad names as combo entries
+ #self.combobox.append_text(pad.get_name())
+ # we use CAM 1 and CAM 2
+ self.combobox.append_text("CAM " + str(i+1))
+ if switch.get_property('active-pad') == pad.get_name():
+ self.combobox.set_active(i)
+ if self.combobox.get_active() == -1:
+ self.combobox.set_active(0)
+
+ def combobox_changed(self):
+ model = self.combobox.get_model()
+ #row = model[self.combobox.get_active()]
+ #padname, = row
+ # we need to translate combo index to "sink0" and "sink1"
+ padname = "sink" + str(self.combobox.get_active())
+ self.player.switch(padname)
+
+ def create_ui(self):
+ vbox = gtk.VBox()
+ self.add(vbox)
+
+ self.videowidget = VideoWidget()
+ vbox.pack_start(self.videowidget)
+
+ hbox = gtk.HBox()
+ vbox.pack_start(hbox, fill=False, expand=False)
+
+ self.combobox = combobox = gtk.combo_box_new_text()
+ combobox.show()
+ hbox.pack_start(combobox)
+
+ self.combobox.connect('changed',
+ lambda *x: self.combobox_changed())
+
+ self.videowidget.connect_after('realize',
+ lambda *x: self.play())
+
+def main(args):
+ def usage():
+ sys.stderr.write("usage: %s\n" % args[0])
+ return 1
+
+ # Need to register our derived widget types for implicit event
+ # handlers to get called.
+ gobject.type_register(SwitchWindow)
+ gobject.type_register(VideoWidget)
+
+ if len(args) != 1:
+ return usage()
+
+ w = SwitchWindow()
+ w.show_all()
+ gtk.main()
+ return 0
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv))

0 comments on commit 33c2883

Please sign in to comment.