Author: tack
Date: Tue May 29 02:53:30 2007
New Revision: 2697
Added:
trunk/popcorn/test/data/music.png (contents, props changed)
trunk/popcorn/test/render_client.py
trunk/popcorn/test/render_manager.py
Log:
WIP video rendering via GL accelerated YUV texture. render_client uses
kaa.xine. Mplayer can be used as a client directly, as long as it's
patched with vo_export.
Added: trunk/popcorn/test/data/music.png
==============================================================================
Binary file. No diff available.
Added: trunk/popcorn/test/render_client.py
==============================================================================
--- (empty file)
+++ trunk/popcorn/test/render_client.py Tue May 29 02:53:30 2007
@@ -0,0 +1,66 @@
+# Xine render client for render_manager.py
+# Usage: python render_client.py /tmp/fifo1 video.avi
+#
+# Render manager must be monitoring /tmp/fifo1
+#
+
+import sys, os, sys
+import kaa.display, kaa.evas, kaa.xine, kaa, kaa.input.stdin
+
+def key(key):
+ if key == 'q':
+ sys.exit(0)
+ elif key == 'm':
+ stream.send_event(kaa.xine.EVENT_INPUT_MENU2)
+
+ if stream.is_in_menu:
+ d = { "up": kaa.xine.EVENT_INPUT_UP, "down": kaa.xine.EVENT_INPUT_DOWN,
+ "left": kaa.xine.EVENT_INPUT_LEFT, "right":
kaa.xine.EVENT_INPUT_RIGHT,
+ "enter": kaa.xine.EVENT_INPUT_SELECT, "space":
kaa.xine.EVENT_INPUT_SELECT }
+ if key in d:
+ stream.send_event(d[key])
+ else:
+ d = { "up": 60, "down": -60, "left": -10, "right": 10 }
+ if key in d:
+ stream.seek_relative(d[key])
+ if key == "space":
+ if stream.get_parameter(kaa.xine.PARAM_SPEED) ==
kaa.xine.SPEED_PAUSE:
+ stream.set_parameter(kaa.xine.PARAM_SPEED,
kaa.xine.SPEED_NORMAL)
+ else:
+ stream.set_parameter(kaa.xine.PARAM_SPEED,
kaa.xine.SPEED_PAUSE)
+
+
+def handle_xine_event(event):
+ stream = event.get_stream()
+ if event.type == kaa.xine.EVENT_UI_NUM_BUTTONS:
+ stream.is_in_menu = event.data["num_buttons"] > 0
+
+
+fd = os.open(sys.argv[1], os.O_RDWR | os.O_NONBLOCK)
+
+l = []
+xine = kaa.xine.Xine()
+vo = xine.open_video_driver('kaa', passthrough = 'none', control_return = l,
notify_fd = fd)
+control = l[0]
+control('set_notify_frame', True)
+try:
+ ao = xine.open_audio_driver()
+except:
+ # Audio device in use, use dummy driver.
+ ao = xine.open_audio_driver('none')
+
+stream = xine.new_stream(ao, vo)
+stream.signals["event"].connect(handle_xine_event)
+stream.is_in_menu = False
+
+deint = xine.post_init('tvtime', video_targets = [vo])
+deint.set_parameters(method = 'LinearBlend', enabled = True, chroma_filter =
False, cheap_mode = False)
+stream.get_video_source().wire(deint.get_default_input())
+
+stream.open(sys.argv[2])
+stream.play()
+
+kaa.signals['stdin_key_press_event'].connect(key)
+kaa.main()
+# We need to break cycles so dealloc handlers get called on shutdown.
+del deint, vo, ao, stream, xine
Added: trunk/popcorn/test/render_manager.py
==============================================================================
--- (empty file)
+++ trunk/popcorn/test/render_manager.py Tue May 29 02:53:30 2007
@@ -0,0 +1,297 @@
+# Rendering manager: renders one or more videos to a canvas. Video info is
+# delivered via fifo by a protocol that's currently implemented in kaa.xine
+# and mplayer vo_export patch (in patches/).
+#
+# This script takes as arguments one or more fifos to monitor for frame
+# notifications. Each fifo is a separate video source. E.g.:
+#
+# mkfifo /tmp/fifo1 /tmp/fifo2 /tmp/fifo3
+# python render_manager.py /tmp/fifo*
+#
+# This is heavily WIP. Will document later.
+
+import os, struct, time
+import kaa.display, kaa.evas, kaa.shm, kaa, kaa.input.stdin, sys
+
+# Default window size.
+WIN_SIZE = 640, 480
+#WIN_SIZE = 1600, 1200
+
+class Manager:
+ def __init__(self, evas_window):
+ self._window = evas_window
+ self._evas = evas_window.get_evas()
+ self._videos = []
+ self._current = None
+ self._render_needed = False
+ self._selecting = False
+
+ def add_video(self, video):
+ self._videos.append(video)
+ self._fit_window()
+
+ def remove_video(self, video):
+ self._videos.remove(video)
+ self._fit_window()
+ if len(self._videos) == 0:
+ self._window.hide()
+ if self._current == video:
+ self._current = None
+
+ def get_videos(self):
+ return self._videos
+
+ def next_video(self):
+ if not self._current:
+ cur = 0
+ else:
+ cur = self._videos.index(self._current)
+
+ for idx in range(cur+1, len(self._videos)) + range(0, cur+1):
+ if self._videos[idx]._shmem:
+ self._current = self._videos[idx]
+ break
+ else:
+ self._current = None
+ self._selecting = True
+ return self._current
+
+ def get_selecting(self):
+ return self._selecting
+
+ def set_selecting(self, value):
+ self._selecting = value
+
+ def get_current(self):
+ return self._current
+
+ def queue_render(self):
+ self._render_needed = True
+
+ def render(self):
+ if not self._render_needed:
+ return
+
+ t0=time.time()
+ e.render()
+ #print "Render:", time.time()-t0
+ self._render_needed = False
+
+
+ def _fit_window(self):
+ if len(self._videos) != 1:
+ return
+ if not self._videos[0]._fit_canvas:
+ size = self._videos[0].geometry_get()[1]
+ self._window.resize(size)
+ self._window.show()
+
+
+class Video(kaa.evas.Image):
+ def __init__(self, evas, fifo_fname):
+ super(Video, self).__init__(evas)
+
+ self._fifo_fname = fifo_fname
+ self._aspect = 1.0
+ self._shmem = None
+ self._fit_canvas = True
+ self._last_width = None
+
+ self._setup_fifo()
+
+ def _setup_fifo(self):
+ fifo = os.open(self._fifo_fname, os.O_RDONLY | os.O_NONBLOCK)
+ try:
+ while len(os.read(fifo, 4096)) != 0:
+ # Consume any pending frame notifications that might be
+ # buffered in the fifo
+ pass
+ except OSError:
+ pass
+
+ print "Setup fifo", fifo
+ kaa.notifier.WeakSocketDispatcher(self._new_frame, fifo).register(fifo)
+
+
+ def _new_frame(self, fifo):
+ t0=time.time()
+ header = os.read(fifo, 16)
+
+ if len(header) == 0:
+ self._setup_fifo()
+ os.close(fifo)
+ return False
+
+ shmid, offset = struct.unpack("II8x", header)
+ if self._shmem and self._shmem.shmid != shmid:
+ self._shmem.detach()
+ self._shmem = None
+
+ if not self._shmem:
+ try:
+ self._shmem = kaa.shm.memory(shmid)
+ except kaa.shm.error:
+ print "Couldn't attach to shmem segment"
+ return False
+ self._shmem.attach()
+ self.object_raise()
+
+ header = self._shmem.read(32, offset)
+ lock, width, height, stride, aspect = struct.unpack("bHHHd16x", header)
+ #print "Newframe", len(header), shmid, offset, lock, width, height,
stride, aspect
+ if self.size_get() != (stride, height) or aspect != self._aspect:
+ self._aspect = aspect
+ self.data_set(0, False)
+ # Bug in evas GL engine when text width != stride, so we must make
+ # the image width the stride and crop after.
+ self.size_set((stride, height))
+ if self._fit_canvas:
+ self.resize(self.evas_get().output_size_get())
+ elif not self._last_width:
+ self.resize((int(height * aspect), 0))
+ else:
+ # Keep last width, correct for new aspect
+ cur_width = self.geometry_get()[1][0]
+ self.resize((cur_width, 0))
+
+ # TODO: crop to width
+
+ t1=time.time()
+ self.data_set(self._shmem.addr + offset + 32, False, stride = stride)
+ self.pixels_dirty_set()
+ manager.queue_render()
+ # FIXME: should be done on render, not now.
+ self._shmem.write('\x00', offset)
+ t2 = time.time()
+ #print "Timing: header=%0.5f evas=%0.5f total=%0.5f" % (t1-t0, t2-t1,
t2-t0)
+
+ def resize(self, (w, h)):
+ h = int(w / self._aspect)
+ self.fill_set((0, 0), (w, h))
+ super(Video, self).resize((w, h))
+ if self._fit_canvas:
+ self.center()
+ self._last_width = w
+
+ def center(self):
+ canvas_w, canvas_h = self.evas_get().output_size_get()
+ w, h = self.geometry_get()[1]
+ self.move(((canvas_w - w) / 2, (canvas_h - h) / 2))
+
+ def set_fit(self, value):
+ if value == self._fit_canvas:
+ return
+ self._fit_canvas = value
+ if value or not self._last_width:
+ self.resize(self.evas_get().output_size_get())
+ else:
+ self.resize((self._last_width, -1))
+
+ def get_fit(self):
+ return self._fit_canvas
+
+
+def resize_window(last, size, canvas, bg):
+ canvas.output_size_set(size)
+ canvas.viewport_set((0, 0), size)
+ bg.resize(size)
+ for video in manager.get_videos():
+ if video.get_fit():
+ video.resize(size)
+
+
+def key(code):
+ video = manager.get_current()
+ if video:
+ r, g, b, a = video.color_get()
+ (x, y), (w, h) = video.geometry_get()
+
+ if code == 'q':
+ sys.exit(0)
+ elif code == 'F':
+ win.set_fullscreen(not win.get_fullscreen())
+
+ elif code == 'space':
+ if manager.get_selecting():
+ if video:
+ video.color_set(255, 255, 255, a)
+ manager.set_selecting(False)
+ else:
+ manager.set_selecting(True)
+ video = manager.get_current()
+ if not video:
+ video = manager.next_video()
+ if video:
+ video.color_set(255, 192, 192, video.color_get()[3])
+
+ elif code == 'tab':
+ if video:
+ video.color_set(255, 255, 255, a)
+ video = manager.next_video()
+ if video:
+ video.object_raise()
+ video.color_set(255, 192, 192, video.color_get()[3])
+
+ if not video or not manager.get_selecting():
+ print "No video selected, hit tab"
+ return
+
+ if code == ']':
+ video.resize((w + 4, -1))
+ elif code == '[':
+ video.resize((w - 4, -1))
+ elif code == 'up':
+ video.move((x, y - 4))
+ video.set_fit(False)
+ elif code == 'down':
+ video.move((x, y + 4))
+ video.set_fit(False)
+ elif code == 'left':
+ video.move((x - 4, y))
+ video.set_fit(False)
+ elif code == 'right':
+ video.move((x + 4, y))
+ video.set_fit(False)
+
+ elif code == 'a':
+ video.color_set(r, g, b, a - 5)
+ elif code == 'A':
+ video.color_set(r, g, b, a + 5)
+ elif code == 'h':
+ video.hide()
+ elif code == 's':
+ video.show()
+ elif code == 'f':
+ video.set_fit(not video.get_fit())
+
+
+win = kaa.display.EvasX11Window(gl = True, size = WIN_SIZE)
+manager = Manager(win)
+e = win.get_evas()
+
+bg = e.object_rectangle_add()
+bg.color_set(0,0,0,255)
+bg.resize(WIN_SIZE)
+bg.show()
+
+for fifo in sys.argv[1:]:
+ video = Video(e, fifo)
+ video.colorspace_set(kaa.evas.COLORSPACE_YCBCR422P601_PL)
+ video.show()
+ manager.add_video(video)
+
+img = e.object_image_add('data/music.png')
+img.color_set(255,255,255,120)
+img.layer_set(10)
+img.show()
+
+e.render()
+
+kaa.signals['step'].connect(manager.render)
+kaa.signals['stdin_key_press_event'].connect(key)
+win.signals['key_press_event'].connect(key)
+win.signals['resize_event'].connect(resize_window, e, bg)
+#win.set_fullscreen(True)
+
+print "Keys: q, arrows, tab, space, F, f, a, A, [, ], h, s"
+kaa.main()
-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
Freevo-cvslog mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/freevo-cvslog