From bddade221b67dc99ea8a175cad744570fe0283d3 Mon Sep 17 00:00:00 2001 From: "hans@localhost.localdomain" Date: Wed, 3 Sep 2008 14:24:30 +0200 Subject: [PATCH] libv4l: Prefer compressed pixformats for resolutions > 176x144 From: Hans de Goede libv4l: Prefer compressed pixformats for resolutions > 176x144 Priority: normal Signed-off-by: Hans de Goede --- lib/ChangeLog | 1 + lib/libv4l2/libv4l2.c | 11 +++++++ lib/libv4lconvert/libv4lconvert-priv.h | 9 ++++++ lib/libv4lconvert/libv4lconvert.c | 58 ++++++++++++++++++---------------- 4 files changed, 52 insertions(+), 27 deletions(-) diff --git a/lib/ChangeLog b/lib/ChangeLog index 31611e0..8a7131a 100644 --- a/lib/ChangeLog +++ b/lib/ChangeLog @@ -1,6 +1,7 @@ libv4l-0.4.3 ------------ * Add suport for YUYV and YVYU packed pixel formats (Jean-Francois Moine) +* Prefer compressed pixformats for resolutions > 176x144 libv4l-0.4.2 ------------ diff --git a/lib/libv4l2/libv4l2.c b/lib/libv4l2/libv4l2.c index 7029f69..937c06c 100644 --- a/lib/libv4l2/libv4l2.c +++ b/lib/libv4l2/libv4l2.c @@ -739,6 +739,17 @@ int v4l2_ioctl (int fd, unsigned long int request, ...) if (result) break; + if (src_fmt.fmt.pix.pixelformat != dest_fmt->fmt.pix.pixelformat && + v4l2_log_file) { + int pixfmt = src_fmt.fmt.pix.pixelformat; + + fprintf(v4l2_log_file, "VIDIOC_S_FMT converting from: %c%c%c%c\n", + pixfmt & 0xff, + (pixfmt >> 8) & 0xff, + (pixfmt >> 16) & 0xff, + pixfmt >> 24); + } + /* Maybe after try format has adjusted width/height etc, to whats available nothing has changed (on the cam side) ? */ if (!memcmp(&devices[index].src_fmt, &src_fmt, sizeof(src_fmt))) { diff --git a/lib/libv4lconvert/libv4lconvert-priv.h b/lib/libv4lconvert/libv4lconvert-priv.h index efe78bb..a2086e6 100644 --- a/lib/libv4lconvert/libv4lconvert-priv.h +++ b/lib/libv4lconvert/libv4lconvert-priv.h @@ -69,8 +69,12 @@ snprintf(data->error_msg, V4LCONVERT_ERROR_MSG_SIZE, \ "v4l-convert: error " __VA_ARGS__) +/* Card flags */ #define V4LCONVERT_UPSIDE_DOWN 0x01 +/* Pixformat flags */ +#define V4LCONVERT_COMPRESSED 0x01 + struct v4lconvert_data { int fd; int flags; /* bitfield */ @@ -85,6 +89,11 @@ struct v4lconvert_flags_info { int flags; }; +struct v4lconvert_pixfmt { + unsigned int fmt; + int flags; +}; + void v4lconvert_yuv420_to_rgb24(const unsigned char *src, unsigned char *dst, int width, int height); diff --git a/lib/libv4lconvert/libv4lconvert.c b/lib/libv4lconvert/libv4lconvert.c index 2a9f6ef..cbd4ca5 100644 --- a/lib/libv4lconvert/libv4lconvert.c +++ b/lib/libv4lconvert/libv4lconvert.c @@ -30,30 +30,32 @@ /* Note for proper functioning of v4lconvert_enum_fmt the first entries in supported_src_pixfmts must match with the entries in supported_dst_pixfmts */ #define SUPPORTED_DST_PIXFMTS \ - V4L2_PIX_FMT_RGB24, \ - V4L2_PIX_FMT_BGR24, \ - V4L2_PIX_FMT_YUV420 + { V4L2_PIX_FMT_RGB24, 0 }, \ + { V4L2_PIX_FMT_BGR24, 0 }, \ + { V4L2_PIX_FMT_YUV420, 0 } -static const unsigned int supported_src_pixfmts[] = { +/* Note uncompressed formats must go first so that they are prefered by + v4lconvert_try_format for low resolutions */ +static const struct v4lconvert_pixfmt supported_src_pixfmts[] = { SUPPORTED_DST_PIXFMTS, - V4L2_PIX_FMT_MJPEG, - V4L2_PIX_FMT_JPEG, - V4L2_PIX_FMT_YUYV, - V4L2_PIX_FMT_YVYU, - V4L2_PIX_FMT_SBGGR8, - V4L2_PIX_FMT_SGBRG8, - V4L2_PIX_FMT_SGRBG8, - V4L2_PIX_FMT_SRGGB8, - V4L2_PIX_FMT_SPCA501, - V4L2_PIX_FMT_SPCA505, - V4L2_PIX_FMT_SPCA508, - V4L2_PIX_FMT_SPCA561, - V4L2_PIX_FMT_SN9C10X, - V4L2_PIX_FMT_PAC207, - V4L2_PIX_FMT_PJPG, + { V4L2_PIX_FMT_YUYV, 0 }, + { V4L2_PIX_FMT_YVYU, 0 }, + { V4L2_PIX_FMT_SBGGR8, 0 }, + { V4L2_PIX_FMT_SGBRG8, 0 }, + { V4L2_PIX_FMT_SGRBG8, 0 }, + { V4L2_PIX_FMT_SRGGB8, 0 }, + { V4L2_PIX_FMT_SPCA501, 0 }, + { V4L2_PIX_FMT_SPCA505, 0 }, + { V4L2_PIX_FMT_SPCA508, 0 }, + { V4L2_PIX_FMT_MJPEG, V4LCONVERT_COMPRESSED }, + { V4L2_PIX_FMT_JPEG, V4LCONVERT_COMPRESSED }, + { V4L2_PIX_FMT_SPCA561, V4LCONVERT_COMPRESSED }, + { V4L2_PIX_FMT_SN9C10X, V4LCONVERT_COMPRESSED }, + { V4L2_PIX_FMT_PAC207, V4LCONVERT_COMPRESSED }, + { V4L2_PIX_FMT_PJPG, V4LCONVERT_COMPRESSED }, }; -static const unsigned int supported_dst_pixfmts[] = { +static const struct v4lconvert_pixfmt supported_dst_pixfmts[] = { SUPPORTED_DST_PIXFMTS }; @@ -87,7 +89,7 @@ struct v4lconvert_data *v4lconvert_create(int fd) break; for (j = 0; j < ARRAY_SIZE(supported_src_pixfmts); j++) - if (fmt.pixelformat == supported_src_pixfmts[j]) { + if (fmt.pixelformat == supported_src_pixfmts[j].fmt) { data->supported_src_formats |= 1 << j; break; } @@ -130,7 +132,7 @@ int v4lconvert_enum_fmt(struct v4lconvert_data *data, struct v4l2_fmtdesc *fmt) for (i = 0; i < ARRAY_SIZE(supported_dst_pixfmts); i++) if (!(data->supported_src_formats & (1 << i))) { - faked_fmts[no_faked_fmts] = supported_dst_pixfmts[i]; + faked_fmts[no_faked_fmts] = supported_dst_pixfmts[i].fmt; no_faked_fmts++; } @@ -162,7 +164,7 @@ int v4lconvert_try_format(struct v4lconvert_data *data, struct v4l2_format try_fmt, closest_fmt = { .type = 0 }; for (i = 0; i < ARRAY_SIZE(supported_dst_pixfmts); i++) - if (supported_dst_pixfmts[i] == desired_pixfmt) + if (supported_dst_pixfmts[i].fmt == desired_pixfmt) break; /* Can we do conversion to the requested format & type? */ @@ -180,11 +182,11 @@ int v4lconvert_try_format(struct v4lconvert_data *data, continue; try_fmt = *dest_fmt; - try_fmt.fmt.pix.pixelformat = supported_src_pixfmts[i]; + try_fmt.fmt.pix.pixelformat = supported_src_pixfmts[i].fmt; if (!syscall(SYS_ioctl, data->fd, VIDIOC_TRY_FMT, &try_fmt)) { - if (try_fmt.fmt.pix.pixelformat == supported_src_pixfmts[i]) { + if (try_fmt.fmt.pix.pixelformat == supported_src_pixfmts[i].fmt) { int size_x_diff = abs((int)try_fmt.fmt.pix.width - (int)dest_fmt->fmt.pix.width); int size_y_diff = abs((int)try_fmt.fmt.pix.height - @@ -193,7 +195,9 @@ int v4lconvert_try_format(struct v4lconvert_data *data, size_y_diff * size_y_diff; if (size_diff < closest_fmt_size_diff || (size_diff == closest_fmt_size_diff && - try_fmt.fmt.pix.pixelformat == desired_pixfmt)) { + (supported_src_pixfmts[i].fmt == desired_pixfmt || + ((try_fmt.fmt.pix.width > 176 || try_fmt.fmt.pix.height > 144) && + (supported_src_pixfmts[i].flags & V4LCONVERT_COMPRESSED))))) { closest_fmt_size_diff = size_diff; closest_fmt = try_fmt; } @@ -249,7 +253,7 @@ int v4lconvert_needs_conversion(struct v4lconvert_data *data, /* Formats are identical, but we need flip, do we support the dest_fmt? */ for (i = 0; i < ARRAY_SIZE(supported_dst_pixfmts); i++) - if (supported_dst_pixfmts[i] == dest_fmt->fmt.pix.pixelformat) + if (supported_dst_pixfmts[i].fmt == dest_fmt->fmt.pix.pixelformat) break; if (i == ARRAY_SIZE(supported_dst_pixfmts)) -- 2.7.4