summaryrefslogtreecommitdiff
path: root/v4l2-apps/lib
diff options
context:
space:
mode:
Diffstat (limited to 'v4l2-apps/lib')
-rw-r--r--v4l2-apps/lib/libv4l/ChangeLog5
-rw-r--r--v4l2-apps/lib/libv4l/include/libv4lconvert.h5
-rw-r--r--v4l2-apps/lib/libv4l/libv4l2/libv4l2.c16
-rw-r--r--v4l2-apps/lib/libv4l/libv4lconvert/Makefile2
-rw-r--r--v4l2-apps/lib/libv4l/libv4lconvert/flip.c60
-rw-r--r--v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert-priv.h11
-rw-r--r--v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert.c72
7 files changed, 159 insertions, 12 deletions
diff --git a/v4l2-apps/lib/libv4l/ChangeLog b/v4l2-apps/lib/libv4l/ChangeLog
index 3d4e40ad2..d9c97c054 100644
--- a/v4l2-apps/lib/libv4l/ChangeLog
+++ b/v4l2-apps/lib/libv4l/ChangeLog
@@ -2,6 +2,11 @@ libv4l-0.4.1
------------
* When the driver supports read() and we are not converting let the driver
handle read() instead of emulating it with mmap mode
+* Fix errors and warnings when compiling with ICC (Gregor Jasny)
+* Add support to libv4lconvert to flipping the image for upside down mounted
+ sensors, libv4lconvert will do this automatically if the webcam sets a
+ flag in its query_fmt reply indicating that this is necessary, this fixes
+ the upside down image on Philips SPC200NC images
libv4l-0.4.0
diff --git a/v4l2-apps/lib/libv4l/include/libv4lconvert.h b/v4l2-apps/lib/libv4l/include/libv4lconvert.h
index d8446dac8..f102858a0 100644
--- a/v4l2-apps/lib/libv4l/include/libv4lconvert.h
+++ b/v4l2-apps/lib/libv4l/include/libv4lconvert.h
@@ -50,6 +50,11 @@ int v4lconvert_try_format(struct v4lconvert_data *data,
the end of the list */
int v4lconvert_enum_fmt(struct v4lconvert_data *data, struct v4l2_fmtdesc *fmt);
+/* Is conversion necessary or can the app use the data directly? */
+int v4lconvert_needs_conversion(struct v4lconvert_data *data,
+ const struct v4l2_format *src_fmt, /* in */
+ const struct v4l2_format *dest_fmt); /* in */
+
/* return value of -1 on error, otherwise the amount of bytes written to
dest */
int v4lconvert_convert(struct v4lconvert_data *data,
diff --git a/v4l2-apps/lib/libv4l/libv4l2/libv4l2.c b/v4l2-apps/lib/libv4l/libv4l2/libv4l2.c
index a40ab4ffe..dd43d938f 100644
--- a/v4l2-apps/lib/libv4l/libv4l2/libv4l2.c
+++ b/v4l2-apps/lib/libv4l/libv4l2/libv4l2.c
@@ -614,7 +614,8 @@ int v4l2_ioctl (int fd, unsigned long int request, ...)
is_capture_request = 1;
break;
case VIDIOC_ENUM_FMT:
- if (((struct v4l2_fmtdesc *)arg)->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ if (((struct v4l2_fmtdesc *)arg)->type == V4L2_BUF_TYPE_VIDEO_CAPTURE &&
+ (devices[index].flags & V4L2_ENABLE_ENUM_FMT_EMULATION))
is_capture_request = 1;
break;
case VIDIOC_TRY_FMT:
@@ -663,9 +664,8 @@ int v4l2_ioctl (int fd, unsigned long int request, ...)
if (stream_needs_locking)
pthread_mutex_lock(&devices[index].stream_lock);
- converting = devices[index].src_fmt.fmt.pix.pixelformat !=
- devices[index].dest_fmt.fmt.pix.pixelformat;
-
+ converting = v4lconvert_needs_conversion(devices[index].convert,
+ &devices[index].src_fmt, &devices[index].dest_fmt);
switch (request) {
case VIDIOC_QUERYCAP:
@@ -914,8 +914,8 @@ ssize_t v4l2_read (int fd, void* buffer, size_t n)
/* When not converting and the device supports read let the kernel handle
it */
if ((devices[index].flags & V4L2_SUPPORTS_READ) &&
- devices[index].src_fmt.fmt.pix.pixelformat ==
- devices[index].dest_fmt.fmt.pix.pixelformat) {
+ !v4lconvert_needs_conversion(devices[index].convert,
+ &devices[index].src_fmt, &devices[index].dest_fmt)) {
result = syscall(SYS_read, fd, buffer, n);
goto leave;
}
@@ -988,8 +988,8 @@ void *v4l2_mmap(void *start, size_t length, int prot, int flags, int fd,
buffer_index = offset & 0xff;
if (buffer_index >= devices[index].no_frames ||
/* Got magic offset and not converting ?? */
- devices[index].src_fmt.fmt.pix.pixelformat ==
- devices[index].dest_fmt.fmt.pix.pixelformat) {
+ !v4lconvert_needs_conversion(devices[index].convert,
+ &devices[index].src_fmt, &devices[index].dest_fmt)) {
errno = EINVAL;
result = MAP_FAILED;
goto leave;
diff --git a/v4l2-apps/lib/libv4l/libv4lconvert/Makefile b/v4l2-apps/lib/libv4l/libv4lconvert/Makefile
index a29410421..3b8a59721 100644
--- a/v4l2-apps/lib/libv4l/libv4lconvert/Makefile
+++ b/v4l2-apps/lib/libv4l/libv4lconvert/Makefile
@@ -10,7 +10,7 @@ CONVERT_LIB = libv4lconvert.so
override CPPFLAGS += -fPIC
endif
-CONVERT_OBJS = libv4lconvert.o tinyjpeg.o sn9c10x.o pac207.o \
+CONVERT_OBJS = libv4lconvert.o tinyjpeg.o sn9c10x.o pac207.o flip.o \
jidctflt.o spca561-decompress.o rgbyuv.o spca501.o bayer.o
TARGETS = $(CONVERT_LIB) libv4lconvert.pc
INCLUDES = ../include/libv4lconvert.h
diff --git a/v4l2-apps/lib/libv4l/libv4lconvert/flip.c b/v4l2-apps/lib/libv4l/libv4lconvert/flip.c
new file mode 100644
index 000000000..de76ecc9a
--- /dev/null
+++ b/v4l2-apps/lib/libv4l/libv4lconvert/flip.c
@@ -0,0 +1,60 @@
+/*
+
+# RGB / YUV flip routines
+
+# (C) 2008 Hans de Goede <j.w.r.degoede@hhs.nl>
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+*/
+
+#include "libv4lconvert-priv.h"
+
+void v4lconvert_flip_rgbbgr24(const unsigned char *src, unsigned char *dst,
+ int width, int height)
+{
+ int i;
+
+ src += 3 * width * height - 3;
+
+ for (i = 0; i < width * height; i++) {
+ dst[0] = src[0];
+ dst[1] = src[1];
+ dst[2] = src[2];
+ dst += 3;
+ src -= 3;
+ }
+}
+
+void v4lconvert_flip_yuv420(const unsigned char *src, unsigned char *dst,
+ int width, int height)
+{
+ int i;
+
+ /* First flip x and y of the Y plane */
+ src += width * height - 1;
+ for (i = 0; i < width * height; i++)
+ *dst++ = *src--;
+
+ /* Now flip the U plane */
+ src += width * height * 5 / 4;
+ for (i = 0; i < width * height / 4; i++)
+ *dst++ = *src--;
+
+ /* Last flip the V plane */
+ src += width * height / 2;
+ for (i = 0; i < width * height / 4; i++)
+ *dst++ = *src--;
+}
diff --git a/v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert-priv.h b/v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert-priv.h
index bdf847186..7d8fcc568 100644
--- a/v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert-priv.h
+++ b/v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert-priv.h
@@ -55,6 +55,10 @@
#define V4L2_PIX_FMT_SRGGB8 v4l2_fourcc('R','G','G','B')
#endif
+#ifndef V4L2_FMT_FLAG_UPSIDEDOWN
+#define V4L2_FMT_FLAG_UPSIDEDOWN 0x0002
+#endif
+
#define V4LCONVERT_ERROR_MSG_SIZE 256
#define V4LCONVERT_ERR(...) \
@@ -65,6 +69,7 @@
struct v4lconvert_data {
int fd;
int supported_src_formats; /* bitfield */
+ int format_needs_flip; /* bitfield */
unsigned int no_formats;
char error_msg[V4LCONVERT_ERROR_MSG_SIZE];
struct jdec_private *jdec;
@@ -107,4 +112,10 @@ void v4lconvert_bayer_to_bgr24(const unsigned char *bayer,
void v4lconvert_bayer_to_yuv420(const unsigned char *bayer,
unsigned char *yuv, int width, int height, unsigned int pixfmt);
+void v4lconvert_flip_rgbbgr24(const unsigned char *src, unsigned char *dst,
+ int width, int height);
+
+void v4lconvert_flip_yuv420(const unsigned char *src, unsigned char *dst,
+ int width, int height);
+
#endif
diff --git a/v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert.c b/v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert.c
index ade797cd9..9b13a6b78 100644
--- a/v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert.c
+++ b/v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert.c
@@ -78,6 +78,8 @@ struct v4lconvert_data *v4lconvert_create(int fd)
for (j = 0; j < ARRAY_SIZE(supported_src_pixfmts); j++)
if (fmt.pixelformat == supported_src_pixfmts[j]) {
data->supported_src_formats |= 1 << j;
+ if (fmt.flags & V4L2_FMT_FLAG_UPSIDEDOWN)
+ data->format_needs_flip |= 1 << j;
break;
}
}
@@ -214,17 +216,55 @@ int v4lconvert_try_format(struct v4lconvert_data *data,
return 0;
}
+static int v4lconvert_needs_flip(struct v4lconvert_data *data,
+ const struct v4l2_format *src_fmt)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(supported_src_pixfmts); i++)
+ if (src_fmt->fmt.pix.pixelformat == supported_src_pixfmts[i] &&
+ (data->format_needs_flip & (1 << i)))
+ return 1;
+
+ return 0;
+}
+
+/* Is conversion necessary ? */
+int v4lconvert_needs_conversion(struct v4lconvert_data *data,
+ const struct v4l2_format *src_fmt, /* in */
+ const struct v4l2_format *dest_fmt) /* in */
+{
+ int i;
+
+ if(memcmp(src_fmt, dest_fmt, sizeof(*src_fmt)))
+ return 1; /* Formats differ */
+
+ if (!v4lconvert_needs_flip(data, src_fmt))
+ return 0; /* Formats identical and we don't need flip */
+
+ /* Formats are identical, but we need flip, do we support the dest_fmt? */
+ for (i = 0; i < ARRAY_SIZE(supported_dst_pixfmts); i++)
+ if (supported_dst_pixfmts[i] == dest_fmt->fmt.pix.pixelformat)
+ break;
+
+ if (i == ARRAY_SIZE(supported_dst_pixfmts))
+ return 0; /* Needs flip but we cannot do it :( */
+ else
+ return 1; /* Needs flip and thus conversion */
+}
+
int v4lconvert_convert(struct v4lconvert_data *data,
const struct v4l2_format *src_fmt, /* in */
const struct v4l2_format *dest_fmt, /* in */
- unsigned char *src, int src_size, unsigned char *dest, int dest_size)
+ unsigned char *src, int src_size, unsigned char *_dest, int dest_size)
{
unsigned int header_width, header_height;
- int result, needed;
+ int result, needed, needs_flip = 0;
unsigned char *components[3];
+ unsigned char *dest = _dest;
/* Special case when no conversion is needed */
- if(!memcmp(src_fmt, dest_fmt, sizeof(*src_fmt))) {
+ if (!v4lconvert_needs_conversion(data, src_fmt, dest_fmt)) {
int to_copy = MIN(dest_size, src_size);
memcpy(dest, src, to_copy);
return to_copy;
@@ -251,6 +291,11 @@ int v4lconvert_convert(struct v4lconvert_data *data,
return -1;
}
+ if (v4lconvert_needs_flip(data, src_fmt)) {
+ needs_flip = 1;
+ dest = alloca(needed);
+ }
+
switch (src_fmt->fmt.pix.pixelformat) {
case V4L2_PIX_FMT_MJPEG:
case V4L2_PIX_FMT_JPEG:
@@ -455,6 +500,27 @@ int v4lconvert_convert(struct v4lconvert_data *data,
return -1;
}
+ if (needs_flip) {
+ /* Note dest is our temporary buffer to which our conversion was done and
+ _dest is the real dest! */
+
+ /* If the formats are identical no conversion has been done! */
+ if (dest_fmt->fmt.pix.pixelformat == src_fmt->fmt.pix.pixelformat)
+ dest = src;
+
+ switch (dest_fmt->fmt.pix.pixelformat) {
+ case V4L2_PIX_FMT_RGB24:
+ case V4L2_PIX_FMT_BGR24:
+ v4lconvert_flip_rgbbgr24(dest, _dest, dest_fmt->fmt.pix.width,
+ dest_fmt->fmt.pix.height);
+ break;
+ case V4L2_PIX_FMT_YUV420:
+ v4lconvert_flip_yuv420(dest, _dest, dest_fmt->fmt.pix.width,
+ dest_fmt->fmt.pix.height);
+ break;
+ }
+ }
+
return needed;
}