Received: by 2002:a5b:505:0:0:0:0:0 with SMTP id o5csp7436720ybp; Wed, 16 Oct 2019 08:37:45 -0700 (PDT) X-Google-Smtp-Source: APXvYqxsAkOGDhokE8h++7U0c12iYrVQHz+HPlpt4+UeFanOaicOamt2GaaEscm5Vg12SOiki0T0 X-Received: by 2002:a17:906:1d02:: with SMTP id n2mr40038669ejh.303.1571240265235; Wed, 16 Oct 2019 08:37:45 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1571240265; cv=none; d=google.com; s=arc-20160816; b=F+7ltwFQA2S2DMLIsfJFjFAWHWtnVMPs/4W5kA+xXKNvug2MN7U8Jp7xk0ufCifloP pNfpt0NCDdr7Leng7WKKb+GxUglcqstZusPW+NtEjgZGmbBj5rfpwlzzYslMD1P32PJl N4upkOXmUwkIxRdajf3A3iIff47d99FZoSNZZeutkJGOmQKwTD1GYRf3NGTLQf5X93vp T41lu/bSJ6PxGccY5y8rcE76evk6uqIT06ZNzzh/8P5p9Pv4jihyhDuBjWI1/YvVkgdh 2zWgLCKmgVt0DH2RCrHDBomSbIcXEIT3MSD2Hg8V2fvx0r1RoaxN1iDiwuzwVGAthnA7 opsQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding :content-language:in-reply-to:mime-version:user-agent:date :message-id:from:references:cc:to:subject; bh=DJv/GcFeyo9Urxf7Esi3rysmK984BFf6l2uLFl0OAxg=; b=rSEfKROIclyzpLU4JebIohNGTwfBagITquq1SXyyU/wOe35g+vwbycS2R/7HByefH1 JE++HWTiY6hr+0Zveh8AOw9eIrtYz4w5H7geIgJMbTgOBOlHYVqWH9+Jp1nmKZujiG/o 0LZnzx6Z5Xu9jbqpZIaDmM87gHBz+WZG0tMb+Pib206CWog0r9xhUdK8cpY3u9GBycsu Dpt6gIkKsON6OnpuQETJfgq1/l/szDaACoM3YPUDc9+UR9vOEaDmmTmvglGAdzVE5dUy w1AiFXmfSWqjuswgYp6iY0sFKtQ+Vrr97pmt5Afvua3xHjzE+/O8/jOaVhH3EJfQ7koa 02Dg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 64si13324549eda.384.2019.10.16.08.37.21; Wed, 16 Oct 2019 08:37:45 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2391281AbfJPMis (ORCPT + 99 others); Wed, 16 Oct 2019 08:38:48 -0400 Received: from lb2-smtp-cloud8.xs4all.net ([194.109.24.25]:43709 "EHLO lb2-smtp-cloud8.xs4all.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726796AbfJPMir (ORCPT ); Wed, 16 Oct 2019 08:38:47 -0400 Received: from [192.168.2.10] ([46.9.232.237]) by smtp-cloud8.xs4all.net with ESMTPA id KiZciHa6UPduvKiZfiqz66; Wed, 16 Oct 2019 14:38:44 +0200 Subject: Re: [PATCH 1/2] media: meson: vdec: bring up to compliance To: Maxime Jourdan , Mauro Carvalho Chehab , Hans Verkuil Cc: Kevin Hilman , Jerome Brunet , Neil Armstrong , Martin Blumenstingl , linux-media@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-amlogic@lists.infradead.org References: <20191007145909.29979-1-mjourdan@baylibre.com> <20191007145909.29979-2-mjourdan@baylibre.com> From: Hans Verkuil Message-ID: <3c6be374-1b89-642a-6307-aca1f2ae7722@xs4all.nl> Date: Wed, 16 Oct 2019 14:38:40 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.9.0 MIME-Version: 1.0 In-Reply-To: <20191007145909.29979-2-mjourdan@baylibre.com> Content-Type: text/plain; charset=utf-8 Content-Language: en-US Content-Transfer-Encoding: 8bit X-CMAE-Envelope: MS4wfPL8FShpAipoNfc1mY3XdDF83ckcXKK215hftmuu2iMMs1W9Bke8ePytD2Nru3dI6wbcbt5ivgoniZC17zV9SmKjOb0RBi31Qg5O3h3y7FOxvlw364ea rKojEOSLx4Pwuxe8REEoF3u+E2WYHNKA1/NZLGfsFkBfe/gpmXT7CjzUbNl8j8XiZOYyIqFh0BTOPSxGJtgX1aVFedJKkn1FHNeXpraARS0FgYQ09dZQub0G Gut/y8oNxNINgyNMv3JKjhdNWOdZnK2oesBSlyxes8T+wC57uPgtZs8RYAhObrqb/MkD4oH3Z0GjwPXr6B8NspXeFTCJ7i/KWym5taMLZraPX9M3olVXY5rh w4safI4KlVSYhq2WV9gbiDP7kE0HYEu6weyOs/PE9bnU81KnMRy5TnyaTzunE6MjEbUtbMq64Qk09DKBt0YeoXdwG6XXPadE82cYepKkRWU1JMH7090/E/Ve 2pYaBt+bceZfzWYM5F/Z9xfdPmbiKHnJP7QdeV4fPM+N2arZBl5iIKEKvY6a6o+f4h+OFr+erYeprSUl9VTRLD3L1dWfhvTVqSBGUw== Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On 10/7/19 4:59 PM, Maxime Jourdan wrote: > Add all the necessary bits to pass v4l2-compliance in stateful decoding > mode. > > Mostly includes tracking the state of the decoder, allowing the OUTPUT > queue to stream while the CAPTURE queue is inactive, handling resolution > change events, draining with V4L2_DEC_CMD_STOP, copying more metadata > from the src buffers to the dst buffers, etc. > > Signed-off-by: Maxime Jourdan > --- > drivers/staging/media/meson/vdec/esparser.c | 34 ++------ > drivers/staging/media/meson/vdec/vdec.c | 70 ++++++++++----- > drivers/staging/media/meson/vdec/vdec.h | 14 ++- > .../staging/media/meson/vdec/vdec_helpers.c | 85 +++++++++---------- > .../staging/media/meson/vdec/vdec_helpers.h | 6 +- > .../staging/media/meson/vdec/vdec_platform.c | 6 ++ > 6 files changed, 120 insertions(+), 95 deletions(-) > > diff --git a/drivers/staging/media/meson/vdec/esparser.c b/drivers/staging/media/meson/vdec/esparser.c > index 95102a4bdc62..a083d67be405 100644 > --- a/drivers/staging/media/meson/vdec/esparser.c > +++ b/drivers/staging/media/meson/vdec/esparser.c > @@ -180,29 +180,25 @@ esparser_queue(struct amvdec_session *sess, struct vb2_v4l2_buffer *vbuf) > int ret; > struct vb2_buffer *vb = &vbuf->vb2_buf; > struct amvdec_core *core = sess->core; > - struct amvdec_codec_ops *codec_ops = sess->fmt_out->codec_ops; > - u32 num_dst_bufs = 0; > u32 payload_size = vb2_get_plane_payload(vb, 0); > dma_addr_t phy = vb2_dma_contig_plane_dma_addr(vb, 0); > u32 offset; > u32 pad_size; > > - if (codec_ops->num_pending_bufs) > - num_dst_bufs = codec_ops->num_pending_bufs(sess); > - > - num_dst_bufs += v4l2_m2m_num_dst_bufs_ready(sess->m2m_ctx); > - > - if (esparser_vififo_get_free_space(sess) < payload_size || > - atomic_read(&sess->esparser_queued_bufs) >= num_dst_bufs) > + if (esparser_vififo_get_free_space(sess) < payload_size) > return -EAGAIN; > > v4l2_m2m_src_buf_remove_by_buf(sess->m2m_ctx, vbuf); > > offset = esparser_get_offset(sess); > > - amvdec_add_ts_reorder(sess, vb->timestamp, offset); > - dev_dbg(core->dev, "esparser: ts = %llu pld_size = %u offset = %08X\n", > - vb->timestamp, payload_size, offset); > + amvdec_add_ts(sess, vb->timestamp, vbuf->timecode, offset, vbuf->flags); > + dev_dbg(core->dev, "esparser: ts = %llu pld_size = %u offset = %08X flags = %08X\n", > + vb->timestamp, payload_size, offset, vbuf->flags); > + > + vbuf->flags = 0; > + vbuf->field = V4L2_FIELD_NONE; > + vbuf->sequence = sess->sequence_out++; > > pad_size = esparser_pad_start_code(vb); > ret = esparser_write_data(core, phy, payload_size + pad_size); > @@ -216,19 +212,7 @@ esparser_queue(struct amvdec_session *sess, struct vb2_v4l2_buffer *vbuf) > return 0; > } > > - /* We need to wait until we parse the first keyframe. > - * All buffers prior to the first keyframe must be dropped. > - */ > - if (!sess->keyframe_found) > - usleep_range(1000, 2000); > - > - if (sess->keyframe_found) > - atomic_inc(&sess->esparser_queued_bufs); > - else > - amvdec_remove_ts(sess, vb->timestamp); > - > - vbuf->flags = 0; > - vbuf->field = V4L2_FIELD_NONE; > + atomic_inc(&sess->esparser_queued_bufs); > v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_DONE); > > return 0; > diff --git a/drivers/staging/media/meson/vdec/vdec.c b/drivers/staging/media/meson/vdec/vdec.c > index 0a1a04fd5d13..0b571b3a1e33 100644 > --- a/drivers/staging/media/meson/vdec/vdec.c > +++ b/drivers/staging/media/meson/vdec/vdec.c > @@ -166,7 +166,10 @@ static void process_num_buffers(struct vb2_queue *q, > { > const struct amvdec_format *fmt_out = sess->fmt_out; > unsigned int buffers_total = q->num_buffers + *num_buffers; > + u32 min_buf_capture = v4l2_ctrl_g_ctrl(sess->ctrl_min_buf_capture); > > + if (q->num_buffers + *num_buffers < min_buf_capture) > + *num_buffers = min_buf_capture - q->num_buffers; > if (is_reqbufs && buffers_total < fmt_out->min_buffers) > *num_buffers = fmt_out->min_buffers - q->num_buffers; > if (buffers_total > fmt_out->max_buffers) > @@ -191,7 +194,8 @@ static int vdec_queue_setup(struct vb2_queue *q, unsigned int *num_buffers, > if (*num_planes) { > switch (q->type) { > case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: > - if (*num_planes != 1 || sizes[0] < output_size) > + if (*num_planes != 1 || > + sizes[0] < sess->src_buffer_size) > return -EINVAL; > break; > case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: > @@ -222,7 +226,7 @@ static int vdec_queue_setup(struct vb2_queue *q, unsigned int *num_buffers, > > switch (q->type) { > case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: > - sizes[0] = amvdec_get_output_size(sess); > + sizes[0] = sess->src_buffer_size; > *num_planes = 1; > break; > case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: > @@ -248,6 +252,7 @@ static int vdec_queue_setup(struct vb2_queue *q, unsigned int *num_buffers, > return -EINVAL; > } > > + sess->changed_format = 1; > return 0; > } > > @@ -259,10 +264,11 @@ static void vdec_vb2_buf_queue(struct vb2_buffer *vb) > > v4l2_m2m_buf_queue(m2m_ctx, vbuf); > > - if (!sess->streamon_out || !sess->streamon_cap) > + if (!sess->streamon_out) > return; > > - if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE && > + if (sess->streamon_cap && > + vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE && > vdec_codec_needs_recycle(sess)) > vdec_queue_recycle(sess, vb); > > @@ -287,16 +293,22 @@ static int vdec_start_streaming(struct vb2_queue *q, unsigned int count) > else > sess->streamon_cap = 1; > > - if (!sess->streamon_out || !sess->streamon_cap) > + if (!sess->streamon_out) > return 0; > > if (sess->status == STATUS_NEEDS_RESUME && > - q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { > + q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE && > + sess->changed_format) { > codec_ops->resume(sess); > sess->status = STATUS_RUNNING; > return 0; > } > > + if (sess->status == STATUS_RUNNING || > + sess->status == STATUS_NEEDS_RESUME || > + sess->status == STATUS_INIT) > + return 0; > + > sess->vififo_size = SIZE_VIFIFO; > sess->vififo_vaddr = > dma_alloc_coherent(sess->core->dev, sess->vififo_size, > @@ -321,13 +333,14 @@ static int vdec_start_streaming(struct vb2_queue *q, unsigned int count) > goto vififo_free; > > sess->sequence_cap = 0; > + sess->sequence_out = 0; > if (vdec_codec_needs_recycle(sess)) > sess->recycle_thread = kthread_run(vdec_recycle_thread, sess, > "vdec_recycle"); > > - sess->status = STATUS_RUNNING; > + sess->status = STATUS_INIT; > core->cur_sess = sess; > - > + schedule_work(&sess->esparser_queue_work); > return 0; > > vififo_free: > @@ -384,6 +397,7 @@ static void vdec_stop_streaming(struct vb2_queue *q) > struct vb2_v4l2_buffer *buf; > > if (sess->status == STATUS_RUNNING || > + sess->status == STATUS_INIT || > (sess->status == STATUS_NEEDS_RESUME && > (!sess->streamon_out || !sess->streamon_cap))) { > if (vdec_codec_needs_recycle(sess)) > @@ -474,20 +488,33 @@ vdec_try_fmt_common(struct amvdec_session *sess, u32 size, > struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp; > struct v4l2_plane_pix_format *pfmt = pixmp->plane_fmt; > const struct amvdec_format *fmts = sess->core->platform->formats; > - const struct amvdec_format *fmt_out; > + const struct amvdec_format *fmt_out = NULL; > + u32 output_size = 0; > > memset(pfmt[0].reserved, 0, sizeof(pfmt[0].reserved)); > memset(pixmp->reserved, 0, sizeof(pixmp->reserved)); > > - if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { > + switch (f->type) { > + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: > fmt_out = find_format(fmts, size, pixmp->pixelformat); > if (!fmt_out) { > pixmp->pixelformat = V4L2_PIX_FMT_MPEG2; > fmt_out = find_format(fmts, size, pixmp->pixelformat); > } > + break; > + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: > + fmt_out = sess->fmt_out; > + break; > + default: > + return NULL; > + } > + > + pixmp->width = clamp(pixmp->width, (u32)256, fmt_out->max_width); > + pixmp->height = clamp(pixmp->height, (u32)144, fmt_out->max_height); > + output_size = get_output_size(pixmp->width, pixmp->height); output_size is never used! drivers/staging/media/meson/vdec/vdec.c: In function ‘vdec_try_fmt_common’: drivers/staging/media/meson/vdec/vdec.c:492:6: warning: variable ‘output_size’ set but not used [-Wunused-but-set-variable] 492 | u32 output_size = 0; | ^~~~~~~~~~~ Regards, Hans > > - pfmt[0].sizeimage = > - get_output_size(pixmp->width, pixmp->height); > + if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { > + pfmt[0].sizeimage = sess->src_buffer_size; > pfmt[0].bytesperline = 0; > pixmp->num_planes = 1; > } else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { > @@ -519,8 +546,6 @@ vdec_try_fmt_common(struct amvdec_session *sess, u32 size, > pfmt[2].bytesperline = ALIGN(pixmp->width, 64) / 2; > pixmp->num_planes = 3; > } > - } else { > - return NULL; > } > > pixmp->width = clamp(pixmp->width, (u32)256, fmt_out->max_width); > @@ -584,6 +609,8 @@ static int vdec_s_fmt(struct file *file, void *fh, struct v4l2_format *f) > orig_pixmp = *pixmp; > > fmt_out = vdec_try_fmt_common(sess, num_formats, f); > + if (!fmt_out) > + return -EINVAL; > > if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { > pixfmt_out = pixmp->pixelformat; > @@ -608,6 +635,7 @@ static int vdec_s_fmt(struct file *file, void *fh, struct v4l2_format *f) > sess->ycbcr_enc = pixmp->ycbcr_enc; > sess->quantization = pixmp->quantization; > sess->xfer_func = pixmp->xfer_func; > + sess->src_buffer_size = pixmp->plane_fmt[0].sizeimage; > } > > memset(&format, 0, sizeof(format)); > @@ -699,29 +727,28 @@ vdec_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *cmd) > if (!(sess->streamon_out & sess->streamon_cap)) > return 0; > > - /* Currently not handled since we do not support dynamic resolution > - * for MPEG2. We consider both queues streaming to mean that the > - * decoding session is started > - */ > - if (cmd->cmd == V4L2_DEC_CMD_START) > + if (cmd->cmd == V4L2_DEC_CMD_START) { > + sess->should_stop = 0; > return 0; > + } > > /* Should not happen */ > if (cmd->cmd != V4L2_DEC_CMD_STOP) > return -EINVAL; > > dev_dbg(dev, "Received V4L2_DEC_CMD_STOP\n"); > - sess->should_stop = 1; > > - vdec_wait_inactive(sess); > + sess->should_stop = 1; > > if (codec_ops->drain) { > + vdec_wait_inactive(sess); > codec_ops->drain(sess); > } else if (codec_ops->eos_sequence) { > u32 len; > const u8 *data = codec_ops->eos_sequence(&len); > > esparser_queue_eos(sess->core, data, len); > + vdec_wait_inactive(sess); > } > > return ret; > @@ -881,6 +908,7 @@ static int vdec_open(struct file *file) > sess->height = 720; > sess->pixelaspect.numerator = 1; > sess->pixelaspect.denominator = 1; > + sess->src_buffer_size = SZ_1M; > > INIT_LIST_HEAD(&sess->timestamps); > INIT_LIST_HEAD(&sess->bufs_recycle); > diff --git a/drivers/staging/media/meson/vdec/vdec.h b/drivers/staging/media/meson/vdec/vdec.h > index d811e7976519..163d6dddfad6 100644 > --- a/drivers/staging/media/meson/vdec/vdec.h > +++ b/drivers/staging/media/meson/vdec/vdec.h > @@ -29,13 +29,19 @@ struct amvdec_buffer { > * struct amvdec_timestamp - stores a src timestamp along with a VIFIFO offset > * > * @list: used to make lists out of this struct > - * @ts: timestamp > + * @tc: timecode from the v4l2 buffer > + * @ts: timestamp from the VB2 buffer > * @offset: offset in the VIFIFO where the associated packet was written > + * @flags: flags from the v4l2 buffer > + * @used_count: times this timestamp was checked for a match with a dst buffer > */ > struct amvdec_timestamp { > struct list_head list; > + struct v4l2_timecode tc; > u64 ts; > u32 offset; > + u32 flags; > + u32 used_count; > }; > > struct amvdec_session; > @@ -164,6 +170,7 @@ struct amvdec_format { > > enum amvdec_status { > STATUS_STOPPED, > + STATUS_INIT, > STATUS_RUNNING, > STATUS_NEEDS_RESUME, > }; > @@ -179,6 +186,7 @@ enum amvdec_status { > * @ctrl_min_buf_capture: V4L2 control V4L2_CID_MIN_BUFFERS_FOR_CAPTURE > * @fmt_out: vdec pixel format for the OUTPUT queue > * @pixfmt_cap: V4L2 pixel format for the CAPTURE queue > + * @src_buffer_size: size in bytes of the OUTPUT buffers' only plane > * @width: current picture width > * @height: current picture height > * @colorspace: current colorspace > @@ -220,6 +228,7 @@ struct amvdec_session { > > const struct amvdec_format *fmt_out; > u32 pixfmt_cap; > + u32 src_buffer_size; > > u32 width; > u32 height; > @@ -234,10 +243,11 @@ struct amvdec_session { > struct work_struct esparser_queue_work; > > unsigned int streamon_cap, streamon_out; > - unsigned int sequence_cap; > + unsigned int sequence_cap, sequence_out; > unsigned int should_stop; > unsigned int keyframe_found; > unsigned int num_dst_bufs; > + unsigned int changed_format; > > u8 canvas_alloc[MAX_CANVAS]; > u32 canvas_num; > diff --git a/drivers/staging/media/meson/vdec/vdec_helpers.c b/drivers/staging/media/meson/vdec/vdec_helpers.c > index f16948bdbf2f..ff4333074197 100644 > --- a/drivers/staging/media/meson/vdec/vdec_helpers.c > +++ b/drivers/staging/media/meson/vdec/vdec_helpers.c > @@ -200,33 +200,23 @@ int amvdec_set_canvases(struct amvdec_session *sess, > } > EXPORT_SYMBOL_GPL(amvdec_set_canvases); > > -void amvdec_add_ts_reorder(struct amvdec_session *sess, u64 ts, u32 offset) > +void amvdec_add_ts(struct amvdec_session *sess, u64 ts, > + struct v4l2_timecode tc, u32 offset, u32 vbuf_flags) > { > - struct amvdec_timestamp *new_ts, *tmp; > + struct amvdec_timestamp *new_ts; > unsigned long flags; > > - new_ts = kmalloc(sizeof(*new_ts), GFP_KERNEL); > + new_ts = kzalloc(sizeof(*new_ts), GFP_KERNEL); > new_ts->ts = ts; > + new_ts->tc = tc; > new_ts->offset = offset; > + new_ts->flags = vbuf_flags; > > spin_lock_irqsave(&sess->ts_spinlock, flags); > - > - if (list_empty(&sess->timestamps)) > - goto add_tail; > - > - list_for_each_entry(tmp, &sess->timestamps, list) { > - if (ts <= tmp->ts) { > - list_add_tail(&new_ts->list, &tmp->list); > - goto unlock; > - } > - } > - > -add_tail: > list_add_tail(&new_ts->list, &sess->timestamps); > -unlock: > spin_unlock_irqrestore(&sess->ts_spinlock, flags); > } > -EXPORT_SYMBOL_GPL(amvdec_add_ts_reorder); > +EXPORT_SYMBOL_GPL(amvdec_add_ts); > > void amvdec_remove_ts(struct amvdec_session *sess, u64 ts) > { > @@ -251,8 +241,8 @@ EXPORT_SYMBOL_GPL(amvdec_remove_ts); > > static void dst_buf_done(struct amvdec_session *sess, > struct vb2_v4l2_buffer *vbuf, > - u32 field, > - u64 timestamp) > + u32 field, u64 timestamp, > + struct v4l2_timecode timecode, u32 flags) > { > struct device *dev = sess->core->dev_dec; > u32 output_size = amvdec_get_output_size(sess); > @@ -271,19 +261,23 @@ static void dst_buf_done(struct amvdec_session *sess, > > vbuf->vb2_buf.timestamp = timestamp; > vbuf->sequence = sess->sequence_cap++; > + vbuf->flags = flags; > + vbuf->timecode = timecode; > > if (sess->should_stop && > - atomic_read(&sess->esparser_queued_bufs) <= 2) { > + atomic_read(&sess->esparser_queued_bufs) <= 1) { > const struct v4l2_event ev = { .type = V4L2_EVENT_EOS }; > > - dev_dbg(dev, "Signaling EOS\n"); > + dev_dbg(dev, "Signaling EOS, sequence_cap = %u\n", > + sess->sequence_cap - 1); > v4l2_event_queue_fh(&sess->fh, &ev); > vbuf->flags |= V4L2_BUF_FLAG_LAST; > } else if (sess->should_stop) > dev_dbg(dev, "should_stop, %u bufs remain\n", > atomic_read(&sess->esparser_queued_bufs)); > > - dev_dbg(dev, "Buffer %u done\n", vbuf->vb2_buf.index); > + dev_dbg(dev, "Buffer %u done, ts = %llu, flags = %08X\n", > + vbuf->vb2_buf.index, timestamp, flags); > vbuf->field = field; > v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_DONE); > > @@ -297,7 +291,9 @@ void amvdec_dst_buf_done(struct amvdec_session *sess, > struct device *dev = sess->core->dev_dec; > struct amvdec_timestamp *tmp; > struct list_head *timestamps = &sess->timestamps; > + struct v4l2_timecode timecode; > u64 timestamp; > + u32 vbuf_flags; > unsigned long flags; > > spin_lock_irqsave(&sess->ts_spinlock, flags); > @@ -312,11 +308,13 @@ void amvdec_dst_buf_done(struct amvdec_session *sess, > > tmp = list_first_entry(timestamps, struct amvdec_timestamp, list); > timestamp = tmp->ts; > + timecode = tmp->tc; > + vbuf_flags = tmp->flags; > list_del(&tmp->list); > kfree(tmp); > spin_unlock_irqrestore(&sess->ts_spinlock, flags); > > - dst_buf_done(sess, vbuf, field, timestamp); > + dst_buf_done(sess, vbuf, field, timestamp, timecode, vbuf_flags); > atomic_dec(&sess->esparser_queued_bufs); > } > EXPORT_SYMBOL_GPL(amvdec_dst_buf_done); > @@ -328,48 +326,43 @@ void amvdec_dst_buf_done_offset(struct amvdec_session *sess, > struct device *dev = sess->core->dev_dec; > struct amvdec_timestamp *match = NULL; > struct amvdec_timestamp *tmp, *n; > + struct v4l2_timecode timecode = { 0 }; > u64 timestamp = 0; > + u32 vbuf_flags = 0; > unsigned long flags; > > spin_lock_irqsave(&sess->ts_spinlock, flags); > > /* Look for our vififo offset to get the corresponding timestamp. */ > list_for_each_entry_safe(tmp, n, &sess->timestamps, list) { > - s64 delta = (s64)offset - tmp->offset; > - > - /* Offsets reported by codecs usually differ slightly, > - * so we need some wiggle room. > - * 4KiB being the minimum packet size, there is no risk here. > - */ > - if (delta > (-1 * (s32)SZ_4K) && delta < SZ_4K) { > - match = tmp; > + if (tmp->offset > offset) { > + /* > + * Delete any record that remained unused for 32 match > + * checks > + */ > + if (tmp->used_count++ >= 32) { > + list_del(&tmp->list); > + kfree(tmp); > + } > break; > } > > - if (!allow_drop) > - continue; > - > - /* Delete any timestamp entry that appears before our target > - * (not all src packets/timestamps lead to a frame) > - */ > - if (delta > 0 || delta < -1 * (s32)sess->vififo_size) { > - atomic_dec(&sess->esparser_queued_bufs); > - list_del(&tmp->list); > - kfree(tmp); > - } > + match = tmp; > } > > if (!match) { > - dev_dbg(dev, "Buffer %u done but can't match offset (%08X)\n", > + dev_err(dev, "Buffer %u done but can't match offset (%08X)\n", > vbuf->vb2_buf.index, offset); > } else { > timestamp = match->ts; > + timecode = match->tc; > + vbuf_flags = match->flags; > list_del(&match->list); > kfree(match); > } > spin_unlock_irqrestore(&sess->ts_spinlock, flags); > > - dst_buf_done(sess, vbuf, field, timestamp); > + dst_buf_done(sess, vbuf, field, timestamp, timecode, vbuf_flags); > if (match) > atomic_dec(&sess->esparser_queued_bufs); > } > @@ -420,7 +413,8 @@ void amvdec_src_change(struct amvdec_session *sess, u32 width, > > v4l2_ctrl_s_ctrl(sess->ctrl_min_buf_capture, dpb_size); > > - /* Check if the capture queue is already configured well for our > + /* > + * Check if the capture queue is already configured well for our > * usecase. If so, keep decoding with it and do not send the event > */ > if (sess->width == width && > @@ -430,6 +424,7 @@ void amvdec_src_change(struct amvdec_session *sess, u32 width, > return; > } > > + sess->changed_format = 0; > sess->width = width; > sess->height = height; > sess->status = STATUS_NEEDS_RESUME; > diff --git a/drivers/staging/media/meson/vdec/vdec_helpers.h b/drivers/staging/media/meson/vdec/vdec_helpers.h > index a455a9ee1cc2..165e6293ffba 100644 > --- a/drivers/staging/media/meson/vdec/vdec_helpers.h > +++ b/drivers/staging/media/meson/vdec/vdec_helpers.h > @@ -44,13 +44,15 @@ void amvdec_dst_buf_done_offset(struct amvdec_session *sess, > u32 offset, u32 field, bool allow_drop); > > /** > - * amvdec_add_ts_reorder() - Add a timestamp to the list in chronological order > + * amvdec_add_ts() - Add a timestamp to the list > * > * @sess: current session > * @ts: timestamp to add > * @offset: offset in the VIFIFO where the associated packet was written > + * @flags the vb2_v4l2_buffer flags > */ > -void amvdec_add_ts_reorder(struct amvdec_session *sess, u64 ts, u32 offset); > +void amvdec_add_ts(struct amvdec_session *sess, u64 ts, > + struct v4l2_timecode tc, u32 offset, u32 flags); > void amvdec_remove_ts(struct amvdec_session *sess, u64 ts); > > /** > diff --git a/drivers/staging/media/meson/vdec/vdec_platform.c b/drivers/staging/media/meson/vdec/vdec_platform.c > index 824dbc7f46f5..accad8f8929a 100644 > --- a/drivers/staging/media/meson/vdec/vdec_platform.c > +++ b/drivers/staging/media/meson/vdec/vdec_platform.c > @@ -21,6 +21,7 @@ static const struct amvdec_format vdec_formats_gxbb[] = { > .codec_ops = &codec_mpeg12_ops, > .firmware_path = "meson/vdec/gxl_mpeg12.bin", > .pixfmts_cap = { V4L2_PIX_FMT_NV12M, V4L2_PIX_FMT_YUV420M, 0 }, > + .flags = V4L2_FMT_FLAG_COMPRESSED, > }, { > .pixfmt = V4L2_PIX_FMT_MPEG2, > .min_buffers = 8, > @@ -31,6 +32,7 @@ static const struct amvdec_format vdec_formats_gxbb[] = { > .codec_ops = &codec_mpeg12_ops, > .firmware_path = "meson/vdec/gxl_mpeg12.bin", > .pixfmts_cap = { V4L2_PIX_FMT_NV12M, V4L2_PIX_FMT_YUV420M, 0 }, > + .flags = V4L2_FMT_FLAG_COMPRESSED, > }, > }; > > @@ -45,6 +47,7 @@ static const struct amvdec_format vdec_formats_gxl[] = { > .codec_ops = &codec_mpeg12_ops, > .firmware_path = "meson/vdec/gxl_mpeg12.bin", > .pixfmts_cap = { V4L2_PIX_FMT_NV12M, V4L2_PIX_FMT_YUV420M, 0 }, > + .flags = V4L2_FMT_FLAG_COMPRESSED, > }, { > .pixfmt = V4L2_PIX_FMT_MPEG2, > .min_buffers = 8, > @@ -55,6 +58,7 @@ static const struct amvdec_format vdec_formats_gxl[] = { > .codec_ops = &codec_mpeg12_ops, > .firmware_path = "meson/vdec/gxl_mpeg12.bin", > .pixfmts_cap = { V4L2_PIX_FMT_NV12M, V4L2_PIX_FMT_YUV420M, 0 }, > + .flags = V4L2_FMT_FLAG_COMPRESSED, > }, > }; > > @@ -69,6 +73,7 @@ static const struct amvdec_format vdec_formats_gxm[] = { > .codec_ops = &codec_mpeg12_ops, > .firmware_path = "meson/vdec/gxl_mpeg12.bin", > .pixfmts_cap = { V4L2_PIX_FMT_NV12M, V4L2_PIX_FMT_YUV420M, 0 }, > + .flags = V4L2_FMT_FLAG_COMPRESSED, > }, { > .pixfmt = V4L2_PIX_FMT_MPEG2, > .min_buffers = 8, > @@ -79,6 +84,7 @@ static const struct amvdec_format vdec_formats_gxm[] = { > .codec_ops = &codec_mpeg12_ops, > .firmware_path = "meson/vdec/gxl_mpeg12.bin", > .pixfmts_cap = { V4L2_PIX_FMT_NV12M, V4L2_PIX_FMT_YUV420M, 0 }, > + .flags = V4L2_FMT_FLAG_COMPRESSED, > }, > }; > >