OSDN Git Service

staging/easycap: Implement interlaced modes and reduced framerates
authorMike Thomas <rmthomas@sciolus.org>
Sun, 7 Nov 2010 20:02:15 +0000 (20:02 +0000)
committerGreg Kroah-Hartman <gregkh@suse.de>
Wed, 10 Nov 2010 00:31:15 +0000 (16:31 -0800)
Interlaced modes are requested by tvtime.  Reduced framerates are
preferred by some userspace programs, e.g. astronomy applications.

Signed-off-by: Mike Thomas <rmthomas@sciolus.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/staging/easycap/easycap.h
drivers/staging/easycap/easycap_ioctl.c
drivers/staging/easycap/easycap_main.c
drivers/staging/easycap/easycap_settings.c

index 20e51dd..7c4cf7a 100644 (file)
 #define  NTSC_M_JP      5
 #define  PAL_60         7
 #define  PAL_M          9
-#define  STANDARD_MANY 10
+#define  PAL_BGHIN_SLOW    10
+#define  PAL_Nc_SLOW       12
+#define  SECAM_SLOW        14
+#define  NTSC_N_SLOW       16
+#define  NTSC_N_443_SLOW   18
+#define  NTSC_M_SLOW       11
+#define  NTSC_443_SLOW     13
+#define  NTSC_M_JP_SLOW    15
+#define  PAL_60_SLOW       17
+#define  PAL_M_SLOW        19
+#define  STANDARD_MANY 20
 /*---------------------------------------------------------------------------*/
 /*
  *  ENUMS
@@ -228,7 +238,6 @@ PIXELFORMAT_MANY
 enum {
 FIELD_NONE,
 FIELD_INTERLACED,
-FIELD_ALTERNATE,
 INTERLACE_MANY
 };
 #define SETTINGS_MANY  (STANDARD_MANY * \
@@ -333,6 +342,8 @@ bool ntsc;
 int fps;
 int usec;
 int tolerate;
+int skip;
+int skipped;
 int merit[180];
 
 struct timeval timeval0;
@@ -399,7 +410,6 @@ int frame_lock;             /* Flag set to 1 by DQBUF and cleared by QBUF        */
  */
 /*---------------------------------------------------------------------------*/
 __u32                   pixelformat;
-__u32                   field;
 int                     width;
 int                     height;
 int                     bytesperpixel;
index 0ed37c2..3fe1385 100644 (file)
@@ -40,6 +40,7 @@
  *          peasycap->fps
  *          peasycap->usec
  *          peasycap->tolerate
+ *          peasycap->skip
  */
 /*---------------------------------------------------------------------------*/
 int adjust_standard(struct easycap *peasycap, v4l2_std_id std_id)
@@ -60,11 +61,19 @@ if ((struct usb_device *)NULL == peasycap->pusb_device) {
 }
 peasycap_standard = &easycap_standard[0];
 while (0xFFFF != peasycap_standard->mask) {
-       if (std_id & peasycap_standard->v4l2_standard.id)
+       if (std_id == peasycap_standard->v4l2_standard.id)
                break;
        peasycap_standard++;
 }
 if (0xFFFF == peasycap_standard->mask) {
+       peasycap_standard = &easycap_standard[0];
+       while (0xFFFF != peasycap_standard->mask) {
+               if (std_id & peasycap_standard->v4l2_standard.id)
+                       break;
+               peasycap_standard++;
+       }
+}
+if (0xFFFF == peasycap_standard->mask) {
        SAM("ERROR: 0x%08X=std_id: standard not found\n", \
                                                        (unsigned int)std_id);
        return -EINVAL;
@@ -92,10 +101,12 @@ if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
 peasycap->fps = peasycap_standard->v4l2_standard.frameperiod.denominator / \
                peasycap_standard->v4l2_standard.frameperiod.numerator;
 switch (peasycap->fps) {
+case 6:
 case 30: {
        peasycap->ntsc = true;
        break;
 }
+case 5:
 case 25: {
        peasycap->ntsc = false;
        break;
@@ -106,9 +117,15 @@ default: {
 }
 }
 JOM(8, "%i frames-per-second\n", peasycap->fps);
-peasycap->usec = 1000000 / (2 * peasycap->fps);
-peasycap->tolerate = 1000 * (25 / peasycap->fps);
-
+if (0x8000 & peasycap_standard->mask) {
+       peasycap->skip = 5;
+       peasycap->usec = 1000000 / (2 * (5 * peasycap->fps));
+       peasycap->tolerate = 1000 * (25 / (5 * peasycap->fps));
+} else {
+       peasycap->skip = 0;
+       peasycap->usec = 1000000 / (2 * peasycap->fps);
+       peasycap->tolerate = 1000 * (25 / peasycap->fps);
+}
 if (peasycap->video_isoc_streaming) {
        resubmit = true;
        kill_video_urbs(peasycap);
@@ -311,7 +328,6 @@ return 0;
  *          peasycap->format_offset
  *          peasycap->inputset[peasycap->input].format_offset
  *          peasycap->pixelformat
- *          peasycap->field
  *          peasycap->height
  *          peasycap->width
  *          peasycap->bytesperpixel
@@ -333,7 +349,7 @@ struct easycap_format *peasycap_format, *peasycap_best_format;
 __u16 mask;
 struct usb_device *p;
 int miss, multiplier, best, k;
-char bf[5], *pc;
+char bf[5], fo[32], *pc;
 __u32 uc;
 bool resubmit;
 
@@ -351,13 +367,62 @@ if ((struct usb_device *)NULL == p) {
        return -EFAULT;
 }
 pc = &bf[0];
-uc = pixelformat;  memcpy((void *)pc, (void *)(&uc), 4);  bf[4] = 0;
-mask = easycap_standard[peasycap->standard_offset].mask;
+uc = pixelformat;
+memcpy((void *)pc, (void *)(&uc), 4);
+bf[4] = 0;
+mask = 0xFF & easycap_standard[peasycap->standard_offset].mask;
 SAM("sought:    %ix%i,%s(0x%08X),%i=field,0x%02X=std mask\n", \
                                width, height, pc, pixelformat, field, mask);
+switch (field) {
+case V4L2_FIELD_ANY: {
+       strcpy(&fo[0], "V4L2_FIELD_ANY ");
+       break;
+}
+case V4L2_FIELD_NONE: {
+       strcpy(&fo[0], "V4L2_FIELD_NONE");
+       break;
+}
+case V4L2_FIELD_TOP: {
+       strcpy(&fo[0], "V4L2_FIELD_TOP");
+       break;
+}
+case V4L2_FIELD_BOTTOM: {
+       strcpy(&fo[0], "V4L2_FIELD_BOTTOM");
+       break;
+}
+case V4L2_FIELD_INTERLACED: {
+       strcpy(&fo[0], "V4L2_FIELD_INTERLACED");
+       break;
+}
+case V4L2_FIELD_SEQ_TB: {
+       strcpy(&fo[0], "V4L2_FIELD_SEQ_TB");
+       break;
+}
+case V4L2_FIELD_SEQ_BT: {
+       strcpy(&fo[0], "V4L2_FIELD_SEQ_BT");
+       break;
+}
+case V4L2_FIELD_ALTERNATE: {
+       strcpy(&fo[0], "V4L2_FIELD_ALTERNATE");
+       break;
+}
+case V4L2_FIELD_INTERLACED_TB: {
+       strcpy(&fo[0], "V4L2_FIELD_INTERLACED_TB");
+       break;
+}
+case V4L2_FIELD_INTERLACED_BT: {
+       strcpy(&fo[0], "V4L2_FIELD_INTERLACED_BT");
+       break;
+}
+default: {
+       strcpy(&fo[0], "V4L2_FIELD_... UNKNOWN  ");
+       break;
+}
+}
+SAM("sought:    %s\n", &fo[0]);
 if (V4L2_FIELD_ANY == field) {
-       field = V4L2_FIELD_INTERLACED;
-       SAM("prefer:    V4L2_FIELD_INTERLACED=field, was V4L2_FIELD_ANY\n");
+       field = V4L2_FIELD_NONE;
+       SAM("prefer:    V4L2_FIELD_NONE=field, was V4L2_FIELD_ANY\n");
 }
 peasycap_best_format = (struct easycap_format *)NULL;
 peasycap_format = &easycap_format[0];
@@ -369,7 +434,7 @@ while (0 != peasycap_format->v4l2_format.fmt.pix.width) {
                peasycap_format->v4l2_format.fmt.pix.width,
                peasycap_format->v4l2_format.fmt.pix.height);
 
-       if (((peasycap_format->mask & 0x0F) == (mask & 0x0F)) && \
+       if (((peasycap_format->mask & 0x1F) == (mask & 0x1F)) && \
                (peasycap_format->v4l2_format.fmt.pix.field == field) && \
                (peasycap_format->v4l2_format.fmt.pix.pixelformat == \
                                                        pixelformat) && \
@@ -385,7 +450,7 @@ if (0 == peasycap_format->v4l2_format.fmt.pix.width) {
                                                        width, height, mask);
        peasycap_format = &easycap_format[0];  best = -1;
        while (0 != peasycap_format->v4l2_format.fmt.pix.width) {
-               if (((peasycap_format->mask & 0x0F) == (mask & 0x0F)) && \
+               if (((peasycap_format->mask & 0x1F) == (mask & 0x1F)) && \
                                 (peasycap_format->v4l2_format.fmt.pix\
                                                .field == field) && \
                                 (peasycap_format->v4l2_format.fmt.pix\
@@ -432,7 +497,6 @@ SAM("actioning: %ix%i %s\n", \
 peasycap->height        = peasycap_format->v4l2_format.fmt.pix.height;
 peasycap->width         = peasycap_format->v4l2_format.fmt.pix.width;
 peasycap->pixelformat   = peasycap_format->v4l2_format.fmt.pix.pixelformat;
-peasycap->field         = peasycap_format->v4l2_format.fmt.pix.field;
 peasycap->format_offset = (int)(peasycap_format - &easycap_format[0]);
 
 
@@ -451,11 +515,15 @@ if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
 
 
 
-peasycap->bytesperpixel = (0x00F0 & peasycap_format->mask) >> 4 ;
+peasycap->bytesperpixel = (0x00E0 & peasycap_format->mask) >> 5 ;
 if (0x0100 & peasycap_format->mask)
        peasycap->byteswaporder = true;
 else
        peasycap->byteswaporder = false;
+if (0x0200 & peasycap_format->mask)
+       peasycap->skip = 5;
+else
+       peasycap->skip = 0;
 if (0x0800 & peasycap_format->mask)
        peasycap->decimatepixel = true;
 else
@@ -472,24 +540,6 @@ peasycap->videofieldamount = multiplier * peasycap->width * \
                                        multiplier * peasycap->height;
 peasycap->frame_buffer_used = peasycap->bytesperpixel * \
                                        peasycap->width * peasycap->height;
-
-if (true == peasycap->offerfields) {
-       SAM("WARNING: %i=peasycap->field is untested: " \
-                               "please report problems\n", peasycap->field);
-
-
-/*
- *    FIXME ---- THIS IS UNTESTED, MAY BE (AND PROBABLY IS) INCORRECT:
- *
- *    peasycap->frame_buffer_used = peasycap->frame_buffer_used / 2;
- *
- *    SO DO NOT RISK IT YET.
- *
- */
-
-
-
-}
 if (peasycap->video_isoc_streaming) {
        resubmit = true;
        kill_video_urbs(peasycap);
@@ -1386,13 +1436,191 @@ case VIDIOC_ENUM_FMT: {
        break;
 }
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+/*
+ *  THE RESPONSE TO VIDIOC_ENUM_FRAMESIZES MUST BE CONDITIONED ON THE
+ *  THE CURRENT STANDARD, BECAUSE THAT IS WHAT gstreamer EXPECTS.  BEWARE.
+*/
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 case VIDIOC_ENUM_FRAMESIZES: {
-       JOM(8, "VIDIOC_ENUM_FRAMESIZES unsupported\n");
-       return -EINVAL;
+       __u32 index;
+       struct v4l2_frmsizeenum v4l2_frmsizeenum;
+
+       JOM(8, "VIDIOC_ENUM_FRAMESIZES\n");
+
+       if (0 != copy_from_user(&v4l2_frmsizeenum, (void __user *)arg, \
+                                       sizeof(struct v4l2_frmsizeenum)))
+               return -EFAULT;
+
+       index = v4l2_frmsizeenum.index;
+
+       v4l2_frmsizeenum.type = (__u32) V4L2_FRMSIZE_TYPE_DISCRETE;
+
+       if (true == peasycap->ntsc) {
+               switch (index) {
+               case 0: {
+                       v4l2_frmsizeenum.discrete.width = 640;
+                       v4l2_frmsizeenum.discrete.height = 480;
+                       JOM(8, "%i=index: %ix%i\n", index, \
+                                       (int)(v4l2_frmsizeenum.\
+                                                discrete.width), \
+                                       (int)(v4l2_frmsizeenum.\
+                                               discrete.height));
+                       break;
+               }
+               case 1: {
+                       v4l2_frmsizeenum.discrete.width = 320;
+                       v4l2_frmsizeenum.discrete.height = 240;
+                       JOM(8, "%i=index: %ix%i\n", index, \
+                                       (int)(v4l2_frmsizeenum.\
+                                               discrete.width), \
+                                       (int)(v4l2_frmsizeenum.\
+                                               discrete.height));
+                       break;
+               }
+               case 2: {
+                       v4l2_frmsizeenum.discrete.width = 720;
+                       v4l2_frmsizeenum.discrete.height = 480;
+                       JOM(8, "%i=index: %ix%i\n", index, \
+                                       (int)(v4l2_frmsizeenum.\
+                                               discrete.width), \
+                                       (int)(v4l2_frmsizeenum.\
+                                               discrete.height));
+                       break;
+               }
+               case 3: {
+                       v4l2_frmsizeenum.discrete.width = 360;
+                       v4l2_frmsizeenum.discrete.height = 240;
+                       JOM(8, "%i=index: %ix%i\n", index, \
+                                       (int)(v4l2_frmsizeenum.\
+                                               discrete.width), \
+                                       (int)(v4l2_frmsizeenum.\
+                                               discrete.height));
+                       break;
+               }
+               default: {
+                       JOM(8, "%i=index: exhausts framesizes\n", index);
+                       return -EINVAL;
+               }
+               }
+       } else {
+               switch (index) {
+               case 0: {
+                       v4l2_frmsizeenum.discrete.width = 640;
+                       v4l2_frmsizeenum.discrete.height = 480;
+                       JOM(8, "%i=index: %ix%i\n", index, \
+                                       (int)(v4l2_frmsizeenum.\
+                                               discrete.width), \
+                                       (int)(v4l2_frmsizeenum.\
+                                               discrete.height));
+                       break;
+               }
+               case 1: {
+                       v4l2_frmsizeenum.discrete.width = 320;
+                       v4l2_frmsizeenum.discrete.height = 240;
+                       JOM(8, "%i=index: %ix%i\n", index, \
+                                       (int)(v4l2_frmsizeenum.\
+                                               discrete.width), \
+                                       (int)(v4l2_frmsizeenum.\
+                                               discrete.height));
+                       break;
+               }
+               case 2: {
+                       v4l2_frmsizeenum.discrete.width = 704;
+                       v4l2_frmsizeenum.discrete.height = 576;
+                       JOM(8, "%i=index: %ix%i\n", index, \
+                                       (int)(v4l2_frmsizeenum.\
+                                               discrete.width), \
+                                       (int)(v4l2_frmsizeenum.\
+                                               discrete.height));
+                       break;
+               }
+               case 3: {
+                       v4l2_frmsizeenum.discrete.width = 720;
+                       v4l2_frmsizeenum.discrete.height = 576;
+                       JOM(8, "%i=index: %ix%i\n", index, \
+                                       (int)(v4l2_frmsizeenum.\
+                                               discrete.width), \
+                                       (int)(v4l2_frmsizeenum.\
+                                               discrete.height));
+                       break;
+               }
+               case 4: {
+                       v4l2_frmsizeenum.discrete.width = 360;
+                       v4l2_frmsizeenum.discrete.height = 288;
+                       JOM(8, "%i=index: %ix%i\n", index, \
+                                       (int)(v4l2_frmsizeenum.\
+                                               discrete.width), \
+                                       (int)(v4l2_frmsizeenum.\
+                                               discrete.height));
+                       break;
+               }
+               default: {
+                       JOM(8, "%i=index: exhausts framesizes\n", index);
+                       return -EINVAL;
+               }
+               }
+       }
+       if (0 != copy_to_user((void __user *)arg, &v4l2_frmsizeenum, \
+                                       sizeof(struct v4l2_frmsizeenum)))
+               return -EFAULT;
+       break;
 }
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+/*
+ *  THE RESPONSE TO VIDIOC_ENUM_FRAMEINTERVALS MUST BE CONDITIONED ON THE
+ *  THE CURRENT STANDARD, BECAUSE THAT IS WHAT gstreamer EXPECTS.  BEWARE.
+*/
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 case VIDIOC_ENUM_FRAMEINTERVALS: {
-       JOM(8, "VIDIOC_ENUM_FRAME_INTERVALS unsupported\n");
-       return -EINVAL;
+       __u32 index;
+       int denominator;
+       struct v4l2_frmivalenum v4l2_frmivalenum;
+
+       JOM(8, "VIDIOC_ENUM_FRAMEINTERVALS\n");
+
+       if (peasycap->fps)
+               denominator = peasycap->fps;
+       else {
+               if (true == peasycap->ntsc)
+                       denominator = 30;
+               else
+                       denominator = 25;
+       }
+
+       if (0 != copy_from_user(&v4l2_frmivalenum, (void __user *)arg, \
+                                       sizeof(struct v4l2_frmivalenum)))
+               return -EFAULT;
+
+       index = v4l2_frmivalenum.index;
+
+       v4l2_frmivalenum.type = (__u32) V4L2_FRMIVAL_TYPE_DISCRETE;
+
+       switch (index) {
+       case 0: {
+               v4l2_frmivalenum.discrete.numerator = 1;
+               v4l2_frmivalenum.discrete.denominator = denominator;
+               JOM(8, "%i=index: %i/%i\n", index, \
+                       (int)(v4l2_frmivalenum.discrete.numerator), \
+                       (int)(v4l2_frmivalenum.discrete.denominator));
+               break;
+       }
+       case 1: {
+               v4l2_frmivalenum.discrete.numerator = 1;
+               v4l2_frmivalenum.discrete.denominator = denominator/5;
+               JOM(8, "%i=index: %i/%i\n", index, \
+                       (int)(v4l2_frmivalenum.discrete.numerator), \
+                       (int)(v4l2_frmivalenum.discrete.denominator));
+               break;
+       }
+       default: {
+               JOM(8, "%i=index: exhausts frameintervals\n", index);
+               return -EINVAL;
+       }
+       }
+       if (0 != copy_to_user((void __user *)arg, &v4l2_frmivalenum, \
+                                       sizeof(struct v4l2_frmivalenum)))
+               return -EFAULT;
+       break;
 }
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 case VIDIOC_G_FMT: {
@@ -1603,6 +1831,10 @@ case VIDIOC_S_STD: {
                                                sizeof(v4l2_std_id)))
                return -EFAULT;
 
+       JOM(8, "User requests standard: 0x%08X%08X\n", \
+               (int)((std_id & (((v4l2_std_id)0xFFFFFFFF) << 32)) >> 32), \
+               (int)(std_id & ((v4l2_std_id)0xFFFFFFFF)));
+
        rc = adjust_standard(peasycap, std_id);
        if (0 > rc) {
                JOM(8, "WARNING: adjust_standard() returned %i\n", rc);
@@ -1675,7 +1907,7 @@ case VIDIOC_QUERYBUF: {
        v4l2_buffer.flags = V4L2_BUF_FLAG_MAPPED | \
                                                peasycap->done[index] | \
                                                peasycap->queued[index];
-       v4l2_buffer.field = peasycap->field;
+       v4l2_buffer.field = V4L2_FIELD_NONE;
        v4l2_buffer.memory = V4L2_MEMORY_MMAP;
        v4l2_buffer.m.offset = index * FRAME_BUFFER_SIZE;
        v4l2_buffer.length = FRAME_BUFFER_SIZE;
@@ -1762,6 +1994,24 @@ case VIDIOC_DQBUF:
        if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
                return -EINVAL;
 
+       if (true == peasycap->offerfields) {
+               /*-----------------------------------------------------------*/
+               /*
+                *  IN ITS 50 "fps" MODE tvtime SEEMS ALWAYS TO REQUEST
+                *  V4L2_FIELD_BOTTOM
+               */
+               /*-----------------------------------------------------------*/
+               if (V4L2_FIELD_TOP == v4l2_buffer.field)
+                       JOM(8, "user wants V4L2_FIELD_TOP\n");
+               else if (V4L2_FIELD_BOTTOM == v4l2_buffer.field)
+                       JOM(8, "user wants V4L2_FIELD_BOTTOM\n");
+               else if (V4L2_FIELD_ANY == v4l2_buffer.field)
+                       JOM(8, "user wants V4L2_FIELD_ANY\n");
+               else
+                       JOM(8, "user wants V4L2_FIELD_...UNKNOWN: %i\n", \
+                                                       v4l2_buffer.field);
+       }
+
        if (!peasycap->video_isoc_streaming) {
                JOM(16, "returning -EIO because video urbs not streaming\n");
                return -EIO;
@@ -1811,11 +2061,10 @@ case VIDIOC_DQBUF:
        v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        v4l2_buffer.bytesused = peasycap->frame_buffer_used;
        v4l2_buffer.flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_DONE;
-       v4l2_buffer.field =  peasycap->field;
-       if (V4L2_FIELD_ALTERNATE == v4l2_buffer.field)
-               v4l2_buffer.field = \
-                               0x000F & (peasycap->\
-                               frame_buffer[peasycap->frame_read][0].kount);
+       if (true == peasycap->offerfields)
+               v4l2_buffer.field = V4L2_FIELD_BOTTOM;
+       else
+               v4l2_buffer.field = V4L2_FIELD_NONE;
        do_gettimeofday(&timeval);
        timeval2 = timeval;
 
@@ -1876,10 +2125,6 @@ case VIDIOC_DQBUF:
                                                sizeof(struct v4l2_buffer)))
                return -EFAULT;
 
-       JOM(8, "..... user is offered frame buffer %i\n", \
-                                                       peasycap->frame_read);
-       peasycap->frame_lock = 1;
-
        input = peasycap->frame_buffer[peasycap->frame_read][0].input;
        if (0x08 & input) {
                JOM(8, "user is offered frame buffer %i, input %i\n", \
@@ -1956,7 +2201,6 @@ case VIDIOC_G_PARM: {
        v4l2_streamparm.parm.capture.capability = 0;
        v4l2_streamparm.parm.capture.capturemode = 0;
        v4l2_streamparm.parm.capture.timeperframe.numerator = 1;
-       v4l2_streamparm.parm.capture.timeperframe.denominator = 30;
 
        if (peasycap->fps) {
                v4l2_streamparm.parm.capture.timeperframe.\
index b522c6e..988feee 100644 (file)
@@ -471,7 +471,7 @@ if (NULL == peasycap->pusb_device) {
        SAM("ERROR: peasycap->pusb_device is NULL\n");
        return -ENODEV;
 }
-rc = usb_set_interface(peasycap->pusb_device, \
+rc = usb_set_interface(peasycap->pusb_device,
                        peasycap->video_interface, \
                        peasycap->video_altsetting_off);
 if (0 != rc) {
@@ -1103,7 +1103,7 @@ else
 int
 easycap_dqbuf(struct easycap *peasycap, int mode)
 {
-int miss, rc;
+int ifield, miss, rc;
 
 JOT(8, "\n");
 
@@ -1111,16 +1111,18 @@ if (NULL == peasycap) {
        SAY("ERROR:  peasycap is NULL\n");
        return -EFAULT;
 }
+ifield = 0;
+JOM(8, "%i=ifield\n", ifield);
 /*---------------------------------------------------------------------------*/
 /*
- *  WAIT FOR FIELD 0
+ *  WAIT FOR FIELD ifield  (0 => TOP, 1 => BOTTOM)
  */
 /*---------------------------------------------------------------------------*/
 miss = 0;
 while ((peasycap->field_read == peasycap->field_fill) || \
                                (0 != (0xFF00 & peasycap->field_buffer\
                                        [peasycap->field_read][0].kount)) || \
-                               (0 != (0x00FF & peasycap->field_buffer\
+                               (ifield != (0x00FF & peasycap->field_buffer\
                                        [peasycap->field_read][0].kount))) {
        if (mode)
                return -EAGAIN;
@@ -1134,7 +1136,7 @@ while ((peasycap->field_read == peasycap->field_fill) || \
                        ((peasycap->field_read != peasycap->field_fill) && \
                                (0 == (0xFF00 & peasycap->field_buffer\
                                        [peasycap->field_read][0].kount)) && \
-                               (0 == (0x00FF & peasycap->field_buffer\
+                               (ifield == (0x00FF & peasycap->field_buffer\
                                        [peasycap->field_read][0].kount))))))) {
                SAM("aborted by signal\n");
                return -EIO;
@@ -1176,33 +1178,20 @@ JOM(8, "first awakening on wq_video after %i waits\n", miss);
 rc = field2frame(peasycap);
 if (0 != rc)
        SAM("ERROR: field2frame() returned %i\n", rc);
-
-if (true == peasycap->offerfields) {
-       peasycap->frame_read = peasycap->frame_fill;
-       (peasycap->frame_fill)++;
-       if (peasycap->frame_buffer_many <= peasycap->frame_fill)
-               peasycap->frame_fill = 0;
-
-       if (0x01 & easycap_standard[peasycap->standard_offset].mask) {
-               peasycap->frame_buffer[peasycap->frame_read][0].kount = \
-                                                       V4L2_FIELD_BOTTOM;
-       } else {
-               peasycap->frame_buffer[peasycap->frame_read][0].kount = \
-                                                       V4L2_FIELD_TOP;
-       }
-JOM(8, "setting:    %i=peasycap->frame_read\n", peasycap->frame_read);
-JOM(8, "bumped to:  %i=peasycap->frame_fill\n", peasycap->frame_fill);
-}
 /*---------------------------------------------------------------------------*/
 /*
- *  WAIT FOR FIELD 1
+ *  WAIT FOR THE OTHER FIELD
  */
 /*---------------------------------------------------------------------------*/
+if (ifield)
+       ifield = 0;
+else
+       ifield = 1;
 miss = 0;
 while ((peasycap->field_read == peasycap->field_fill) || \
                                (0 != (0xFF00 & peasycap->field_buffer\
                                        [peasycap->field_read][0].kount)) || \
-                               (0 == (0x00FF & peasycap->field_buffer\
+                               (ifield != (0x00FF & peasycap->field_buffer\
                                        [peasycap->field_read][0].kount))) {
        if (mode)
                return -EAGAIN;
@@ -1215,8 +1204,9 @@ while ((peasycap->field_read == peasycap->field_fill) || \
                        ((peasycap->field_read != peasycap->field_fill) && \
                                (0 == (0xFF00 & peasycap->field_buffer\
                                        [peasycap->field_read][0].kount)) && \
-                               (0 != (0x00FF & peasycap->field_buffer\
-                                       [peasycap->field_read][0].kount))))))) {
+                               (ifield == (0x00FF & peasycap->field_buffer\
+                                       [peasycap->field_read][0].\
+                                                               kount))))))) {
                SAM("aborted by signal\n");
                return -EIO;
        }
@@ -1257,7 +1247,18 @@ JOM(8, "second awakening on wq_video after %i waits\n", miss);
 rc = field2frame(peasycap);
 if (0 != rc)
        SAM("ERROR: field2frame() returned %i\n", rc);
-
+/*---------------------------------------------------------------------------*/
+/*
+ *  WASTE THIS FRAME
+*/
+/*---------------------------------------------------------------------------*/
+if (0 != peasycap->skip) {
+       peasycap->skipped++;
+       if (peasycap->skip != peasycap->skipped)
+               return peasycap->skip - peasycap->skipped;
+       peasycap->skipped = 0;
+}
+/*---------------------------------------------------------------------------*/
 peasycap->frame_read = peasycap->frame_fill;
 peasycap->queued[peasycap->frame_read] = 0;
 peasycap->done[peasycap->frame_read]   = V4L2_BUF_FLAG_DONE;
@@ -1289,8 +1290,7 @@ return 0;
  *  odd==false IS TRANSFERRED TO THE FRAME BUFFER.
  *
  *  THE BOOLEAN PARAMETER offerfields IS true ONLY WHEN THE USER PROGRAM
- *  CHOOSES THE OPTION V4L2_FIELD_ALTERNATE.  NO USERSPACE PROGRAM TESTED
- *  TO DATE HAS DONE THIS.  BUGS ARE LIKELY.
+ *  CHOOSES THE OPTION V4L2_FIELD_INTERLACED.
  */
 /*---------------------------------------------------------------------------*/
 int
@@ -1315,8 +1315,10 @@ if ((struct easycap *)NULL == peasycap) {
 
 badinput = false;
 
-JOM(8, "=====  parity %i, field buffer %i --> frame buffer %i\n", \
+JOM(8, "=====  parity %i, input 0x%02X, field buffer %i --> " \
+                                               "frame buffer %i\n", \
                        peasycap->field_buffer[peasycap->field_read][0].kount,\
+                       peasycap->field_buffer[peasycap->field_read][0].input,\
                        peasycap->field_read, peasycap->frame_fill);
 JOM(8, "=====  %i=bytesperpixel\n", peasycap->bytesperpixel);
 if (true == peasycap->offerfields)
@@ -1374,7 +1376,7 @@ if (peasycap->field_buffer[kex][0].kount)
 else
        odd = false;
 
-if ((true == odd) && (false == offerfields) &&(false == decimatepixel)) {
+if ((true == odd) && (false == decimatepixel)) {
        JOM(8, "  initial skipping    %4i          bytes p.%4i\n", \
                                                        w3/multiplier, mad);
        pad += (w3 / multiplier);  rad -= (w3 / multiplier);
@@ -1494,7 +1496,7 @@ while (cz < wz) {
  *  UNLESS IT IS THE LAST LINE OF AN ODD FRAME
  */
 /*---------------------------------------------------------------------------*/
-               if (((false == odd) || (cz != wz))&&(false == offerfields)) {
+               if ((false == odd) || (cz != wz)) {
                        over = w3;
                        do {
                                if (!rad) {
@@ -3162,6 +3164,15 @@ if (purb->status) {
                                                        [peasycap->field_page];
                                        pfield_buffer->pto = \
                                                        pfield_buffer->pgo;
+                                       pfield_buffer->input = 0x08 | \
+                                               (0x07 & peasycap->input);
+                                       if ((peasycap->field_buffer[peasycap->\
+                                                       field_fill][0]).\
+                                                               input != \
+                                                       pfield_buffer->input)
+                                               (peasycap->field_buffer\
+                                                       [peasycap->field_fill]\
+                                                       [0]).kount |= 0x1000;
                                }
 
                                much = PAGE_SIZE - (int)(pfield_buffer->pto - \
@@ -3441,7 +3452,6 @@ if (0 == bInterfaceNumber) {
                        break;
                }
        }
-
        if (DONGLE_MANY <= dongle_this) {
                SAM("ERROR: too many dongles\n");
                return -ENOMEM;
@@ -3481,6 +3491,8 @@ if (0 == bInterfaceNumber) {
 
        peasycap->frame_buffer_many = FRAME_BUFFER_MANY;
 
+       peasycap->skip = 0;
+       peasycap->skipped = 0;
        peasycap->offerfields = 0;
 /*---------------------------------------------------------------------------*/
 /*
index 67f2e4f..df3f17d 100644 (file)
  *  THE LEAST SIGNIFICANT BIT OF easycap_standard.mask HAS MEANING:
  *                         0 => 25 fps
  *                         1 => 30 fps
+ *
+ *  THE MOST  SIGNIFICANT BIT OF easycap_standard.mask HAS MEANING:
+ *                         0 => full framerate
+ *                         1 => 20%  framerate
  */
 /*---------------------------------------------------------------------------*/
 const struct easycap_standard easycap_standard[] = {
 {
-.mask = 0x000F & PAL_BGHIN ,
+.mask = 0x00FF & PAL_BGHIN ,
 .v4l2_standard = {
        .index = PAL_BGHIN,
        .id = (V4L2_STD_PAL_B | V4L2_STD_PAL_G | V4L2_STD_PAL_H | \
@@ -50,7 +54,7 @@ const struct easycap_standard easycap_standard[] = {
 },
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 {
-.mask = 0x000F & NTSC_N_443 ,
+.mask = 0x00FF & NTSC_N_443 ,
 .v4l2_standard = {
        .index = NTSC_N_443,
        .id = V4L2_STD_UNKNOWN,
@@ -62,7 +66,7 @@ const struct easycap_standard easycap_standard[] = {
 },
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 {
-.mask = 0x000F & PAL_Nc ,
+.mask = 0x00FF & PAL_Nc ,
 .v4l2_standard = {
        .index = PAL_Nc,
        .id = V4L2_STD_PAL_Nc,
@@ -74,7 +78,7 @@ const struct easycap_standard easycap_standard[] = {
 },
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 {
-.mask = 0x000F & NTSC_N ,
+.mask = 0x00FF & NTSC_N ,
 .v4l2_standard = {
        .index = NTSC_N,
        .id = V4L2_STD_UNKNOWN,
@@ -86,7 +90,7 @@ const struct easycap_standard easycap_standard[] = {
 },
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 {
-.mask = 0x000F & SECAM ,
+.mask = 0x00FF & SECAM ,
 .v4l2_standard = {
        .index = SECAM,
        .id = V4L2_STD_SECAM,
@@ -98,7 +102,7 @@ const struct easycap_standard easycap_standard[] = {
 },
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 {
-.mask = 0x000F & NTSC_M ,
+.mask = 0x00FF & NTSC_M ,
 .v4l2_standard = {
        .index = NTSC_M,
        .id = V4L2_STD_NTSC_M,
@@ -110,7 +114,7 @@ const struct easycap_standard easycap_standard[] = {
 },
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 {
-.mask = 0x000F & NTSC_M_JP ,
+.mask = 0x00FF & NTSC_M_JP ,
 .v4l2_standard = {
        .index = NTSC_M_JP,
        .id = V4L2_STD_NTSC_M_JP,
@@ -122,7 +126,7 @@ const struct easycap_standard easycap_standard[] = {
 },
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 {
-.mask = 0x000F & PAL_60 ,
+.mask = 0x00FF & PAL_60 ,
 .v4l2_standard = {
        .index = PAL_60,
        .id = V4L2_STD_PAL_60,
@@ -134,7 +138,7 @@ const struct easycap_standard easycap_standard[] = {
 },
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 {
-.mask = 0x000F & NTSC_443 ,
+.mask = 0x00FF & NTSC_443 ,
 .v4l2_standard = {
        .index = NTSC_443,
        .id = V4L2_STD_NTSC_443,
@@ -146,7 +150,7 @@ const struct easycap_standard easycap_standard[] = {
 },
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 {
-.mask = 0x000F & PAL_M ,
+.mask = 0x00FF & PAL_M ,
 .v4l2_standard = {
        .index = PAL_M,
        .id = V4L2_STD_PAL_M,
@@ -158,6 +162,128 @@ const struct easycap_standard easycap_standard[] = {
 },
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 {
+.mask = 0x8000 | (0x00FF & PAL_BGHIN_SLOW),
+.v4l2_standard = {
+       .index = PAL_BGHIN_SLOW,
+       .id = (V4L2_STD_PAL_B | V4L2_STD_PAL_G | V4L2_STD_PAL_H | \
+                               V4L2_STD_PAL_I | V4L2_STD_PAL_N | \
+                                       (((v4l2_std_id)0x01) << 32)),
+       .name = "PAL_BGHIN_SLOW",
+       .frameperiod = {1, 5},
+       .framelines = 625,
+       .reserved = {0, 0, 0, 0}
+}
+},
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+{
+.mask = 0x8000 | (0x00FF & NTSC_N_443_SLOW),
+.v4l2_standard = {
+       .index = NTSC_N_443_SLOW,
+       .id = (V4L2_STD_UNKNOWN | (((v4l2_std_id)0x11) << 32)),
+       .name = "NTSC_N_443_SLOW",
+       .frameperiod = {1, 5},
+       .framelines = 480,
+       .reserved = {0, 0, 0, 0}
+}
+},
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+{
+.mask = 0x8000 | (0x00FF & PAL_Nc_SLOW),
+.v4l2_standard = {
+       .index = PAL_Nc_SLOW,
+       .id = (V4L2_STD_PAL_Nc | (((v4l2_std_id)0x01) << 32)),
+       .name = "PAL_Nc_SLOW",
+       .frameperiod = {1, 5},
+       .framelines = 625,
+       .reserved = {0, 0, 0, 0}
+}
+},
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+{
+.mask = 0x8000 | (0x00FF & NTSC_N_SLOW),
+.v4l2_standard = {
+       .index = NTSC_N_SLOW,
+       .id = (V4L2_STD_UNKNOWN | (((v4l2_std_id)0x21) << 32)),
+       .name = "NTSC_N_SLOW",
+       .frameperiod = {1, 5},
+       .framelines = 525,
+       .reserved = {0, 0, 0, 0}
+}
+},
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+{
+.mask = 0x8000 | (0x00FF & SECAM_SLOW),
+.v4l2_standard = {
+       .index = SECAM_SLOW,
+       .id = (V4L2_STD_SECAM | (((v4l2_std_id)0x01) << 32)),
+       .name = "SECAM_SLOW",
+       .frameperiod = {1, 5},
+       .framelines = 625,
+       .reserved = {0, 0, 0, 0}
+}
+},
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+{
+.mask = 0x8000 | (0x00FF & NTSC_M_SLOW),
+.v4l2_standard = {
+       .index = NTSC_M_SLOW,
+       .id = (V4L2_STD_NTSC_M | (((v4l2_std_id)0x01) << 32)),
+       .name = "NTSC_M_SLOW",
+       .frameperiod = {1, 6},
+       .framelines = 525,
+       .reserved = {0, 0, 0, 0}
+}
+},
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+{
+.mask = 0x8000 | (0x00FF & NTSC_M_JP_SLOW),
+.v4l2_standard = {
+       .index = NTSC_M_JP_SLOW,
+       .id = (V4L2_STD_NTSC_M_JP | (((v4l2_std_id)0x01) << 32)),
+       .name = "NTSC_M_JP_SLOW",
+       .frameperiod = {1, 6},
+       .framelines = 525,
+       .reserved = {0, 0, 0, 0}
+}
+},
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+{
+.mask = 0x8000 | (0x00FF & PAL_60_SLOW),
+.v4l2_standard = {
+       .index = PAL_60_SLOW,
+       .id = (V4L2_STD_PAL_60 | (((v4l2_std_id)0x01) << 32)),
+       .name = "PAL_60_SLOW",
+       .frameperiod = {1, 6},
+       .framelines = 525,
+       .reserved = {0, 0, 0, 0}
+}
+},
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+{
+.mask = 0x8000 | (0x00FF & NTSC_443_SLOW),
+.v4l2_standard = {
+       .index = NTSC_443_SLOW,
+       .id = (V4L2_STD_NTSC_443 | (((v4l2_std_id)0x01) << 32)),
+       .name = "NTSC_443_SLOW",
+       .frameperiod = {1, 6},
+       .framelines = 525,
+       .reserved = {0, 0, 0, 0}
+}
+},
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+{
+.mask = 0x8000 | (0x00FF & PAL_M_SLOW),
+.v4l2_standard = {
+       .index = PAL_M_SLOW,
+       .id = (V4L2_STD_PAL_M | (((v4l2_std_id)0x01) << 32)),
+       .name = "PAL_M_SLOW",
+       .frameperiod = {1, 6},
+       .framelines = 525,
+       .reserved = {0, 0, 0, 0}
+}
+},
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+{
 .mask = 0xFFFF
 }
 };
@@ -165,15 +291,16 @@ const struct easycap_standard easycap_standard[] = {
 /*
  *  THE 16-BIT easycap_format.mask HAS MEANING:
  *    (least significant) BIT  0:     0 => PAL, 25 FPS;   1 => NTSC, 30 FPS
- *                        BITS 1-3:   RESERVED FOR DIFFERENTIATING STANDARDS
- *                        BITS 4-7:   NUMBER OF BYTES PER PIXEL
+ *                        BITS 2-4:   RESERVED FOR DIFFERENTIATING STANDARDS
+ *                        BITS 5-7:   NUMBER OF BYTES PER PIXEL
  *                        BIT  8:     0 => NATIVE BYTE ORDER;  1 => SWAPPED
  *                        BITS 9-10:  RESERVED FOR OTHER BYTE PERMUTATIONS
- *                        BIT 11:     0 => UNDECIMATED;  1 => DECIMATED
- *                        BIT 12:     0 => OFFER FRAMES; 1 => OFFER FIELDS
- *     (most significant) BITS 13-15: RESERVED FOR OTHER FIELD ORDER OPTIONS
+ *                        BIT 11:     0 => UNDECIMATED;    1 => DECIMATED
+ *                        BIT 12:     0 => OFFER FRAMES;   1 => OFFER FIELDS
+ *                        BIT 13:     0 => FULL FRAMERATE; 1 => REDUCED
+ *     (most significant) BITS 14-15: RESERVED FOR OTHER FIELD/FRAME OPTIONS
  *  IT FOLLOWS THAT:
- *     bytesperpixel IS         ((0x00F0 & easycap_format.mask) >> 4)
+ *     bytesperpixel IS         ((0x00E0 & easycap_format.mask) >> 5)
  *     byteswaporder IS true IF (0 != (0x0100 & easycap_format.mask))
  *
  *     decimatepixel IS true IF (0 != (0x0800 & easycap_format.mask))
@@ -197,65 +324,135 @@ for (i = 0, n = 0; i < STANDARD_MANY; i++) {
        mask1 = 0x0000;
        switch (i) {
        case PAL_BGHIN: {
-               mask1 = PAL_BGHIN;
+               mask1 = 0x1F & PAL_BGHIN;
                strcpy(&name1[0], "PAL_BGHIN");
                colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
                break;
        }
        case SECAM: {
-               mask1 = SECAM;
+               mask1 = 0x1F & SECAM;
                strcpy(&name1[0], "SECAM");
                colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
                break;
        }
        case PAL_Nc: {
-               mask1 = PAL_Nc;
+               mask1 = 0x1F & PAL_Nc;
                strcpy(&name1[0], "PAL_Nc");
                colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
                break;
        }
        case PAL_60: {
-               mask1 = PAL_60;
+               mask1 = 0x1F & PAL_60;
                strcpy(&name1[0], "PAL_60");
                colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
                break;
        }
        case PAL_M: {
-               mask1 = PAL_M;
+               mask1 = 0x1F & PAL_M;
                strcpy(&name1[0], "PAL_M");
                colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
                break;
        }
        case NTSC_M: {
-               mask1 = NTSC_M;
+               mask1 = 0x1F & NTSC_M;
                strcpy(&name1[0], "NTSC_M");
                colorspace = V4L2_COLORSPACE_470_SYSTEM_M;
                break;
        }
        case NTSC_443: {
-               mask1 = NTSC_443;
+               mask1 = 0x1F & NTSC_443;
                strcpy(&name1[0], "NTSC_443");
                colorspace = V4L2_COLORSPACE_470_SYSTEM_M;
                break;
        }
        case NTSC_M_JP: {
-               mask1 = NTSC_M_JP;
+               mask1 = 0x1F & NTSC_M_JP;
                strcpy(&name1[0], "NTSC_M_JP");
                colorspace = V4L2_COLORSPACE_470_SYSTEM_M;
                break;
        }
        case NTSC_N: {
-               mask1 = NTSC_M;
+               mask1 = 0x1F & NTSC_M;
                strcpy(&name1[0], "NTSC_N");
                colorspace = V4L2_COLORSPACE_470_SYSTEM_M;
                break;
        }
        case NTSC_N_443: {
-               mask1 = NTSC_N_443;
+               mask1 = 0x1F & NTSC_N_443;
                strcpy(&name1[0], "NTSC_N_443");
                colorspace = V4L2_COLORSPACE_470_SYSTEM_M;
                break;
        }
+       case PAL_BGHIN_SLOW: {
+               mask1 = 0x001F & PAL_BGHIN_SLOW;
+               mask1 |= 0x0200;
+               strcpy(&name1[0], "PAL_BGHIN_SLOW");
+               colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
+               break;
+       }
+       case SECAM_SLOW: {
+               mask1 = 0x001F & SECAM_SLOW;
+               mask1 |= 0x0200;
+               strcpy(&name1[0], "SECAM_SLOW");
+               colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
+               break;
+       }
+       case PAL_Nc_SLOW: {
+               mask1 = 0x001F & PAL_Nc_SLOW;
+               mask1 |= 0x0200;
+               strcpy(&name1[0], "PAL_Nc_SLOW");
+               colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
+               break;
+       }
+       case PAL_60_SLOW: {
+               mask1 = 0x001F & PAL_60_SLOW;
+               mask1 |= 0x0200;
+               strcpy(&name1[0], "PAL_60_SLOW");
+               colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
+               break;
+       }
+       case PAL_M_SLOW: {
+               mask1 = 0x001F & PAL_M_SLOW;
+               mask1 |= 0x0200;
+               strcpy(&name1[0], "PAL_M_SLOW");
+               colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
+               break;
+       }
+       case NTSC_M_SLOW: {
+               mask1 = 0x001F & NTSC_M_SLOW;
+               mask1 |= 0x0200;
+               strcpy(&name1[0], "NTSC_M_SLOW");
+               colorspace = V4L2_COLORSPACE_470_SYSTEM_M;
+               break;
+       }
+       case NTSC_443_SLOW: {
+               mask1 = 0x001F & NTSC_443_SLOW;
+               mask1 |= 0x0200;
+               strcpy(&name1[0], "NTSC_443_SLOW");
+               colorspace = V4L2_COLORSPACE_470_SYSTEM_M;
+               break;
+       }
+       case NTSC_M_JP_SLOW: {
+               mask1 = 0x001F & NTSC_M_JP_SLOW;
+               mask1 |= 0x0200;
+               strcpy(&name1[0], "NTSC_M_JP_SLOW");
+               colorspace = V4L2_COLORSPACE_470_SYSTEM_M;
+               break;
+       }
+       case NTSC_N_SLOW: {
+               mask1 = 0x001F & NTSC_N_SLOW;
+               mask1 |= 0x0200;
+               strcpy(&name1[0], "NTSC_N_SLOW");
+               colorspace = V4L2_COLORSPACE_470_SYSTEM_M;
+               break;
+       }
+       case NTSC_N_443_SLOW: {
+               mask1 = 0x001F & NTSC_N_443_SLOW;
+               mask1 |= 0x0200;
+               strcpy(&name1[0], "NTSC_N_443_SLOW");
+               colorspace = V4L2_COLORSPACE_470_SYSTEM_M;
+               break;
+       }
        default:
                return -1;
        }
@@ -311,39 +508,39 @@ for (i = 0, n = 0; i < STANDARD_MANY; i++) {
                        case FMT_UYVY: {
                                strcpy(&name3[0], "_" STRINGIZE(FMT_UYVY));
                                pixelformat = V4L2_PIX_FMT_UYVY;
-                               mask3 |= (0x02 << 4);
+                               mask3 |= (0x02 << 5);
                                break;
                        }
                        case FMT_YUY2: {
                                strcpy(&name3[0], "_" STRINGIZE(FMT_YUY2));
                                pixelformat = V4L2_PIX_FMT_YUYV;
-                               mask3 |= (0x02 << 4);
+                               mask3 |= (0x02 << 5);
                                mask3 |= 0x0100;
                                break;
                        }
                        case FMT_RGB24: {
                                strcpy(&name3[0], "_" STRINGIZE(FMT_RGB24));
                                pixelformat = V4L2_PIX_FMT_RGB24;
-                               mask3 |= (0x03 << 4);
+                               mask3 |= (0x03 << 5);
                                break;
                        }
                        case FMT_RGB32: {
                                strcpy(&name3[0], "_" STRINGIZE(FMT_RGB32));
                                pixelformat = V4L2_PIX_FMT_RGB32;
-                               mask3 |= (0x04 << 4);
+                               mask3 |= (0x04 << 5);
                                break;
                        }
                        case FMT_BGR24: {
                                strcpy(&name3[0], "_" STRINGIZE(FMT_BGR24));
                                pixelformat = V4L2_PIX_FMT_BGR24;
-                               mask3 |= (0x03 << 4);
+                               mask3 |= (0x03 << 5);
                                mask3 |= 0x0100;
                                break;
                        }
                        case FMT_BGR32: {
                                strcpy(&name3[0], "_" STRINGIZE(FMT_BGR32));
                                pixelformat = V4L2_PIX_FMT_BGR32;
-                               mask3 |= (0x04 << 4);
+                               mask3 |= (0x04 << 5);
                                mask3 |= 0x0100;
                                break;
                        }
@@ -363,13 +560,8 @@ for (i = 0, n = 0; i < STANDARD_MANY; i++) {
                                }
                                case FIELD_INTERLACED: {
                                        strcpy(&name4[0], "-i");
-                                       field = V4L2_FIELD_INTERLACED;
-                                       break;
-                               }
-                               case FIELD_ALTERNATE: {
-                                       strcpy(&name4[0], "-a");
                                        mask4 |= 0x1000;
-                                       field = V4L2_FIELD_ALTERNATE;
+                                       field = V4L2_FIELD_INTERLACED;
                                        break;
                                }
                                default: