The patch number 10999 was added via h...@rhel5-devel.localdomain to http://linuxtv.org/hg/v4l-dvb master development tree.
Kernel patches in this development tree may be modified to be backward compatible with older kernels. Compatibility modifications will be removed before inclusion into the mainstream Kernel If anyone has any objections, please let us know by sending a message to: Linux Media Mailing List <linux-me...@vger.kernel.org> ------ From: Luk?? Karas <lukas.ka...@centrum.cz> libv4l: add support for downscaling 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.ka...@centrum.cz> Signed-off-by: Hans de Goede <hdego...@redhat.com> --- v4l2-apps/libv4l/ChangeLog | 3 v4l2-apps/libv4l/libv4lconvert/crop.c | 83 ++++++++++++++++- v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c | 29 +++-- 3 files changed, 99 insertions(+), 16 deletions(-) diff -r a2245987c979 -r 4501d0d183ea v4l2-apps/libv4l/ChangeLog --- a/v4l2-apps/libv4l/ChangeLog Wed Mar 11 13:09:27 2009 +0100 +++ b/v4l2-apps/libv4l/ChangeLog Wed Mar 11 13:09:42 2009 +0100 @@ -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.ka...@centrum.cz>). libv4l-0.5.3 ------------ diff -r a2245987c979 -r 4501d0d183ea v4l2-apps/libv4l/libv4lconvert/crop.c --- a/v4l2-apps/libv4l/libv4lconvert/crop.c Wed Mar 11 13:09:27 2009 +0100 +++ b/v4l2-apps/libv4l/libv4lconvert/crop.c Wed Mar 11 13:09:42 2009 +0100 @@ -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) { @@ -36,6 +59,53 @@ static void v4lconvert_crop_rgbbgr24(uns memcpy(dest, src, dest_fmt->fmt.pix.width * 3); src += src_fmt->fmt.pix.bytesperline; dest += dest_fmt->fmt.pix.bytesperline; + } +} + +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 */ } } @@ -79,10 +149,19 @@ void v4lconvert_crop(unsigned char *src, 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 -r a2245987c979 -r 4501d0d183ea v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c --- a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c Wed Mar 11 13:09:27 2009 +0100 +++ b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c Wed Mar 11 13:09:42 2009 +0100 @@ -268,29 +268,30 @@ int v4lconvert_try_format(struct v4lconv 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; --- Patch is available at: http://linuxtv.org/hg/v4l-dvb/rev/4501d0d183eaf47b961fb27a362db34625dae6f9
_______________________________________________ linuxtv-commits mailing list linuxtv-commits@linuxtv.org http://www.linuxtv.org/cgi-bin/mailman/listinfo/linuxtv-commits