Commit 8a652a17 authored by Adam Goode's avatar Adam Goode Committed by Mauro Carvalho Chehab

media: uvcvideo: Ensure all probed info is returned to v4l2

bFrameIndex and bFormatIndex can be negotiated by the camera during
probing, resulting in the camera choosing a different format than
expected. v4l2 can already accommodate such changes, but the code was
not updating the proper fields.

Without such a change, v4l2 would potentially interpret the payload
incorrectly, causing corrupted output. This was happening on the
Elgato HD60 S+, which currently always renegotiates to format 1.

As an aside, the Elgato firmware is buggy and should not be renegotating,
but it is still a valid thing for the camera to do. Both macOS and Windows
will properly probe and read uncorrupted images from this camera.

With this change, both qv4l2 and chromium can now read uncorrupted video
from the Elgato HD60 S+.

[Add blank lines, remove periods at the of messages]
Signed-off-by: default avatarAdam Goode <agoode@google.com>
Signed-off-by: default avatarLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+huawei@kernel.org>
parent 171994e4
...@@ -247,11 +247,41 @@ static int uvc_v4l2_try_format(struct uvc_streaming *stream, ...@@ -247,11 +247,41 @@ static int uvc_v4l2_try_format(struct uvc_streaming *stream,
if (ret < 0) if (ret < 0)
goto done; goto done;
/* After the probe, update fmt with the values returned from
* negotiation with the device.
*/
for (i = 0; i < stream->nformats; ++i) {
if (probe->bFormatIndex == stream->format[i].index) {
format = &stream->format[i];
break;
}
}
if (i == stream->nformats) {
uvc_trace(UVC_TRACE_FORMAT, "Unknown bFormatIndex %u\n",
probe->bFormatIndex);
return -EINVAL;
}
for (i = 0; i < format->nframes; ++i) {
if (probe->bFrameIndex == format->frame[i].bFrameIndex) {
frame = &format->frame[i];
break;
}
}
if (i == format->nframes) {
uvc_trace(UVC_TRACE_FORMAT, "Unknown bFrameIndex %u\n",
probe->bFrameIndex);
return -EINVAL;
}
fmt->fmt.pix.width = frame->wWidth; fmt->fmt.pix.width = frame->wWidth;
fmt->fmt.pix.height = frame->wHeight; fmt->fmt.pix.height = frame->wHeight;
fmt->fmt.pix.field = V4L2_FIELD_NONE; fmt->fmt.pix.field = V4L2_FIELD_NONE;
fmt->fmt.pix.bytesperline = uvc_v4l2_get_bytesperline(format, frame); fmt->fmt.pix.bytesperline = uvc_v4l2_get_bytesperline(format, frame);
fmt->fmt.pix.sizeimage = probe->dwMaxVideoFrameSize; fmt->fmt.pix.sizeimage = probe->dwMaxVideoFrameSize;
fmt->fmt.pix.pixelformat = format->fcc;
fmt->fmt.pix.colorspace = format->colorspace; fmt->fmt.pix.colorspace = format->colorspace;
if (uvc_format != NULL) if (uvc_format != NULL)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment