diff options
author | hans@rhel5-devel.localdomain <hans@rhel5-devel.localdomain> | 2009-03-11 13:09:42 +0100 |
---|---|---|
committer | hans@rhel5-devel.localdomain <hans@rhel5-devel.localdomain> | 2009-03-11 13:09:42 +0100 |
commit | b326eb353c8691cc4c32ca59c0a2cf60ca74c3b6 (patch) | |
tree | 883f28c9ca9e08af2d13a77eac28a9e2b2dd8ce7 /v4l2-apps/libv4l | |
parent | 93d4ae910ce9eeaa5998e3aa1980c3647d959fc6 (diff) | |
download | mediapointer-dvb-s2-b326eb353c8691cc4c32ca59c0a2cf60ca74c3b6.tar.gz mediapointer-dvb-s2-b326eb353c8691cc4c32ca59c0a2cf60ca74c3b6.tar.bz2 |
libv4l: add support for downscaling
From: Lukáš Karas <lukas.karas@centrum.cz>
Add support for downscaling to make apps which want low resolutions
(skype, spcaview) happy when used with cams which can only do high
resolutions.
Priority: normal
Signed-off-by: Lukáš Karas <lukas.karas@centrum.cz>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Diffstat (limited to 'v4l2-apps/libv4l')
-rw-r--r-- | v4l2-apps/libv4l/ChangeLog | 3 | ||||
-rw-r--r-- | v4l2-apps/libv4l/libv4lconvert/crop.c | 83 | ||||
-rw-r--r-- | v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c | 29 |
3 files changed, 99 insertions, 16 deletions
diff --git a/v4l2-apps/libv4l/ChangeLog b/v4l2-apps/libv4l/ChangeLog index 624f6dc43..b6097fe41 100644 --- a/v4l2-apps/libv4l/ChangeLog +++ b/v4l2-apps/libv4l/ChangeLog @@ -2,6 +2,9 @@ libv4l-0.5.4 ------------ * Don't report DQBUF errors when errno is EAGAIN, this fixes flooding the screen with errors when applications use non blocking mode +* Add support for downscaling to make apps which want low resolutions + (skype, spcaview) happy when used with cams which can only do high + resolutions (by Lukáš Karas <lukas.karas@centrum.cz>). libv4l-0.5.3 ------------ diff --git a/v4l2-apps/libv4l/libv4lconvert/crop.c b/v4l2-apps/libv4l/libv4lconvert/crop.c index 290756b99..dcfa5152a 100644 --- a/v4l2-apps/libv4l/libv4lconvert/crop.c +++ b/v4l2-apps/libv4l/libv4lconvert/crop.c @@ -23,6 +23,29 @@ #include <string.h> #include "libv4lconvert-priv.h" + +static void v4lconvert_reduceandcrop_rgbbgr24( + unsigned char *src, unsigned char *dest, + const struct v4l2_format *src_fmt, const struct v4l2_format *dest_fmt) +{ + int x, y; + int startx = src_fmt->fmt.pix.width / 2 - dest_fmt->fmt.pix.width; + int starty = src_fmt->fmt.pix.height / 2 - dest_fmt->fmt.pix.height; + + src += starty * src_fmt->fmt.pix.bytesperline + 3 * startx; + + for (y = 0; y < dest_fmt->fmt.pix.height; y++) { + unsigned char *mysrc = src; + for (x = 0; x < dest_fmt->fmt.pix.width; x++) { + *(dest++) = *(mysrc++); + *(dest++) = *(mysrc++); + *(dest++) = *(mysrc++); + mysrc += 3; /* skip one pixel */ + } + src += 2 * src_fmt->fmt.pix.bytesperline; /* skip one line */ + } +} + static void v4lconvert_crop_rgbbgr24(unsigned char *src, unsigned char *dest, const struct v4l2_format *src_fmt, const struct v4l2_format *dest_fmt) { @@ -39,6 +62,53 @@ static void v4lconvert_crop_rgbbgr24(unsigned char *src, unsigned char *dest, } } +static void v4lconvert_reduceandcrop_yuv420( + unsigned char *src, unsigned char *dest, + const struct v4l2_format *src_fmt, const struct v4l2_format *dest_fmt) +{ + int x,y; + int dest_height_half = dest_fmt->fmt.pix.height / 2; + int dest_width_half = dest_fmt->fmt.pix.width / 2; + int startx = src_fmt->fmt.pix.width / 2 - dest_fmt->fmt.pix.width; + int starty = src_fmt->fmt.pix.height / 2 - dest_fmt->fmt.pix.height; + unsigned char *mysrc, *mysrc2; + + /* Y */ + mysrc = src + starty * src_fmt->fmt.pix.bytesperline + startx; + for (y = 0; y < dest_fmt->fmt.pix.height; y++){ + mysrc2 = mysrc; + for (x = 0; x < dest_fmt->fmt.pix.width; x++){ + *(dest++) = *mysrc2; + mysrc2 += 2; /* skip one pixel */ + } + mysrc += 2 * src_fmt->fmt.pix.bytesperline; /* skip one line */ + } + + /* U */ + mysrc = src + src_fmt->fmt.pix.height * src_fmt->fmt.pix.bytesperline + + (starty / 2) * src_fmt->fmt.pix.bytesperline / 2 + startx / 2; + for (y = 0; y < dest_height_half; y++){ + mysrc2 = mysrc; + for (x = 0; x < dest_width_half; x++){ + *(dest++) = *mysrc2; + mysrc2 += 2; /* skip one pixel */ + } + mysrc += src_fmt->fmt.pix.bytesperline ; /* skip one line */ + } + + /* V */ + mysrc = src + src_fmt->fmt.pix.height * src_fmt->fmt.pix.bytesperline * 5 / 4 + + (starty / 2) * src_fmt->fmt.pix.bytesperline / 2 + startx / 2; + for (y = 0; y < dest_height_half; y++){ + mysrc2 = mysrc; + for (x = 0; x < dest_width_half; x++){ + *(dest++) = *mysrc2; + mysrc2 += 2; /* skip one pixel */ + } + mysrc += src_fmt->fmt.pix.bytesperline ; /* skip one line */ + } +} + static void v4lconvert_crop_yuv420(unsigned char *src, unsigned char *dest, const struct v4l2_format *src_fmt, const struct v4l2_format *dest_fmt) { @@ -79,10 +149,19 @@ void v4lconvert_crop(unsigned char *src, unsigned char *dest, switch (dest_fmt->fmt.pix.pixelformat) { case V4L2_PIX_FMT_RGB24: case V4L2_PIX_FMT_BGR24: - v4lconvert_crop_rgbbgr24(src, dest, src_fmt, dest_fmt); + if (src_fmt->fmt.pix.width >= 2 * dest_fmt->fmt.pix.width && + src_fmt->fmt.pix.height >= 2 * dest_fmt->fmt.pix.height) + v4lconvert_reduceandcrop_rgbbgr24(src, dest, src_fmt, dest_fmt); + else + v4lconvert_crop_rgbbgr24(src, dest, src_fmt, dest_fmt); break; case V4L2_PIX_FMT_YUV420: - v4lconvert_crop_yuv420(src, dest, src_fmt, dest_fmt); + if (src_fmt->fmt.pix.width >= 2 * dest_fmt->fmt.pix.width && + src_fmt->fmt.pix.height >= 2 * dest_fmt->fmt.pix.height) + v4lconvert_reduceandcrop_yuv420(src, dest, src_fmt, dest_fmt); + else + v4lconvert_crop_yuv420(src, dest, src_fmt, dest_fmt); + break; } } diff --git a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c index ee6ef33a0..536e5363d 100644 --- a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c +++ b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c @@ -268,29 +268,30 @@ int v4lconvert_try_format(struct v4lconvert_data *data, return result; } - /* In case of a non exact resolution match, see if this is a resolution we - can support by cropping a slightly larger resolution to give the app - exactly what it asked for */ + /* In case of a non exact resolution match, see if this is a well known + resolution some apps are hardcoded too and try to give the app what it + asked for by cropping a slightly larger resolution */ if (try_dest.fmt.pix.width != desired_width || try_dest.fmt.pix.height != desired_height) { for (i = 0; i < ARRAY_SIZE(v4lconvert_crop_res); i++) { if (v4lconvert_crop_res[i][0] == desired_width && v4lconvert_crop_res[i][1] == desired_height) { - struct v4l2_format try2_dest, try2_src; + struct v4l2_format try2_src, try2_dest = *dest_fmt; + /* Note these are chosen so that cropping to vga res just works for vv6410 sensor cams, which have 356x292 and 180x148 */ - unsigned int max_width = desired_width * 113 / 100; - unsigned int max_height = desired_height * 124 / 100; - - try2_dest = *dest_fmt; - try2_dest.fmt.pix.width = max_width; - try2_dest.fmt.pix.height = max_height; + try2_dest.fmt.pix.width = desired_width * 113 / 100; + try2_dest.fmt.pix.height = desired_height * 124 / 100; result = v4lconvert_do_try_format(data, &try2_dest, &try2_src); if (result == 0 && - try2_dest.fmt.pix.width >= desired_width && - try2_dest.fmt.pix.width <= max_width && - try2_dest.fmt.pix.height >= desired_height && - try2_dest.fmt.pix.height <= max_height) { + ((try2_dest.fmt.pix.width >= desired_width && + try2_dest.fmt.pix.width <= desired_width * 5 / 4 && + try2_dest.fmt.pix.height >= desired_height && + try2_dest.fmt.pix.height <= desired_height * 5 / 4) || + (try2_dest.fmt.pix.width >= desired_width * 2 && + try2_dest.fmt.pix.width <= desired_width * 5 / 2 && + try2_dest.fmt.pix.height >= desired_height && + try2_dest.fmt.pix.height <= desired_height * 5 / 2))) { /* Success! */ try2_dest.fmt.pix.width = desired_width; try2_dest.fmt.pix.height = desired_height; |