From patchwork Tue Jul 2 11:56:38 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lubomir Rintel X-Patchwork-Id: 2812691 Return-Path: X-Original-To: patchwork-linux-media@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 1A1DB9F3C3 for ; Tue, 2 Jul 2013 11:57:31 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id EB6B020172 for ; Tue, 2 Jul 2013 11:57:29 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 525F12016A for ; Tue, 2 Jul 2013 11:57:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751959Ab3GBL4u (ORCPT ); Tue, 2 Jul 2013 07:56:50 -0400 Received: from shell.v3.sk ([195.168.3.45]:59945 "EHLO norkia.v3.sk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751464Ab3GBL4t (ORCPT ); Tue, 2 Jul 2013 07:56:49 -0400 Received: from localhost (localhost.localdomain [127.0.0.1]) by norkia.v3.sk (Postfix) with ESMTP id 2EEAE12A0E1; Tue, 2 Jul 2013 13:56:46 +0200 (CEST) X-Virus-Scanned: amavisd-new at v3.sk Received: from norkia.v3.sk ([127.0.0.1]) by localhost (norkia.v3.sk [127.0.0.1]) (amavisd-new, port 10024) with SMTP id 8Gn0YpWhVcFg; Tue, 2 Jul 2013 13:56:42 +0200 (CEST) Received: from localhost.localdomain (unknown [158.193.130.168]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) (Authenticated sender: lkundrak@v3.sk) by norkia.v3.sk (Postfix) with ESMTP id 9363612A0DF; Tue, 2 Jul 2013 13:56:42 +0200 (CEST) From: Lubomir Rintel To: linux-media@vger.kernel.org Cc: Lubomir Rintel , Hans Verkuil , Mauro Carvalho Chehab , linux-kernel@vger.kernel.org Subject: [PATCH 1/2] [media] usbtv: Fix deinterlacing Date: Tue, 2 Jul 2013 13:56:38 +0200 Message-Id: <1372766199-28771-1-git-send-email-lkundrak@v3.sk> X-Mailer: git-send-email 1.7.1 Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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 Cc: Hans Verkuil Cc: Mauro Carvalho Chehab Cc: linux-kernel@vger.kernel.org Cc: linux-media@vger.kernel.org --- drivers/media/usb/usbtv/usbtv.c | 36 +++++++++++++++++++++++++----------- 1 files changed, 25 insertions(+), 11 deletions(-) diff --git a/drivers/media/usb/usbtv/usbtv.c b/drivers/media/usb/usbtv/usbtv.c index d44fa63..bdb87d7 100644 --- a/drivers/media/usb/usbtv/usbtv.c +++ b/drivers/media/usb/usbtv/usbtv.c @@ -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 == 0) *nbuffers = 2; *nplanes = 1; - sizes[0] = USBTV_CHUNK * USBTV_CHUNKS * sizeof(u32); + sizes[0] = USBTV_WIDTH * USBTV_HEIGHT / 2 * sizeof(u32); return 0; }