diff options
Diffstat (limited to 'v4l2-apps/lib/libv4l/libv4lconvert')
-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 |
4 files changed, 141 insertions, 4 deletions
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; } |