diff options
author | Lubomir Rintel <lkundrak@v3.sk> | 2013-07-02 06:56:39 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <m.chehab@samsung.com> | 2013-07-26 09:30:36 -0400 |
commit | f52dc448a344ddb90c8516c06656d62710baa869 (patch) | |
tree | d4834131e91eb55a9fd37f7cdd787aad2bb0986e /drivers | |
parent | a34cacab1565fdee77544b12407274ffb4d9daa0 (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>
Diffstat (limited to 'drivers')
-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 9dcc677f3015..91650173941a 100644 --- a/drivers/media/usb/usbtv/usbtv.c +++ b/drivers/media/usb/usbtv/usbtv.c | |||
@@ -89,6 +89,7 @@ struct usbtv { | |||
89 | /* Number of currently processed frame, useful find | 89 | /* Number of currently processed frame, useful find |
90 | * out when a new one begins. */ | 90 | * out when a new one begins. */ |
91 | u32 frame_id; | 91 | u32 frame_id; |
92 | int chunks_done; | ||
92 | 93 | ||
93 | int iso_size; | 94 | int iso_size; |
94 | unsigned int sequence; | 95 | unsigned int sequence; |
@@ -242,8 +243,13 @@ static void usbtv_image_chunk(struct usbtv *usbtv, u32 *chunk) | |||
242 | return; | 243 | return; |
243 | 244 | ||
244 | /* Beginning of a frame. */ | 245 | /* Beginning of a frame. */ |
245 | if (chunk_no == 0) | 246 | if (chunk_no == 0) { |
246 | usbtv->frame_id = frame_id; | 247 | usbtv->frame_id = frame_id; |
248 | usbtv->chunks_done = 0; | ||
249 | } | ||
250 | |||
251 | if (usbtv->frame_id != frame_id) | ||
252 | return; | ||
247 | 253 | ||
248 | spin_lock_irqsave(&usbtv->buflock, flags); | 254 | spin_lock_irqsave(&usbtv->buflock, flags); |
249 | if (list_empty(&usbtv->bufs)) { | 255 | if (list_empty(&usbtv->bufs)) { |
@@ -258,16 +264,21 @@ static void usbtv_image_chunk(struct usbtv *usbtv, u32 *chunk) | |||
258 | 264 | ||
259 | /* Copy the chunk data. */ | 265 | /* Copy the chunk data. */ |
260 | usbtv_chunk_to_vbuf(frame, &chunk[1], chunk_no, odd); | 266 | usbtv_chunk_to_vbuf(frame, &chunk[1], chunk_no, odd); |
267 | usbtv->chunks_done++; | ||
261 | 268 | ||
262 | /* Last chunk in a frame, signalling an end */ | 269 | /* Last chunk in a frame, signalling an end */ |
263 | if (odd && chunk_no == USBTV_CHUNKS-1) { | 270 | if (odd && chunk_no == USBTV_CHUNKS-1) { |
264 | int size = vb2_plane_size(&buf->vb, 0); | 271 | int size = vb2_plane_size(&buf->vb, 0); |
272 | enum vb2_buffer_state state = usbtv->chunks_done == | ||
273 | USBTV_CHUNKS ? | ||
274 | VB2_BUF_STATE_DONE : | ||
275 | VB2_BUF_STATE_ERROR; | ||
265 | 276 | ||
266 | buf->vb.v4l2_buf.field = V4L2_FIELD_INTERLACED; | 277 | buf->vb.v4l2_buf.field = V4L2_FIELD_INTERLACED; |
267 | buf->vb.v4l2_buf.sequence = usbtv->sequence++; | 278 | buf->vb.v4l2_buf.sequence = usbtv->sequence++; |
268 | v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp); | 279 | v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp); |
269 | vb2_set_plane_payload(&buf->vb, 0, size); | 280 | vb2_set_plane_payload(&buf->vb, 0, size); |
270 | vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE); | 281 | vb2_buffer_done(&buf->vb, state); |
271 | list_del(&buf->list); | 282 | list_del(&buf->list); |
272 | } | 283 | } |
273 | 284 | ||