Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/olpcgames/video.py
diff options
context:
space:
mode:
authorBrian Jordan <brian@laptop.org>2008-06-27 18:17:45 (GMT)
committer Brian Jordan <brian@laptop.org>2008-06-27 18:22:14 (GMT)
commit392a0c5a4d19da8f06b3ccab8b9d7fdcd558e64d (patch)
tree7fefd02a04479932b4afe7ccd14b12de3c6294c6 /olpcgames/video.py
Initial commit
Diffstat (limited to 'olpcgames/video.py')
-rwxr-xr-xolpcgames/video.py178
1 files changed, 178 insertions, 0 deletions
diff --git a/olpcgames/video.py b/olpcgames/video.py
new file mode 100755
index 0000000..032aa13
--- /dev/null
+++ b/olpcgames/video.py
@@ -0,0 +1,178 @@
+"""Video widget for displaying a gstreamer pipe
+
+Note: currently this module is not all that elegant or useful,
+we need a better recipe for using and working with Video
+under OLPCGames.
+"""
+import logging
+log = logging.getLogger( 'olpcgames.video' )
+#log.setLevel( logging.INFO )
+import os
+import signal
+import pygame
+import weakref
+import olpcgames
+from olpcgames import _gtkmain
+
+import pygtk
+pygtk.require('2.0')
+import gtk
+import gst
+
+class VideoWidget(gtk.DrawingArea):
+ """Widget to render GStreamer video over our Pygame Canvas
+
+ The VideoWidget is a simple GTK window which is
+ held by the PygameCanvas, just as is the Pygame
+ window we normally use. As such this approach
+ *cannot* work without the GTK wrapper.
+
+ It *should* be possible to use raw X11 operations
+ to create a child window of the Pygame/SDL window
+ and use that for the same purpose, but that would
+ require some pretty low-level ctypes hacking.
+
+ Attributes of Note:
+
+ rect -- Pygame rectangle which tells us where to
+ display ourselves, setting the rect changes the
+ position and size of the window.
+ """
+ _imagesink = None
+ _renderedRect = None
+ def __init__(self, rect=None, force_aspect_ratio=True):
+ super(VideoWidget, self).__init__()
+ self.unset_flags(gtk.DOUBLE_BUFFERED)
+ if rect is None:
+ rect = pygame.Rect( (0,0), (160,120))
+ self.rect = rect
+ self.force_aspect_ratio = force_aspect_ratio
+ self.set_size_request(rect.width,rect.height)
+ olpcgames.WIDGET.put( self, rect.left,rect.top)
+ self._renderedRect = rect
+ self.show()
+
+ def set_rect( self, rect ):
+ """Set our rectangle (area of the screen)"""
+ log.debug( 'Set rectangle: %s', rect )
+ self.set_size_request(rect.width,rect.height)
+ olpcgames.WIDGET.move( self, rect.left,rect.top)
+ self.rect = rect
+
+ def do_expose_event(self, event):
+ """Handle exposure event (trigger redraw by gst)"""
+ if self._imagesink:
+ self._imagesink.expose()
+ return False
+ else:
+ return True
+
+ def set_sink(self, sink):
+ """Set our window-sink for output"""
+ assert self.window.xid
+ self._imagesink = sink
+ self._imagesink.set_xwindow_id(self.window.xid)
+ self._imagesink.set_property('force-aspect-ratio', self.force_aspect_ratio)
+
+class PygameWidget( object ):
+ """Render "full-screen" video to the entire Pygame screen
+
+ Not particularly useful unless this happens to be exactly what you need.
+ """
+ def __init__( self ):
+ try:
+ window_id = pygame.display.get_wm_info()['window']
+ except KeyError, err: # pygame-ctypes...
+ window_id = int(os.environ['SDL_WINDOWID'])
+ self.window_id = window_id
+ self._imagesink = None
+ #self._holder = _gtkmain.Holder()
+ def set_sink( self, sink ):
+ """Set up our gst sink"""
+ log.info( 'Setting sink: %s', sink )
+ self._imagesink = sink
+ sink.set_xwindow_id( self.window_id )
+
+#pipe_desc = 'v4l2src ! video/x-raw-yuv,width=160,height=120 ! ffmpegcolorspace ! xvimagesink'
+class Player(object):
+ pipe_desc = 'v4l2src ! ffmpegcolorspace ! video/x-raw-yuv ! xvimagesink'
+ test_pipe_desc = 'videotestsrc ! ffmpegcolorspace ! video/x-raw-yuv ! xvimagesink'
+ _synchronized = False
+ def __init__(self, videowidget, pipe_desc=pipe_desc):
+ self._playing = False
+ self._videowidget = videowidget
+
+ self._pipeline = gst.parse_launch(pipe_desc)
+
+ 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 play(self):
+ log.info( 'Play' )
+ if self._playing == False:
+ self._pipeline.set_state(gst.STATE_PLAYING)
+ self._playing = True
+
+ def pause(self):
+ log.info( 'Pause' )
+ if self._playing == True:
+ if self._synchronized:
+ log.debug( ' pause already sync\'d' )
+ self._pipeline.set_state(gst.STATE_PAUSED)
+ self._playing = False
+ def stop( self ):
+ """Stop all playback"""
+ self._pipeline.set_state( gst.STATE_NULL )
+
+ def on_sync_message(self, bus, message):
+ log.info( 'Sync: %s', message )
+ if message.structure is None:
+ return
+ if message.structure.get_name() == 'prepare-xwindow-id':
+ self._synchronized = True
+ self._videowidget.set_sink(message.src)
+
+ def on_message(self, bus, message):
+ log.info( 'Message: %s', message )
+ t = message.type
+ if t == gst.MESSAGE_ERROR:
+ err, debug = message.parse_error()
+ log.warn("Video error: (%s) %s" ,err, debug)
+ self._playing = False
+
+if __name__ == "__main__":
+ # Simple testing code...
+ logging.basicConfig()
+ log.setLevel( logging.DEBUG )
+ from pygame import image,display, event
+ import pygame
+ def main():
+ display.init()
+ maxX,maxY = display.list_modes()[0]
+ screen = display.set_mode( (maxX/3, maxY/3 ) )
+
+ display.flip()
+
+ pgw = PygameWidget( )
+ p = Player( pgw, pipe_desc=Player.test_pipe_desc )
+ p.play()
+
+ clock = pygame.time.Clock()
+
+ running = True
+ while running:
+ clock.tick( 60 )
+ for evt in [pygame.event.wait()] + pygame.event.get():
+ if evt.type == pygame.KEYDOWN:
+ if p._playing:
+ p.pause()
+ else:
+ p.play()
+ elif evt.type == pygame.QUIT:
+ p.stop()
+ running = False
+ #display.flip()
+ main()