Received: by 2002:a05:6a10:8c0a:0:0:0:0 with SMTP id go10csp1089212pxb; Fri, 26 Feb 2021 02:10:29 -0800 (PST) X-Google-Smtp-Source: ABdhPJxLe52+Z+JygxZdmc9/bvhttuFaS8+tL7bYjZpMSHBOUAYXPEWwx6I7B2x8g9oh05neogtn X-Received: by 2002:a17:907:2bcd:: with SMTP id gv13mr2397062ejc.95.1614334229680; Fri, 26 Feb 2021 02:10:29 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1614334229; cv=none; d=google.com; s=arc-20160816; b=Y6OUsZlfzXU9QAx4CkXQk70HStz9nbZzxCw5iDzxq4LKEShTpwlw+21Ya8Y3thA3Jy DADgyxNmaUDY9uwgBM+ARZb+G40DJAKj+javKf3vQr7c8NamzBQbeQzwRenXmhxa9s4K TIOfNmV9i421CHNr1quXRK+1t9xPv/qUWbjai20G1Jq6np2Mk/QiWETozp+BeLm3NcF5 xiWqBAyeKIVW+i+22KdU1P9DS6lqbGvWv9zyFJOm0VXbcbK7Ip9uFjBk7wX2NfZDuk33 HoiStPhGPFSqGvbFsHd+Hi0bG6/yaaI05/HNWgW4d6kfLDz/PNcx0yKC8e9RkdKrWP82 z9JA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=RU3m0vnoHc5l7K5s4IBbXI+lLB4VI5TXPJDbkmiuUIQ=; b=AeShcTI3xRup0PqM0QI0kF0c48wO3nR7yLSLZfgGjNHFpJVZqqE8fn/LDfOAEDojM7 If5lT+ZoKKkEB+lzZpX60ONVFDItM7jXFL/KG1QvJ9GmC3YGVonBiqTsXutE5uIGBVvz iAgrSR/ODZt9gHbiwJMm3ju6UdorDWXbAVdSqq2rS1Rh/Y5Cl+TVhaC9YWoS7CVK8Alb ZRgt7iHFnYGkTfNh2calgtwosOVZbjOwtSdRBW62bIAYsEEXgI3YONXM6sNBj5sjalk3 ZXeHE2G1wnayknfiZiSL2tCAw8T/I6iB5It0qRwJsJqUh49MFJQx3VcSXo1PGSUOf/P2 aVGg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=muWch6NU; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=chromium.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id dn4si6179784ejc.686.2021.02.26.02.10.06; Fri, 26 Feb 2021 02:10:29 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=muWch6NU; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=chromium.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231152AbhBZKIS (ORCPT + 99 others); Fri, 26 Feb 2021 05:08:18 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51244 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230454AbhBZKFL (ORCPT ); Fri, 26 Feb 2021 05:05:11 -0500 Received: from mail-pf1-x436.google.com (mail-pf1-x436.google.com [IPv6:2607:f8b0:4864:20::436]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6285FC061574 for ; Fri, 26 Feb 2021 02:02:41 -0800 (PST) Received: by mail-pf1-x436.google.com with SMTP id r5so5909234pfh.13 for ; Fri, 26 Feb 2021 02:02:41 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=RU3m0vnoHc5l7K5s4IBbXI+lLB4VI5TXPJDbkmiuUIQ=; b=muWch6NUQJmt5mo3Y2qo0Skw/PjV9ZDRYVB58BLwQFTaMlpxBL4idvgo2OTfEwpnwx 85+EhVYM3NYncmzxv/fTR5d3CiytfPDsN9sWGwkNHD6uLfcrybgLvRw6TCcW3tmouXeZ vGILIfPc81FO35fIUMkYBxSi8lRPpAjtAicN4= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=RU3m0vnoHc5l7K5s4IBbXI+lLB4VI5TXPJDbkmiuUIQ=; b=l5BKdQIqxRbll+lyWq5jais7kHD3MVN1BSXvyUY2T0WHrnqhiEDT/vatcd4qtxP81k H9jF06Z0EnD72OY2io+NGXdJXNCHVc5jqkW0yhknl/W/qgUWF4rr4sPHOFcKTRka6hjX u02k0Q22nMOs2ID0MhCwaRmm44zkNH8uUqxHdaoa/GkHTvLxS/G2A/V25UGV3R+t9cWN 2w1FWNXEVh0dY5IJD+9UiamYVl1DbVnoW+ERfmKjpEKvZmea3yF9IrKCAN9hwK0l9MCn 92lvV/Y5kQlgBczeadz/Nyc0exsiSQ416KLRtnnTARgF78A+T51Q53mIWZ1A0JTodR07 62Kg== X-Gm-Message-State: AOAM531zR4XTQiFfq2hdl0+u6L/RAlFlRJOSI28nnc1UPcKGMskG+v+A 4UF77oQ+m+39ym/IPTHxlM8uqA== X-Received: by 2002:a63:5b5d:: with SMTP id l29mr2245348pgm.272.1614333760899; Fri, 26 Feb 2021 02:02:40 -0800 (PST) Received: from acourbot.tok.corp.google.com ([2401:fa00:8f:203:5c91:233c:dd5b:b1b0]) by smtp.gmail.com with ESMTPSA id o23sm9201565pfp.89.2021.02.26.02.02.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 26 Feb 2021 02:02:40 -0800 (PST) From: Alexandre Courbot To: Tiffany Lin , Andrew-CT Chen , Rob Herring , Yunfei Dong Cc: Mauro Carvalho Chehab , Hans Verkuil , linux-media@vger.kernel.org, linux-kernel@vger.kernel.org, linux-mediatek@lists.infradead.org, Alexandre Courbot Subject: [PATCH v3 14/15] media: mtk-vcodec: venc: support START and STOP commands Date: Fri, 26 Feb 2021 19:01:47 +0900 Message-Id: <20210226100148.1663389-15-acourbot@chromium.org> X-Mailer: git-send-email 2.30.1.766.gb4fecdf3b7-goog In-Reply-To: <20210226100148.1663389-1-acourbot@chromium.org> References: <20210226100148.1663389-1-acourbot@chromium.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The V4L2 encoder specification requires encoders to support the V4L2_ENC_CMD_START and V4L2_ENC_CMD_STOP commands. Add support for these to the mtk-vcodec encoder by reusing the same flush buffer as used by the decoder driver. Signed-off-by: Alexandre Courbot --- .../platform/mtk-vcodec/mtk_vcodec_drv.h | 2 + .../platform/mtk-vcodec/mtk_vcodec_enc.c | 123 +++++++++++++++++- .../platform/mtk-vcodec/mtk_vcodec_enc_drv.c | 4 + 3 files changed, 122 insertions(+), 7 deletions(-) diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h b/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h index 8dab9f520283..73da6c7b69a8 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h @@ -253,6 +253,7 @@ struct vdec_pic_info { * @last_decoded_picinfo: pic information get from latest decode * @empty_flush_buf: a fake size-0 capture buffer that indicates flush. Only * to be used with encoder and stateful decoder. + * @is_flushing: set to true if flushing is in progress. * @current_codec: current set input codec, in V4L2 pixel format * * @colorspace: enum v4l2_colorspace; supplemental to pixelformat @@ -292,6 +293,7 @@ struct mtk_vcodec_ctx { struct work_struct encode_work; struct vdec_pic_info last_decoded_picinfo; struct v4l2_m2m_buffer empty_flush_buf; + bool is_flushing; u32 current_codec; diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c index 8c917969c2f1..4de381b522ae 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c @@ -658,6 +658,7 @@ static int vidioc_venc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) { struct mtk_vcodec_ctx *ctx = fh_to_ctx(priv); + int ret; if (ctx->state == MTK_STATE_ABORT) { mtk_v4l2_err("[%d] Call on QBUF after unrecoverable error", @@ -665,7 +666,77 @@ static int vidioc_venc_dqbuf(struct file *file, void *priv, return -EIO; } - return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf); + ret = v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf); + if (ret) + return ret; + + /* + * Complete flush if the user dequeued the 0-payload LAST buffer. + * We check the payload because a buffer with the LAST flag can also + * be seen during resolution changes. If we happen to be flushing at + * that time, the last buffer before the resolution changes could be + * misinterpreted for the buffer generated by the flush and terminate + * it earlier than we want. + */ + if (!V4L2_TYPE_IS_OUTPUT(buf->type) && + buf->flags & V4L2_BUF_FLAG_LAST && + buf->m.planes[0].bytesused == 0 && + ctx->is_flushing) { + /* + * Last CAPTURE buffer is dequeued, we can allow another flush + * to take place. + */ + ctx->is_flushing = false; + } + + return 0; +} + +static int vidioc_encoder_cmd(struct file *file, void *priv, + struct v4l2_encoder_cmd *cmd) +{ + struct mtk_vcodec_ctx *ctx = fh_to_ctx(priv); + struct vb2_queue *src_vq, *dst_vq; + int ret; + + ret = v4l2_m2m_ioctl_try_encoder_cmd(file, priv, cmd); + if (ret) + return ret; + + /* Calling START or STOP is invalid if a flush is in progress */ + if (ctx->is_flushing) + return -EBUSY; + + mtk_v4l2_debug(1, "encoder cmd=%u", cmd->cmd); + + dst_vq = v4l2_m2m_get_vq(ctx->m2m_ctx, + V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + switch (cmd->cmd) { + case V4L2_ENC_CMD_STOP: + src_vq = v4l2_m2m_get_vq(ctx->m2m_ctx, + V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + if (!vb2_is_streaming(src_vq)) { + mtk_v4l2_debug(1, "Output stream is off. No need to flush."); + return 0; + } + if (!vb2_is_streaming(dst_vq)) { + mtk_v4l2_debug(1, "Capture stream is off. No need to flush."); + return 0; + } + ctx->is_flushing = true; + v4l2_m2m_buf_queue(ctx->m2m_ctx, &ctx->empty_flush_buf.vb); + v4l2_m2m_try_schedule(ctx->m2m_ctx); + break; + + case V4L2_ENC_CMD_START: + vb2_clear_last_buffer_dequeued(dst_vq); + break; + + default: + return -EINVAL; + } + + return 0; } const struct v4l2_ioctl_ops mtk_venc_ioctl_ops = { @@ -701,6 +772,9 @@ const struct v4l2_ioctl_ops mtk_venc_ioctl_ops = { .vidioc_g_selection = vidioc_venc_g_selection, .vidioc_s_selection = vidioc_venc_s_selection, + + .vidioc_encoder_cmd = vidioc_encoder_cmd, + .vidioc_try_encoder_cmd = v4l2_m2m_ioctl_try_encoder_cmd, }; static int vb2ops_venc_queue_setup(struct vb2_queue *vq, @@ -857,9 +931,27 @@ static void vb2ops_venc_stop_streaming(struct vb2_queue *q) dst_buf->vb2_buf.planes[0].bytesused = 0; v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_ERROR); } + /* STREAMOFF on the CAPTURE queue completes any ongoing flush */ + if (ctx->is_flushing) { + mtk_v4l2_debug(1, "STREAMOFF called while flushing"); + v4l2_m2m_buf_remove_by_buf(&ctx->m2m_ctx->out_q_ctx, + &ctx->empty_flush_buf.vb); + ctx->is_flushing = false; + } } else { - while ((src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx))) - v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_ERROR); + while ((src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx))) { + if (src_buf != &ctx->empty_flush_buf.vb) + v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_ERROR); + } + if (ctx->is_flushing) { + /* + * If we are in the middle of a flush, put the flush + * buffer back into the queue so the next CAPTURE + * buffer gets returned with the LAST flag set. + */ + v4l2_m2m_buf_queue(ctx->m2m_ctx, + &ctx->empty_flush_buf.vb); + } } if ((q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE && @@ -955,12 +1047,15 @@ static int mtk_venc_param_change(struct mtk_vcodec_ctx *ctx) { struct venc_enc_param enc_prm; struct vb2_v4l2_buffer *vb2_v4l2 = v4l2_m2m_next_src_buf(ctx->m2m_ctx); - struct mtk_video_enc_buf *mtk_buf = - container_of(vb2_v4l2, struct mtk_video_enc_buf, - m2m_buf.vb); - + struct mtk_video_enc_buf *mtk_buf; int ret = 0; + /* Don't upcast the empty flush buffer */ + if (vb2_v4l2 == &ctx->empty_flush_buf.vb) + return 0; + + mtk_buf = container_of(vb2_v4l2, struct mtk_video_enc_buf, m2m_buf.vb); + memset(&enc_prm, 0, sizeof(enc_prm)); if (mtk_buf->param_change == MTK_ENCODE_PARAM_NONE) return 0; @@ -1046,6 +1141,20 @@ static void mtk_venc_worker(struct work_struct *work) } src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx); + + /* + * If we see the flush buffer, send an empty buffer with the LAST flag + * to the client. is_flushing will be reset at the time the buffer + * is dequeued. + */ + if (src_buf == &ctx->empty_flush_buf.vb) { + vb2_set_plane_payload(&dst_buf->vb2_buf, 0, 0); + dst_buf->flags |= V4L2_BUF_FLAG_LAST; + v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_DONE); + v4l2_m2m_job_finish(ctx->dev->m2m_dev_enc, ctx->m2m_ctx); + return; + } + memset(&frm_buf, 0, sizeof(frm_buf)); for (i = 0; i < src_buf->vb2_buf.num_planes ; i++) { frm_buf.fb_addr[i].dma_addr = diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c index be3842e6ca47..b2ba8db32fea 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c @@ -150,6 +150,7 @@ static int fops_vcodec_open(struct file *file) struct mtk_vcodec_dev *dev = video_drvdata(file); struct mtk_vcodec_ctx *ctx = NULL; int ret = 0; + struct vb2_queue *src_vq; ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); if (!ctx) @@ -183,6 +184,9 @@ static int fops_vcodec_open(struct file *file) ret); goto err_m2m_ctx_init; } + src_vq = v4l2_m2m_get_vq(ctx->m2m_ctx, + V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + ctx->empty_flush_buf.vb.vb2_buf.vb2_queue = src_vq; mtk_vcodec_enc_set_default_params(ctx); if (v4l2_fh_is_singular(&ctx->fh)) { -- 2.30.1.766.gb4fecdf3b7-goog