summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhans@rhel5-devel.localdomain <hans@rhel5-devel.localdomain>2009-05-20 07:23:00 +0200
committerhans@rhel5-devel.localdomain <hans@rhel5-devel.localdomain>2009-05-20 07:23:00 +0200
commit34a210b573f9c8ff8f07077f239be95d9d9248c5 (patch)
treed7a5f1bd73afbaa0a7a8ef7d2de10a03c6c5265e
parenta077e421fe63a7102f6bbaa7057df7690e239cf6 (diff)
downloadmediapointer-dvb-s2-34a210b573f9c8ff8f07077f239be95d9d9248c5.tar.gz
mediapointer-dvb-s2-34a210b573f9c8ff8f07077f239be95d9d9248c5.tar.bz2
libv4l: add fake controls controlling the software h- and v-flipping
From: Hans de Goede <hdegoede@redhat.com> When we need to go through the fake mmap buffer anyways, we can add fake controls at no cost. So in the case of webcams which only support non standard pixformats, export fake flipping controls, as this can be done at no (performace) cost (until the user activates them). Priority: normal Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-rw-r--r--v4l2-apps/libv4l/ChangeLog1
-rw-r--r--v4l2-apps/libv4l/TODO3
-rw-r--r--v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c42
-rw-r--r--v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.h12
-rw-r--r--v4l2-apps/libv4l/libv4lconvert/flip.c27
-rw-r--r--v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h5
-rw-r--r--v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c65
7 files changed, 97 insertions, 58 deletions
diff --git a/v4l2-apps/libv4l/ChangeLog b/v4l2-apps/libv4l/ChangeLog
index aa0a3ea3c..9bfecab85 100644
--- a/v4l2-apps/libv4l/ChangeLog
+++ b/v4l2-apps/libv4l/ChangeLog
@@ -9,6 +9,7 @@ libv4l-0.5.98
* Add ability to determine upside down cams based on DMI info
* Fix a bug in v4lconvert_uyvy_to_yuv420()
* Add support for separate vflipping and hflipping
+* Add fake controls controlling the software h- and v-flipping
libv4l-0.5.97
-------------
diff --git a/v4l2-apps/libv4l/TODO b/v4l2-apps/libv4l/TODO
index 94c40b84e..b676bfeb5 100644
--- a/v4l2-apps/libv4l/TODO
+++ b/v4l2-apps/libv4l/TODO
@@ -13,9 +13,6 @@
-make updating of parameters happen based on time elapsed rather then
frames
--add fake flip controls on devices where we are already limiting the
- formats which can be set
-
-add reverse cropping (adding black borders) to get from 320x232 ->
320x240, for zc3xx webcams with a broken (last row of jpeg blocks missing)
320x240 mode
diff --git a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c
index 1ffd05cc4..b120aa2fc 100644
--- a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c
+++ b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c
@@ -198,12 +198,13 @@ static void v4lcontrol_init_flags(struct v4lcontrol_data *data)
}
}
-struct v4lcontrol_data *v4lcontrol_create(int fd)
+struct v4lcontrol_data *v4lcontrol_create(int fd, int always_needs_conversion)
{
int shm_fd;
int i, init = 0;
char *s, shm_name[256];
struct v4l2_capability cap;
+ struct v4l2_queryctrl ctrl;
struct v4lcontrol_data *data = calloc(1, sizeof(struct v4lcontrol_data));
@@ -214,6 +215,17 @@ struct v4lcontrol_data *v4lcontrol_create(int fd)
v4lcontrol_init_flags(data);
+ /* If the device always needs conversion, we can add fake controls at no cost
+ (no cost when not activated by the user that is) */
+ if (always_needs_conversion || v4lcontrol_needs_conversion(data)) {
+ ctrl.id = V4L2_CID_HFLIP;
+ if (syscall(SYS_ioctl, data->fd, VIDIOC_QUERYCTRL, &ctrl) == -1)
+ data->controls |= 1 << V4LCONTROL_HFLIP;
+ ctrl.id = V4L2_CID_VFLIP;
+ if (syscall(SYS_ioctl, data->fd, VIDIOC_QUERYCTRL, &ctrl) == -1)
+ data->controls |= 1 << V4LCONTROL_VFLIP;
+ }
+
/* Allow overriding through environment */
if ((s = getenv("LIBV4LCONTROL_FLAGS")))
data->flags = strtol(s, NULL, 0);
@@ -313,6 +325,26 @@ struct v4l2_queryctrl fake_controls[V4LCONTROL_COUNT] = {
.default_value = 255,
.flags = 0
},
+{
+ .id = V4L2_CID_HFLIP,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Horizontal flip",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ .flags = 0
+},
+{
+ .id = V4L2_CID_VFLIP,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Vertical flip",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ .flags = 0
+},
};
int v4lcontrol_vidioc_queryctrl(struct v4lcontrol_data *data, void *arg)
@@ -390,8 +422,14 @@ int v4lcontrol_get_flags(struct v4lcontrol_data *data)
int v4lcontrol_get_ctrl(struct v4lcontrol_data *data, int ctrl)
{
- if (data->controls & (1 << ctrl))
+ if (data->controls & (1 << ctrl)) {
+ /* Special case for devices with flipped input */
+ if ((ctrl == V4LCONTROL_HFLIP && (data->flags & V4LCONTROL_HFLIPPED)) ||
+ (ctrl == V4LCONTROL_VFLIP && (data->flags & V4LCONTROL_VFLIPPED)))
+ return !data->shm_values[ctrl];
+
return data->shm_values[ctrl];
+ }
return 0;
}
diff --git a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.h b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.h
index 28308bc55..43ef7c49f 100644
--- a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.h
+++ b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.h
@@ -28,12 +28,18 @@
#define V4LCONTROL_ROTATED_90_JPEG 0x04
/* Controls */
-enum { V4LCONTROL_WHITEBALANCE, V4LCONTROL_NORMALIZE,
- V4LCONTROL_NORM_LOW_BOUND, V4LCONTROL_NORM_HIGH_BOUND, V4LCONTROL_COUNT };
+enum {
+ V4LCONTROL_WHITEBALANCE,
+ V4LCONTROL_NORMALIZE,
+ V4LCONTROL_NORM_LOW_BOUND,
+ V4LCONTROL_NORM_HIGH_BOUND,
+ V4LCONTROL_HFLIP,
+ V4LCONTROL_VFLIP,
+ V4LCONTROL_COUNT };
struct v4lcontrol_data;
-struct v4lcontrol_data* v4lcontrol_create(int fd);
+struct v4lcontrol_data* v4lcontrol_create(int fd, int always_needs_conversion);
void v4lcontrol_destroy(struct v4lcontrol_data *data);
/* Functions used by v4lprocessing to get the control state */
diff --git a/v4l2-apps/libv4l/libv4lconvert/flip.c b/v4l2-apps/libv4l/libv4lconvert/flip.c
index 5d881844a..8c4d8233c 100644
--- a/v4l2-apps/libv4l/libv4lconvert/flip.c
+++ b/v4l2-apps/libv4l/libv4lconvert/flip.c
@@ -222,24 +222,22 @@ void v4lconvert_rotate90(unsigned char *src, unsigned char *dest,
}
void v4lconvert_flip(unsigned char *src, unsigned char *dest,
- struct v4l2_format *fmt, int flags)
+ struct v4l2_format *fmt, int hflip, int vflip)
{
- switch (flags & (V4LCONTROL_VFLIPPED|V4LCONTROL_HFLIPPED)) {
-
- case V4LCONTROL_VFLIPPED:
+ if (vflip && hflip) {
switch (fmt->fmt.pix.pixelformat) {
case V4L2_PIX_FMT_RGB24:
case V4L2_PIX_FMT_BGR24:
- v4lconvert_vflip_rgbbgr24(src, dest, fmt);
+ v4lconvert_rotate180_rgbbgr24(src, dest, fmt->fmt.pix.width,
+ fmt->fmt.pix.height);
break;
case V4L2_PIX_FMT_YUV420:
case V4L2_PIX_FMT_YVU420:
- v4lconvert_vflip_yuv420(src, dest, fmt);
+ v4lconvert_rotate180_yuv420(src, dest, fmt->fmt.pix.width,
+ fmt->fmt.pix.height);
break;
}
- break;
-
- case V4LCONTROL_HFLIPPED:
+ } else if (hflip) {
switch (fmt->fmt.pix.pixelformat) {
case V4L2_PIX_FMT_RGB24:
case V4L2_PIX_FMT_BGR24:
@@ -250,22 +248,17 @@ void v4lconvert_flip(unsigned char *src, unsigned char *dest,
v4lconvert_hflip_yuv420(src, dest, fmt);
break;
}
- break;
-
- case (V4LCONTROL_VFLIPPED|V4LCONTROL_HFLIPPED):
+ } else if (vflip) {
switch (fmt->fmt.pix.pixelformat) {
case V4L2_PIX_FMT_RGB24:
case V4L2_PIX_FMT_BGR24:
- v4lconvert_rotate180_rgbbgr24(src, dest, fmt->fmt.pix.width,
- fmt->fmt.pix.height);
+ v4lconvert_vflip_rgbbgr24(src, dest, fmt);
break;
case V4L2_PIX_FMT_YUV420:
case V4L2_PIX_FMT_YVU420:
- v4lconvert_rotate180_yuv420(src, dest, fmt->fmt.pix.width,
- fmt->fmt.pix.height);
+ v4lconvert_vflip_yuv420(src, dest, fmt);
break;
}
- break;
}
/* Our newly written data has no padding */
diff --git a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h
index 2d34bd6a4..60e62af97 100644
--- a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h
+++ b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h
@@ -96,7 +96,8 @@
#define V4LCONVERT_IS_SN9C20X 0x02
/* Pixformat flags */
-#define V4LCONVERT_COMPRESSED 0x01
+#define V4LCONVERT_COMPRESSED 0x01 /* Compressed format */
+#define V4LCONVERT_NEEDS_CONVERSION 0x02 /* Apps likely wont know this */
struct v4lconvert_data {
int fd;
@@ -217,7 +218,7 @@ void v4lconvert_rotate90(unsigned char *src, unsigned char *dest,
struct v4l2_format *fmt);
void v4lconvert_flip(unsigned char *src, unsigned char *dest,
- struct v4l2_format *fmt, int flags);
+ struct v4l2_format *fmt, int hflip, int vflip);
void v4lconvert_crop(unsigned char *src, unsigned char *dest,
const struct v4l2_format *src_fmt, const struct v4l2_format *dest_fmt);
diff --git a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c
index a175973ef..94539e376 100644
--- a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c
+++ b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c
@@ -47,15 +47,15 @@ static const struct v4lconvert_pixfmt supported_src_pixfmts[] = {
{ V4L2_PIX_FMT_YUYV, 0 },
{ V4L2_PIX_FMT_YVYU, 0 },
{ V4L2_PIX_FMT_UYVY, 0 },
- { V4L2_PIX_FMT_SN9C20X_I420, 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_HM12, 0 },
+ { V4L2_PIX_FMT_SN9C20X_I420, V4LCONVERT_NEEDS_CONVERSION },
+ { V4L2_PIX_FMT_SBGGR8, V4LCONVERT_NEEDS_CONVERSION },
+ { V4L2_PIX_FMT_SGBRG8, V4LCONVERT_NEEDS_CONVERSION },
+ { V4L2_PIX_FMT_SGRBG8, V4LCONVERT_NEEDS_CONVERSION },
+ { V4L2_PIX_FMT_SRGGB8, V4LCONVERT_NEEDS_CONVERSION },
+ { V4L2_PIX_FMT_SPCA501, V4LCONVERT_NEEDS_CONVERSION },
+ { V4L2_PIX_FMT_SPCA505, V4LCONVERT_NEEDS_CONVERSION },
+ { V4L2_PIX_FMT_SPCA508, V4LCONVERT_NEEDS_CONVERSION },
+ { V4L2_PIX_FMT_HM12, V4LCONVERT_NEEDS_CONVERSION },
{ V4L2_PIX_FMT_MJPEG, V4LCONVERT_COMPRESSED },
{ V4L2_PIX_FMT_JPEG, V4LCONVERT_COMPRESSED },
{ V4L2_PIX_FMT_SPCA561, V4LCONVERT_COMPRESSED },
@@ -88,6 +88,10 @@ struct v4lconvert_data *v4lconvert_create(int fd)
int i, j;
struct v4lconvert_data *data = calloc(1, sizeof(struct v4lconvert_data));
struct v4l2_capability cap;
+ /* This keeps tracks of devices which have only formats for which apps
+ most likely will need conversion and we can thus safely add software
+ processing controls without a performance impact. */
+ int always_needs_conversion = 1;
if (!data)
return NULL;
@@ -107,8 +111,13 @@ struct v4lconvert_data *v4lconvert_create(int fd)
if (fmt.pixelformat == supported_src_pixfmts[j].fmt) {
data->supported_src_formats |= 1 << j;
v4lconvert_get_framesizes(data, fmt.pixelformat, j);
+ if (!supported_src_pixfmts[j].flags)
+ always_needs_conversion = 0;
break;
}
+
+ if (j == ARRAY_SIZE(supported_src_pixfmts))
+ always_needs_conversion = 0;
}
data->no_formats = i;
@@ -121,7 +130,7 @@ struct v4lconvert_data *v4lconvert_create(int fd)
data->flags |= V4LCONVERT_IS_SN9C20X;
}
- data->control = v4lcontrol_create(fd);
+ data->control = v4lcontrol_create(fd, always_needs_conversion);
if (!data->control) {
free(data);
return NULL;
@@ -854,7 +863,8 @@ int v4lconvert_convert(struct v4lconvert_data *data,
const struct v4l2_format *dest_fmt, /* in */
unsigned char *src, int src_size, unsigned char *dest, int dest_size)
{
- int res, dest_needed, temp_needed, processing, convert = 0, crop = 0;
+ int res, dest_needed, temp_needed, processing, convert = 0;
+ int rotate90, vflip, hflip, crop;
unsigned char *convert1_dest = dest;
unsigned char *convert2_src = src, *convert2_dest = dest;
unsigned char *rotate90_src = src, *rotate90_dest = dest;
@@ -864,14 +874,15 @@ int v4lconvert_convert(struct v4lconvert_data *data,
struct v4l2_format my_dest_fmt = *dest_fmt;
processing = v4lprocessing_pre_processing(data->processing);
+ rotate90 = data->control_flags & V4LCONTROL_ROTATED_90_JPEG;
+ hflip = v4lcontrol_get_ctrl(data->control, V4LCONTROL_HFLIP);
+ vflip = v4lcontrol_get_ctrl(data->control, V4LCONTROL_VFLIP);
+ crop = my_dest_fmt.fmt.pix.width != my_src_fmt.fmt.pix.width ||
+ my_dest_fmt.fmt.pix.height != my_src_fmt.fmt.pix.height;
if (/* If no conversion/processing is needed */
- (src_fmt->fmt.pix.width == dest_fmt->fmt.pix.width &&
- src_fmt->fmt.pix.height == dest_fmt->fmt.pix.height &&
- src_fmt->fmt.pix.pixelformat == dest_fmt->fmt.pix.pixelformat &&
- !processing &&
- !(data->control_flags & (V4LCONTROL_ROTATED_90_JPEG |
- V4LCONTROL_VFLIPPED | V4LCONTROL_HFLIPPED))) ||
+ (src_fmt->fmt.pix.pixelformat == dest_fmt->fmt.pix.pixelformat &&
+ !processing && !rotate90 && !hflip && !vflip && !crop) ||
/* or if we should do processing/rotating/flipping but the app tries to
use the native cam format, we just return an unprocessed frame copy */
!v4lconvert_supported_dst_format(dest_fmt->fmt.pix.pixelformat)) {
@@ -923,10 +934,6 @@ int v4lconvert_convert(struct v4lconvert_data *data,
else if (my_dest_fmt.fmt.pix.pixelformat != my_src_fmt.fmt.pix.pixelformat)
convert = 1;
- if (my_dest_fmt.fmt.pix.width != my_src_fmt.fmt.pix.width ||
- my_dest_fmt.fmt.pix.height != my_src_fmt.fmt.pix.height)
- crop = 1;
-
/* convert_pixfmt (only if convert == 2) -> processing -> convert_pixfmt ->
rotate -> flip -> crop, all steps are optional */
if (convert == 2) {
@@ -939,8 +946,7 @@ int v4lconvert_convert(struct v4lconvert_data *data,
convert2_src = convert1_dest;
}
- if (convert && ((data->control_flags & (V4LCONTROL_ROTATED_90_JPEG |
- V4LCONTROL_VFLIPPED | V4LCONTROL_HFLIPPED)) || crop)) {
+ if (convert && (rotate90 || hflip || vflip || crop)) {
convert2_dest = v4lconvert_alloc_buffer(data, temp_needed,
&data->convert2_buf, &data->convert2_buf_size);
if (!convert2_dest)
@@ -949,9 +955,7 @@ int v4lconvert_convert(struct v4lconvert_data *data,
rotate90_src = flip_src = crop_src = convert2_dest;
}
- if ((data->control_flags & V4LCONTROL_ROTATED_90_JPEG) &&
- ((data->control_flags & (V4LCONTROL_VFLIPPED | V4LCONTROL_HFLIPPED)) ||
- crop)) {
+ if (rotate90 && (hflip || vflip || crop)) {
rotate90_dest = v4lconvert_alloc_buffer(data, temp_needed,
&data->rotate90_buf, &data->rotate90_buf_size);
if (!rotate90_dest)
@@ -960,8 +964,7 @@ int v4lconvert_convert(struct v4lconvert_data *data,
flip_src = crop_src = rotate90_dest;
}
- if ((data->control_flags & (V4LCONTROL_VFLIPPED | V4LCONTROL_HFLIPPED)) &&
- crop) {
+ if ((vflip || hflip) && crop) {
flip_dest = v4lconvert_alloc_buffer(data, temp_needed, &data->flip_buf,
&data->flip_buf_size);
if (!flip_dest)
@@ -1001,11 +1004,11 @@ int v4lconvert_convert(struct v4lconvert_data *data,
if (processing)
v4lprocessing_processing(data->processing, rotate90_src, &my_src_fmt);
- if (data->control_flags & V4LCONTROL_ROTATED_90_JPEG)
+ if (rotate90)
v4lconvert_rotate90(rotate90_src, rotate90_dest, &my_src_fmt);
- if (data->control_flags & (V4LCONTROL_VFLIPPED | V4LCONTROL_HFLIPPED))
- v4lconvert_flip(flip_src, flip_dest, &my_src_fmt, data->control_flags);
+ if (hflip || vflip)
+ v4lconvert_flip(flip_src, flip_dest, &my_src_fmt, hflip, vflip);
if (crop)
v4lconvert_crop(crop_src, dest, &my_src_fmt, &my_dest_fmt);