aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
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-07-26 09:30:36 -0400
commitf52dc448a344ddb90c8516c06656d62710baa869 (patch)
treed4834131e91eb55a9fd37f7cdd787aad2bb0986e /drivers
parenta34cacab1565fdee77544b12407274ffb4d9daa0 (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.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 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