[PATCH 3/3] media: uvcvideo: Implement dual stream quirk to fix loss of usb packets

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Some cameras, such as the Sonix Technology Co. 292A exhibit issues when
running two parallel streams, causing USB packets to be dropped when an
H.264 stream posts a keyframe while an MJPEG stream is running
simultaneously. This occasionally causes the driver to erroneously
output two consecutive JPEG images as a single frame.

To fix this, we inspect the buffer, and trigger a new frame when we
find an SOI, inverting the FID to make sure no frames are erroneously
dropped.

Signed-off-by: Isaac Scott <isaac.scott@xxxxxxxxxxxxxxxx>
---
 drivers/media/usb/uvc/uvc_video.c | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c
index 2fb9f2b59afc..f754109f5e96 100644
--- a/drivers/media/usb/uvc/uvc_video.c
+++ b/drivers/media/usb/uvc/uvc_video.c
@@ -1211,6 +1211,30 @@ static int uvc_video_decode_start(struct uvc_streaming *stream,
 		return -EAGAIN;
 	}
 
+	/*
+	 * Some cameras, such as the Sonix Technology Co. 292A exhibit issues
+	 * when running two parallel streams, causing USB packets to be dropped
+	 * when an H.264 stream posts a keyframe while an MJPEG stream is
+	 * running simultaneously. This occasionally causes the driver to
+	 * erroneously output two consecutive JPEG images as a single frame.
+	 *
+	 * Check the buffer for a new SOI on JPEG streams and complete the
+	 * preceding buffer using EAGAIN, and invert the FID to make sure the
+	 * erroneous frame is not dropped.
+	 */
+	if ((stream->dev->quirks & UVC_QUIRK_MJPEG_NO_EOF) &&
+	    (stream->cur_format->fcc == V4L2_PIX_FMT_MJPEG ||
+	     stream->cur_format->fcc == V4L2_PIX_FMT_JPEG)) {
+		const u8 *packet = data + header_len;
+
+		if ((packet[0] == 0xff && packet[1] == 0xd8) && buf->bytesused != 0) {
+			buf->state = UVC_BUF_STATE_READY;
+			buf->error = 1;
+			stream->last_fid ^= UVC_STREAM_FID;
+			return -EAGAIN;
+		}
+	}
+
 	stream->last_fid = fid;
 
 	return header_len;
-- 
2.43.0





[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux