summaryrefslogtreecommitdiff
path: root/v4l2-apps/lib/libv4l
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2008-09-24 10:35:08 -0300
committerMauro Carvalho Chehab <mchehab@redhat.com>2008-09-24 10:35:08 -0300
commitec1abc6d3b2508366efa97c0f3f08078902e47ac (patch)
tree62bc233c7f844731de7d63d8466aa857fb43a31c /v4l2-apps/lib/libv4l
parente25691821b5e4762b3e642f3f78a1327aa5f6767 (diff)
parent37365f711151fceee2bbc87ef7836c5f08b7c1f1 (diff)
downloadmediapointer-dvb-s2-ec1abc6d3b2508366efa97c0f3f08078902e47ac.tar.gz
mediapointer-dvb-s2-ec1abc6d3b2508366efa97c0f3f08078902e47ac.tar.bz2
merge: http://linuxtv.org/hg/~hgoede/v4l-dvb
From: Mauro Carvalho Chehab <mchehab@redhat.com> Priority: normal Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'v4l2-apps/lib/libv4l')
-rw-r--r--v4l2-apps/lib/libv4l/ChangeLog14
-rw-r--r--v4l2-apps/lib/libv4l/Makefile2
-rw-r--r--v4l2-apps/lib/libv4l/include/libv4lconvert.h10
-rw-r--r--v4l2-apps/lib/libv4l/libv4l1/libv4l1.c15
-rw-r--r--v4l2-apps/lib/libv4l/libv4l1/log.c6
-rw-r--r--v4l2-apps/lib/libv4l/libv4l2/libv4l2.c24
-rw-r--r--v4l2-apps/lib/libv4l/libv4l2/v4l2convert.c15
-rw-r--r--v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert-priv.h34
-rw-r--r--v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert.c239
-rw-r--r--v4l2-apps/lib/libv4l/libv4lconvert/rgbyuv.c170
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)
{