diff options
author | Lubomir Rintel <lkundrak@v3.sk> | 2013-07-02 06:56:39 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <m.chehab@samsung.com> | 2013-09-03 08:24:19 -0400 |
commit | 6ee0faa52676ab648e486afb654fc92313d55943 (patch) | |
tree | 8182eef894d1e06b7623330e943285d6ef259d5c /drivers/media | |
parent | 3080072460bb0efd156e415bfea783279bf64e92 (diff) |
[media] usbtv: Throw corrupted frames away
Ignore out of order data and mark incomplete buffers as errored.
This gets rid of annoying flicker due to occassional garbage from hardware.
Signed-off-by: Lubomir Rintel <lkundrak@v3.sk>
Cc: Hans Verkuil <hans.verkuil@cisco.com>
Cc: Mauro Carvalho Chehab <mchehab@redhat.com>
Cc: linux-kernel@vger.kernel.org
Cc: linux-media@vger.kernel.org
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
Cc: stable@vger.kernel.org
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/usb/usbtv/usbtv.c | 15 |
1 files changed, 13 insertions, 2 deletions
diff --git a/drivers/media/usb/usbtv/usbtv.c b/drivers/media/usb/usbtv/usbtv.c index 55a45d34df22..8a505a90d318 100644 --- a/drivers/media/usb/usbtv/usbtv.c +++ b/drivers/media/usb/usbtv/usbtv.c | |||
@@ -88,6 +88,7 @@ struct usbtv { | |||
88 | /* Number of currently processed frame, useful find | 88 | /* Number of currently processed frame, useful find |
89 | * out when a new one begins. */ | 89 | * out when a new one begins. */ |
90 | u32 frame_id; | 90 | u32 frame_id; |
91 | int chunks_done; | ||
91 | 92 | ||
92 | enum { | 93 | enum { |
93 | USBTV_COMPOSITE_INPUT, | 94 | USBTV_COMPOSITE_INPUT, |
@@ -299,8 +300,13 @@ static void usbtv_image_chunk(struct usbtv *usbtv, u32 *chunk) | |||
299 | return; | 300 | return; |
300 | 301 | ||
301 | /* Beginning of a frame. */ | 302 | /* Beginning of a frame. */ |
302 | if (chunk_no == 0) | 303 | if (chunk_no == 0) { |
303 | usbtv->frame_id = frame_id; | 304 | usbtv->frame_id = frame_id; |
305 | usbtv->chunks_done = 0; | ||
306 | } | ||
307 | |||
308 | if (usbtv->frame_id != frame_id) | ||
309 | return; | ||
304 | 310 | ||
305 | spin_lock_irqsave(&usbtv->buflock, flags); | 311 | spin_lock_irqsave(&usbtv->buflock, flags); |
306 | if (list_empty(&usbtv->bufs)) { | 312 | if (list_empty(&usbtv->bufs)) { |
@@ -315,16 +321,21 @@ static void usbtv_image_chunk(struct usbtv *usbtv, u32 *chunk) | |||
315 | 321 | ||
316 | /* Copy the chunk data. */ | 322 | /* Copy the chunk data. */ |
317 | usbtv_chunk_to_vbuf(frame, &chunk[1], chunk_no, odd); | 323 | usbtv_chunk_to_vbuf(frame, &chunk[1], chunk_no, odd); |
324 | usbtv->chunks_done++; | ||
318 | 325 | ||
319 | /* Last chunk in a frame, signalling an end */ | 326 | /* Last chunk in a frame, signalling an end */ |
320 | if (odd && chunk_no == USBTV_CHUNKS-1) { | 327 | if (odd && chunk_no == USBTV_CHUNKS-1) { |
321 | int size = vb2_plane_size(&buf->vb, 0); | 328 | int size = vb2_plane_size(&buf->vb, 0); |
329 | enum vb2_buffer_state state = usbtv->chunks_done == | ||
330 | USBTV_CHUNKS ? | ||
331 | VB2_BUF_STATE_DONE : | ||
332 | VB2_BUF_STATE_ERROR; | ||
322 | 333 | ||
323 | buf->vb.v4l2_buf.field = V4L2_FIELD_INTERLACED; | 334 | buf->vb.v4l2_buf.field = V4L2_FIELD_INTERLACED; |
324 | buf->vb.v4l2_buf.sequence = usbtv->sequence++; | 335 | buf->vb.v4l2_buf.sequence = usbtv->sequence++; |
325 | v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp); | 336 | v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp); |
326 | vb2_set_plane_payload(&buf->vb, 0, size); | 337 | vb2_set_plane_payload(&buf->vb, 0, size); |
327 | vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE); | 338 | vb2_buffer_done(&buf->vb, state); |
328 | list_del(&buf->list); | 339 | list_del(&buf->list); |
329 | } | 340 | } |
330 | 341 | ||