From 1697726fa0142739acbed38bd1a8434300d3a87b Mon Sep 17 00:00:00 2001 From: Mathieu Virbel Date: Wed, 12 Jan 2011 02:24:31 +0100 Subject: [PATCH] update Camera core class to use EventDispatcher + add on_load and on_frame event + uniform the camera selection to a index, starting from 0 --- examples/kv/app_camera.kv | 25 ++++++++++++++ kivy/core/camera/__init__.py | 43 ++++++++++++++++++------- kivy/core/camera/camera_gstreamer.py | 18 ++++++++--- kivy/core/camera/camera_opencv.py | 11 ++----- kivy/core/camera/camera_videocapture.py | 9 ++---- 5 files changed, 75 insertions(+), 31 deletions(-) create mode 100644 examples/kv/app_camera.kv diff --git a/examples/kv/app_camera.kv b/examples/kv/app_camera.kv new file mode 100644 index 000000000..8994e0715 --- /dev/null +++ b/examples/kv/app_camera.kv @@ -0,0 +1,25 @@ +Camera: + canvas: + Color: + rgb: (1, 1, 1) + Rectangle: + texture: self.texture + size: (320, 240) + Color: + rgb: (.5, 0, 1) + Rectangle: + texture: self.texture + pos: (320, 0) + size: (320, 240) + Color: + rgb: (0, 1, 0) + Rectangle: + texture: self.texture + pos: (320, 240) + size: (320, 240) + Color: + rgb: (1, 0, 0) + Rectangle: + texture: self.texture + pos: (0, 240) + size: (320, 240) diff --git a/kivy/core/camera/__init__.py b/kivy/core/camera/__init__.py index 69dabc229..0b5438f54 100644 --- a/kivy/core/camera/__init__.py +++ b/kivy/core/camera/__init__.py @@ -8,16 +8,19 @@ Core class for acquiring the camera, and convert the input to a __all__ = ('CameraBase', 'Camera') +from kivy.event import EventDispatcher from kivy.logger import Logger from kivy.core import core_select_lib -class CameraBase(object): +class CameraBase(EventDispatcher): '''Abstract Camera Widget class. Concrete camera classes must implement initialization and frame capturing to buffer that can be uploaded to gpu. :Parameters: + `index`: int + Source index of the camera. `size` : tuple (int, int) Size at which the image is drawn. If no size is specified, it defaults to resolution of the camera image. @@ -26,23 +29,32 @@ class CameraBase(object): Used in the gstreamer pipeline by forcing the appsink caps to this resolution. If the camera doesnt support the resolution a negotiation error might be thrown. + + :Events: + `on_load` + Fired when the camera is loaded, and the texture became available + `on_frame` + Fired each time the camera texture is updated ''' def __init__(self, **kwargs): kwargs.setdefault('stopped', False) kwargs.setdefault('resolution', (640, 480)) - kwargs.setdefault('video_src', 0) + kwargs.setdefault('index', 0) self.stopped = kwargs.get('stopped') self._resolution = kwargs.get('resolution') - self._video_src = kwargs.get('video_src') + self._index = kwargs.get('index') self._buffer = None self._format = 'rgb' self._texture = None self.capture_device = None kwargs.setdefault('size', self._resolution) - super(CameraBase, self).__init__(**kwargs) + super(CameraBase, self).__init__() + + self.register_event_type('on_load') + self.register_event_type('on_frame') self.init_camera() @@ -58,14 +70,16 @@ class CameraBase(object): lambda self, x: self._set_resolution(x), doc='Resolution of camera capture (width, height)') - def _set_video_src(self, src): - self._video_src = src + def _set_index(self, x): + if x == self._index: + return + self._index = x self.init_camera() - def _get_video_src(self): - return self._video_src - video_src = property(lambda self: self._get_video_src(), - lambda self, x: self._set_video_src(x), - doc='Source of the camera') + def _get_index(self): + return self._x + index = property(lambda self: self._get_index(), + lambda self, x: self._set_index(x), + doc='Source index of the camera') def _get_texture(self): return self._texture @@ -95,6 +109,13 @@ class CameraBase(object): return self._texture.blit_buffer(self._buffer, fmt=self._format) self._buffer = None + self.dispatch('on_frame') + + def on_frame(self): + pass + + def on_load(self): + pass # Load the appropriate provider Camera = core_select_lib('camera', ( diff --git a/kivy/core/camera/camera_gstreamer.py b/kivy/core/camera/camera_gstreamer.py index 2580f3637..35e5223b8 100644 --- a/kivy/core/camera/camera_gstreamer.py +++ b/kivy/core/camera/camera_gstreamer.py @@ -4,7 +4,8 @@ GStreamer Camera: Implement CameraBase with GStreamer __all__ = ('CameraGStreamer', ) -import kivy + +from kivy.graphics.texture import Texture from . import CameraBase try: @@ -33,11 +34,11 @@ class CameraGStreamer(CameraBase): ''' def __init__(self, **kwargs): - kwargs.setdefault('video_src', 'v4l2src') self._pipeline = None self._camerasink = None self._decodebin = None self._texturesize = None + self._video_src = kwargs.get('video_src', 'v4l2src') super(CameraGStreamer, self).__init__(**kwargs) def init_camera(self): @@ -46,8 +47,16 @@ class CameraGStreamer(CameraBase): if self._pipeline: self._pipeline = None + video_src = self._video_src + if video_src == 'v4l2src': + video_src += ' device=/dev/video%d' % self._index + elif video_src == 'dc1394src': + video_src += ' camera-number=%d' % self._index + + print video_src + GL_CAPS = 'video/x-raw-rgb,red_mask=(int)0xff0000,green_mask=(int)0x00ff00,blue_mask=(int)0x0000ff' - self._pipeline = gst.parse_launch('%s ! decodebin name=decoder ! ffmpegcolorspace ! appsink name=camerasink emit-signals=True caps=%s' % (self.video_src, GL_CAPS) ) + self._pipeline = gst.parse_launch('%s ! decodebin name=decoder ! ffmpegcolorspace ! appsink name=camerasink emit-signals=True caps=%s' % (video_src, GL_CAPS) ) self._camerasink = self._pipeline.get_by_name('camerasink') self._camerasink.connect('new-buffer', self._gst_new_buffer) self._decodebin = self._pipeline.get_by_name('decoder') @@ -81,6 +90,7 @@ class CameraGStreamer(CameraBase): return self._copy_to_gpu() if self._texture is None and self._texturesize is not None: - self._texture = kivy.Texture.create( + self._texture = Texture.create( size=self._texturesize, fmt='rgb') self._texture.flip_vertical() + self.dispatch('on_load') diff --git a/kivy/core/camera/camera_opencv.py b/kivy/core/camera/camera_opencv.py index 1ecfdb4cf..a4bf66452 100644 --- a/kivy/core/camera/camera_opencv.py +++ b/kivy/core/camera/camera_opencv.py @@ -20,23 +20,15 @@ except: class CameraOpenCV(CameraBase): '''Implementation of CameraBase using OpenCV - - :Parameters: - `video_src` : int, default is 0 - Index of OpenCV camera to use (0 mean default camera) ''' def __init__(self, **kwargs): - # override the default source of video - kwargs.setdefault('video_src', 0) - self._device = None - super(CameraOpenCV, self).__init__(**kwargs) def init_camera(self): # create the device - self._device = hg.cvCreateCameraCapture(self.video_src) + self._device = hg.cvCreateCameraCapture(self._index) try: # try first to set resolution @@ -68,6 +60,7 @@ class CameraOpenCV(CameraBase): # create texture ! self._texture = Texture.create(*self._resolution) self._texture.flip_vertical() + self.dispatch('on_load') if not self.stopped: self.start() diff --git a/kivy/core/camera/camera_videocapture.py b/kivy/core/camera/camera_videocapture.py index 5a3057920..30645dff7 100644 --- a/kivy/core/camera/camera_videocapture.py +++ b/kivy/core/camera/camera_videocapture.py @@ -18,22 +18,16 @@ except: class CameraVideoCapture(CameraBase): '''Implementation of CameraBase using VideoCapture - - :Parameters: - `video_src` : int, default is 0 - Index of VideoCapture camera to use (0 mean default camera) ''' def __init__(self, **kwargs): - # override the default source of video - kwargs.setdefault('video_src', 0) self._device = None super(CameraVideoCapture, self).__init__(**kwargs) self._format = 'rgb' def init_camera(self): # create the device - self._device = Device(devnum=self.video_src, showVideoWindow=0) + self._device = Device(devnum=self._index, showVideoWindow=0) # set resolution try: self._device.setResolution(self.resolution[0], self.resolution[1]) @@ -48,6 +42,7 @@ class CameraVideoCapture(CameraBase): # and create texture self._texture = kivy.Texture.create( size=self.size, fmt='bgr') + self.dispatch('on_load') # update buffer self._buffer = data