There are many dropped fields with some sources, leading to many redundant fields without counterparts. When this redundant field is odd, a new frame is pushed containing this odd field interleaved with whatever was left in the buffer, causing video artifacts. Do not push a new frame after processing every odd field, but do it only after those which come after an even field. Signed-off-by: Nikola Forró <nikola.forro@xxxxxxxxx> --- drivers/media/usb/usbtv/usbtv-video.c | 33 +++++++++++++++++++-------------- drivers/media/usb/usbtv/usbtv.h | 1 + 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/drivers/media/usb/usbtv/usbtv-video.c b/drivers/media/usb/usbtv/usbtv-video.c index e645c9d..a20fd60 100644 --- a/drivers/media/usb/usbtv/usbtv-video.c +++ b/drivers/media/usb/usbtv/usbtv-video.c @@ -312,20 +312,24 @@ static void usbtv_image_chunk(struct usbtv *usbtv, __be32 *chunk) usbtv_chunk_to_vbuf(frame, &chunk[1], chunk_no, odd); usbtv->chunks_done++; - /* Last chunk in a frame, signalling an end */ - if (odd && chunk_no == usbtv->n_chunks-1) { - int size = vb2_plane_size(&buf->vb.vb2_buf, 0); - enum vb2_buffer_state state = usbtv->chunks_done == - usbtv->n_chunks ? - VB2_BUF_STATE_DONE : - VB2_BUF_STATE_ERROR; - - buf->vb.field = V4L2_FIELD_INTERLACED; - buf->vb.sequence = usbtv->sequence++; - v4l2_get_timestamp(&buf->vb.timestamp); - vb2_set_plane_payload(&buf->vb.vb2_buf, 0, size); - vb2_buffer_done(&buf->vb.vb2_buf, state); - list_del(&buf->list); + /* Last chunk in a field */ + if (chunk_no == usbtv->n_chunks-1) { + /* Last chunk in a frame, signalling an end */ + if (odd && !usbtv->last_odd) { + int size = vb2_plane_size(&buf->vb.vb2_buf, 0); + enum vb2_buffer_state state = usbtv->chunks_done == + usbtv->n_chunks ? + VB2_BUF_STATE_DONE : + VB2_BUF_STATE_ERROR; + + buf->vb.field = V4L2_FIELD_INTERLACED; + buf->vb.sequence = usbtv->sequence++; + v4l2_get_timestamp(&buf->vb.timestamp); + vb2_set_plane_payload(&buf->vb.vb2_buf, 0, size); + vb2_buffer_done(&buf->vb.vb2_buf, state); + list_del(&buf->list); + } + usbtv->last_odd = odd; } spin_unlock_irqrestore(&usbtv->buflock, flags); @@ -640,6 +644,7 @@ static int usbtv_start_streaming(struct vb2_queue *vq, unsigned int count) if (usbtv->udev == NULL) return -ENODEV; + usbtv->last_odd = 1; usbtv->sequence = 0; return usbtv_start(usbtv); } diff --git a/drivers/media/usb/usbtv/usbtv.h b/drivers/media/usb/usbtv/usbtv.h index 19cb8bf..161b38d 100644 --- a/drivers/media/usb/usbtv/usbtv.h +++ b/drivers/media/usb/usbtv/usbtv.h @@ -95,6 +95,7 @@ struct usbtv { int width, height; int n_chunks; int iso_size; + int last_odd; unsigned int sequence; struct urb *isoc_urbs[USBTV_ISOC_TRANSFERS]; -- 2.6.4 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html