summaryrefslogtreecommitdiff
path: root/v4l2-apps/libv4l
diff options
context:
space:
mode:
authorhans@rhel5-devel.localdomain <hans@rhel5-devel.localdomain>2009-03-11 13:09:42 +0100
committerhans@rhel5-devel.localdomain <hans@rhel5-devel.localdomain>2009-03-11 13:09:42 +0100
commitb326eb353c8691cc4c32ca59c0a2cf60ca74c3b6 (patch)
tree883f28c9ca9e08af2d13a77eac28a9e2b2dd8ce7 /v4l2-apps/libv4l
parent93d4ae910ce9eeaa5998e3aa1980c3647d959fc6 (diff)
downloadmediapointer-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/ChangeLog3
-rw-r--r--v4l2-apps/libv4l/libv4lconvert/crop.c83
-rw-r--r--v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c29
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;