Re: [PATCH] media i.MX27 camera: properly detect frame loss.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Javier

On Mon, 2 Jan 2012, Javier Martin wrote:

> As V4L2 specification states, frame_count must also
> regard lost frames so that the user can handle that
> case properly.
> 
> This patch adds a mechanism to increment the frame
> counter even when a video buffer is not available
> and a discard buffer is used.
> 
> Signed-off-by: Javier Martin <javier.martin@xxxxxxxxxxxxxxxxx>
> ---
>  drivers/media/video/mx2_camera.c |   54 ++++++++++++++++++++++++--------------
>  1 files changed, 34 insertions(+), 20 deletions(-)
> 
> diff --git a/drivers/media/video/mx2_camera.c b/drivers/media/video/mx2_camera.c
> index ca76dd2..b244714 100644
> --- a/drivers/media/video/mx2_camera.c
> +++ b/drivers/media/video/mx2_camera.c
> @@ -256,6 +256,7 @@ struct mx2_camera_dev {
>  	size_t			discard_size;
>  	struct mx2_fmt_cfg	*emma_prp;
>  	u32			frame_count;
> +	unsigned int		firstirq;

_if_ we indeed end up using this field, it seems it can be just a bool.

>  };
>  
>  /* buffer for one video frame */
> @@ -370,6 +371,7 @@ static int mx2_camera_add_device(struct soc_camera_device *icd)
>  
>  	pcdev->icd = icd;
>  	pcdev->frame_count = 0;
> +	pcdev->firstirq = 1;
>  
>  	dev_info(icd->parent, "Camera driver attached to camera %d\n",
>  		 icd->devnum);
> @@ -572,6 +574,7 @@ static void mx2_videobuf_queue(struct videobuf_queue *vq,
>  	struct soc_camera_host *ici =
>  		to_soc_camera_host(icd->parent);
>  	struct mx2_camera_dev *pcdev = ici->priv;
> +	struct mx2_fmt_cfg *prp = pcdev->emma_prp;
>  	struct mx2_buffer *buf = container_of(vb, struct mx2_buffer, vb);
>  	unsigned long flags;
>  
> @@ -584,6 +587,26 @@ static void mx2_videobuf_queue(struct videobuf_queue *vq,
>  	list_add_tail(&vb->queue, &pcdev->capture);
>  
>  	if (mx27_camera_emma(pcdev)) {
> +		if (prp->cfg.channel == 1) {
> +			writel(PRP_CNTL_CH1EN |
> +				PRP_CNTL_CSIEN |
> +				prp->cfg.in_fmt |
> +				prp->cfg.out_fmt |
> +				PRP_CNTL_CH1_LEN |
> +				PRP_CNTL_CH1BYP |
> +				PRP_CNTL_CH1_TSKIP(0) |
> +				PRP_CNTL_IN_TSKIP(0),
> +				pcdev->base_emma + PRP_CNTL);
> +		} else {
> +			writel(PRP_CNTL_CH2EN |
> +				PRP_CNTL_CSIEN |
> +				prp->cfg.in_fmt |
> +				prp->cfg.out_fmt |
> +				PRP_CNTL_CH2_LEN |
> +				PRP_CNTL_CH2_TSKIP(0) |
> +				PRP_CNTL_IN_TSKIP(0),
> +				pcdev->base_emma + PRP_CNTL);
> +		}

Is this related and why is this needed?

>  		goto out;
>  	} else { /* cpu_is_mx25() */
>  		u32 csicr3, dma_inten = 0;
> @@ -747,16 +770,6 @@ static void mx27_camera_emma_buf_init(struct soc_camera_device *icd,
>  		writel(pcdev->discard_buffer_dma,
>  				pcdev->base_emma + PRP_DEST_RGB2_PTR);
>  
> -		writel(PRP_CNTL_CH1EN |
> -				PRP_CNTL_CSIEN |
> -				prp->cfg.in_fmt |
> -				prp->cfg.out_fmt |
> -				PRP_CNTL_CH1_LEN |
> -				PRP_CNTL_CH1BYP |
> -				PRP_CNTL_CH1_TSKIP(0) |
> -				PRP_CNTL_IN_TSKIP(0),
> -				pcdev->base_emma + PRP_CNTL);
> -
>  		writel((icd->user_width << 16) | icd->user_height,
>  			pcdev->base_emma + PRP_SRC_FRAME_SIZE);
>  		writel((icd->user_width << 16) | icd->user_height,
> @@ -784,15 +797,6 @@ static void mx27_camera_emma_buf_init(struct soc_camera_device *icd,
>  				pcdev->base_emma + PRP_SOURCE_CR_PTR);
>  		}
>  
> -		writel(PRP_CNTL_CH2EN |
> -			PRP_CNTL_CSIEN |
> -			prp->cfg.in_fmt |
> -			prp->cfg.out_fmt |
> -			PRP_CNTL_CH2_LEN |
> -			PRP_CNTL_CH2_TSKIP(0) |
> -			PRP_CNTL_IN_TSKIP(0),
> -			pcdev->base_emma + PRP_CNTL);
> -
>  		writel((icd->user_width << 16) | icd->user_height,
>  			pcdev->base_emma + PRP_SRC_FRAME_SIZE);
>  
> @@ -1214,7 +1218,6 @@ static void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev,
>  		vb->state = state;
>  		do_gettimeofday(&vb->ts);
>  		vb->field_count = pcdev->frame_count * 2;
> -		pcdev->frame_count++;
>  
>  		wake_up(&vb->done);
>  	}

Wouldn't you achieve the same by simply initialising frame_count to -1 and 
incrementing it unconditionally just below this if?

> @@ -1239,6 +1242,17 @@ static void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev,
>  		return;
>  	}
>  
> +	/*
> +	 * According to V4L2 specification, first valid sequence number must
> +	 * be 0. However, by design the first received frame is written to the
> +	 * discard buffer even when a video buffer is available. For that reason
> +	 * we don't increment frame_count the first time.
> +	 */
> +	if (pcdev->firstirq)
> +		pcdev->firstirq = 0;
> +	else
> +		pcdev->frame_count++;
> +
>  	buf = list_entry(pcdev->capture.next,
>  			struct mx2_buffer, vb.queue);

Aren't you losing frames, that you receive, while the capture queue is 
empty? Whereas the above proposed approach should catch them all, I think.

Thanks
Guennadi
---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
http://www.open-technology.de/
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux