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

Reply via email to