Commit 30800724 authored by Lubomir Rintel's avatar Lubomir Rintel Committed by Mauro Carvalho Chehab

[media] usbtv: Fix deinterlacing

The image data is laid out a bit more weirdly and thus needs more work to
properly interlace. What we get from hardware is V4L2_FIELD_ALTERNATE, but
since userspace support for it is practically nonexistent, thus we make
V4L2_FIELD_INTERLACED from it so that it's more easily interpreted.
Signed-off-by: default avatarLubomir Rintel <lkundrak@v3.sk>
Signed-off-by: default avatarHans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: default avatarMauro Carvalho Chehab <m.chehab@samsung.com>
Cc: stable@vger.kernel.org
parent a19dec6e
...@@ -56,7 +56,7 @@ ...@@ -56,7 +56,7 @@
#define USBTV_CHUNK_SIZE 256 #define USBTV_CHUNK_SIZE 256
#define USBTV_CHUNK 240 #define USBTV_CHUNK 240
#define USBTV_CHUNKS (USBTV_WIDTH * USBTV_HEIGHT \ #define USBTV_CHUNKS (USBTV_WIDTH * USBTV_HEIGHT \
/ 2 / USBTV_CHUNK) / 4 / USBTV_CHUNK)
/* Chunk header. */ /* Chunk header. */
#define USBTV_MAGIC_OK(chunk) ((be32_to_cpu(chunk[0]) & 0xff000000) \ #define USBTV_MAGIC_OK(chunk) ((be32_to_cpu(chunk[0]) & 0xff000000) \
...@@ -259,6 +259,26 @@ static int usbtv_setup_capture(struct usbtv *usbtv) ...@@ -259,6 +259,26 @@ static int usbtv_setup_capture(struct usbtv *usbtv)
return 0; 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. /* Called for each 256-byte image chunk.
* First word identifies the chunk, followed by 240 words of image * First word identifies the chunk, followed by 240 words of image
* data and padding. */ * data and padding. */
...@@ -275,11 +295,6 @@ static void usbtv_image_chunk(struct usbtv *usbtv, u32 *chunk) ...@@ -275,11 +295,6 @@ static void usbtv_image_chunk(struct usbtv *usbtv, u32 *chunk)
frame_id = USBTV_FRAME_ID(chunk); frame_id = USBTV_FRAME_ID(chunk);
odd = USBTV_ODD(chunk); odd = USBTV_ODD(chunk);
chunk_no = USBTV_CHUNK_NO(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) if (chunk_no >= USBTV_CHUNKS)
return; return;
...@@ -298,12 +313,11 @@ static void usbtv_image_chunk(struct usbtv *usbtv, u32 *chunk) ...@@ -298,12 +313,11 @@ static void usbtv_image_chunk(struct usbtv *usbtv, u32 *chunk)
buf = list_first_entry(&usbtv->bufs, struct usbtv_buf, list); buf = list_first_entry(&usbtv->bufs, struct usbtv_buf, list);
frame = vb2_plane_vaddr(&buf->vb, 0); frame = vb2_plane_vaddr(&buf->vb, 0);
/* Copy the chunk. */ /* Copy the chunk data. */
memcpy(&frame[chunk_no * USBTV_CHUNK], &chunk[1], usbtv_chunk_to_vbuf(frame, &chunk[1], chunk_no, odd);
USBTV_CHUNK * sizeof(chunk[1]));
/* Last chunk in a frame, signalling an end */ /* 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); int size = vb2_plane_size(&buf->vb, 0);
buf->vb.v4l2_buf.field = V4L2_FIELD_INTERLACED; buf->vb.v4l2_buf.field = V4L2_FIELD_INTERLACED;
...@@ -582,7 +596,7 @@ static int usbtv_queue_setup(struct vb2_queue *vq, ...@@ -582,7 +596,7 @@ static int usbtv_queue_setup(struct vb2_queue *vq,
if (*nbuffers < 2) if (*nbuffers < 2)
*nbuffers = 2; *nbuffers = 2;
*nplanes = 1; *nplanes = 1;
sizes[0] = USBTV_CHUNK * USBTV_CHUNKS * sizeof(u32); sizes[0] = USBTV_WIDTH * USBTV_HEIGHT / 2 * sizeof(u32);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment