On Monday 07 May 2001 01:17, Dmitri wrote:
> Quoting Stefan Nilsen <[EMAIL PROTECTED]>:
> > The camera separates images using one or more 0 length frames. It doesn't
> > have any "magic" number that indicates the start of a new image. Can
> > usbvideo handle that case?
> usbvideo, as it is now, has only one ring queue for the collected data,
> and it has no attributes attached to any place of that queue (which
> could tell that a new transfer starts here or something.) To correctly
> implement what you need requires a message queue instead of ring queue.
>
> However this is irrelevant to your problem because (for now) you just
> need to insert your own "magic" marker (which is unlikely to appear
> on its own in the valid data stream). Then the decoding routine will
> be looking for that marker (as ibmcam does), and you know where each
> transfer (or frame) starts. Make change in usbvideo_IsocIrq() to do that.

It looked more logical (easier) to put a change in 
usbvideo_CompressIsochronous to add a marker in the ringqueue. I have a patch 
here that adds support for drivers to add a marker sequence. I hope it doesnt 
make the other drivers stop working. I now have CVS access so if it looks ok 
to you i can submit the changes.

Btw: I also found the reason that my processing callbacks where not called. 
Stupid me added the FLAGS_NO_DECODING when initializing the camera... :-(

/Stefan

Index: usbvideo.c
===================================================================
RCS file: /cvsroot/linux-usb/usbvideo/usbvideo.c,v
retrieving revision 1.12
diff -u -r1.12 usbvideo.c
--- usbvideo.c  2001/02/13 12:21:36     1.12
+++ usbvideo.c  2001/05/08 00:16:32
@@ -933,6 +933,21 @@
                            proc, i, up, up->user_data);
                        kfree(up->user_data);
                }
+               if (up->empty_marker != NULL) {
+                       if (up->empty_marker_size <= 0)
+                               ++warning;
+               } else {
+                       if (up->empty_marker_size > 0)
+                               ++warning;
+               }
+               if (warning) {
+                       err("%s: Warning: empty_marker=$%p empty_marker_size=%d.",
+                           proc, up->empty_marker, up->empty_marker_size);
+               } else {
+                       dbg("%s: Freeing %d. $%p->empty_marker=$%p",
+                           proc, i, up, up->empty_marker);
+                       kfree(up->empty_marker);
+               }
        }
        /* Whole array was allocated in one chunk */
        dbg("%s: Freed %d uvd_t structures",
@@ -1813,6 +1828,13 @@
                /* Detect and ignore empty packets */
                if (n <= 0) {
                        uvd->stats.iso_skip_count++;
+                       if (uvd->empty_marker_size > 0) {
+                               assert(uvd->empty_marker);
+                               if (uvd->debug >= 1) {
+                                       info("Inserting empty marker: size = %d", 
+uvd->empty_marker_size);
+                               }
+                               RingQueue_Enqueue(&uvd->dp, uvd->empty_marker, 
+uvd->empty_marker_size);
+                       }
                        continue;
                }
                totlen += n;    /* Little local accounting */
Index: usbvideo.h
===================================================================
RCS file: /cvsroot/linux-usb/usbvideo/usbvideo.h,v
retrieving revision 1.10
diff -u -r1.10 usbvideo.h
--- usbvideo.h  2001/04/12 07:19:46     1.10
+++ usbvideo.h  2001/05/08 00:16:32
@@ -212,6 +212,12 @@
        struct s_usbvideo_t *handle;    /* Points back to the usbvideo_t */
        void *user_data;                /* Camera-dependent data */
        int user_size;                  /* Size of that camera-dependent data */
+       void *empty_marker; /* Optional empty marker for empty frames in an 
iso-stream
+                                                                                      
+          The empty marker is inserted in ringbuffer when a 0 length
+                                                                                      
+          frame is recieved in the iso stream and the 
+                                                                                      
+          empty_marker_size > 0
+                                                                                      
+    Needed for webcamgo driver */
+  int empty_marker_size; /* Size of the empty marker */
        int debug;                      /* Debug level for usbvideo */
        unsigned char iface;            /* Video interface number */
        unsigned char video_endp;
Index: webcamgo.c
===================================================================
RCS file: /cvsroot/linux-usb/usbvideo/webcamgo.c,v
retrieving revision 1.1
diff -u -r1.1 webcamgo.c
--- webcamgo.c  2001/05/07 20:13:16     1.1
+++ webcamgo.c  2001/05/08 00:16:33
@@ -31,7 +31,9 @@
 
 #define MAX_CAMERAS            4       /* How many devices we allow to connect */
 
-// #define JPEG_COMPRESSED     1
+#define EMPTY_MARKER "[Frame break]"
+
+#define JPEG_COMPRESSED        1
 #define PLANAR 1
 // #define YUV420 1
 
@@ -50,7 +52,7 @@
 
 static int debug = 0;
 
-static int flags = 0; /* FLAGS_NO_DECODING; */ /* FLAGS_DISPLAY_HINTS | 
FLAGS_OVERLAY_STATS; */
+static int flags = /* 0; */ /* FLAGS_NO_DECODING; */ FLAGS_RETRY_VIDIOCSYNC; 
/* FLAGS_DISPLAY_HINTS | FLAGS_OVERLAY_STATS; */
 
 static const int min_canvasWidth  = 8;
 static const int min_canvasHeight = 4;
@@ -134,10 +136,9 @@
        assert(uvd != NULL);
        assert(frame != NULL);
 
-#if 1
-       info("in webcamgo_ProcessIsocData");
-       err("in webcamgo_ProcessIsocData");
-#endif
+       if (uvd->debug >= 1) {
+               info("in webcamgo_ProcessIsocData");
+       }
 
        /* Try to move data from queue into frame buffer */
        n = RingQueue_GetLength(&uvd->dp);
@@ -416,7 +417,6 @@
        if (!WEBCAMGO_T(uvd)->initialized) {
 
                webcamgo = WEBCAMGO_T(uvd);
-               uvd->flags = uvd->flags | FLAGS_NO_DECODING;            
 
                webcamgo_alternateSetting(uvd, 0x00); /* Maybe don't need this */
                webcamgo_veio(uvd, 0x01, 0x0000, 0x00, 0); /* Read the control reg. 
Dont 
know why... 
@@ -1221,6 +1221,8 @@
 
 static void webcamgo_configure_video(uvd_t *uvd)
 {
+       int marker_size;
+
        if (uvd == NULL)
                return;
 
@@ -1257,6 +1259,12 @@
        uvd->vchan.channel = 0;
        uvd->vchan.type = VIDEO_TYPE_CAMERA;
        strcpy(uvd->vchan.name, "Camera");
+
+       marker_size = strlen(EMPTY_MARKER);
+       uvd->empty_marker = kmalloc(marker_size, GFP_KERNEL);
+       assert(uvd->empty_marker);
+       memcpy(uvd->empty_marker, EMPTY_MARKER, marker_size);
+       uvd->empty_marker_size = marker_size;
 }
 
 /*
@@ -1399,6 +1407,7 @@
        int len;
        
        /* Stay under PAGE_SIZE or else */
+       /* TODO: Show the latest reading of button status in CR02 here */
        out += sprintf(out, "Chapter MMCMLXXX: Hello World! the hard way...\n");
        len = out - page;
        len -= off;
@@ -1412,6 +1421,127 @@
        return len;     
 }
 
+int webcamgo_GetFrame(uvd_t *uvd, int frameNum)
+{
+       static const char proc[] = "usbvideo_GetFrame";
+       usbvideo_frame_t *frame = &uvd->frame[frameNum];
+
+       if (uvd->debug >= 2)
+               info("%s($%p,%d.)", proc, uvd, frameNum);
+       
+       switch (frame->frameState) {
+       case FrameState_Unused:
+               if (uvd->debug >= 2)
+                       info("%s: FrameState_Unused", proc);
+               return -EINVAL;
+       case FrameState_Ready:
+       case FrameState_Grabbing:
+       case FrameState_Error:
+               {
+                       int ntries, signalPending;
+               redo:
+                       info("label redo:");
+                       if (!CAMERA_IS_OPERATIONAL(uvd)) {
+                               if (uvd->debug >= 2)
+                                       info("%s: Camera is not operational (1)", 
+proc);
+                               return -EIO;
+                       }
+                       ntries = 0; 
+                       do {
+                               RingQueue_InterruptibleSleepOn(&uvd->dp);
+                               signalPending = signal_pending(current);
+                               if (!CAMERA_IS_OPERATIONAL(uvd)) {
+                                       if (uvd->debug >= 2)
+                                               info("%s: Camera is not operational 
+(2)", proc);
+                                       return -EIO;
+                               }
+                               assert(uvd->fbuf != NULL);
+                               if (signalPending) {
+                                       if (uvd->debug >= 2)
+                                               info("%s: Signal=$%08x", proc, 
+signalPending);
+                                       if (uvd->flags & FLAGS_RETRY_VIDIOCSYNC) {
+                                               usbvideo_TestPattern(uvd, 1, 0);
+                                               uvd->curframe = -1;
+                                               uvd->stats.frame_num++;
+                                               if (uvd->debug >= 2)
+                                                       info("%s: Forced test pattern 
+screen", proc);
+                                               return 0;
+                                       } else {
+                                               /* Standard answer: Interrupted! */
+                                               if (uvd->debug >= 2)
+                                                       info("%s: Interrupted!", proc);
+                                               return -EINTR;
+                                       }
+                               } else {
+                                       /* No signals - we just got new data in dp 
+queue */
+                                       if (uvd->flags & FLAGS_NO_DECODING)
+                                               usbvideo_CollectRawData(uvd, frame);
+                                       else if (VALID_CALLBACK(uvd, processData)) {
+                                               GET_CALLBACK(uvd, processData)(uvd, 
+frame);
+                                       } else 
+                                               err("%s: processData not set", proc);
+                               }
+                       } while (frame->frameState == FrameState_Grabbing);
+                       if (uvd->debug >= 2) {
+                               info("%s: Grabbing done; state=%d. (%lu. bytes)",
+                                                proc, frame->frameState, 
+frame->seqRead_Length);
+                       }
+                       if (frame->frameState == FrameState_Error) {
+                               int ret = usbvideo_NewFrame(uvd, frameNum);
+                               if (ret < 0) {
+                                       err("%s: usbvideo_NewFrame() failed (%d.)", 
+proc, ret);
+                                       return ret;
+                               }
+                               goto redo;
+                       }
+                       /* Note that we fall through to meet our destiny below */
+               }
+       case FrameState_Done:
+               /*
+                * Do all necessary postprocessing of data prepared in
+                * "interrupt" code and the collecting code above. The
+                * frame gets marked as FrameState_Done by queue parsing code.
+                * This status means that we collected enough data and
+                * most likely processed it as we went through. However
+                * the data may need postprocessing, such as deinterlacing
+                * or picture adjustments implemented in software (horror!)
+                *
+                * As soon as the frame becomes "final" it gets promoted to
+                * FrameState_Done_Hold status where it will remain until the
+                * caller consumed all the video data from the frame. Then
+                * the empty shell of ex-frame is thrown out for dogs to eat.
+                * But we, worried about pets, will recycle the frame!
+                */
+               uvd->stats.frame_num++;
+               if ((uvd->flags & FLAGS_NO_DECODING) == 0) {
+                       if (VALID_CALLBACK(uvd, postProcess))
+                               GET_CALLBACK(uvd, postProcess)(uvd, frame);
+                       if (frame->flags & USBVIDEO_FRAME_FLAG_SOFTWARE_CONTRAST)
+                               usbvideo_SoftwareContrastAdjustment(uvd, frame);
+               }
+               frame->frameState = FrameState_Done_Hold;
+               if (uvd->debug >= 2)
+                       info("%s: Entered FrameState_Done_Hold state.", proc);
+               return 0;
+
+       case FrameState_Done_Hold:
+               /*
+                * We stay in this state indefinitely until someone external,
+                * like ioctl() or read() call finishes digesting the frame
+                * data. Then it will mark the frame as FrameState_Unused and
+                * it will be released back into the wild to roam freely.
+                */
+               if (uvd->debug >= 2)
+                       info("%s: FrameState_Done_Hold state.", proc);
+               return 0;
+       }
+
+       /* Catch-all for other cases. We shall not be here. */
+       err("%s: Invalid state %d.", proc, frame->frameState);
+       frame->frameState = FrameState_Unused;
+       return 0;
+}
+
 /*
  * webcamgo_init()
  *
@@ -1430,6 +1560,7 @@
        cbTbl.adjustPicture = webcamgo_adjust_picture;
        cbTbl.getFPS = webcamgo_calculate_fps;
        cbTbl.procfs_read = webcamgo_procfs_read_proc;
+       cbTbl.getFrame = webcamgo_GetFrame;
        return usbvideo_register(
                &cams,
                MAX_CAMERAS,

_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
http://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to