Discussion:
[linux-uvc-devel] [PATCHv2 1/2] videodev2: add V4L2_PIX_FMT_Sxxxx10_1X10 formats
Peter Ross
2014-02-23 05:54:25 UTC
Permalink
Signed-off-by: Peter Ross <***@xvid.org>
---
include/uapi/linux/videodev2.h | 4 ++++
1 file changed, 4 insertions(+)

diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 6ae7bbe..a12381e 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -366,6 +366,10 @@ struct v4l2_pix_format {
#define V4L2_PIX_FMT_SGBRG10 v4l2_fourcc('G', 'B', '1', '0') /* 10 GBGB.. RGRG.. */
#define V4L2_PIX_FMT_SGRBG10 v4l2_fourcc('B', 'A', '1', '0') /* 10 GRGR.. BGBG.. */
#define V4L2_PIX_FMT_SRGGB10 v4l2_fourcc('R', 'G', '1', '0') /* 10 RGRG.. GBGB.. */
+#define V4L2_PIX_FMT_SBGGR10_1X10 v4l2_fourcc('B', 'G', '1', 10) /* 10 BGBG.. GRGR.. (10 bits per sample; no padding) */
+#define V4L2_PIX_FMT_SGBRG10_1X10 v4l2_fourcc('G', 'B', '1', 10) /* 10 GBGB.. RGRG.. (10 bits per sample; no padding) */
+#define V4L2_PIX_FMT_SGRBG10_1X10 v4l2_fourcc('B', 'A', '1', 10) /* 10 GRGR.. BGBG.. (10 bits per sample; no padding) */
+#define V4L2_PIX_FMT_SRGGB10_1X10 v4l2_fourcc('R', 'G', '1', 10) /* 10 RGRG.. GBGB.. (10 bits per sample; no padding) */
#define V4L2_PIX_FMT_SBGGR12 v4l2_fourcc('B', 'G', '1', '2') /* 12 BGBG.. GRGR.. */
#define V4L2_PIX_FMT_SGBRG12 v4l2_fourcc('G', 'B', '1', '2') /* 12 GBGB.. RGRG.. */
#define V4L2_PIX_FMT_SGRBG12 v4l2_fourcc('B', 'A', '1', '2') /* 12 GRGR.. BGBG.. */
--
1.8.3.2

-- Peter
(A907 E02F A6E5 0CD2 34CD 20D2 6760 79C5 AC40 DD6B)
Peter Ross
2014-02-23 05:54:45 UTC
Permalink
Logitech UVC webcams can be manipulated to output RGB Bayer formats. When
such a camera is detected, the formats list is appended.

Tested on Logitech Webcam C500 ('first generation'), and HD Webcam C270
('second generation').

Signed-off-by: Peter Ross <***@xvid.org>
---
drivers/media/usb/uvc/uvc_driver.c | 176 +++++++++++++++++++++++++++++++++++++
drivers/media/usb/uvc/uvc_video.c | 48 ++++++++++
drivers/media/usb/uvc/uvcvideo.h | 22 +++++
3 files changed, 246 insertions(+)

diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c
index b6cac17..9ed2da4 100644
--- a/drivers/media/usb/uvc/uvc_driver.c
+++ b/drivers/media/usb/uvc/uvc_driver.c
@@ -1152,6 +1152,17 @@ static int uvc_parse_standard_control(struct uvc_device *dev,
else
sprintf(unit->name, "Extension %u", buffer[3]);

+ /* Detect Logitech extension units */
+ if (!memcmp(unit->extension.guidExtensionCode,
+ (const __u8[])UVC_GUID_XU_LOGITECH_VIDEO, 16)) {
+ dev->logitech_type = 1;
+ dev->logitech_video_xu = unit->id;
+ } else if (!memcmp(unit->extension.guidExtensionCode,
+ (const __u8[])UVC_GUID_XU_LOGITECH_VIDEO2, 16)) {
+ dev->logitech_type = 2;
+ dev->logitech_video_xu = unit->id;
+ }
+
list_add_tail(&unit->list, &dev->entities);
break;

@@ -1211,6 +1222,149 @@ next_descriptor:
return 0;
}

+static void copy_format(struct uvc_format **dst_format, struct uvc_frame **dst_frame,
+ __u32 **dst_interval, const struct uvc_format *src)
+{
+ int i;
+ memcpy(*dst_format, src, sizeof **dst_format);
+
+ if (src->frame) {
+ memcpy(*dst_frame, src->frame, src->nframes * sizeof **dst_frame);
+ (*dst_format)->frame = *dst_frame;
+ *dst_frame += src->nframes;
+ }
+
+ if (dst_interval) {
+ for (i = 0; i < src->nframes; i++) {
+ struct uvc_frame * srcframe = &src->frame[i];
+ if (srcframe->dwFrameInterval) {
+ memcpy(*dst_interval, srcframe->dwFrameInterval,
+ srcframe->bFrameIntervalType * sizeof **dst_interval);
+ srcframe->dwFrameInterval = *dst_interval;
+ *dst_interval += srcframe->bFrameIntervalType;
+ }
+ }
+ }
+}
+
+static void recaclulate_frame_buffer_sizes(struct uvc_format *format)
+{
+ int i;
+ for (i = 0; i < format->nframes; i++) {
+ struct uvc_frame * frame = &format->frame[i];
+ frame->dwMaxVideoFrameBufferSize =
+ (frame->wWidth * frame->wHeight * format->bpp + 7) / 8;
+ }
+}
+
+/* For each stream, recreate the format data-structure to include RGB Bayer formats
+ */
+static void uvc_append_logitech_raw_formats(struct uvc_device *dev)
+{
+ struct uvc_streaming *stream;
+ int i, j;
+ struct uvc_format * format;
+ struct uvc_frame * frame;
+ __u32 * interval;
+
+ list_for_each_entry(stream, &dev->streams, list) {
+ struct uvc_format * srcformats = stream->format;
+ int skip = 0;
+ int nframes = 0, nintervals = 0;
+ int raw_formats = 0, raw_frames = 0;
+ unsigned int size;
+
+ if (stream->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ continue;
+
+ /* count the number of existing frames and intervals */
+
+ for (i = 0; i < stream->nformats; i++) {
+ struct uvc_format * old = &srcformats[i];
+
+ /* if the bFormatIndex high bits are in use, then we
+ * can't append RAW formats */
+ if ((old->index & (UVC_FORMATINDEX_LOGITECH_RAW|
+ UVC_FORMATINDEX_LOGITECH_10BPP))) {
+ skip = 1;
+ break;
+ }
+
+ nframes += old->nframes;
+
+ for (j = 0; j < old->nframes; j++)
+ nintervals += old->frame[j].bFrameIntervalType;
+
+ if (!(old->flags & UVC_FMT_FLAG_COMPRESSED)) {
+ if (dev->logitech_type == 1) {
+ raw_formats++;
+ raw_frames += old->nframes;
+ }
+ raw_formats++;
+ raw_frames += old->nframes;
+ }
+ }
+
+ if (skip)
+ continue;
+
+ size = (stream->nformats + raw_formats) * sizeof(*format) +
+ (nframes + raw_frames) * sizeof(struct uvc_frame) +
+ nintervals * sizeof(__u32);
+
+ format = kzalloc(size, GFP_KERNEL);
+ if (!format)
+ return;
+
+ stream->format = format;
+ frame = (struct uvc_frame *)&format[stream->nformats + raw_formats];
+ interval = (__u32 *)&frame[nframes + raw_frames];
+
+ for (i = 0; i < stream->nformats; i++) {
+ struct uvc_format * cache_format = format;
+
+ /* copy the old format into the new kalloc block */
+ copy_format(&format, &frame, &interval, &srcformats[i]);
+ format++;
+
+ if ((srcformats[i].flags & UVC_FMT_FLAG_COMPRESSED))
+ continue;
+
+ /* append 8-bit RGB Bayer format */
+ if (dev->logitech_type == 1) {
+ copy_format(&format, &frame, NULL, cache_format);
+ format->index |= UVC_FORMATINDEX_LOGITECH_RAW;
+ format->bpp = 8;
+ format->fcc = V4L2_PIX_FMT_SRGGB8;
+ strlcpy(format->name, "RGB Bayer (RG/GB 8-bit)",
+ sizeof format->name);
+ recaclulate_frame_buffer_sizes(format);
+ format++;
+ }
+
+ /* append 10-bit RGB Bayer format */
+ copy_format(&format, &frame, NULL, cache_format);
+ format->index |= UVC_FORMATINDEX_LOGITECH_RAW;
+ format->bpp = 10;
+ if (dev->logitech_type == 1) {
+ format->index |= UVC_FORMATINDEX_LOGITECH_10BPP;
+ format->fcc = V4L2_PIX_FMT_SRGGB10_1X10;
+ strlcpy(format->name, "RGB Bayer (RG/GB 10-bit)",
+ sizeof format->name);
+ } else {
+ format->fcc = V4L2_PIX_FMT_SGBRG10_1X10;
+ strlcpy(format->name, "RGB Bayer (GB/RG 10-bit)",
+ sizeof format->name);
+ }
+ recaclulate_frame_buffer_sizes(format);
+ format++;
+ }
+
+ stream->nformats += raw_formats;
+ kfree(srcformats);
+ }
+}
+
/* ------------------------------------------------------------------------
* UVC device scan
*/
@@ -1860,6 +2014,9 @@ static int uvc_probe(struct usb_interface *intf,
goto error;
}

+ if (dev->logitech_type)
+ uvc_append_logitech_raw_formats(dev);
+
uvc_printk(KERN_INFO, "Found UVC %u.%02x device %s (%04x:%04x)\n",
dev->uvc_version >> 8, dev->uvc_version & 0xff,
udev->product ? udev->product : "<unnamed>",
@@ -1926,6 +2083,25 @@ static void uvc_disconnect(struct usb_interface *intf)
{
struct uvc_device *dev = usb_get_intfdata(intf);

+ /* Reset Logitech 'disable_video_processing' and 'raw_data_bpp' controls. */
+ if (dev->logitech_type) {
+ const struct uvc_logitech_controls * controls =
+ &logitech_controls_table[dev->logitech_type];
+ __u8 value = 0;
+
+ uvc_query_ctrl(dev, UVC_SET_CUR,
+ dev->logitech_video_xu, dev->intfnum,
+ 1 + controls->disable_video_processing,
+ &value, sizeof(value));
+
+ if (controls->raw_data_bpp) {
+ uvc_query_ctrl(dev, UVC_SET_CUR,
+ dev->logitech_video_xu, dev->intfnum,
+ 1 + controls->raw_data_bpp,
+ &value, sizeof(value));
+ }
+ }
+
/* Set the USB interface data to NULL. This can be done outside the
* lock, as there's no other reader.
*/
diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c
index 103cd4e..2dfa0cc 100644
--- a/drivers/media/usb/uvc/uvc_video.c
+++ b/drivers/media/usb/uvc/uvc_video.c
@@ -155,6 +155,11 @@ static void uvc_fixup_video_ctrl(struct uvc_streaming *stream,
}
}

+const struct uvc_logitech_controls logitech_controls_table[] = {
+ [1] = { .disable_video_processing = 4, .raw_data_bpp = 7 },
+ [2] = { .disable_video_processing = 12 },
+};
+
static int uvc_get_video_ctrl(struct uvc_streaming *stream,
struct uvc_streaming_control *ctrl, int probe, __u8 query)
{
@@ -207,6 +212,27 @@ static int uvc_get_video_ctrl(struct uvc_streaming *stream,

ctrl->bmHint = le16_to_cpup((__le16 *)&data[0]);
ctrl->bFormatIndex = data[2];
+
+ if (stream->dev->logitech_type) {
+ const struct uvc_logitech_controls * controls =
+ &logitech_controls_table[stream->dev->logitech_type];
+
+ __u8 value = 0;
+ uvc_query_ctrl(stream->dev, UVC_GET_CUR,
+ stream->dev->logitech_video_xu, stream->dev->intfnum,
+ 1 + controls->disable_video_processing,
+ &value, sizeof(value));
+ if (value)
+ ctrl->bFormatIndex |= UVC_FORMATINDEX_LOGITECH_RAW;
+
+ value = 0;
+ if (controls->raw_data_bpp)
+ uvc_query_ctrl(stream->dev, UVC_GET_CUR,
+ stream->dev->logitech_video_xu, stream->dev->intfnum,
+ 1 + controls->raw_data_bpp, &value, sizeof(value));
+ if (value)
+ ctrl->bFormatIndex |= UVC_FORMATINDEX_LOGITECH_10BPP;
+ }
ctrl->bFrameIndex = data[3];
ctrl->dwFrameInterval = le32_to_cpup((__le32 *)&data[4]);
ctrl->wKeyFrameRate = le16_to_cpup((__le16 *)&data[8]);
@@ -257,6 +283,28 @@ static int uvc_set_video_ctrl(struct uvc_streaming *stream,

*(__le16 *)&data[0] = cpu_to_le16(ctrl->bmHint);
data[2] = ctrl->bFormatIndex;
+
+ if (stream->dev->logitech_type) {
+ const struct uvc_logitech_controls * controls =
+ &logitech_controls_table[stream->dev->logitech_type];
+
+ __u8 value = !!(ctrl->bFormatIndex & UVC_FORMATINDEX_LOGITECH_RAW);
+ uvc_query_ctrl(stream->dev, UVC_SET_CUR,
+ stream->dev->logitech_video_xu, stream->dev->intfnum,
+ 1 + controls->disable_video_processing,
+ &value, sizeof(value));
+
+ if (controls->raw_data_bpp) {
+ value = !!(ctrl->bFormatIndex & UVC_FORMATINDEX_LOGITECH_10BPP);
+ uvc_query_ctrl(stream->dev, UVC_SET_CUR,
+ stream->dev->logitech_video_xu, stream->dev->intfnum,
+ 1 + controls->raw_data_bpp,
+ &value, sizeof(value));
+ }
+
+ data[2] &= ~(UVC_FORMATINDEX_LOGITECH_RAW|UVC_FORMATINDEX_LOGITECH_10BPP);
+ }
+
data[3] = ctrl->bFrameIndex;
*(__le32 *)&data[4] = cpu_to_le32(ctrl->dwFrameInterval);
*(__le16 *)&data[8] = cpu_to_le16(ctrl->wKeyFrameRate);
diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h
index 143d5e5..c5a5060 100644
--- a/drivers/media/usb/uvc/uvcvideo.h
+++ b/drivers/media/usb/uvc/uvcvideo.h
@@ -105,6 +105,13 @@
{ 'H', '2', '6', '4', 0x00, 0x00, 0x10, 0x00, \
0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}

+#define UVC_GUID_XU_LOGITECH_VIDEO \
+ {0x82, 0x06, 0x61, 0x63, 0x70, 0x50, 0xab, 0x49, \
+ 0xb8, 0xcc, 0xb3, 0x85, 0x5e, 0x8d, 0x22, 0x50}
+#define UVC_GUID_XU_LOGITECH_VIDEO2 \
+ {0xA9, 0x4C, 0x5D, 0x1F, 0x11, 0xdE, 0x87, 0x44, \
+ 0x84, 0x0D, 0x50, 0x93, 0x3C, 0x8E, 0xC8, 0xD1}
+
/* ------------------------------------------------------------------------
* Driver specific constants.
*/
@@ -140,6 +147,10 @@
#define UVC_FMT_FLAG_COMPRESSED 0x00000001
#define UVC_FMT_FLAG_STREAM 0x00000002

+/* Repurpose some bFormatIndex bits to indicate additional Logitech RAW formats */
+#define UVC_FORMATINDEX_LOGITECH_10BPP 0x40
+#define UVC_FORMATINDEX_LOGITECH_RAW 0x80
+
/* ------------------------------------------------------------------------
* Structures.
*/
@@ -537,6 +548,10 @@ struct uvc_device {
__u8 *status;
struct input_dev *input;
char input_phys[64];
+
+ /* Logitech Video XU */
+ __u8 logitech_type; /* 0=not detected, 1=first generation, 2=second generation */
+ __u8 logitech_video_xu; /* XU number */
};

enum uvc_handle_state {
@@ -722,4 +737,11 @@ void uvc_debugfs_cleanup_stream(struct uvc_streaming *stream);
size_t uvc_video_stats_dump(struct uvc_streaming *stream, char *buf,
size_t size);

+struct uvc_logitech_controls {
+ __u8 disable_video_processing;
+ __u8 raw_data_bpp;
+};
+
+extern const struct uvc_logitech_controls logitech_controls_table[];
+
#endif
--
1.8.3.2

-- Peter
(A907 E02F A6E5 0CD2 34CD 20D2 6760 79C5 AC40 DD6B)
Oleksij Rempel
2014-02-23 11:39:17 UTC
Permalink
PATCHv1 discussion: http://sourceforge.net/mailarchive/message.php?msg_id=31541036
and http://article.gmane.org/gmane.linux.drivers.video-input-infrastructure/70192
[..]
Hello Peter, Laurent,
Peter do have time to update this patches for latest kernel? Laurent
would you accept them?
Here are is updated pachset. They have been tested against uvcvideo-next
today (3.14.0-rc) using FFmpeg's V4L2 grabber.
videodev2: add V4L2_PIX_FMT_Sxxxx10_1X10 formats
uvcvideo: Support Logitech RGB Bayer formats
drivers/media/usb/uvc/uvc_driver.c | 176 +++++++++++++++++++++++++++++++++++++
drivers/media/usb/uvc/uvc_video.c | 48 ++++++++++
drivers/media/usb/uvc/uvcvideo.h | 22 +++++
include/uapi/linux/videodev2.h | 4 +
4 files changed, 250 insertions(+)
I have some problems to use this patch set with guvcview. Frame rate
info seems to be corrupt for bayer. There are only some random values.
--
Regards,
Oleksij
Peter Ross
2014-02-23 14:24:59 UTC
Permalink
Logitech UVC webcams can be manipulated to output RGB Bayer formats. When
such a camera is detected, the formats list is appended.

Tested on Logitech Webcam C500 ('first generation'), and HD Webcam C270
('second generation').

Signed-off-by: Peter Ross <***@xvid.org>
---
Post by Oleksij Rempel
I have some problems to use this patch set with guvcview. Frame rate
info seems to be corrupt for bayer. There are only some random values.
Well spotted. This is fixed in PATCHv3. The frame intervals array was not
copied correctly, leaving dwFrameInterval pointing to unallocated memory.
Have added comment explaining how this works.

Additionally the length of the array was incorretly calculated when
bFrameIntervalType=0. This doesn't occur on my test cameras, but may occur
with other devices.

Cheers,



drivers/media/usb/uvc/uvc_driver.c | 190 +++++++++++++++++++++++++++++++++++++
drivers/media/usb/uvc/uvc_video.c | 48 ++++++++++
drivers/media/usb/uvc/uvcvideo.h | 22 +++++
3 files changed, 260 insertions(+)

diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c
index b6cac17..0a590bd 100644
--- a/drivers/media/usb/uvc/uvc_driver.c
+++ b/drivers/media/usb/uvc/uvc_driver.c
@@ -1152,6 +1152,17 @@ static int uvc_parse_standard_control(struct uvc_device *dev,
else
sprintf(unit->name, "Extension %u", buffer[3]);

+ /* Detect Logitech extension units */
+ if (!memcmp(unit->extension.guidExtensionCode,
+ (const __u8[])UVC_GUID_XU_LOGITECH_VIDEO, 16)) {
+ dev->logitech_type = 1;
+ dev->logitech_video_xu = unit->id;
+ } else if (!memcmp(unit->extension.guidExtensionCode,
+ (const __u8[])UVC_GUID_XU_LOGITECH_VIDEO2, 16)) {
+ dev->logitech_type = 2;
+ dev->logitech_video_xu = unit->id;
+ }
+
list_add_tail(&unit->list, &dev->entities);
break;

@@ -1211,6 +1222,163 @@ next_descriptor:
return 0;
}

+/**
+ * Convert bFrameIntervalType to dwFrameInterval[] element size
+ */
+#define NB_FRAME_INTERVAL_ELEMS(bFrameIntervalType) \
+ ((bFrameIntervalType) ? (bFrameIntervalType) : 3)
+
+static void copy_format(struct uvc_format **dst_format, struct uvc_frame **dst_frame,
+ __u32 **dst_interval, const struct uvc_format *src)
+{
+ int i;
+ memcpy(*dst_format, src, sizeof **dst_format);
+
+ if (src->frame) {
+ memcpy(*dst_frame, src->frame, src->nframes * sizeof **dst_frame);
+ (*dst_format)->frame = *dst_frame;
+ *dst_frame += src->nframes;
+ }
+
+ if (dst_interval) {
+ for (i = 0; i < src->nframes; i++) {
+ struct uvc_frame * srcframe = &src->frame[i];
+ struct uvc_frame * dstframe = &(*dst_format)->frame[i];
+ if (srcframe->dwFrameInterval) {
+ int n = NB_FRAME_INTERVAL_ELEMS(srcframe->bFrameIntervalType);
+ memcpy(*dst_interval, srcframe->dwFrameInterval,
+ n * sizeof **dst_interval);
+
+ /* Update source frame dwFrameInterval with the new
+ interval block. This ensures RAW frames derived from
+ the source frame obtain the new intervals block. */
+ srcframe->dwFrameInterval =
+ dstframe->dwFrameInterval = *dst_interval;
+
+ *dst_interval += n;
+ }
+ }
+ }
+}
+
+static void recaclulate_frame_buffer_sizes(struct uvc_format *format)
+{
+ int i;
+ for (i = 0; i < format->nframes; i++) {
+ struct uvc_frame * frame = &format->frame[i];
+ frame->dwMaxVideoFrameBufferSize =
+ (frame->wWidth * frame->wHeight * format->bpp + 7) / 8;
+ }
+}
+
+/* For each stream, recreate the format data-structure to include RGB Bayer formats
+ */
+static void uvc_append_logitech_raw_formats(struct uvc_device *dev)
+{
+ struct uvc_streaming *stream;
+ int i, j;
+ struct uvc_format * format;
+ struct uvc_frame * frame;
+ __u32 * interval;
+
+ list_for_each_entry(stream, &dev->streams, list) {
+ struct uvc_format * srcformats = stream->format;
+ int skip = 0;
+ int nframes = 0, nintervals = 0;
+ int raw_formats = 0, raw_frames = 0;
+ unsigned int size;
+
+ if (stream->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ continue;
+
+ /* count the number of existing frames and intervals */
+
+ for (i = 0; i < stream->nformats; i++) {
+ struct uvc_format * old = &srcformats[i];
+
+ /* if the bFormatIndex high bits are in use, then we
+ * can't append RAW formats */
+ if ((old->index & (UVC_FORMATINDEX_LOGITECH_RAW|
+ UVC_FORMATINDEX_LOGITECH_10BPP))) {
+ skip = 1;
+ break;
+ }
+
+ nframes += old->nframes;
+
+ for (j = 0; j < old->nframes; j++)
+ nintervals += NB_FRAME_INTERVAL_ELEMS(old->frame[j].bFrameIntervalType);
+
+ if (!(old->flags & UVC_FMT_FLAG_COMPRESSED)) {
+ if (dev->logitech_type == 1) {
+ raw_formats++;
+ raw_frames += old->nframes;
+ }
+ raw_formats++;
+ raw_frames += old->nframes;
+ }
+ }
+
+ if (skip)
+ continue;
+
+ size = (stream->nformats + raw_formats) * sizeof(*format) +
+ (nframes + raw_frames) * sizeof(struct uvc_frame) +
+ nintervals * sizeof(__u32);
+
+ format = kzalloc(size, GFP_KERNEL);
+ if (!format)
+ return;
+
+ stream->format = format;
+ frame = (struct uvc_frame *)&format[stream->nformats + raw_formats];
+ interval = (__u32 *)&frame[nframes + raw_frames];
+
+ for (i = 0; i < stream->nformats; i++) {
+ struct uvc_format * cache_format = format;
+
+ /* copy the old format into the new kalloc block */
+ copy_format(&format, &frame, &interval, &srcformats[i]);
+ format++;
+
+ if ((srcformats[i].flags & UVC_FMT_FLAG_COMPRESSED))
+ continue;
+
+ /* append 8-bit RGB Bayer format */
+ if (dev->logitech_type == 1) {
+ copy_format(&format, &frame, NULL, cache_format);
+ format->index |= UVC_FORMATINDEX_LOGITECH_RAW;
+ format->bpp = 8;
+ format->fcc = V4L2_PIX_FMT_SRGGB8;
+ strlcpy(format->name, "RGB Bayer (RG/GB 8-bit)",
+ sizeof format->name);
+ recaclulate_frame_buffer_sizes(format);
+ format++;
+ }
+
+ /* append 10-bit RGB Bayer format */
+ copy_format(&format, &frame, NULL, cache_format);
+ format->index |= UVC_FORMATINDEX_LOGITECH_RAW;
+ format->bpp = 10;
+ if (dev->logitech_type == 1) {
+ format->index |= UVC_FORMATINDEX_LOGITECH_10BPP;
+ format->fcc = V4L2_PIX_FMT_SRGGB10_1X10;
+ strlcpy(format->name, "RGB Bayer (RG/GB 10-bit)",
+ sizeof format->name);
+ } else {
+ format->fcc = V4L2_PIX_FMT_SGBRG10_1X10;
+ strlcpy(format->name, "RGB Bayer (GB/RG 10-bit)",
+ sizeof format->name);
+ }
+ recaclulate_frame_buffer_sizes(format);
+ format++;
+ }
+
+ stream->nformats += raw_formats;
+ kfree(srcformats);
+ }
+}
+
/* ------------------------------------------------------------------------
* UVC device scan
*/
@@ -1860,6 +2028,9 @@ static int uvc_probe(struct usb_interface *intf,
goto error;
}

+ if (dev->logitech_type)
+ uvc_append_logitech_raw_formats(dev);
+
uvc_printk(KERN_INFO, "Found UVC %u.%02x device %s (%04x:%04x)\n",
dev->uvc_version >> 8, dev->uvc_version & 0xff,
udev->product ? udev->product : "<unnamed>",
@@ -1926,6 +2097,25 @@ static void uvc_disconnect(struct usb_interface *intf)
{
struct uvc_device *dev = usb_get_intfdata(intf);

+ /* Reset Logitech 'disable_video_processing' and 'raw_data_bpp' controls. */
+ if (dev->logitech_type) {
+ const struct uvc_logitech_controls * controls =
+ &logitech_controls_table[dev->logitech_type];
+ __u8 value = 0;
+
+ uvc_query_ctrl(dev, UVC_SET_CUR,
+ dev->logitech_video_xu, dev->intfnum,
+ 1 + controls->disable_video_processing,
+ &value, sizeof(value));
+
+ if (controls->raw_data_bpp) {
+ uvc_query_ctrl(dev, UVC_SET_CUR,
+ dev->logitech_video_xu, dev->intfnum,
+ 1 + controls->raw_data_bpp,
+ &value, sizeof(value));
+ }
+ }
+
/* Set the USB interface data to NULL. This can be done outside the
* lock, as there's no other reader.
*/
diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c
index 103cd4e..2dfa0cc 100644
--- a/drivers/media/usb/uvc/uvc_video.c
+++ b/drivers/media/usb/uvc/uvc_video.c
@@ -155,6 +155,11 @@ static void uvc_fixup_video_ctrl(struct uvc_streaming *stream,
}
}

+const struct uvc_logitech_controls logitech_controls_table[] = {
+ [1] = { .disable_video_processing = 4, .raw_data_bpp = 7 },
+ [2] = { .disable_video_processing = 12 },
+};
+
static int uvc_get_video_ctrl(struct uvc_streaming *stream,
struct uvc_streaming_control *ctrl, int probe, __u8 query)
{
@@ -207,6 +212,27 @@ static int uvc_get_video_ctrl(struct uvc_streaming *stream,

ctrl->bmHint = le16_to_cpup((__le16 *)&data[0]);
ctrl->bFormatIndex = data[2];
+
+ if (stream->dev->logitech_type) {
+ const struct uvc_logitech_controls * controls =
+ &logitech_controls_table[stream->dev->logitech_type];
+
+ __u8 value = 0;
+ uvc_query_ctrl(stream->dev, UVC_GET_CUR,
+ stream->dev->logitech_video_xu, stream->dev->intfnum,
+ 1 + controls->disable_video_processing,
+ &value, sizeof(value));
+ if (value)
+ ctrl->bFormatIndex |= UVC_FORMATINDEX_LOGITECH_RAW;
+
+ value = 0;
+ if (controls->raw_data_bpp)
+ uvc_query_ctrl(stream->dev, UVC_GET_CUR,
+ stream->dev->logitech_video_xu, stream->dev->intfnum,
+ 1 + controls->raw_data_bpp, &value, sizeof(value));
+ if (value)
+ ctrl->bFormatIndex |= UVC_FORMATINDEX_LOGITECH_10BPP;
+ }
ctrl->bFrameIndex = data[3];
ctrl->dwFrameInterval = le32_to_cpup((__le32 *)&data[4]);
ctrl->wKeyFrameRate = le16_to_cpup((__le16 *)&data[8]);
@@ -257,6 +283,28 @@ static int uvc_set_video_ctrl(struct uvc_streaming *stream,

*(__le16 *)&data[0] = cpu_to_le16(ctrl->bmHint);
data[2] = ctrl->bFormatIndex;
+
+ if (stream->dev->logitech_type) {
+ const struct uvc_logitech_controls * controls =
+ &logitech_controls_table[stream->dev->logitech_type];
+
+ __u8 value = !!(ctrl->bFormatIndex & UVC_FORMATINDEX_LOGITECH_RAW);
+ uvc_query_ctrl(stream->dev, UVC_SET_CUR,
+ stream->dev->logitech_video_xu, stream->dev->intfnum,
+ 1 + controls->disable_video_processing,
+ &value, sizeof(value));
+
+ if (controls->raw_data_bpp) {
+ value = !!(ctrl->bFormatIndex & UVC_FORMATINDEX_LOGITECH_10BPP);
+ uvc_query_ctrl(stream->dev, UVC_SET_CUR,
+ stream->dev->logitech_video_xu, stream->dev->intfnum,
+ 1 + controls->raw_data_bpp,
+ &value, sizeof(value));
+ }
+
+ data[2] &= ~(UVC_FORMATINDEX_LOGITECH_RAW|UVC_FORMATINDEX_LOGITECH_10BPP);
+ }
+
data[3] = ctrl->bFrameIndex;
*(__le32 *)&data[4] = cpu_to_le32(ctrl->dwFrameInterval);
*(__le16 *)&data[8] = cpu_to_le16(ctrl->wKeyFrameRate);
diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h
index 143d5e5..c5a5060 100644
--- a/drivers/media/usb/uvc/uvcvideo.h
+++ b/drivers/media/usb/uvc/uvcvideo.h
@@ -105,6 +105,13 @@
{ 'H', '2', '6', '4', 0x00, 0x00, 0x10, 0x00, \
0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}

+#define UVC_GUID_XU_LOGITECH_VIDEO \
+ {0x82, 0x06, 0x61, 0x63, 0x70, 0x50, 0xab, 0x49, \
+ 0xb8, 0xcc, 0xb3, 0x85, 0x5e, 0x8d, 0x22, 0x50}
+#define UVC_GUID_XU_LOGITECH_VIDEO2 \
+ {0xA9, 0x4C, 0x5D, 0x1F, 0x11, 0xdE, 0x87, 0x44, \
+ 0x84, 0x0D, 0x50, 0x93, 0x3C, 0x8E, 0xC8, 0xD1}
+
/* ------------------------------------------------------------------------
* Driver specific constants.
*/
@@ -140,6 +147,10 @@
#define UVC_FMT_FLAG_COMPRESSED 0x00000001
#define UVC_FMT_FLAG_STREAM 0x00000002

+/* Repurpose some bFormatIndex bits to indicate additional Logitech RAW formats */
+#define UVC_FORMATINDEX_LOGITECH_10BPP 0x40
+#define UVC_FORMATINDEX_LOGITECH_RAW 0x80
+
/* ------------------------------------------------------------------------
* Structures.
*/
@@ -537,6 +548,10 @@ struct uvc_device {
__u8 *status;
struct input_dev *input;
char input_phys[64];
+
+ /* Logitech Video XU */
+ __u8 logitech_type; /* 0=not detected, 1=first generation, 2=second generation */
+ __u8 logitech_video_xu; /* XU number */
};

enum uvc_handle_state {
@@ -722,4 +737,11 @@ void uvc_debugfs_cleanup_stream(struct uvc_streaming *stream);
size_t uvc_video_stats_dump(struct uvc_streaming *stream, char *buf,
size_t size);

+struct uvc_logitech_controls {
+ __u8 disable_video_processing;
+ __u8 raw_data_bpp;
+};
+
+extern const struct uvc_logitech_controls logitech_controls_table[];
+
#endif
--
1.8.3.2

-- Peter
(A907 E02F A6E5 0CD2 34CD 20D2 6760 79C5 AC40 DD6B)
Moritz Barsnick
2014-02-23 17:36:40 UTC
Permalink
Post by Peter Ross
+static void recaclulate_frame_buffer_sizes(struct uvc_format *format)
+ recaclulate_frame_buffer_sizes(format);
+ recaclulate_frame_buffer_sizes(format);
s/cacl/calc/g

Nitpicking,
Moritz
Oleksij Rempel
2014-02-23 17:45:18 UTC
Permalink
Post by Peter Ross
Logitech UVC webcams can be manipulated to output RGB Bayer formats. When
such a camera is detected, the formats list is appended.
Tested on Logitech Webcam C500 ('first generation'), and HD Webcam C270
('second generation').
---
Post by Oleksij Rempel
I have some problems to use this patch set with guvcview. Frame rate
info seems to be corrupt for bayer. There are only some random values.
Well spotted. This is fixed in PATCHv3. The frame intervals array was not
copied correctly, leaving dwFrameInterval pointing to unallocated memory.
Have added comment explaining how this works.
Additionally the length of the array was incorretly calculated when
bFrameIntervalType=0. This doesn't occur on my test cameras, but may occur
with other devices.
Thank you,

now it works.

I see there are some limitations if we use RGGB format:
- setting frame size less then maximal will crop, not scale down the frame.
- automatic aperture is not working. But it is possible to control
framerate.
- if maximal frame size is set, there is no framerate choice.

Can we some how work around this limitations...?
--
Regards,
Oleksij
Peter Ross
2014-02-24 00:11:51 UTC
Permalink
Post by Oleksij Rempel
Post by Peter Ross
Logitech UVC webcams can be manipulated to output RGB Bayer formats. When
such a camera is detected, the formats list is appended.
Tested on Logitech Webcam C500 ('first generation'), and HD Webcam C270
('second generation').
---
Post by Oleksij Rempel
I have some problems to use this patch set with guvcview. Frame rate
info seems to be corrupt for bayer. There are only some random values.
Well spotted. This is fixed in PATCHv3. The frame intervals array was not
copied correctly, leaving dwFrameInterval pointing to unallocated memory.
Have added comment explaining how this works.
Additionally the length of the array was incorretly calculated when
bFrameIntervalType=0. This doesn't occur on my test cameras, but may occur
with other devices.
Thank you,
now it works.
great! thanks for taking the time to test. what camera are you using.
Post by Oleksij Rempel
- setting frame size less then maximal will crop, not scale down the frame.
true for the second generation cameras.

behaviour is the same on the first generation (c500) with one exception.
it also returns uncropped video for 640x480 _but only when_ frame rate is 30 fps.
Post by Oleksij Rempel
- automatic aperture is not working. But it is possible to control
framerate.
true. i have tried manipulating all the undocumented controls (yep!) with no luck.
Post by Oleksij Rempel
- if maximal frame size is set, there is no framerate choice.
the framerates should be duplcted per copy_format().
can you post your 'uvcdynctrl -f' output. below is what i am getting:


Logitech C270
Pixel format: GB1
(RGB Bayer (GB/RG 10-bit))
Frame size: 640x480
Frame rates: 30, 25, 20, 15, 10, 5
Frame size: 160x120
Frame rates: 30, 25, 20, 15, 10, 5
Frame size: 176x144
Frame rates: 30, 25, 20, 15, 10, 5
Frame size: 320x176
Frame rates: 30, 25, 20, 15, 10, 5
Frame size: 320x240
Frame rates: 30, 25, 20, 15, 10, 5
Frame size: 352x288
Frame rates: 30, 25, 20, 15, 10, 5
Frame size: 432x240
Frame rates: 30, 25, 20, 15, 10, 5
Frame size: 544x288
Frame rates: 30, 25, 20, 15, 10, 5
Frame size: 640x360
Frame rates: 30, 25, 20, 15, 10, 5
Frame size: 752x416
Frame rates: 25, 20, 15, 10, 5
Frame size: 800x448
Frame rates: 25, 20, 15, 10, 5
Frame size: 800x600
Frame rates: 20, 15, 10, 5
Frame size: 864x480
Frame rates: 20, 15, 10, 5
Frame size: 960x544
Frame rates: 15, 10, 5
Frame size: 960x720
Frame rates: 10, 5
Frame size: 1024x576
Frame rates: 10, 5
Frame size: 1184x656
Frame rates: 10, 5
Frame size: 1280x720
Frame rates: 10, 5
Frame size: 1280x960
Frame intervals: 2/15, 1/5


Logitech C500
Pixel format: RGGB (RGB Bayer (RG/GB 8-bit))
Frame size: 640x480
Frame rates: 30, 25, 20, 15, 10, 5
Frame size: 160x120
Frame rates: 30, 25, 20, 15, 10, 5
Frame size: 176x144
Frame rates: 30, 25, 20, 15, 10, 5
Frame size: 320x240
Frame rates: 30, 25, 20, 15, 10, 5
Frame size: 352x288
Frame rates: 30, 25, 20, 15, 10, 5
Frame size: 640x360
Frame rates: 30, 25, 20, 15, 10, 5
Frame size: 640x400
Frame rates: 30, 25, 20, 15, 10, 5
Frame size: 800x600
Frame rates: 15, 10, 5
Frame size: 960x720
Frame rates: 10, 5
Frame size: 1280x720
Frame rates: 10, 5
Frame size: 1280x800
Frame rates: 10, 5
Frame size: 1280x1024
Frame intervals: 2/15, 1/5
Pixel format: RG1
(RGB Bayer (RG/GB 10-bit))
Frame size: 640x480
Frame rates: 30, 25, 20, 15, 10, 5
Frame size: 160x120
Frame rates: 30, 25, 20, 15, 10, 5
Frame size: 176x144
Frame rates: 30, 25, 20, 15, 10, 5
Frame size: 320x240
Frame rates: 30, 25, 20, 15, 10, 5
Frame size: 352x288
Frame rates: 30, 25, 20, 15, 10, 5
Frame size: 640x360
Frame rates: 30, 25, 20, 15, 10, 5
Frame size: 640x400
Frame rates: 30, 25, 20, 15, 10, 5
Frame size: 800x600
Frame rates: 15, 10, 5
Frame size: 960x720
Frame rates: 10, 5
Frame size: 1280x720
Frame rates: 10, 5
Frame size: 1280x800
Frame rates: 10, 5
Frame size: 1280x1024
Frame intervals: 2/15, 1/5

-- Peter
(A907 E02F A6E5 0CD2 34CD 20D2 6760 79C5 AC40 DD6B)
Oleksij Rempel
2014-02-24 08:14:49 UTC
Permalink
Post by Peter Ross
Post by Oleksij Rempel
Post by Peter Ross
Logitech UVC webcams can be manipulated to output RGB Bayer formats. When
such a camera is detected, the formats list is appended.
Tested on Logitech Webcam C500 ('first generation'), and HD Webcam C270
('second generation').
---
Post by Oleksij Rempel
I have some problems to use this patch set with guvcview. Frame rate
info seems to be corrupt for bayer. There are only some random values.
Well spotted. This is fixed in PATCHv3. The frame intervals array was not
copied correctly, leaving dwFrameInterval pointing to unallocated memory.
Have added comment explaining how this works.
Additionally the length of the array was incorretly calculated when
bFrameIntervalType=0. This doesn't occur on my test cameras, but may occur
with other devices.
Thank you,
now it works.
great! thanks for taking the time to test. what camera are you using.
I tested C905, C600, E3500 and C920. But only C600 have this XU.
Post by Peter Ross
Post by Oleksij Rempel
- setting frame size less then maximal will crop, not scale down the frame.
true for the second generation cameras.
behaviour is the same on the first generation (c500) with one exception.
it also returns uncropped video for 640x480 _but only when_ frame rate is 30 fps.
Post by Oleksij Rempel
- automatic aperture is not working. But it is possible to control
framerate.
true. i have tried manipulating all the undocumented controls (yep!) with no luck.
Post by Oleksij Rempel
- if maximal frame size is set, there is no framerate choice.
the framerates should be duplcted per copy_format().
Listing available frame formats for device /dev/video1:
Pixel format: YUYV (YUV 4:2:2 (YUYV); MIME type: video/x-raw-yuv)
Frame size: 640x480
Frame rates: 30, 25, 20, 15, 10, 5
Frame size: 160x120
Frame rates: 30, 25, 20, 15, 10, 5
Frame size: 176x144
Frame rates: 30, 25, 20, 15, 10, 5
Frame size: 320x240
Frame rates: 30, 25, 20, 15, 10, 5
Frame size: 352x288
Frame rates: 30, 25, 20, 15, 10, 5
Frame size: 640x360
Frame rates: 30, 25, 20, 15, 10, 5
Frame size: 640x400
Frame rates: 30, 25, 20, 15, 10, 5
Frame size: 768x480
Frame rates: 25, 20, 15, 10, 5
Frame size: 800x456
Frame rates: 25, 20, 15, 10, 5
Frame size: 800x504
Frame rates: 25, 20, 15, 10, 5
Frame size: 800x600
Frame rates: 25, 20, 15, 10, 5
Frame size: 864x480
Frame rates: 25, 20, 15, 10, 5
Frame size: 960x720
Frame rates: 15, 10, 5
Frame size: 1280x720
Frame intervals: 2/15, 1/5
Frame size: 1280x800
Frame intervals: 2/15, 1/5
Frame size: 1600x904
Frame rates: 5
Frame size: 1600x1000
Frame rates: 5
Frame size: 1600x1200
Frame rates: 5
Pixel format: RGGB (RGB Bayer (RG/GB 8-bit))
Frame size: 640x480
Frame rates: 30, 25, 20, 15, 10, 5
Frame size: 160x120
Frame rates: 30, 25, 20, 15, 10, 5
Frame size: 176x144
Frame rates: 30, 25, 20, 15, 10, 5
Frame size: 320x240
Frame rates: 30, 25, 20, 15, 10, 5
Frame size: 352x288
Frame rates: 30, 25, 20, 15, 10, 5
Frame size: 640x360
Frame rates: 30, 25, 20, 15, 10, 5
Frame size: 640x400
Frame rates: 30, 25, 20, 15, 10, 5
Frame size: 768x480
Frame rates: 25, 20, 15, 10, 5
Frame size: 800x456
Frame rates: 25, 20, 15, 10, 5
Frame size: 800x504
Frame rates: 25, 20, 15, 10, 5
Frame size: 800x600
Frame rates: 25, 20, 15, 10, 5
Frame size: 864x480
Frame rates: 25, 20, 15, 10, 5
Frame size: 960x720
Frame rates: 15, 10, 5
Frame size: 1280x720
Frame intervals: 2/15, 1/5
Frame size: 1280x800
Frame intervals: 2/15, 1/5
Frame size: 1600x904
Frame rates: 5
Frame size: 1600x1000
Frame rates: 5
Frame size: 1600x1200
Frame rates: 5
Pixel format: RG1
(RGB Bayer (RG/GB 10-bit))
Frame size: 640x480
Frame rates: 30, 25, 20, 15, 10, 5
Frame size: 160x120
Frame rates: 30, 25, 20, 15, 10, 5
Frame size: 176x144
Frame rates: 30, 25, 20, 15, 10, 5
Frame size: 320x240
Frame rates: 30, 25, 20, 15, 10, 5
Frame size: 352x288
Frame rates: 30, 25, 20, 15, 10, 5
Frame size: 640x360
Frame rates: 30, 25, 20, 15, 10, 5
Frame size: 640x400
Frame rates: 30, 25, 20, 15, 10, 5
Frame size: 768x480
Frame rates: 25, 20, 15, 10, 5
Frame size: 800x456
Frame rates: 25, 20, 15, 10, 5
Frame size: 800x504
Frame rates: 25, 20, 15, 10, 5
Frame size: 800x600
Frame rates: 25, 20, 15, 10, 5
Frame size: 864x480
Frame rates: 25, 20, 15, 10, 5
Frame size: 960x720
Frame rates: 15, 10, 5
Frame size: 1280x720
Frame intervals: 2/15, 1/5
Frame size: 1280x800
Frame intervals: 2/15, 1/5
Frame size: 1600x904
Frame rates: 5
Frame size: 1600x1000
Frame rates: 5
Frame size: 1600x1200
Frame rates: 5
Pixel format: MJPG (MJPEG; MIME type: image/jpeg)
Frame size: 640x480
Frame rates: 30, 25, 20, 15, 10, 5
Frame size: 160x120
Frame rates: 30, 25, 20, 15, 10, 5
Frame size: 176x144
Frame rates: 30, 25, 20, 15, 10, 5
Frame size: 320x240
Frame rates: 30, 25, 20, 15, 10, 5
Frame size: 352x288
Frame rates: 30, 25, 20, 15, 10, 5
Frame size: 640x360
Frame rates: 30, 25, 20, 15, 10, 5
Frame size: 640x400
Frame rates: 30, 25, 20, 15, 10, 5
Frame size: 768x480
Frame rates: 30, 25, 20, 15, 10, 5
Frame size: 800x456
Frame rates: 30, 25, 20, 15, 10, 5
Frame size: 800x504
Frame rates: 30, 25, 20, 15, 10, 5
Frame size: 800x600
Frame rates: 30, 25, 20, 15, 10, 5
Frame size: 864x480
Frame rates: 30, 25, 20, 15, 10, 5
Frame size: 960x720
Frame rates: 30, 25, 20, 15, 10, 5
Frame size: 1280x720
Frame rates: 30, 25, 20, 15, 10, 5
Frame size: 1280x800
Frame rates: 25, 20, 15, 10, 5
Frame size: 1600x904
Frame rates: 10, 5
Frame size: 1600x1000
Frame rates: 10, 5
Frame size: 1600x1200
Frame rates: 10, 5
--
Regards,
Oleksij
Peter Ross
2014-02-26 09:44:10 UTC
Permalink
Post by Oleksij Rempel
Post by Peter Ross
Post by Oleksij Rempel
Post by Peter Ross
Logitech UVC webcams can be manipulated to output RGB Bayer formats. When
such a camera is detected, the formats list is appended.
Tested on Logitech Webcam C500 ('first generation'), and HD Webcam C270
('second generation').
---
Post by Oleksij Rempel
I have some problems to use this patch set with guvcview. Frame rate
info seems to be corrupt for bayer. There are only some random values.
Well spotted. This is fixed in PATCHv3. The frame intervals array was not
copied correctly, leaving dwFrameInterval pointing to unallocated memory.
Have added comment explaining how this works.
Additionally the length of the array was incorretly calculated when
bFrameIntervalType=0. This doesn't occur on my test cameras, but may occur
with other devices.
Thank you,
now it works.
great! thanks for taking the time to test. what camera are you using.
I tested C905, C600, E3500 and C920. But only C600 have this XU.
Post by Peter Ross
Post by Oleksij Rempel
- setting frame size less then maximal will crop, not scale down the frame.
true for the second generation cameras.
behaviour is the same on the first generation (c500) with one exception.
it also returns uncropped video for 640x480 _but only when_ frame rate is 30 fps.
Post by Oleksij Rempel
- automatic aperture is not working. But it is possible to control
framerate.
true. i have tried manipulating all the undocumented controls (yep!) with no luck.
Post by Oleksij Rempel
- if maximal frame size is set, there is no framerate choice.
the framerates should be duplcted per copy_format().
Pixel format: YUYV (YUV 4:2:2 (YUYV); MIME type: video/x-raw-yuv)
Frame size: 640x480
Frame rates: 30, 25, 20, 15, 10, 5
Frame size: 160x120
Frame rates: 30, 25, 20, 15, 10, 5
Frame size: 176x144
Frame rates: 30, 25, 20, 15, 10, 5
Frame size: 320x240
Frame rates: 30, 25, 20, 15, 10, 5
[..]
Post by Oleksij Rempel
Frame size: 1600x904
Frame rates: 5
Frame size: 1600x1000
Frame rates: 5
Frame size: 1600x1200
Frame rates: 5
okay thats working as expected.

when bayer rgb is enabled, the webcam just returns the color field array at the native
resolution of the sensor. there doesn't appear to be any cropping or resiing functionality
built into the camera, so we're stuck with those resolutions and frame rates.

-- Peter
(A907 E02F A6E5 0CD2 34CD 20D2 6760 79C5 AC40 DD6B)

Loading...