]> err.no Git - linux-2.6/commitdiff
V4L/DVB (6095): ivtv: fix VIDIOC_G_ENC_INDEX flag handling
authorHans Verkuil <hverkuil@xs4all.nl>
Thu, 23 Aug 2007 20:48:41 +0000 (17:48 -0300)
committerMauro Carvalho Chehab <mchehab@infradead.org>
Fri, 14 Sep 2007 16:13:40 +0000 (13:13 -0300)
Due to a documentation bug (the type mask is 3 bits long, not 2) the wrong
frame types were filled in: the B and P frame types were swapped.

This bug also hid a second bug: when a capture is stopped a last entry is
written into the pgm index buffer with internal type 0, denoting the end
of the program. This entry wasn't ignored, instead it was accidentally
returned to the caller as a P frame.

Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Documentation/video4linux/cx2341x/fw-encoder-api.txt
drivers/media/video/ivtv/ivtv-fileops.c
drivers/media/video/ivtv/ivtv-ioctl.c

index 5dd3109a8b3fed135b64cef2b5f56249d1ef31ea..5a27af2ee1c66ee74d2032e998168ee209e19ae2 100644 (file)
@@ -407,8 +407,10 @@ Description
                u32 length;             // Length of this frame
                u32 offset_low;         // Offset in the file of the
                u32 offset_high;        // start of this frame
-               u32 mask1;              // Bits 0-1 are the type mask:
+               u32 mask1;              // Bits 0-2 are the type mask:
                                        // 1=I, 2=P, 4=B
+                                       // 0=End of Program Index, other fields
+                                       //   are invalid.
                u32 pts;                // The PTS of the frame
                u32 mask2;              // Bit 0 is bit 32 of the pts.
        };
index 5dd519caf81d5dcbe52f788d65c4e337c719ac08..0285c4a830eb61938d044adc965bf0bef4c49784 100644 (file)
@@ -190,7 +190,9 @@ static void ivtv_update_pgm_info(struct ivtv *itv)
                int idx = (itv->pgm_info_write_idx + i) % itv->pgm_info_num;
                struct v4l2_enc_idx_entry *e = itv->pgm_info + idx;
                u32 addr = itv->pgm_info_offset + 4 + idx * 24;
-               const int mapping[] = { V4L2_ENC_IDX_FRAME_P, V4L2_ENC_IDX_FRAME_I, V4L2_ENC_IDX_FRAME_B, 0 };
+               const int mapping[8] = { -1, V4L2_ENC_IDX_FRAME_I, V4L2_ENC_IDX_FRAME_P, -1,
+                       V4L2_ENC_IDX_FRAME_B, -1, -1, -1 };
+                                       // 1=I, 2=P, 4=B
 
                e->offset = read_enc(addr + 4) + ((u64)read_enc(addr + 8) << 32);
                if (e->offset > itv->mpg_data_received) {
@@ -199,7 +201,7 @@ static void ivtv_update_pgm_info(struct ivtv *itv)
                e->offset += itv->vbi_data_inserted;
                e->length = read_enc(addr);
                e->pts = read_enc(addr + 16) + ((u64)(read_enc(addr + 20) & 1) << 32);
-               e->flags = mapping[read_enc(addr + 12) & 3];
+               e->flags = mapping[read_enc(addr + 12) & 7];
                i++;
        }
        itv->pgm_info_write_idx = (itv->pgm_info_write_idx + i) % itv->pgm_info_num;
index 5977a79619c210e5dcb39a310300e822baf7a618..dfe0aedc60fd0ba1a8862d966e9674e273ce4b6b 100644 (file)
@@ -1099,14 +1099,21 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
 
        case VIDIOC_G_ENC_INDEX: {
                struct v4l2_enc_idx *idx = arg;
+               struct v4l2_enc_idx_entry *e = idx->entry;
+               int entries;
                int i;
 
-               idx->entries = (itv->pgm_info_write_idx + IVTV_MAX_PGM_INDEX - itv->pgm_info_read_idx) %
+               entries = (itv->pgm_info_write_idx + IVTV_MAX_PGM_INDEX - itv->pgm_info_read_idx) %
                                        IVTV_MAX_PGM_INDEX;
-               if (idx->entries > V4L2_ENC_IDX_ENTRIES)
-                       idx->entries = V4L2_ENC_IDX_ENTRIES;
-               for (i = 0; i < idx->entries; i++) {
-                       idx->entry[i] = itv->pgm_info[(itv->pgm_info_read_idx + i) % IVTV_MAX_PGM_INDEX];
+               if (entries > V4L2_ENC_IDX_ENTRIES)
+                       entries = V4L2_ENC_IDX_ENTRIES;
+               idx->entries = 0;
+               for (i = 0; i < entries; i++) {
+                       *e = itv->pgm_info[(itv->pgm_info_read_idx + i) % IVTV_MAX_PGM_INDEX];
+                       if ((e->flags & V4L2_ENC_IDX_FRAME_MASK) <= V4L2_ENC_IDX_FRAME_B) {
+                               idx->entries++;
+                               e++;
+                       }
                }
                itv->pgm_info_read_idx = (itv->pgm_info_read_idx + idx->entries) % IVTV_MAX_PGM_INDEX;
                break;