summaryrefslogtreecommitdiff
path: root/v4l2-apps/libv4l
diff options
context:
space:
mode:
Diffstat (limited to 'v4l2-apps/libv4l')
-rw-r--r--v4l2-apps/libv4l/ChangeLog2
-rw-r--r--v4l2-apps/libv4l/TODO4
-rw-r--r--v4l2-apps/libv4l/libv4lconvert/crop.c130
-rw-r--r--v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c14
4 files changed, 138 insertions, 12 deletions
diff --git a/v4l2-apps/libv4l/ChangeLog b/v4l2-apps/libv4l/ChangeLog
index 673eee4c0..532421ed0 100644
--- a/v4l2-apps/libv4l/ChangeLog
+++ b/v4l2-apps/libv4l/ChangeLog
@@ -11,6 +11,8 @@ libv4l-0.5.98
(and with little extra processing cost). As part of this the normalize
filter has been removed as it wasn't functioning satisfactory anyways
* Various small bugfixes and tweaks
+* Add the capability to provide 320x240 to apps if the cam can only
+ do 320x232 (some zc3xx cams) by adding black borders
libv4l-0.5.97
-------------
diff --git a/v4l2-apps/libv4l/TODO b/v4l2-apps/libv4l/TODO
index 959adc574..f4abad05d 100644
--- a/v4l2-apps/libv4l/TODO
+++ b/v4l2-apps/libv4l/TODO
@@ -9,13 +9,9 @@
-take the possibility of pitch != width into account everywhere
-
-make updating of parameters happen based on time elapsed rather then
frames
--add reverse cropping (adding black borders) to get from 320x232 ->
- 320x240, for zc3xx webcams with a broken (last row of jpeg blocks missing)
- 320x240 mode
-add software auto exposure (for spca561 cams)
diff --git a/v4l2-apps/libv4l/libv4lconvert/crop.c b/v4l2-apps/libv4l/libv4lconvert/crop.c
index 4294fbeaf..f01772c07 100644
--- a/v4l2-apps/libv4l/libv4lconvert/crop.c
+++ b/v4l2-apps/libv4l/libv4lconvert/crop.c
@@ -143,26 +143,146 @@ static void v4lconvert_crop_yuv420(unsigned char *src, unsigned char *dest,
}
}
+/* Ok, so this is not really cropping, but more the reverse, whatever */
+static void v4lconvert_add_border_rgbbgr24(
+ unsigned char *src, unsigned char *dest,
+ const struct v4l2_format *src_fmt, const struct v4l2_format *dest_fmt)
+{
+ int y;
+ int borderx = (dest_fmt->fmt.pix.width - src_fmt->fmt.pix.width) / 2;
+ int bordery = (dest_fmt->fmt.pix.height - src_fmt->fmt.pix.height) / 2;
+
+ for (y = 0; y < bordery; y++) {
+ memset(dest, 0, dest_fmt->fmt.pix.width * 3);
+ dest += dest_fmt->fmt.pix.bytesperline;
+ }
+
+ for (y = 0; y < src_fmt->fmt.pix.height; y++) {
+ memset(dest, 0, borderx * 3);
+ dest += borderx * 3;
+
+ memcpy(dest, src, src_fmt->fmt.pix.width * 3);
+ src += src_fmt->fmt.pix.bytesperline;
+ dest += src_fmt->fmt.pix.width * 3;
+
+ memset(dest, 0, borderx * 3);
+ dest += dest_fmt->fmt.pix.bytesperline -
+ (borderx + src_fmt->fmt.pix.width) * 3;
+ }
+
+ for (y = 0; y < bordery; y++) {
+ memset(dest, 0, dest_fmt->fmt.pix.width * 3);
+ dest += dest_fmt->fmt.pix.bytesperline;
+ }
+}
+
+static void v4lconvert_add_border_yuv420(
+ unsigned char *src, unsigned char *dest,
+ const struct v4l2_format *src_fmt, const struct v4l2_format *dest_fmt)
+{
+ int y;
+ int borderx = (dest_fmt->fmt.pix.width - src_fmt->fmt.pix.width) / 2;
+ int bordery = (dest_fmt->fmt.pix.height - src_fmt->fmt.pix.height) / 2;
+
+ /* Y */
+ for (y = 0; y < bordery; y++) {
+ memset(dest, 16, dest_fmt->fmt.pix.width);
+ dest += dest_fmt->fmt.pix.bytesperline;
+ }
+
+ for (y = 0; y < src_fmt->fmt.pix.height; y++) {
+ memset(dest, 16, borderx);
+ dest += borderx;
+
+ memcpy(dest, src, src_fmt->fmt.pix.width);
+ src += src_fmt->fmt.pix.bytesperline;
+ dest += src_fmt->fmt.pix.width;
+
+ memset(dest, 16, borderx);
+ dest += dest_fmt->fmt.pix.bytesperline -
+ (borderx + src_fmt->fmt.pix.width);
+ }
+
+ for (y = 0; y < bordery; y++) {
+ memset(dest, 16, dest_fmt->fmt.pix.width);
+ dest += dest_fmt->fmt.pix.bytesperline;
+ }
+
+ /* U */
+ for (y = 0; y < bordery / 2; y++) {
+ memset(dest, 128, dest_fmt->fmt.pix.width / 2);
+ dest += dest_fmt->fmt.pix.bytesperline / 2;
+ }
+
+ for (y = 0; y < src_fmt->fmt.pix.height / 2; y++) {
+ memset(dest, 128, borderx / 2);
+ dest += borderx / 2;
+
+ memcpy(dest, src, src_fmt->fmt.pix.width / 2);
+ src += src_fmt->fmt.pix.bytesperline / 2;
+ dest += src_fmt->fmt.pix.width / 2;
+
+ memset(dest, 128, borderx / 2);
+ dest += (dest_fmt->fmt.pix.bytesperline -
+ (borderx + src_fmt->fmt.pix.width)) / 2;
+ }
+
+ for (y = 0; y < bordery / 2; y++) {
+ memset(dest, 128, dest_fmt->fmt.pix.width / 2);
+ dest += dest_fmt->fmt.pix.bytesperline / 2;
+ }
+
+ /* V */
+ for (y = 0; y < bordery / 2; y++) {
+ memset(dest, 128, dest_fmt->fmt.pix.width / 2);
+ dest += dest_fmt->fmt.pix.bytesperline / 2;
+ }
+
+ for (y = 0; y < src_fmt->fmt.pix.height / 2; y++) {
+ memset(dest, 128, borderx / 2);
+ dest += borderx / 2;
+
+ memcpy(dest, src, src_fmt->fmt.pix.width / 2);
+ src += src_fmt->fmt.pix.bytesperline / 2;
+ dest += src_fmt->fmt.pix.width / 2;
+
+ memset(dest, 128, borderx / 2);
+ dest += (dest_fmt->fmt.pix.bytesperline -
+ (borderx + src_fmt->fmt.pix.width)) / 2;
+ }
+
+ for (y = 0; y < bordery / 2; y++) {
+ memset(dest, 128, dest_fmt->fmt.pix.width / 2);
+ dest += dest_fmt->fmt.pix.bytesperline / 2;
+ }
+}
+
void v4lconvert_crop(unsigned char *src, unsigned char *dest,
const struct v4l2_format *src_fmt, const struct v4l2_format *dest_fmt)
{
switch (dest_fmt->fmt.pix.pixelformat) {
case V4L2_PIX_FMT_RGB24:
case V4L2_PIX_FMT_BGR24:
- if (src_fmt->fmt.pix.width >= 2 * dest_fmt->fmt.pix.width &&
- src_fmt->fmt.pix.height >= 2 * dest_fmt->fmt.pix.height)
+ if (src_fmt->fmt.pix.width <= dest_fmt->fmt.pix.width &&
+ src_fmt->fmt.pix.height <= dest_fmt->fmt.pix.height)
+ v4lconvert_add_border_rgbbgr24(src, dest, src_fmt, dest_fmt);
+ else 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:
case V4L2_PIX_FMT_YVU420:
- if (src_fmt->fmt.pix.width >= 2 * dest_fmt->fmt.pix.width &&
- src_fmt->fmt.pix.height >= 2 * dest_fmt->fmt.pix.height)
+ if (src_fmt->fmt.pix.width <= dest_fmt->fmt.pix.width &&
+ src_fmt->fmt.pix.height <= dest_fmt->fmt.pix.height)
+ v4lconvert_add_border_yuv420(src, dest, src_fmt, dest_fmt);
+ else 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 1a94b53ba..afb0c854c 100644
--- a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c
+++ b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c
@@ -373,7 +373,8 @@ int v4lconvert_try_format(struct v4lconvert_data *data,
/* 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 */
+ asked for by cropping a slightly larger resolution or adding a small
+ black border to a slightly smaller 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++) {
@@ -387,13 +388,20 @@ int v4lconvert_try_format(struct v4lconvert_data *data,
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 &&
+ (/* Add a small black border of max 16 pixels */
+ (try2_dest.fmt.pix.width >= desired_width - 16 &&
+ try2_dest.fmt.pix.width <= desired_width &&
+ try2_dest.fmt.pix.height >= desired_height - 16 &&
+ try2_dest.fmt.pix.height <= desired_height) ||
+ /* Standard cropping to max 80% of actual width / 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) ||
+ /* Downscale 2x + cropping to max 80% of actual width / height */
(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 * 2 &&
try2_dest.fmt.pix.height <= desired_height * 5 / 2))) {
/* Success! */
try2_dest.fmt.pix.width = desired_width;