Skip to content

Commit

Permalink
V4L/DVB: uvcvideo: Drop corrupted compressed frames
Browse files Browse the repository at this point in the history
Corrupted video frames are dropped by default by the driver for
uncompressed formats. Data corruption is not less problematic for
compressed formats, so frame drop should be enabled by default for those
formats as well.

Mark buffers as faulty when an isochronous packet loss is detected for
any format, or when the buffer length doesn't match the image size for
uncompressed formats. Drop erroneous buffers regardless of whether the
format is compressed or uncompressed.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
  • Loading branch information
Laurent Pinchart authored and Mauro Carvalho Chehab committed Aug 9, 2010
1 parent df49d11 commit 9bde9f2
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 14 deletions.
13 changes: 9 additions & 4 deletions drivers/media/video/uvc/uvc_queue.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,14 @@
*
*/

void uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type)
void uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type,
int drop_corrupted)
{
mutex_init(&queue->mutex);
spin_lock_init(&queue->irqlock);
INIT_LIST_HEAD(&queue->mainqueue);
INIT_LIST_HEAD(&queue->irqqueue);
queue->flags = drop_corrupted ? UVC_QUEUE_DROP_CORRUPTED : 0;
queue->type = type;
}

Expand Down Expand Up @@ -435,8 +437,10 @@ int uvc_queue_enable(struct uvc_video_queue *queue, int enable)
uvc_queue_cancel(queue, 0);
INIT_LIST_HEAD(&queue->mainqueue);

for (i = 0; i < queue->count; ++i)
for (i = 0; i < queue->count; ++i) {
queue->buffer[i].error = 0;
queue->buffer[i].state = UVC_BUF_STATE_IDLE;
}

queue->flags &= ~UVC_QUEUE_STREAMING;
}
Expand Down Expand Up @@ -488,15 +492,16 @@ struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue,
struct uvc_buffer *nextbuf;
unsigned long flags;

if ((queue->flags & UVC_QUEUE_DROP_INCOMPLETE) &&
buf->buf.length != buf->buf.bytesused) {
if ((queue->flags & UVC_QUEUE_DROP_CORRUPTED) && buf->error) {
buf->error = 0;
buf->state = UVC_BUF_STATE_QUEUED;
buf->buf.bytesused = 0;
return buf;
}

spin_lock_irqsave(&queue->irqlock, flags);
list_del(&buf->queue);
buf->error = 0;
buf->state = UVC_BUF_STATE_DONE;
if (!list_empty(&queue->irqqueue))
nextbuf = list_first_entry(&queue->irqqueue, struct uvc_buffer,
Expand Down
19 changes: 11 additions & 8 deletions drivers/media/video/uvc/uvc_video.c
Original file line number Diff line number Diff line change
Expand Up @@ -555,6 +555,9 @@ static void uvc_video_decode_isoc(struct urb *urb, struct uvc_streaming *stream,
if (urb->iso_frame_desc[i].status < 0) {
uvc_trace(UVC_TRACE_FRAME, "USB isochronous frame "
"lost (%d).\n", urb->iso_frame_desc[i].status);
/* Mark the buffer as faulty. */
if (buf != NULL)
buf->error = 1;
continue;
}

Expand All @@ -579,8 +582,14 @@ static void uvc_video_decode_isoc(struct urb *urb, struct uvc_streaming *stream,
uvc_video_decode_end(stream, buf, mem,
urb->iso_frame_desc[i].actual_length);

if (buf->state == UVC_BUF_STATE_READY)
if (buf->state == UVC_BUF_STATE_READY) {
if (buf->buf.length != buf->buf.bytesused &&
!(stream->cur_format->flags &
UVC_FMT_FLAG_COMPRESSED))
buf->error = 1;

buf = uvc_queue_next_buffer(&stream->queue, buf);
}
}
}

Expand Down Expand Up @@ -1104,7 +1113,7 @@ int uvc_video_init(struct uvc_streaming *stream)
atomic_set(&stream->active, 0);

/* Initialize the video buffers queue. */
uvc_queue_init(&stream->queue, stream->type);
uvc_queue_init(&stream->queue, stream->type, !uvc_no_drop_param);

/* Alternate setting 0 should be the default, yet the XBox Live Vision
* Cam (and possibly other devices) crash or otherwise misbehave if
Expand Down Expand Up @@ -1197,12 +1206,6 @@ int uvc_video_enable(struct uvc_streaming *stream, int enable)
return 0;
}

if ((stream->cur_format->flags & UVC_FMT_FLAG_COMPRESSED) ||
uvc_no_drop_param)
stream->queue.flags &= ~UVC_QUEUE_DROP_INCOMPLETE;
else
stream->queue.flags |= UVC_QUEUE_DROP_INCOMPLETE;

ret = uvc_queue_enable(&stream->queue, 1);
if (ret < 0)
return ret;
Expand Down
5 changes: 3 additions & 2 deletions drivers/media/video/uvc/uvcvideo.h
Original file line number Diff line number Diff line change
Expand Up @@ -379,11 +379,12 @@ struct uvc_buffer {
struct list_head queue;
wait_queue_head_t wait;
enum uvc_buffer_state state;
unsigned int error;
};

#define UVC_QUEUE_STREAMING (1 << 0)
#define UVC_QUEUE_DISCONNECTED (1 << 1)
#define UVC_QUEUE_DROP_INCOMPLETE (1 << 2)
#define UVC_QUEUE_DROP_CORRUPTED (1 << 2)

struct uvc_video_queue {
enum v4l2_buf_type type;
Expand Down Expand Up @@ -562,7 +563,7 @@ extern struct uvc_driver uvc_driver;

/* Video buffers queue management. */
extern void uvc_queue_init(struct uvc_video_queue *queue,
enum v4l2_buf_type type);
enum v4l2_buf_type type, int drop_corrupted);
extern int uvc_alloc_buffers(struct uvc_video_queue *queue,
unsigned int nbuffers, unsigned int buflength);
extern int uvc_free_buffers(struct uvc_video_queue *queue);
Expand Down

0 comments on commit 9bde9f2

Please sign in to comment.