lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <3c6be374-1b89-642a-6307-aca1f2ae7722@xs4all.nl>
Date:   Wed, 16 Oct 2019 14:38:40 +0200
From:   Hans Verkuil <hverkuil@...all.nl>
To:     Maxime Jourdan <mjourdan@...libre.com>,
        Mauro Carvalho Chehab <mchehab@...nel.org>,
        Hans Verkuil <hans.verkuil@...co.com>
Cc:     Kevin Hilman <khilman@...libre.com>,
        Jerome Brunet <jbrunet@...libre.com>,
        Neil Armstrong <narmstrong@...libre.com>,
        Martin Blumenstingl <martin.blumenstingl@...glemail.com>,
        linux-media@...r.kernel.org, linux-kernel@...r.kernel.org,
        linux-arm-kernel@...ts.infradead.org,
        linux-amlogic@...ts.infradead.org
Subject: Re: [PATCH 1/2] media: meson: vdec: bring up to compliance

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 <mjourdan@...libre.com>
> ---
>  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,
>  	},
>  };
>  
> 

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ