|
@@ -57,7 +57,7 @@
|
|
|
#define USBTV_CHUNK_SIZE 256
|
|
|
#define USBTV_CHUNK 240
|
|
|
#define USBTV_CHUNKS (USBTV_WIDTH * USBTV_HEIGHT \
|
|
|
- / 2 / USBTV_CHUNK)
|
|
|
+ / 4 / USBTV_CHUNK)
|
|
|
|
|
|
/* Chunk header. */
|
|
|
#define USBTV_MAGIC_OK(chunk) ((be32_to_cpu(chunk[0]) & 0xff000000) \
|
|
@@ -202,6 +202,26 @@ static int usbtv_setup_capture(struct usbtv *usbtv)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+/* Copy data from chunk into a frame buffer, deinterlacing the data
|
|
|
+ * into every second line. Unfortunately, they don't align nicely into
|
|
|
+ * 720 pixel lines, as the chunk is 240 words long, which is 480 pixels.
|
|
|
+ * Therefore, we break down the chunk into two halves before copyting,
|
|
|
+ * so that we can interleave a line if needed. */
|
|
|
+static void usbtv_chunk_to_vbuf(u32 *frame, u32 *src, int chunk_no, int odd)
|
|
|
+{
|
|
|
+ int half;
|
|
|
+
|
|
|
+ for (half = 0; half < 2; half++) {
|
|
|
+ int part_no = chunk_no * 2 + half;
|
|
|
+ int line = part_no / 3;
|
|
|
+ int part_index = (line * 2 + !odd) * 3 + (part_no % 3);
|
|
|
+
|
|
|
+ u32 *dst = &frame[part_index * USBTV_CHUNK/2];
|
|
|
+ memcpy(dst, src, USBTV_CHUNK/2 * sizeof(*src));
|
|
|
+ src += USBTV_CHUNK/2;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
/* Called for each 256-byte image chunk.
|
|
|
* First word identifies the chunk, followed by 240 words of image
|
|
|
* data and padding. */
|
|
@@ -218,11 +238,6 @@ static void usbtv_image_chunk(struct usbtv *usbtv, u32 *chunk)
|
|
|
frame_id = USBTV_FRAME_ID(chunk);
|
|
|
odd = USBTV_ODD(chunk);
|
|
|
chunk_no = USBTV_CHUNK_NO(chunk);
|
|
|
-
|
|
|
- /* Deinterlace. TODO: Use interlaced frame format. */
|
|
|
- chunk_no = (chunk_no - chunk_no % 3) * 2 + chunk_no % 3;
|
|
|
- chunk_no += !odd * 3;
|
|
|
-
|
|
|
if (chunk_no >= USBTV_CHUNKS)
|
|
|
return;
|
|
|
|
|
@@ -241,12 +256,11 @@ static void usbtv_image_chunk(struct usbtv *usbtv, u32 *chunk)
|
|
|
buf = list_first_entry(&usbtv->bufs, struct usbtv_buf, list);
|
|
|
frame = vb2_plane_vaddr(&buf->vb, 0);
|
|
|
|
|
|
- /* Copy the chunk. */
|
|
|
- memcpy(&frame[chunk_no * USBTV_CHUNK], &chunk[1],
|
|
|
- USBTV_CHUNK * sizeof(chunk[1]));
|
|
|
+ /* Copy the chunk data. */
|
|
|
+ usbtv_chunk_to_vbuf(frame, &chunk[1], chunk_no, odd);
|
|
|
|
|
|
/* Last chunk in a frame, signalling an end */
|
|
|
- if (usbtv->frame_id && chunk_no == USBTV_CHUNKS-1) {
|
|
|
+ if (odd && chunk_no == USBTV_CHUNKS-1) {
|
|
|
int size = vb2_plane_size(&buf->vb, 0);
|
|
|
|
|
|
buf->vb.v4l2_buf.field = V4L2_FIELD_INTERLACED;
|
|
@@ -518,7 +532,7 @@ static int usbtv_queue_setup(struct vb2_queue *vq,
|
|
|
if (*nbuffers < 2)
|
|
|
*nbuffers = 2;
|
|
|
*nplanes = 1;
|
|
|
- sizes[0] = USBTV_CHUNK * USBTV_CHUNKS * sizeof(u32);
|
|
|
+ sizes[0] = USBTV_WIDTH * USBTV_HEIGHT / 2 * sizeof(u32);
|
|
|
|
|
|
return 0;
|
|
|
}
|