diff options
Diffstat (limited to 'v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert.c')
-rw-r--r-- | v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert.c | 737 |
1 files changed, 0 insertions, 737 deletions
diff --git a/v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert.c b/v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert.c deleted file mode 100644 index 93bc67c7e..000000000 --- a/v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert.c +++ /dev/null @@ -1,737 +0,0 @@ -/* -# (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 <errno.h> -#include <string.h> -#include <stdlib.h> -#include <syscall.h> -#include <unistd.h> -#include "libv4lconvert.h" -#include "libv4lconvert-priv.h" - -#define MIN(a,b) (((a)<(b))?(a):(b)) -#define ARRAY_SIZE(x) ((int)sizeof(x)/(int)sizeof((x)[0])) - -/* Note for proper functioning of v4lconvert_enum_fmt the first entries in - supported_src_pixfmts must match with the entries in supported_dst_pixfmts */ -#define SUPPORTED_DST_PIXFMTS \ - { V4L2_PIX_FMT_RGB24, 0 }, \ - { V4L2_PIX_FMT_BGR24, 0 }, \ - { V4L2_PIX_FMT_YUV420, 0 } - -static void v4lconvert_get_framesizes(struct v4lconvert_data *data, - unsigned int pixelformat); - -/* Note uncompressed formats must go first so that they are prefered by - v4lconvert_try_format for low resolutions */ -static const struct v4lconvert_pixfmt supported_src_pixfmts[] = { - SUPPORTED_DST_PIXFMTS, - { V4L2_PIX_FMT_YUYV, 0 }, - { V4L2_PIX_FMT_YVYU, 0 }, - { V4L2_PIX_FMT_SBGGR8, 0 }, - { V4L2_PIX_FMT_SGBRG8, 0 }, - { V4L2_PIX_FMT_SGRBG8, 0 }, - { V4L2_PIX_FMT_SRGGB8, 0 }, - { V4L2_PIX_FMT_SPCA501, 0 }, - { V4L2_PIX_FMT_SPCA505, 0 }, - { V4L2_PIX_FMT_SPCA508, 0 }, - { V4L2_PIX_FMT_MJPEG, V4LCONVERT_COMPRESSED }, - { V4L2_PIX_FMT_JPEG, V4LCONVERT_COMPRESSED }, - { V4L2_PIX_FMT_SPCA561, V4LCONVERT_COMPRESSED }, - { V4L2_PIX_FMT_SN9C10X, V4LCONVERT_COMPRESSED }, - { V4L2_PIX_FMT_PAC207, V4LCONVERT_COMPRESSED }, - { V4L2_PIX_FMT_PJPG, V4LCONVERT_COMPRESSED }, -}; - -static const struct v4lconvert_pixfmt supported_dst_pixfmts[] = { - SUPPORTED_DST_PIXFMTS -}; - -/* List of cams which need special flags */ -static const struct v4lconvert_flags_info v4lconvert_flags[] = { - { "SPC 200NC ", V4LCONVERT_UPSIDE_DOWN }, - { "SPC 300NC ", V4LCONVERT_UPSIDE_DOWN }, - { "USB Camera (0471:0325)", V4LCONVERT_UPSIDE_DOWN }, /* SPC200NC */ - { "USB Camera (0471:0326)", V4LCONVERT_UPSIDE_DOWN }, /* SPC300NC */ - { "USB Camera (093a:2476)", V4LCONVERT_UPSIDE_DOWN }, /* Genius E-M 112 */ -}; - -struct v4lconvert_data *v4lconvert_create(int fd) -{ - int i, j; - struct v4lconvert_data *data = calloc(1, sizeof(struct v4lconvert_data)); - struct v4l2_capability cap; - - if (!data) - return NULL; - - data->fd = fd; - data->jdec = NULL; - - /* Check supported formats */ - for (i = 0; ; i++) { - struct v4l2_fmtdesc fmt = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE }; - - fmt.index = i; - - if (syscall(SYS_ioctl, fd, VIDIOC_ENUM_FMT, &fmt)) - break; - - for (j = 0; j < ARRAY_SIZE(supported_src_pixfmts); j++) - if (fmt.pixelformat == supported_src_pixfmts[j].fmt) { - data->supported_src_formats |= 1 << j; - break; - } - - v4lconvert_get_framesizes(data, fmt.pixelformat); - } - - data->no_formats = i; - - /* Check if this cam has any special flags */ - if (syscall(SYS_ioctl, fd, VIDIOC_QUERYCAP, &cap) == 0) { - for (i = 0; i < ARRAY_SIZE(v4lconvert_flags); i++) - if (!strcmp((const char *)v4lconvert_flags[i].card, (char *)cap.card)) { - data->flags = v4lconvert_flags[i].flags; - break; - } - } - - return data; -} - -void v4lconvert_destroy(struct v4lconvert_data *data) -{ - if (data->jdec) { - unsigned char *comps[3] = { NULL, NULL, NULL }; - tinyjpeg_set_components(data->jdec, comps, 3); - tinyjpeg_free(data->jdec); - } - free(data); -} - -static int v4lconvert_supported_dst_format(unsigned int pixelformat) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(supported_dst_pixfmts); i++) - if (supported_dst_pixfmts[i].fmt == pixelformat) - break; - - return i != ARRAY_SIZE(supported_dst_pixfmts); -} - -/* See libv4lconvert.h for description of in / out parameters */ -int v4lconvert_enum_fmt(struct v4lconvert_data *data, struct v4l2_fmtdesc *fmt) -{ - int i, no_faked_fmts = 0; - unsigned int faked_fmts[ARRAY_SIZE(supported_dst_pixfmts)]; - - if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || - fmt->index < data->no_formats || - !data->supported_src_formats) - return syscall(SYS_ioctl, data->fd, VIDIOC_ENUM_FMT, fmt); - - for (i = 0; i < ARRAY_SIZE(supported_dst_pixfmts); i++) - if (!(data->supported_src_formats & (1 << i))) { - faked_fmts[no_faked_fmts] = supported_dst_pixfmts[i].fmt; - no_faked_fmts++; - } - - i = fmt->index - data->no_formats; - if (i >= no_faked_fmts) { - errno = EINVAL; - return -1; - } - - fmt->flags = 0; - fmt->pixelformat = faked_fmts[i]; - fmt->description[0] = faked_fmts[i] & 0xff; - fmt->description[1] = (faked_fmts[i] >> 8) & 0xff; - fmt->description[2] = (faked_fmts[i] >> 16) & 0xff; - fmt->description[3] = faked_fmts[i] >> 24; - fmt->description[4] = '\0'; - memset(fmt->reserved, 0, 4); - - return 0; -} - -/* See libv4lconvert.h for description of in / out parameters */ -int v4lconvert_try_format(struct v4lconvert_data *data, - struct v4l2_format *dest_fmt, struct v4l2_format *src_fmt) -{ - int i; - unsigned int closest_fmt_size_diff = -1; - unsigned int desired_pixfmt = dest_fmt->fmt.pix.pixelformat; - struct v4l2_format try_fmt, closest_fmt = { .type = 0 }; - - /* Can we do conversion to the requested format & type? */ - if (!v4lconvert_supported_dst_format(desired_pixfmt) || - dest_fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { - int ret = syscall(SYS_ioctl, data->fd, VIDIOC_TRY_FMT, dest_fmt); - if (src_fmt) - *src_fmt = *dest_fmt; - return ret; - } - - for (i = 0; i < ARRAY_SIZE(supported_src_pixfmts); i++) { - /* is this format supported? */ - if (!(data->supported_src_formats & (1 << i))) - continue; - - try_fmt = *dest_fmt; - try_fmt.fmt.pix.pixelformat = supported_src_pixfmts[i].fmt; - - if (!syscall(SYS_ioctl, data->fd, VIDIOC_TRY_FMT, &try_fmt)) - { - if (try_fmt.fmt.pix.pixelformat == supported_src_pixfmts[i].fmt) { - int size_x_diff = abs((int)try_fmt.fmt.pix.width - - (int)dest_fmt->fmt.pix.width); - int size_y_diff = abs((int)try_fmt.fmt.pix.height - - (int)dest_fmt->fmt.pix.height); - unsigned int size_diff = size_x_diff * size_x_diff + - size_y_diff * size_y_diff; - if (size_diff < closest_fmt_size_diff || - (size_diff == closest_fmt_size_diff && - (supported_src_pixfmts[i].fmt == desired_pixfmt || - ((try_fmt.fmt.pix.width > 176 || try_fmt.fmt.pix.height > 144) && - (supported_src_pixfmts[i].flags & V4LCONVERT_COMPRESSED))))) { - closest_fmt_size_diff = size_diff; - closest_fmt = try_fmt; - } - } - } - } - - if (closest_fmt.type == 0) { - int ret = syscall(SYS_ioctl, data->fd, VIDIOC_TRY_FMT, dest_fmt); - if (src_fmt) - *src_fmt = *dest_fmt; - return ret; - } - - *dest_fmt = closest_fmt; - - /* Are we converting? */ - if (closest_fmt.fmt.pix.pixelformat != desired_pixfmt) { - dest_fmt->fmt.pix.pixelformat = desired_pixfmt; - switch (dest_fmt->fmt.pix.pixelformat) { - case V4L2_PIX_FMT_RGB24: - case V4L2_PIX_FMT_BGR24: - dest_fmt->fmt.pix.bytesperline = dest_fmt->fmt.pix.width * 3; - dest_fmt->fmt.pix.sizeimage = dest_fmt->fmt.pix.width * - dest_fmt->fmt.pix.height * 3; - break; - case V4L2_PIX_FMT_YUV420: - dest_fmt->fmt.pix.bytesperline = dest_fmt->fmt.pix.width; - dest_fmt->fmt.pix.sizeimage = (dest_fmt->fmt.pix.width * - dest_fmt->fmt.pix.height * 3) / 2; - break; - } - } - - if (src_fmt) - *src_fmt = closest_fmt; - - 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 */ -{ - if(memcmp(src_fmt, dest_fmt, sizeof(*src_fmt))) - return 1; /* Formats differ */ - - if (!(data->flags & V4LCONVERT_UPSIDE_DOWN)) - return 0; /* Formats identical and we don't need flip */ - - /* Formats are identical, but we need flip, do we support the dest_fmt? */ - if (!v4lconvert_supported_dst_format(dest_fmt->fmt.pix.pixelformat)) - 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 int header_width, header_height; - int result, needed, rotate = 0, jpeg_flags = TINYJPEG_FLAGS_MJPEG_TABLE; - unsigned char *components[3]; - unsigned char *dest = _dest; - - /* Special case when no conversion is needed */ - 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; - } - - /* sanity check, is the dest buffer large enough? */ - switch (dest_fmt->fmt.pix.pixelformat) { - case V4L2_PIX_FMT_RGB24: - case V4L2_PIX_FMT_BGR24: - needed = dest_fmt->fmt.pix.width * dest_fmt->fmt.pix.height * 3; - break; - case V4L2_PIX_FMT_YUV420: - needed = (dest_fmt->fmt.pix.width * dest_fmt->fmt.pix.height * 3) / 2; - break; - default: - V4LCONVERT_ERR("Unknown dest format in conversion\n"); - errno = EINVAL; - return -1; - } - - if (dest_size < needed) { - V4LCONVERT_ERR("destination buffer too small\n"); - errno = EFAULT; - return -1; - } - - if (data->flags & V4LCONVERT_UPSIDE_DOWN) { - rotate = 180; - dest = alloca(needed); - } - - switch (src_fmt->fmt.pix.pixelformat) { - case V4L2_PIX_FMT_PJPG: - jpeg_flags |= TINYJPEG_FLAGS_PIXART_JPEG; - /* Fall through */ - case V4L2_PIX_FMT_MJPEG: - case V4L2_PIX_FMT_JPEG: - if (!data->jdec) { - data->jdec = tinyjpeg_init(); - if (!data->jdec) { - V4LCONVERT_ERR("out of memory!\n"); - errno = ENOMEM; - return -1; - } - } - tinyjpeg_set_flags(data->jdec, jpeg_flags); - if (tinyjpeg_parse_header(data->jdec, src, src_size)) { - V4LCONVERT_ERR("parsing JPEG header: %s\n", - tinyjpeg_get_errorstring(data->jdec)); - errno = EIO; - return -1; - } - tinyjpeg_get_size(data->jdec, &header_width, &header_height); - - if (header_width != dest_fmt->fmt.pix.width || - header_height != dest_fmt->fmt.pix.height) { - /* Check for (pixart) rotated JPEG */ - if (header_width == dest_fmt->fmt.pix.height || - header_height == dest_fmt->fmt.pix.width) { - if (!rotate) - dest = alloca(needed); - rotate += 90; - } else { - V4LCONVERT_ERR("unexpected width / height in JPEG header" - "expected: %ux%u, header: %ux%u\n", - dest_fmt->fmt.pix.width, dest_fmt->fmt.pix.height, - header_width, header_height); - errno = EIO; - return -1; - } - } - - components[0] = dest; - components[1] = components[0] + dest_fmt->fmt.pix.width * - dest_fmt->fmt.pix.height; - components[2] = components[1] + (dest_fmt->fmt.pix.width * - dest_fmt->fmt.pix.height) / 4; - - switch (dest_fmt->fmt.pix.pixelformat) { - case V4L2_PIX_FMT_RGB24: - tinyjpeg_set_components(data->jdec, components, 1); - result = tinyjpeg_decode(data->jdec, TINYJPEG_FMT_RGB24); - break; - case V4L2_PIX_FMT_BGR24: - tinyjpeg_set_components(data->jdec, components, 1); - result = tinyjpeg_decode(data->jdec, TINYJPEG_FMT_BGR24); - break; - default: - tinyjpeg_set_components(data->jdec, components, 3); - result = tinyjpeg_decode(data->jdec, TINYJPEG_FMT_YUV420P); - break; - } - - if (result) { - /* Pixart webcam's seem to regulary generate corrupt frames, which - are best thrown away to avoid flashes in the video stream. Tell - the upper layer this is an intermediate fault and it should try - again with a new buffer by setting errno to EAGAIN */ - if (src_fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_PJPG) { - V4LCONVERT_ERR("Error decompressing JPEG: %s", - tinyjpeg_get_errorstring(data->jdec)); - errno = EAGAIN; - return -1; - } else { - /* If the JPEG header checked out ok and we get an error during actual - decompression, log the error, but don't return an errorcode to the - application, so that the user gets what we managed to decompress */ - fprintf(stderr, "libv4lconvert: Error decompressing JPEG: %s", - tinyjpeg_get_errorstring(data->jdec)); - } - } - break; - - case V4L2_PIX_FMT_SBGGR8: - case V4L2_PIX_FMT_SGBRG8: - case V4L2_PIX_FMT_SGRBG8: - case V4L2_PIX_FMT_SRGGB8: - switch (dest_fmt->fmt.pix.pixelformat) { - case V4L2_PIX_FMT_RGB24: - v4lconvert_bayer_to_rgb24(src, dest, dest_fmt->fmt.pix.width, - dest_fmt->fmt.pix.height, src_fmt->fmt.pix.pixelformat); - break; - case V4L2_PIX_FMT_BGR24: - v4lconvert_bayer_to_bgr24(src, dest, dest_fmt->fmt.pix.width, - dest_fmt->fmt.pix.height, src_fmt->fmt.pix.pixelformat); - break; - default: - v4lconvert_bayer_to_yuv420(src, dest, dest_fmt->fmt.pix.width, - dest_fmt->fmt.pix.height, src_fmt->fmt.pix.pixelformat); - break; - } - break; - - /* YUYV line by line formats */ - case V4L2_PIX_FMT_SPCA501: - case V4L2_PIX_FMT_SPCA505: - case V4L2_PIX_FMT_SPCA508: - { - unsigned char tmpbuf[dest_fmt->fmt.pix.width * dest_fmt->fmt.pix.height * - 3 / 2]; - unsigned char *my_dst = (dest_fmt->fmt.pix.pixelformat != - V4L2_PIX_FMT_YUV420) ? tmpbuf : dest; - - switch (src_fmt->fmt.pix.pixelformat) { - case V4L2_PIX_FMT_SPCA501: - v4lconvert_spca501_to_yuv420(src, my_dst, dest_fmt->fmt.pix.width, - dest_fmt->fmt.pix.height); - break; - case V4L2_PIX_FMT_SPCA505: - v4lconvert_spca505_to_yuv420(src, my_dst, dest_fmt->fmt.pix.width, - dest_fmt->fmt.pix.height); - break; - case V4L2_PIX_FMT_SPCA508: - v4lconvert_spca508_to_yuv420(src, my_dst, dest_fmt->fmt.pix.width, - dest_fmt->fmt.pix.height); - break; - } - - switch (dest_fmt->fmt.pix.pixelformat) { - case V4L2_PIX_FMT_RGB24: - v4lconvert_yuv420_to_rgb24(tmpbuf, dest, dest_fmt->fmt.pix.width, - dest_fmt->fmt.pix.height); - break; - case V4L2_PIX_FMT_BGR24: - v4lconvert_yuv420_to_bgr24(tmpbuf, dest, dest_fmt->fmt.pix.width, - dest_fmt->fmt.pix.height); - break; - } - break; - } - - /* compressed bayer formats */ - case V4L2_PIX_FMT_SPCA561: - case V4L2_PIX_FMT_SN9C10X: - case V4L2_PIX_FMT_PAC207: - { - unsigned char tmpbuf[dest_fmt->fmt.pix.width*dest_fmt->fmt.pix.height]; - unsigned int bayer_fmt = 0; - - switch (src_fmt->fmt.pix.pixelformat) { - case V4L2_PIX_FMT_SPCA561: - v4lconvert_decode_spca561(src, tmpbuf, dest_fmt->fmt.pix.width, - dest_fmt->fmt.pix.height); - bayer_fmt = V4L2_PIX_FMT_SGBRG8; - break; - case V4L2_PIX_FMT_SN9C10X: - v4lconvert_decode_sn9c10x(src, tmpbuf, dest_fmt->fmt.pix.width, - dest_fmt->fmt.pix.height); - bayer_fmt = V4L2_PIX_FMT_SBGGR8; - break; - case V4L2_PIX_FMT_PAC207: - v4lconvert_decode_pac207(src, tmpbuf, dest_fmt->fmt.pix.width, - dest_fmt->fmt.pix.height); - bayer_fmt = V4L2_PIX_FMT_SBGGR8; - break; - } - - switch (dest_fmt->fmt.pix.pixelformat) { - case V4L2_PIX_FMT_RGB24: - v4lconvert_bayer_to_rgb24(tmpbuf, dest, dest_fmt->fmt.pix.width, - dest_fmt->fmt.pix.height, bayer_fmt); - break; - case V4L2_PIX_FMT_BGR24: - v4lconvert_bayer_to_bgr24(tmpbuf, dest, dest_fmt->fmt.pix.width, - dest_fmt->fmt.pix.height, bayer_fmt); - break; - default: - v4lconvert_bayer_to_yuv420(tmpbuf, dest, dest_fmt->fmt.pix.width, - dest_fmt->fmt.pix.height, bayer_fmt); - break; - } - break; - } - - case V4L2_PIX_FMT_RGB24: - switch (dest_fmt->fmt.pix.pixelformat) { - case V4L2_PIX_FMT_BGR24: - v4lconvert_swap_rgb(src, dest, dest_fmt->fmt.pix.width, - dest_fmt->fmt.pix.height); - break; - case V4L2_PIX_FMT_YUV420: - printf("FIXME add rgb24 -> yuv420 conversion\n"); - break; - } - break; - case V4L2_PIX_FMT_BGR24: - switch (dest_fmt->fmt.pix.pixelformat) { - case V4L2_PIX_FMT_RGB24: - v4lconvert_swap_rgb(src, dest, dest_fmt->fmt.pix.width, - dest_fmt->fmt.pix.height); - break; - case V4L2_PIX_FMT_YUV420: - printf("FIXME add bgr24 -> yuv420 conversion\n"); - break; - } - break; - - case V4L2_PIX_FMT_YUV420: - switch (dest_fmt->fmt.pix.pixelformat) { - case V4L2_PIX_FMT_RGB24: - v4lconvert_yuv420_to_rgb24(src, dest, dest_fmt->fmt.pix.width, - dest_fmt->fmt.pix.height); - break; - case V4L2_PIX_FMT_BGR24: - v4lconvert_yuv420_to_bgr24(src, dest, dest_fmt->fmt.pix.width, - dest_fmt->fmt.pix.height); - break; - } - break; - - case V4L2_PIX_FMT_YUYV: - switch (dest_fmt->fmt.pix.pixelformat) { - case V4L2_PIX_FMT_RGB24: - v4lconvert_yuyv_to_rgb24(src, dest, dest_fmt->fmt.pix.width, - dest_fmt->fmt.pix.height); - break; - case V4L2_PIX_FMT_BGR24: - v4lconvert_yuyv_to_bgr24(src, dest, dest_fmt->fmt.pix.width, - dest_fmt->fmt.pix.height); - break; - default: - v4lconvert_yuyv_to_yuv420(src, dest, dest_fmt->fmt.pix.width, - dest_fmt->fmt.pix.height); - break; - } - break; - - case V4L2_PIX_FMT_YVYU: - switch (dest_fmt->fmt.pix.pixelformat) { - case V4L2_PIX_FMT_RGB24: - v4lconvert_yvyu_to_rgb24(src, dest, dest_fmt->fmt.pix.width, - dest_fmt->fmt.pix.height); - break; - case V4L2_PIX_FMT_BGR24: - v4lconvert_yvyu_to_bgr24(src, dest, dest_fmt->fmt.pix.width, - dest_fmt->fmt.pix.height); - break; - default: - v4lconvert_yvyu_to_yuv420(src, dest, dest_fmt->fmt.pix.width, - dest_fmt->fmt.pix.height); - break; - } - break; - - default: - V4LCONVERT_ERR("Unknown src format in conversion\n"); - errno = EINVAL; - return -1; - } - - /* Note when rotating 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 (rotate && dest_fmt->fmt.pix.pixelformat == src_fmt->fmt.pix.pixelformat) - dest = src; - - switch (rotate) { - case 0: - break; - case 90: - switch (dest_fmt->fmt.pix.pixelformat) { - case V4L2_PIX_FMT_RGB24: - case V4L2_PIX_FMT_BGR24: - v4lconvert_rotate90_rgbbgr24(dest, _dest, dest_fmt->fmt.pix.width, - dest_fmt->fmt.pix.height); - break; - case V4L2_PIX_FMT_YUV420: - v4lconvert_rotate90_yuv420(dest, _dest, dest_fmt->fmt.pix.width, - dest_fmt->fmt.pix.height); - break; - } - break; - case 180: - switch (dest_fmt->fmt.pix.pixelformat) { - case V4L2_PIX_FMT_RGB24: - case V4L2_PIX_FMT_BGR24: - v4lconvert_rotate180_rgbbgr24(dest, _dest, dest_fmt->fmt.pix.width, - dest_fmt->fmt.pix.height); - break; - case V4L2_PIX_FMT_YUV420: - v4lconvert_rotate180_yuv420(dest, _dest, dest_fmt->fmt.pix.width, - dest_fmt->fmt.pix.height); - break; - } - break; - default: - printf("FIXME add %d degrees rotation\n", rotate); - } - - return needed; -} - -const char *v4lconvert_get_error_message(struct v4lconvert_data *data) -{ - return data->error_msg; -} - -static void v4lconvert_get_framesizes(struct v4lconvert_data *data, - unsigned int pixelformat) -{ - int i, j, match; - struct v4l2_frmsizeenum frmsize = { .pixel_format = pixelformat }; - - for (i = 0; ; i++) { - frmsize.index = i; - if (syscall(SYS_ioctl, data->fd, VIDIOC_ENUM_FRAMESIZES, &frmsize)) - break; - - /* We got a framesize, check we don't have the same one already */ - match = 0; - for (j = 0; j < data->no_framesizes && !match; j++) { - if (frmsize.type != data->framesizes[j].type) - continue; - - switch(frmsize.type) { - case V4L2_FRMSIZE_TYPE_DISCRETE: - if(!memcmp(&frmsize.discrete, &data->framesizes[j].discrete, - sizeof(frmsize.discrete))) - match = 1; - break; - case V4L2_FRMSIZE_TYPE_CONTINUOUS: - case V4L2_FRMSIZE_TYPE_STEPWISE: - if(!memcmp(&frmsize.stepwise, &data->framesizes[j].stepwise, - sizeof(frmsize.stepwise))) - match = 1; - break; - } - } - /* Add this framesize if it is not already in our list */ - if (!match) { - if (data->no_framesizes == V4LCONVERT_MAX_FRAMESIZES) { - fprintf(stderr, - "libv4lconvert: warning more framesizes then I can handle!\n"); - return; - } - data->framesizes[data->no_framesizes].type = frmsize.type; - switch(frmsize.type) { - case V4L2_FRMSIZE_TYPE_DISCRETE: - data->framesizes[data->no_framesizes].discrete = frmsize.discrete; - break; - case V4L2_FRMSIZE_TYPE_CONTINUOUS: - case V4L2_FRMSIZE_TYPE_STEPWISE: - data->framesizes[data->no_framesizes].stepwise = frmsize.stepwise; - break; - } - data->no_framesizes++; - } - } -} - -int v4lconvert_enum_framesizes(struct v4lconvert_data *data, - struct v4l2_frmsizeenum *frmsize) -{ - if (!v4lconvert_supported_dst_format(frmsize->pixel_format)) - return syscall(SYS_ioctl, data->fd, VIDIOC_ENUM_FRAMESIZES, frmsize); - - if (frmsize->index >= data->no_framesizes) { - errno = EINVAL; - return -1; - } - - frmsize->type = data->framesizes[frmsize->index].type; - switch(frmsize->type) { - case V4L2_FRMSIZE_TYPE_DISCRETE: - frmsize->discrete = data->framesizes[frmsize->index].discrete; - break; - case V4L2_FRMSIZE_TYPE_CONTINUOUS: - case V4L2_FRMSIZE_TYPE_STEPWISE: - frmsize->stepwise = data->framesizes[frmsize->index].stepwise; - break; - } - - return 0; -} - -int v4lconvert_enum_frameintervals(struct v4lconvert_data *data, - struct v4l2_frmivalenum *frmival) -{ - int res; - struct v4l2_format src_fmt, dest_fmt; - - if (!v4lconvert_supported_dst_format(frmival->pixel_format)) - return syscall(SYS_ioctl, data->fd, VIDIOC_ENUM_FRAMEINTERVALS, frmival); - - /* Check which format we will be using to convert to frmival->pixel_format */ - memset(&dest_fmt, 0, sizeof(dest_fmt)); - dest_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - dest_fmt.fmt.pix.pixelformat = frmival->pixel_format; - dest_fmt.fmt.pix.width = frmival->width; - dest_fmt.fmt.pix.height = frmival->height; - if ((res = v4lconvert_try_format(data, &dest_fmt, &src_fmt))) - return res; - - /* Check the requested format is supported exactly as requested */ - if (dest_fmt.fmt.pix.pixelformat != frmival->pixel_format || - dest_fmt.fmt.pix.width != frmival->width || - dest_fmt.fmt.pix.height != frmival->height) { - errno = EINVAL; - return -1; - } - - /* Enumerate the frameintervals of the source format we will be using */ - frmival->pixel_format = src_fmt.fmt.pix.pixelformat; - frmival->width = src_fmt.fmt.pix.width; - frmival->height = src_fmt.fmt.pix.height; - res = syscall(SYS_ioctl, data->fd, VIDIOC_ENUM_FRAMEINTERVALS, frmival); - - /* Restore the requested format in the frmival struct */ - frmival->pixel_format = dest_fmt.fmt.pix.pixelformat; - frmival->width = dest_fmt.fmt.pix.width; - frmival->height = dest_fmt.fmt.pix.height; - - return res; -} |