[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

Re: [pygame] Proposed Module: Camera



On Tuesday 03 June 2008 01:27:19 Nirav Patel wrote:
> The code I'm working on is at http://git.n0r.org/?p=pygame-nrp;a=summary
>
> As of the latest snapshot, it currently supports YUYV and RGB24
> (though that is untested) cameras.  I've tested it so far with vivi
> and the webcam in the OLPC XO.

Further to my last email, I've made progress. 

It turns out that rather than the V4L2 interface being misused (which
"protocol error" implies :), by any program I could find, that the problem
I was seeing:
   * Acer laptop built in Crystal Eye webcam
   * Every application, including your new pygame code having a protocol
      error with it.
   * But being able to made work if you can cause a program to crash in the
      right way at the right time, leaving the light on.

Is in fact a bug in the kernel module "uvcvideo.ko" . Your bindings actually
made it *a lot* easier to find where the problem was, since I could
determine where and when things where going wrong in initialisation,
allowing me to dive from python to your C code, and then into the
kernel module code with much greater speed and precision than when
I'd looked before :-)

In case other people are using Linux, on an Acer Laptop using the built in
crystal eye webcam, you can fix support as follows.

Using this version from svn:
~/linux-uvc> svn info
    Path: .
    URL: svn://svn.berlios.de/linux-uvc/linux-uvc/trunk
    Repository Root: svn://svn.berlios.de/linux-uvc
    Repository UUID: 790547d8-3c09-0410-a358-857946b093de
    Revision: 211
    Node Kind: directory
    Schedule: normal
    Last Changed Author: pinchartl
    Last Changed Rev: 211
    Last Changed Date: 2008-05-22 23:51:05 +0100 (Thu, 22 May 2008)

Apply the following patch:

~/linux-uvc> svn diff
Index: uvc_video.c
===================================================================
--- uvc_video.c (revision 211)
+++ uvc_video.c (working copy)
@@ -750,8 +750,13 @@
                if (i >= intf->num_altsetting)
                        return -EIO;

-               if ((ret = usb_set_interface(video->dev->udev, intfnum, i)) < 0)
-                       return ret;
+               if ((ret = usb_set_interface(video->dev->udev, intfnum, i)) < 0) {
+                       if (ret == -71) { // If we get this error, give it another go & retry
+                               if ((ret = usb_set_interface(video->dev->udev, intfnum, i)) < 0)
+                                       return ret;
+                       } else
+                               return ret;
+               }

                ret = uvc_init_video_isoc(video, ep);
        } else {

I realise that's really slightly nasty, and is probably wrong (just retrying),
but it does work. I'll be forwarding this to the linux-uvc people as well.
(it also fixes every other bit of software I have unsurprisingly)

Upshot? Your code now works /really/ nicely for me :-) I do also have a small
wishlist as a result :)
   * Non blocking access would be great. If the file handle is something I
      can pass to select.select to have it tell me when the camera is ready,
      even better. (This would also benefit twisted users probably)
   * I note that you pass back only RGB data. Whilst this is great, it'd be
      really useful if you could pass back YUV data seperately as well if
      requested. This would avoid a double conversion (yuv->rgb, rgb->yuv)
      if piping the output into a video codec.

      For YUV data, a nice format which would be really handy to get back
      would be the same as we use here:
         http://edit.kamaelia.org/Components/pydoc/Kamaelia.Codec.RawYUVFramer          

      I would say that though - the key thing of course for me is anything that
      gives us a known byte sequence would be great :-)

      Since (I think) not all cameras give you that though, I'm only suggesting
      providing that if it's available.

I'm not sure how to deal with python lists/etc in C so I could probably come
up with a patch for you though if necessary.

Beyond that, I've include a nice little example which I've since turned into
a Kamaelia component, but makes a nice little demo. (Acts as a mirror)
It works flawlessly :-)

Many thanks for writing this - it's fantastic :-)

I'll try and test with another couple of webcams if I can lay my hands on them :-)

Best Regards,


Michael.
 --

#!/usr/bin/python
#
# This import line is required to pull in pygame.camera support
#
# pygame support built using "python setup.py build", but not installed.
#

import sys ; sys.path.insert(0, "/home/michael./Incoming/pygame-nrp/build/lib.linux-i686-2.5")


import time
import pygame
import pygame.camera

pygame.init()

class VideoCapturePlayer(object):
    displaysize = (800, 600)
    capturesize = ( 640, 480 )
    mirror = True
    delay = 0
    fps = -1
    def __init__(self, **argd):
        self.__dict__.update(**argd)
        self.display = pygame.display.set_mode( self.displaysize )
        self.camera = X=pygame.camera.Camera("/dev/video0", self.capturesize)
        self.camera.start()
        if self.fps != -1:
            self.delay = 1.0/self.fps # fps overrides delay