aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorLubomir Rintel <lkundrak@v3.sk>2013-07-02 06:56:39 -0400
committerMauro Carvalho Chehab <m.chehab@samsung.com>2013-09-03 08:24:19 -0400
commit6ee0faa52676ab648e486afb654fc92313d55943 (patch)
tree8182eef894d1e06b7623330e943285d6ef259d5c /drivers/media
parent3080072460bb0efd156e415bfea783279bf64e92 (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.c15
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