From patchwork Fri Mar 1 13:24:22 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mauro Carvalho Chehab X-Patchwork-Id: 10835319 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 47C441575 for ; Fri, 1 Mar 2019 13:24:35 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 365EF2DD97 for ; Fri, 1 Mar 2019 13:24:35 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 2A9EC2EE31; Fri, 1 Mar 2019 13:24:35 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.7 required=2.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9377A2DD97 for ; Fri, 1 Mar 2019 13:24:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387601AbfCANYd (ORCPT ); Fri, 1 Mar 2019 08:24:33 -0500 Received: from bombadil.infradead.org ([198.137.202.133]:50534 "EHLO bombadil.infradead.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1732910AbfCANYa (ORCPT ); Fri, 1 Mar 2019 08:24:30 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=bombadil.20170209; h=Sender:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help: List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=BHHrEQZI+5S4/LwUdO/s8e2FpWWYq4AOxIetfF7icw0=; b=Cx4Ital9N2dP3j067oN9A4Wxfy DkwidvhlA167bsIBuXgKbxon9pnPjFqi5ze/DB4NGxUrVi8Onlk074Qn7Xpzb1CiFrPQo30JytqGe QrMun5qXbI5tdmeHEhnXLO1vgJFzz7dxQZFuWoXbfo3aPB/Pg5GN1tUThpuv6/il9OPl9s87E+jTx GdoWbqYwsbgHtxtbfdiCz/BimQVsgF7nl5f6l+xFcGLusYHz8zaW8YJedk1gMNlx7OmVXhXRVbU1I hyvuhTsWKbpM66SySO44jzLOh7NTkyx0rTQBrjj9v2IaV6sTXLm6jEaB5lJ0L6oGz4WBGLufjT0du jxuwNzvQ==; Received: from 177.41.113.159.dynamic.adsl.gvt.net.br ([177.41.113.159] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtpsa (Exim 4.90_1 #2 (Red Hat Linux)) id 1gzi9N-0003y1-VO; Fri, 01 Mar 2019 13:24:29 +0000 Received: from mchehab by bombadil.infradead.org with local (Exim 4.92) (envelope-from ) id 1gzi9L-0002NS-SB; Fri, 01 Mar 2019 10:24:27 -0300 From: Mauro Carvalho Chehab To: Linux Media Mailing List Cc: Mauro Carvalho Chehab , Mauro Carvalho Chehab , Hans Verkuil , Ezequiel Garcia Subject: [PATCH 06/10] media: vim2m: better handle cap/out buffers with different sizes Date: Fri, 1 Mar 2019 10:24:22 -0300 Message-Id: X-Mailer: git-send-email 2.20.1 In-Reply-To: References: MIME-Version: 1.0 Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The vim2m driver doesn't enforce that the capture and output buffers would have the same size. Do the right thing if the buffers are different, zeroing the buffer before writing, ensuring that lines will be aligned and it won't write past the buffer area. This is a temporary fix. A proper fix is to either implement a simple scaler at vim2m, or to better define the behaviour of M2M transform drivers at V4L2 API with regards to its capability of scaling the image or not. In any case, such changes would deserve a separate patch anyway, as it would imply on some behavoral change. Also, as we have an actual bug of writing data at wrong places, let's fix this here, and add a mental note that we need to properly address it. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vim2m.c | 117 +++++++++++++++++++++++---------- 1 file changed, 81 insertions(+), 36 deletions(-) diff --git a/drivers/media/platform/vim2m.c b/drivers/media/platform/vim2m.c index 5157a59aeb58..ec177de144b6 100644 --- a/drivers/media/platform/vim2m.c +++ b/drivers/media/platform/vim2m.c @@ -267,46 +267,66 @@ static const char *type_name(enum v4l2_buf_type type) #define CLIP(__color) \ (u8)(((__color) > 0xff) ? 0xff : (((__color) < 0) ? 0 : (__color))) -static void copy_two_pixels(struct vim2m_fmt *in, struct vim2m_fmt *out, +static int fast_copy_two_pixels(struct vim2m_q_data *q_data_in, + struct vim2m_q_data *q_data_out, + u8 **src, u8 **dst, int ypos, bool reverse) +{ + int depth = q_data_out->fmt->depth >> 3; + + /* Only do fast copy when format and resolution are identical */ + if (q_data_in->fmt->fourcc != q_data_out->fmt->fourcc || + q_data_in->width != q_data_out->width || + q_data_in->height != q_data_out->height) + return 0; + + if (!reverse) { + memcpy(*dst, *src, depth << 1); + *src += depth << 1; + *dst += depth << 1; + return 1; + } + + /* Copy line at reverse order - YUYV format */ + if (q_data_in->fmt->fourcc == V4L2_PIX_FMT_YUYV) { + int u, v, y, y1; + + *src -= 2; + + y1 = (*src)[0]; /* copy as second point */ + u = (*src)[1]; + y = (*src)[2]; /* copy as first point */ + v = (*src)[3]; + + *src -= 2; + + *(*dst)++ = y; + *(*dst)++ = u; + *(*dst)++ = y1; + *(*dst)++ = v; + return 1; + } + + /* copy RGB formats in reverse order */ + memcpy(*dst, *src, depth); + memcpy(*dst + depth, *src - depth, depth); + *src -= depth << 1; + *dst += depth << 1; + return 1; +} + +static void copy_two_pixels(struct vim2m_q_data *q_data_in, + struct vim2m_q_data *q_data_out, u8 **src, u8 **dst, int ypos, bool reverse) { + struct vim2m_fmt *out = q_data_out->fmt; + struct vim2m_fmt *in = q_data_in->fmt; u8 _r[2], _g[2], _b[2], *r, *g, *b; int i, step; // If format is the same just copy the data, respecting the width - if (in->fourcc == out->fourcc) { - int depth = out->depth >> 3; - - if (reverse) { - if (in->fourcc == V4L2_PIX_FMT_YUYV) { - int u, v, y, y1; - - *src -= 2; - - y1 = (*src)[0]; /* copy as second point */ - u = (*src)[1]; - y = (*src)[2]; /* copy as first point */ - v = (*src)[3]; - - *src -= 2; - - *(*dst)++ = y; - *(*dst)++ = u; - *(*dst)++ = y1; - *(*dst)++ = v; - return; - } - - memcpy(*dst, *src, depth); - memcpy(*dst + depth, *src - depth, depth); - *src -= depth << 1; - } else { - memcpy(*dst, *src, depth << 1); - *src += depth << 1; - } - *dst += depth << 1; - return; - } + if (fast_copy_two_pixels(q_data_in, q_data_out, + src, dst, ypos, reverse)) + return; /* Step 1: read two consecutive pixels from src pointer */ @@ -506,7 +526,9 @@ static int device_process(struct vim2m_ctx *ctx, struct vim2m_dev *dev = ctx->dev; struct vim2m_q_data *q_data_in, *q_data_out; u8 *p_in, *p, *p_out; - int width, height, bytesperline, x, y, y_out, start, end, step; + unsigned int width, height, bytesperline, bytesperline_out; + unsigned int x, y, y_out; + int start, end, step; struct vim2m_fmt *in, *out; q_data_in = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); @@ -516,8 +538,15 @@ static int device_process(struct vim2m_ctx *ctx, bytesperline = (q_data_in->width * q_data_in->fmt->depth) >> 3; q_data_out = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); + bytesperline_out = (q_data_out->width * q_data_out->fmt->depth) >> 3; out = q_data_out->fmt; + /* Crop to the limits of the destination image */ + if (width > q_data_out->width) + width = q_data_out->width; + if (height > q_data_out->height) + height = q_data_out->height; + p_in = vb2_plane_vaddr(&in_vb->vb2_buf, 0); p_out = vb2_plane_vaddr(&out_vb->vb2_buf, 0); if (!p_in || !p_out) { @@ -526,6 +555,17 @@ static int device_process(struct vim2m_ctx *ctx, return -EFAULT; } + /* + * FIXME: instead of cropping the image and zeroing any + * extra data, the proper behavior is to either scale the + * data or report that scale is not supported (with depends + * on some API for such purpose). + */ + + /* Image size is different. Zero buffer first */ + if (q_data_in->width != q_data_out->width || + q_data_in->height != q_data_out->height) + memset(p_out, 0, q_data_out->sizeimage); out_vb->sequence = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE)->sequence++; in_vb->sequence = q_data_in->sequence++; @@ -547,8 +587,13 @@ static int device_process(struct vim2m_ctx *ctx, p += bytesperline - (q_data_in->fmt->depth >> 3); for (x = 0; x < width >> 1; x++) - copy_two_pixels(in, out, &p, &p_out, y_out, + copy_two_pixels(q_data_in, q_data_out, &p, &p_out, y_out, ctx->mode & MEM2MEM_HFLIP); + + /* Go to the next line at the out buffer */ + if (width < q_data_out->width) + p_out += ((q_data_out->width - width) + * q_data_out->fmt->depth) >> 3; } return 0;