aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorLubomir Rintel <lkundrak@v3.sk>2013-07-02 06:56:38 -0400
committerMauro Carvalho Chehab <m.chehab@samsung.com>2013-09-03 08:24:19 -0400
commit3080072460bb0efd156e415bfea783279bf64e92 (patch)
treef368022fb18e38a2d6ed9d27264fb6bd18d1ecc0 /drivers/media
parenta19dec6ea94c036af68c31930c1c92681f55af41 (diff)
[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: Lubomir Rintel <lkundrak@v3.sk> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com> Cc: stable@vger.kernel.org
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/usb/usbtv/usbtv.c36
1 files changed, 25 insertions, 11 deletions
diff --git a/drivers/media/usb/usbtv/usbtv.c b/drivers/media/usb/usbtv/usbtv.c
index 095231608d25..55a45d34df22 100644
--- a/drivers/media/usb/usbtv/usbtv.c
+++ b/drivers/media/usb/usbtv/usbtv.c
@@ -56,7 +56,7 @@
56#define USBTV_CHUNK_SIZE 256 56#define USBTV_CHUNK_SIZE 256
57#define USBTV_CHUNK 240 57#define USBTV_CHUNK 240
58#define USBTV_CHUNKS (USBTV_WIDTH * USBTV_HEIGHT \ 58#define USBTV_CHUNKS (USBTV_WIDTH * USBTV_HEIGHT \
59 / 2 / USBTV_CHUNK) 59 / 4 / USBTV_CHUNK)
60 60
61/* Chunk header. */ 61/* Chunk header. */
62#define USBTV_MAGIC_OK(chunk) ((be32_to_cpu(chunk[0]) & 0xff000000) \ 62#define USBTV_MAGIC_OK(chunk) ((be32_to_cpu(chunk[0]) & 0xff000000) \
@@ -259,6 +259,26 @@ static int usbtv_setup_capture(struct usbtv *usbtv)
259 return 0; 259 return 0;
260} 260}
261 261
262/* Copy data from chunk into a frame buffer, deinterlacing the data
263 * into every second line. Unfortunately, they don't align nicely into
264 * 720 pixel lines, as the chunk is 240 words long, which is 480 pixels.
265 * Therefore, we break down the chunk into two halves before copyting,
266 * so that we can interleave a line if needed. */
267static void usbtv_chunk_to_vbuf(u32 *frame, u32 *src, int chunk_no, int odd)
268{
269 int half;
270
271 for (half = 0; half < 2; half++) {
272 int part_no = chunk_no * 2 + half;
273 int line = part_no / 3;
274 int part_index = (line * 2 + !odd) * 3 + (part_no % 3);
275
276 u32 *dst = &frame[part_index * USBTV_CHUNK/2];
277 memcpy(dst, src, USBTV_CHUNK/2 * sizeof(*src));
278 src += USBTV_CHUNK/2;
279 }
280}
281
262/* Called for each 256-byte image chunk. 282/* Called for each 256-byte image chunk.
263 * First word identifies the chunk, followed by 240 words of image 283 * First word identifies the chunk, followed by 240 words of image
264 * data and padding. */ 284 * data and padding. */
@@ -275,11 +295,6 @@ static void usbtv_image_chunk(struct usbtv *usbtv, u32 *chunk)
275 frame_id = USBTV_FRAME_ID(chunk); 295 frame_id = USBTV_FRAME_ID(chunk);
276 odd = USBTV_ODD(chunk); 296 odd = USBTV_ODD(chunk);
277 chunk_no = USBTV_CHUNK_NO(chunk); 297 chunk_no = USBTV_CHUNK_NO(chunk);
278
279 /* Deinterlace. TODO: Use interlaced frame format. */
280 chunk_no = (chunk_no - chunk_no % 3) * 2 + chunk_no % 3;
281 chunk_no += !odd * 3;
282
283 if (chunk_no >= USBTV_CHUNKS) 298 if (chunk_no >= USBTV_CHUNKS)
284 return; 299 return;
285 300
@@ -298,12 +313,11 @@ static void usbtv_image_chunk(struct usbtv *usbtv, u32 *chunk)
298 buf = list_first_entry(&usbtv->bufs, struct usbtv_buf, list); 313 buf = list_first_entry(&usbtv->bufs, struct usbtv_buf, list);
299 frame = vb2_plane_vaddr(&buf->vb, 0); 314 frame = vb2_plane_vaddr(&buf->vb, 0);
300 315
301 /* Copy the chunk. */ 316 /* Copy the chunk data. */
302 memcpy(&frame[chunk_no * USBTV_CHUNK], &chunk[1], 317 usbtv_chunk_to_vbuf(frame, &chunk[1], chunk_no, odd);
303 USBTV_CHUNK * sizeof(chunk[1]));
304 318
305 /* Last chunk in a frame, signalling an end */ 319 /* Last chunk in a frame, signalling an end */
306 if (usbtv->frame_id && chunk_no == USBTV_CHUNKS-1) { 320 if (odd && chunk_no == USBTV_CHUNKS-1) {
307 int size = vb2_plane_size(&buf->vb, 0); 321 int size = vb2_plane_size(&buf->vb, 0);
308 322
309 buf->vb.v4l2_buf.field = V4L2_FIELD_INTERLACED; 323 buf->vb.v4l2_buf.field = V4L2_FIELD_INTERLACED;
@@ -582,7 +596,7 @@ static int usbtv_queue_setup(struct vb2_queue *vq,
582 if (*nbuffers < 2) 596 if (*nbuffers < 2)
583 *nbuffers = 2; 597 *nbuffers = 2;
584 *nplanes = 1; 598 *nplanes = 1;
585 sizes[0] = USBTV_CHUNK * USBTV_CHUNKS * sizeof(u32); 599 sizes[0] = USBTV_WIDTH * USBTV_HEIGHT / 2 * sizeof(u32);
586 600
587 return 0; 601 return 0;
588} 602}