diff options
Diffstat (limited to 'v4l2-apps/lib')
-rw-r--r-- | v4l2-apps/lib/libv4l/ChangeLog | 14 | ||||
-rw-r--r-- | v4l2-apps/lib/libv4l/Makefile | 2 | ||||
-rw-r--r-- | v4l2-apps/lib/libv4l/include/libv4lconvert.h | 10 | ||||
-rw-r--r-- | v4l2-apps/lib/libv4l/libv4l1/libv4l1.c | 15 | ||||
-rw-r--r-- | v4l2-apps/lib/libv4l/libv4l1/log.c | 6 | ||||
-rw-r--r-- | v4l2-apps/lib/libv4l/libv4l2/libv4l2.c | 24 | ||||
-rw-r--r-- | v4l2-apps/lib/libv4l/libv4l2/v4l2convert.c | 15 | ||||
-rw-r--r-- | v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert-priv.h | 34 | ||||
-rw-r--r-- | v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert.c | 239 | ||||
-rw-r--r-- | v4l2-apps/lib/libv4l/libv4lconvert/rgbyuv.c | 170 |
10 files changed, 481 insertions, 48 deletions
diff --git a/v4l2-apps/lib/libv4l/ChangeLog b/v4l2-apps/lib/libv4l/ChangeLog index eefe0028b..dd53eced9 100644 --- a/v4l2-apps/lib/libv4l/ChangeLog +++ b/v4l2-apps/lib/libv4l/ChangeLog @@ -1,3 +1,17 @@ +libv4l-0.5.0 +------------ +* Add support for enumerating framesizes and frameintervals of emulated + formats when the driver supports it for the real format +* Make sure the video device always gets opened RW even if the application + asks for RO +* Add Genius E-Messenger 112 (093a:2476) to list of cams which have their + sensor upside down + +libv4l-0.4.3 +------------ +* Add suport for YUYV and YVYU packed pixel formats (Jean-Francois Moine) +* Prefer compressed pixformats for resolutions > 176x144 + libv4l-0.4.2 ------------ * The bayer pixel order in gspca's sonixb driver was different from that in diff --git a/v4l2-apps/lib/libv4l/Makefile b/v4l2-apps/lib/libv4l/Makefile index 92928271a..4c99c3167 100644 --- a/v4l2-apps/lib/libv4l/Makefile +++ b/v4l2-apps/lib/libv4l/Makefile @@ -1,5 +1,5 @@ LIB_RELEASE=0 -V4L2_LIB_VERSION=$(LIB_RELEASE).4.2 +V4L2_LIB_VERSION=$(LIB_RELEASE).5.0 all clean install: $(MAKE) -C libv4lconvert V4L2_LIB_VERSION=$(V4L2_LIB_VERSION) $@ diff --git a/v4l2-apps/lib/libv4l/include/libv4lconvert.h b/v4l2-apps/lib/libv4l/include/libv4lconvert.h index 87e41ceaa..626c43473 100644 --- a/v4l2-apps/lib/libv4l/include/libv4lconvert.h +++ b/v4l2-apps/lib/libv4l/include/libv4lconvert.h @@ -71,6 +71,16 @@ LIBV4L_PUBLIC int v4lconvert_convert(struct v4lconvert_data *data, /* get a string describing the last error*/ LIBV4L_PUBLIC const char *v4lconvert_get_error_message(struct v4lconvert_data *data); +/* Just like VIDIOC_ENUM_FRAMESIZE, except that the framesizes of emulated + formats can be enumerated as well. */ +LIBV4L_PUBLIC int v4lconvert_enum_framesizes(struct v4lconvert_data *data, + struct v4l2_frmsizeenum *frmsize); + +/* Just like VIDIOC_ENUM_FRAMEINTERVALS, except that the intervals of emulated + formats can be enumerated as well. */ +LIBV4L_PUBLIC int v4lconvert_enum_frameintervals(struct v4lconvert_data *data, + struct v4l2_frmivalenum *frmival); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/v4l2-apps/lib/libv4l/libv4l1/libv4l1.c b/v4l2-apps/lib/libv4l/libv4l1/libv4l1.c index 39f2d29e0..797c8768a 100644 --- a/v4l2-apps/lib/libv4l/libv4l1/libv4l1.c +++ b/v4l2-apps/lib/libv4l/libv4l1/libv4l1.c @@ -259,6 +259,15 @@ int v4l1_open (const char *file, int oflag, ...) struct v4l2_format fmt2; struct v4l2_input input2; struct v4l2_standard standard2; + int v4l_device = 0; + + /* check if we're opening a video4linux2 device */ + if (!strncmp(file, "/dev/video", 10) || !strncmp(file, "/dev/v4l/", 9)) { + /* Some apps open the device read only, but we need rw rights as the + buffers *MUST* be mapped rw */ + oflag = (oflag & ~O_ACCMODE) | O_RDWR; + v4l_device = 1; + } /* original open code */ if (oflag & O_CREAT) @@ -276,11 +285,7 @@ int v4l1_open (const char *file, int oflag, ...) fd = syscall(SYS_open, file, oflag); /* end of original open code */ - if (fd == -1) - return fd; - - /* check if we're opening a video4linux2 device */ - if (strncmp(file, "/dev/video", 10) && strncmp(file, "/dev/v4l/", 9)) + if (fd == -1 || !v4l_device) return fd; /* check that this is an v4l2 device, no need to emulate v4l1 on diff --git a/v4l2-apps/lib/libv4l/libv4l1/log.c b/v4l2-apps/lib/libv4l/libv4l1/log.c index 74ce0f20b..9ff0cea46 100644 --- a/v4l2-apps/lib/libv4l/libv4l1/log.c +++ b/v4l2-apps/lib/libv4l/libv4l1/log.c @@ -66,6 +66,7 @@ static const char *v4l1_ioctls[] = { void v4l1_log_ioctl(unsigned long int request, void *arg, int result) { const char *ioctl_str = "unknown"; + char buf[40]; if (!v4l1_log_file) return; @@ -77,6 +78,11 @@ void v4l1_log_ioctl(unsigned long int request, void *arg, int result) if (_IOC_TYPE(request) == 'v' && _IOC_NR(request) < ARRAY_SIZE(v4l1_ioctls)) ioctl_str = v4l1_ioctls[_IOC_NR(request)]; + else { + snprintf(buf, sizeof(buf), "unknown request: %c %d\n", + (int)_IOC_TYPE(request), (int)_IOC_NR(request)); + ioctl_str = buf; + } fprintf(v4l1_log_file, "request == %s\n", ioctl_str); diff --git a/v4l2-apps/lib/libv4l/libv4l2/libv4l2.c b/v4l2-apps/lib/libv4l/libv4l2/libv4l2.c index 7029f69c3..b4a10afac 100644 --- a/v4l2-apps/lib/libv4l/libv4l2/libv4l2.c +++ b/v4l2-apps/lib/libv4l/libv4l2/libv4l2.c @@ -649,6 +649,11 @@ int v4l2_ioctl (int fd, unsigned long int request, ...) (devices[index].flags & V4L2_ENABLE_ENUM_FMT_EMULATION)) is_capture_request = 1; break; + case VIDIOC_ENUM_FRAMESIZES: + case VIDIOC_ENUM_FRAMEINTERVALS: + if (devices[index].flags & V4L2_ENABLE_ENUM_FMT_EMULATION) + is_capture_request = 1; + break; case VIDIOC_TRY_FMT: if (((struct v4l2_format *)arg)->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) is_capture_request = 1; @@ -714,6 +719,14 @@ int v4l2_ioctl (int fd, unsigned long int request, ...) result = v4lconvert_enum_fmt(devices[index].convert, arg); break; + case VIDIOC_ENUM_FRAMESIZES: + result = v4lconvert_enum_framesizes(devices[index].convert, arg); + break; + + case VIDIOC_ENUM_FRAMEINTERVALS: + result = v4lconvert_enum_frameintervals(devices[index].convert, arg); + break; + case VIDIOC_TRY_FMT: result = v4lconvert_try_format(devices[index].convert, arg, NULL); break; @@ -739,6 +752,17 @@ int v4l2_ioctl (int fd, unsigned long int request, ...) if (result) break; + if (src_fmt.fmt.pix.pixelformat != dest_fmt->fmt.pix.pixelformat && + v4l2_log_file) { + int pixfmt = src_fmt.fmt.pix.pixelformat; + + fprintf(v4l2_log_file, "VIDIOC_S_FMT converting from: %c%c%c%c\n", + pixfmt & 0xff, + (pixfmt >> 8) & 0xff, + (pixfmt >> 16) & 0xff, + pixfmt >> 24); + } + /* Maybe after try format has adjusted width/height etc, to whats available nothing has changed (on the cam side) ? */ if (!memcmp(&devices[index].src_fmt, &src_fmt, sizeof(src_fmt))) { diff --git a/v4l2-apps/lib/libv4l/libv4l2/v4l2convert.c b/v4l2-apps/lib/libv4l/libv4l2/v4l2convert.c index e8756f338..307a03ce5 100644 --- a/v4l2-apps/lib/libv4l/libv4l2/v4l2convert.c +++ b/v4l2-apps/lib/libv4l/libv4l2/v4l2convert.c @@ -53,6 +53,15 @@ LIBV4L_PUBLIC int open (const char *file, int oflag, ...) { int fd; struct v4l2_capability cap; + int v4l_device = 0; + + /* check if we're opening a video4linux2 device */ + if (!strncmp(file, "/dev/video", 10) || !strncmp(file, "/dev/v4l/", 9)) { + /* Some apps open the device read only, but we need rw rights as the + buffers *MUST* be mapped rw */ + oflag = (oflag & ~O_ACCMODE) | O_RDWR; + v4l_device = 1; + } /* original open code */ if (oflag & O_CREAT) @@ -70,11 +79,7 @@ LIBV4L_PUBLIC int open (const char *file, int oflag, ...) fd = syscall(SYS_open, file, oflag); /* end of original open code */ - if (fd == -1) - return fd; - - /* check if we're opening a video4linux2 device */ - if (strncmp(file, "/dev/video", 10) && strncmp(file, "/dev/v4l/", 9)) + if (fd == -1 || !v4l_device) return fd; /* check that this is an v4l2 device, libv4l2 only supports v4l2 devices */ diff --git a/v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert-priv.h b/v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert-priv.h index 915c33283..0c4eff6ce 100644 --- a/v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert-priv.h +++ b/v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert-priv.h @@ -59,14 +59,23 @@ #define V4L2_PIX_FMT_SRGGB8 v4l2_fourcc('R','G','G','B') #endif +#ifndef V4L2_PIX_FMT_YVYU +#define V4L2_PIX_FMT_YVYU v4l2_fourcc('Y', 'V', 'Y', 'U') +#endif + #define V4LCONVERT_ERROR_MSG_SIZE 256 +#define V4LCONVERT_MAX_FRAMESIZES 16 #define V4LCONVERT_ERR(...) \ snprintf(data->error_msg, V4LCONVERT_ERROR_MSG_SIZE, \ "v4l-convert: error " __VA_ARGS__) +/* Card flags */ #define V4LCONVERT_UPSIDE_DOWN 0x01 +/* Pixformat flags */ +#define V4LCONVERT_COMPRESSED 0x01 + struct v4lconvert_data { int fd; int flags; /* bitfield */ @@ -74,6 +83,8 @@ struct v4lconvert_data { unsigned int no_formats; char error_msg[V4LCONVERT_ERROR_MSG_SIZE]; struct jdec_private *jdec; + struct v4l2_frmsizeenum framesizes[V4LCONVERT_MAX_FRAMESIZES]; + unsigned int no_framesizes; }; struct v4lconvert_flags_info { @@ -81,12 +92,35 @@ struct v4lconvert_flags_info { int flags; }; +struct v4lconvert_pixfmt { + unsigned int fmt; + int flags; +}; + void v4lconvert_yuv420_to_rgb24(const unsigned char *src, unsigned char *dst, int width, int height); void v4lconvert_yuv420_to_bgr24(const unsigned char *src, unsigned char *dst, int width, int height); +void v4lconvert_yuyv_to_rgb24(const unsigned char *src, unsigned char *dst, + int width, int height); + +void v4lconvert_yuyv_to_bgr24(const unsigned char *src, unsigned char *dst, + int width, int height); + +void v4lconvert_yuyv_to_yuv420(const unsigned char *src, unsigned char *dst, + int width, int height); + +void v4lconvert_yvyu_to_rgb24(const unsigned char *src, unsigned char *dst, + int width, int height); + +void v4lconvert_yvyu_to_bgr24(const unsigned char *src, unsigned char *dst, + int width, int height); + +void v4lconvert_yvyu_to_yuv420(const unsigned char *src, unsigned char *dst, + int width, int height); + void v4lconvert_swap_rgb(const unsigned char *src, unsigned char *dst, int width, int height); diff --git a/v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert.c b/v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert.c index 4b48bfac4..93bc67c7e 100644 --- a/v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert.c +++ b/v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert.c @@ -30,37 +30,45 @@ /* 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, \ - V4L2_PIX_FMT_BGR24, \ - V4L2_PIX_FMT_YUV420 + { V4L2_PIX_FMT_RGB24, 0 }, \ + { V4L2_PIX_FMT_BGR24, 0 }, \ + { V4L2_PIX_FMT_YUV420, 0 } -static const unsigned int supported_src_pixfmts[] = { +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_MJPEG, - V4L2_PIX_FMT_JPEG, - V4L2_PIX_FMT_SBGGR8, - V4L2_PIX_FMT_SGBRG8, - V4L2_PIX_FMT_SGRBG8, - V4L2_PIX_FMT_SRGGB8, - V4L2_PIX_FMT_SPCA501, - V4L2_PIX_FMT_SPCA505, - V4L2_PIX_FMT_SPCA508, - V4L2_PIX_FMT_SPCA561, - V4L2_PIX_FMT_SN9C10X, - V4L2_PIX_FMT_PAC207, - V4L2_PIX_FMT_PJPG, + { 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 unsigned int supported_dst_pixfmts[] = { +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[] = { - { "USB Camera (0471:0325)", V4LCONVERT_UPSIDE_DOWN }, /* SPC200NC */ - { "USB Camera (0471:0326)", V4LCONVERT_UPSIDE_DOWN }, /* SPC300NC */ { "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) @@ -85,10 +93,12 @@ struct v4lconvert_data *v4lconvert_create(int fd) break; for (j = 0; j < ARRAY_SIZE(supported_src_pixfmts); j++) - if (fmt.pixelformat == 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; @@ -115,6 +125,17 @@ void v4lconvert_destroy(struct v4lconvert_data *data) 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) { @@ -128,7 +149,7 @@ int v4lconvert_enum_fmt(struct v4lconvert_data *data, struct v4l2_fmtdesc *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]; + faked_fmts[no_faked_fmts] = supported_dst_pixfmts[i].fmt; no_faked_fmts++; } @@ -159,12 +180,8 @@ int v4lconvert_try_format(struct v4lconvert_data *data, unsigned int desired_pixfmt = dest_fmt->fmt.pix.pixelformat; struct v4l2_format try_fmt, closest_fmt = { .type = 0 }; - for (i = 0; i < ARRAY_SIZE(supported_dst_pixfmts); i++) - if (supported_dst_pixfmts[i] == desired_pixfmt) - break; - /* Can we do conversion to the requested format & type? */ - if (i == ARRAY_SIZE(supported_dst_pixfmts) || + 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) @@ -178,11 +195,11 @@ int v4lconvert_try_format(struct v4lconvert_data *data, continue; try_fmt = *dest_fmt; - try_fmt.fmt.pix.pixelformat = supported_src_pixfmts[i]; + 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]) { + 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 - @@ -191,7 +208,9 @@ int v4lconvert_try_format(struct v4lconvert_data *data, size_y_diff * size_y_diff; if (size_diff < closest_fmt_size_diff || (size_diff == closest_fmt_size_diff && - try_fmt.fmt.pix.pixelformat == desired_pixfmt)) { + (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; } @@ -237,8 +256,6 @@ 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 */ @@ -246,11 +263,7 @@ int v4lconvert_needs_conversion(struct v4lconvert_data *data, 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)) + 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 */ @@ -518,6 +531,40 @@ int v4lconvert_convert(struct v4lconvert_data *data, } 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; @@ -570,3 +617,121 @@ 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; +} diff --git a/v4l2-apps/lib/libv4l/libv4lconvert/rgbyuv.c b/v4l2-apps/lib/libv4l/libv4lconvert/rgbyuv.c index 883d62330..0f26b227a 100644 --- a/v4l2-apps/lib/libv4l/libv4lconvert/rgbyuv.c +++ b/v4l2-apps/lib/libv4l/libv4lconvert/rgbyuv.c @@ -130,6 +130,176 @@ void v4lconvert_yuv420_to_rgb24(const unsigned char *src, unsigned char *dest, } } +void v4lconvert_yuyv_to_bgr24(const unsigned char *src, unsigned char *dest, + int width, int height) +{ + int j; + + while (--height >= 0) { + for (j = 0; j < width; j += 2) { + int u = src[1]; + int v = src[3]; + int u1 = (((u - 128) << 7) + (u - 128)) >> 6; + int rg = (((u - 128) << 1) + (u - 128) + + ((v - 128) << 2) + ((v - 128) << 1)) >> 3; + int v1 = (((v - 128) << 1) + (v - 128)) >> 1; + + *dest++ = CLIP(src[0] + u1); + *dest++ = CLIP(src[0] - rg); + *dest++ = CLIP(src[0] + v1); + + *dest++ = CLIP(src[2] + u1); + *dest++ = CLIP(src[2] - rg); + *dest++ = CLIP(src[2] + v1); + src += 4; + } + } +} + +void v4lconvert_yuyv_to_rgb24(const unsigned char *src, unsigned char *dest, + int width, int height) +{ + int j; + + while (--height >= 0) { + for (j = 0; j < width; j += 2) { + int u = src[1]; + int v = src[3]; + int u1 = (((u - 128) << 7) + (u - 128)) >> 6; + int rg = (((u - 128) << 1) + (u - 128) + + ((v - 128) << 2) + ((v - 128) << 1)) >> 3; + int v1 = (((v - 128) << 1) + (v - 128)) >> 1; + + *dest++ = CLIP(src[0] + v1); + *dest++ = CLIP(src[0] - rg); + *dest++ = CLIP(src[0] + u1); + + *dest++ = CLIP(src[2] + v1); + *dest++ = CLIP(src[2] - rg); + *dest++ = CLIP(src[2] + u1); + src += 4; + } + } +} + +void v4lconvert_yuyv_to_yuv420(const unsigned char *src, unsigned char *dest, + int width, int height) +{ + int i, j; + const unsigned char *src1; + unsigned char *vdest; + + /* copy the Y values */ + src1 = src; + for (i = 0; i < height; i++) { + for (j = 0; j < width; j += 2) { + *dest++ = src1[0]; + *dest++ = src1[2]; + src1 += 4; + } + } + + /* copy the U and V values */ + src++; /* point to V */ + src1 = src + width * 2; /* next line */ + vdest = dest + width * height / 4; + for (i = 0; i < height; i += 2) { + for (j = 0; j < width; j += 2) { + *dest++ = ((int) src[0] + src1[0]) / 2; /* U */ + *vdest++ = ((int) src[2] + src1[2]) / 2; /* V */ + src += 4; + src1 += 4; + } + src = src1; + src1 += width * 2; + } +} + +void v4lconvert_yvyu_to_bgr24(const unsigned char *src, unsigned char *dest, + int width, int height) +{ + int j; + + while (--height >= 0) { + for (j = 0; j < width; j += 2) { + int u = src[3]; + int v = src[1]; + int u1 = (((u - 128) << 7) + (u - 128)) >> 6; + int rg = (((u - 128) << 1) + (u - 128) + + ((v - 128) << 2) + ((v - 128) << 1)) >> 3; + int v1 = (((v - 128) << 1) + (v - 128)) >> 1; + + *dest++ = CLIP(src[0] + u1); + *dest++ = CLIP(src[0] - rg); + *dest++ = CLIP(src[0] + v1); + + *dest++ = CLIP(src[2] + u1); + *dest++ = CLIP(src[2] - rg); + *dest++ = CLIP(src[2] + v1); + src += 4; + } + } +} + +void v4lconvert_yvyu_to_rgb24(const unsigned char *src, unsigned char *dest, + int width, int height) +{ + int j; + + while (--height >= 0) { + for (j = 0; j < width; j += 2) { + int u = src[3]; + int v = src[1]; + int u1 = (((u - 128) << 7) + (u - 128)) >> 6; + int rg = (((u - 128) << 1) + (u - 128) + + ((v - 128) << 2) + ((v - 128) << 1)) >> 3; + int v1 = (((v - 128) << 1) + (v - 128)) >> 1; + + *dest++ = CLIP(src[0] + v1); + *dest++ = CLIP(src[0] - rg); + *dest++ = CLIP(src[0] + u1); + + *dest++ = CLIP(src[2] + v1); + *dest++ = CLIP(src[2] - rg); + *dest++ = CLIP(src[2] + u1); + src += 4; + } + } +} + +void v4lconvert_yvyu_to_yuv420(const unsigned char *src, unsigned char *dest, + int width, int height) +{ + int i, j; + const unsigned char *src1; + unsigned char *vdest; + + /* copy the Y values */ + src1 = src; + for (i = 0; i < height; i++) { + for (j = 0; j < width; j += 2) { + *dest++ = src1[0]; + *dest++ = src1[2]; + src1 += 4; + } + } + + /* copy the U and V values */ + src++; /* point to V */ + src1 = src + width * 2; /* next line */ + vdest = dest + width * height / 4; + for (i = 0; i < height; i += 2) { + for (j = 0; j < width; j += 2) { + *dest++ = ((int) src[2] + src1[2]) / 2; /* U */ + *vdest++ = ((int) src[0] + src1[0]) / 2; /* V */ + src += 4; + src1 += 4; + } + src = src1; + src1 += width * 2; + } +} + void v4lconvert_swap_rgb(const unsigned char *src, unsigned char *dst, int width, int height) { |