diff options
Diffstat (limited to 'v4l2-apps/lib')
-rw-r--r-- | v4l2-apps/lib/libv4l/ChangeLog | 5 | ||||
-rw-r--r-- | v4l2-apps/lib/libv4l/include/libv4lconvert.h | 5 | ||||
-rw-r--r-- | v4l2-apps/lib/libv4l/libv4l2/libv4l2.c | 16 | ||||
-rw-r--r-- | v4l2-apps/lib/libv4l/libv4lconvert/Makefile | 2 | ||||
-rw-r--r-- | v4l2-apps/lib/libv4l/libv4lconvert/flip.c | 60 | ||||
-rw-r--r-- | v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert-priv.h | 11 | ||||
-rw-r--r-- | v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert.c | 72 |
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; } |