summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhans@rhel5-devel.localdomain <hans@rhel5-devel.localdomain>2009-04-14 15:03:07 +0200
committerhans@rhel5-devel.localdomain <hans@rhel5-devel.localdomain>2009-04-14 15:03:07 +0200
commit58d3334b54c207b8e04e7035969e0c2acfa1ce73 (patch)
tree79bfcb91241d0468871696b189ac8ee344ea1ed0
parent10a09b9ec6e08fb95c36f26d7f69834b0387386b (diff)
downloadmediapointer-dvb-s2-58d3334b54c207b8e04e7035969e0c2acfa1ce73.tar.gz
mediapointer-dvb-s2-58d3334b54c207b8e04e7035969e0c2acfa1ce73.tar.bz2
libv4l: Only allow supported destination formats when doing processing
From: Hans de Goede <hdegoede@redhat.com> Only report / allow supported destination formats in enum_fmt / try_fmt / g_fmt / s_fmt when processing, rotating or flipping. Priority: normal Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-rw-r--r--v4l2-apps/libv4l/ChangeLog8
-rw-r--r--v4l2-apps/libv4l/TODO14
-rw-r--r--v4l2-apps/libv4l/include/libv4lconvert.h21
-rw-r--r--v4l2-apps/libv4l/libv4l1/libv4l1.c17
-rw-r--r--v4l2-apps/libv4l/libv4l2/libv4l2.c8
-rw-r--r--v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c5
-rw-r--r--v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.h5
-rw-r--r--v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c91
8 files changed, 127 insertions, 42 deletions
diff --git a/v4l2-apps/libv4l/ChangeLog b/v4l2-apps/libv4l/ChangeLog
index 52b429687..3a7d3f3a8 100644
--- a/v4l2-apps/libv4l/ChangeLog
+++ b/v4l2-apps/libv4l/ChangeLog
@@ -8,6 +8,14 @@ libv4l-0.5.97
for example v4l2ucp is there.
The initial version of this code was written by 3 of my computer science
students: Elmar Kleijn, Sjoerd Piepenbrink and Radjnies Bhansingh
+* Currently whitebalancing gets enabled based on USB-ID's and it only gets
+ enabled for Pixart webcam's. You can force it being enabled with other
+ webcams by setting the environment variable LIBV4LCONTROL_CONTROLS, this
+ sets a bitmask enabling certain v4l2 controls which control the video
+ processing set it to 15 to enable both whitebalancing and normalize. You
+ can then change the settings using a v4l2 control panel like v4l2ucp
+* Only report / allow supported destination formats in enum_fmt / try_fmt /
+ g_fmt / s_fmt when processing, rotating or flipping.
* Add dependency generation to libv4l by: Gilles Gigan <gilles.gigan@gmail.com>
* Add support to use orientation from VIDIOC_ENUMINPUT by:
Adam Baker <linux@baker-net.org.uk>
diff --git a/v4l2-apps/libv4l/TODO b/v4l2-apps/libv4l/TODO
index f1aac5a95..94c40b84e 100644
--- a/v4l2-apps/libv4l/TODO
+++ b/v4l2-apps/libv4l/TODO
@@ -10,11 +10,19 @@
-take the possibility of pitch != width into account everywhere
--only report faked formats in list formats and only allow setting fake
- formats when processing or flipping.
-
-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
+
+-add software auto exposure (for spca561 cams)
+
+-change video processing to use a per component lookup table for easy combining of
+ of different effects in 1 pass
+
+-add gamma correction video processing
diff --git a/v4l2-apps/libv4l/include/libv4lconvert.h b/v4l2-apps/libv4l/include/libv4lconvert.h
index fcc31dace..7901b35dc 100644
--- a/v4l2-apps/libv4l/include/libv4lconvert.h
+++ b/v4l2-apps/libv4l/include/libv4lconvert.h
@@ -42,18 +42,30 @@ struct v4lconvert_data;
LIBV4L_PUBLIC struct v4lconvert_data *v4lconvert_create(int fd);
LIBV4L_PUBLIC void v4lconvert_destroy(struct v4lconvert_data *data);
+/* When doing flipping / rotating / video-processing, only supported
+ destination formats can be used (as flipping / rotating / video-processing
+ is not supported on other formats). This function can be used to query
+ if that is the case. */
+LIBV4L_PUBLIC int v4lconvert_supported_dst_fmt_only(
+ struct v4lconvert_data *data);
+
/* With regards to dest_fmt just like VIDIOC_TRY_FMT, except that the try
format will succeed and return the requested V4L2_PIX_FMT_foo in dest_fmt if
the cam has a format from which v4lconvert can convert to dest_fmt.
The real format to which the cam should be set is returned through src_fmt
- when not NULL. */
+ when not NULL.
+ Note that just like the real VIDIOC_TRY_FMT this function will change the
+ dest_fmt when not supported. This includes changing it to a supported
+ destination format when trying a native format of the camera and
+ v4lconvert_supported_dst_fmt_only() returns true. */
LIBV4L_PUBLIC int v4lconvert_try_format(struct v4lconvert_data *data,
struct v4l2_format *dest_fmt, /* in / out */
struct v4l2_format *src_fmt /* out */
);
-/* Just like VIDIOC_ENUM_FMT, except that the emulated formats are added at
- the end of the list */
+/* Like VIDIOC_ENUM_FMT, but the emulated formats are added at the end of the
+ list, except if flipping / processing is active for the device, then only
+ supported destination formats are listed */
LIBV4L_PUBLIC int v4lconvert_enum_fmt(struct v4lconvert_data *data, struct v4l2_fmtdesc *fmt);
/* Is conversion necessary or can the app use the data directly? */
@@ -89,6 +101,9 @@ LIBV4L_PUBLIC int v4lconvert_vidioc_g_ctrl(struct v4lconvert_data *data,
LIBV4L_PUBLIC int v4lconvert_vidioc_s_ctrl(struct v4lconvert_data *data,
void *arg);
+/* Is the passed in pixelformat supported as destination format ? */
+LIBV4L_PUBLIC int v4lconvert_supported_dst_format(unsigned int pixelformat);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
diff --git a/v4l2-apps/libv4l/libv4l1/libv4l1.c b/v4l2-apps/libv4l/libv4l1/libv4l1.c
index 797c8768a..a7de0af8e 100644
--- a/v4l2-apps/libv4l/libv4l1/libv4l1.c
+++ b/v4l2-apps/libv4l/libv4l1/libv4l1.c
@@ -155,8 +155,10 @@ static int v4l1_set_format(int index, unsigned int width,
/* Do we need to change the resolution / format ? */
if (width == devices[index].width && height == devices[index].height &&
- v4l2_pixfmt == devices[index].v4l2_pixfmt)
+ v4l2_pixfmt == devices[index].v4l2_pixfmt) {
+ devices[index].v4l1_pal = v4l1_pal;
return 0;
+ }
/* Get current settings, apply our changes and try the new setting */
if ((result = v4l2_ioctl(devices[index].fd, VIDIOC_G_FMT, &fmt2))) {
@@ -308,19 +310,18 @@ int v4l1_open (const char *file, int oflag, ...)
if (!v4l2_log_file)
v4l2_log_file = v4l1_log_file;
- /* Get initial width, height and pixelformat */
- fmt2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- if (syscall(SYS_ioctl, fd, VIDIOC_G_FMT, &fmt2)) {
+ /* Register with libv4l2, as we use that todo format conversion and read()
+ emulation for us */
+ if (v4l2_fd_open(fd, V4L2_ENABLE_ENUM_FMT_EMULATION) == -1) {
int saved_err = errno;
- V4L1_LOG_ERR("getting pixformat: %s\n", strerror(errno));
syscall(SYS_close, fd);
errno = saved_err;
return -1;
}
- /* Register with libv4l2, as we use that todo format conversion and read()
- emulation for us */
- if (v4l2_fd_open(fd, V4L2_ENABLE_ENUM_FMT_EMULATION) == -1) {
+ /* Get initial width, height and pixelformat */
+ fmt2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ if (v4l2_ioctl(fd, VIDIOC_G_FMT, &fmt2)) {
int saved_err = errno;
syscall(SYS_close, fd);
errno = saved_err;
diff --git a/v4l2-apps/libv4l/libv4l2/libv4l2.c b/v4l2-apps/libv4l/libv4l2/libv4l2.c
index 91e0193ee..8d01b034c 100644
--- a/v4l2-apps/libv4l/libv4l2/libv4l2.c
+++ b/v4l2-apps/libv4l/libv4l2/libv4l2.c
@@ -516,6 +516,14 @@ int v4l2_fd_open(int fd, int v4l2_flags)
V4L2_LOG("open: %d\n", fd);
+ if (v4lconvert_supported_dst_fmt_only(convert) &&
+ !v4lconvert_supported_dst_format(fmt.fmt.pix.pixelformat)) {
+ V4L2_LOG("open %d: setting pixelformat to RGB24\n", fd);
+ fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB24;
+ v4l2_ioctl(fd, VIDIOC_S_FMT, &fmt);
+ V4L2_LOG("open %d: done setting pixelformat\n", fd);
+ }
+
return fd;
}
diff --git a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c
index de8b608f9..b09ffc582 100644
--- a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c
+++ b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c
@@ -339,3 +339,8 @@ int v4lcontrol_get_ctrl(struct v4lcontrol_data *data, int ctrl)
return 0;
}
+
+/* See the comment about this in libv4lconvert.h */
+int v4lcontrol_needs_conversion(struct v4lcontrol_data *data) {
+ return data->flags || data->controls;
+}
diff --git a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.h b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.h
index 344e68055..28308bc55 100644
--- a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.h
+++ b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.h
@@ -39,6 +39,11 @@ void v4lcontrol_destroy(struct v4lcontrol_data *data);
/* Functions used by v4lprocessing to get the control state */
int v4lcontrol_get_flags(struct v4lcontrol_data *data);
int v4lcontrol_get_ctrl(struct v4lcontrol_data *data, int ctrl);
+/* Check if we must go through the conversion path (and thus alloc conversion
+ buffers, etc. in libv4l2). Note this always return 1 if we *may* need
+ rotate90 / flipping / processing, as if we actually need this may change
+ on the fly while the stream is active. */
+int v4lcontrol_needs_conversion(struct v4lcontrol_data *data);
/* Functions used by v4lconvert to pass vidioc calls from libv4l2 */
int v4lcontrol_vidioc_queryctrl(struct v4lcontrol_data *data, void *arg);
diff --git a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c
index 5ec85324e..2e029a81c 100644
--- a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c
+++ b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c
@@ -155,7 +155,7 @@ void v4lconvert_destroy(struct v4lconvert_data *data)
free(data);
}
-static int v4lconvert_supported_dst_format(unsigned int pixelformat)
+int v4lconvert_supported_dst_format(unsigned int pixelformat)
{
int i;
@@ -166,6 +166,12 @@ static int v4lconvert_supported_dst_format(unsigned int pixelformat)
return i != ARRAY_SIZE(supported_dst_pixfmts);
}
+int v4lconvert_supported_dst_fmt_only(struct v4lconvert_data *data)
+{
+ return v4lcontrol_needs_conversion(data->control) &&
+ data->supported_src_formats;
+}
+
/* See libv4lconvert.h for description of in / out parameters */
int v4lconvert_enum_fmt(struct v4lconvert_data *data, struct v4l2_fmtdesc *fmt)
{
@@ -173,17 +179,22 @@ int v4lconvert_enum_fmt(struct v4lconvert_data *data, struct v4l2_fmtdesc *fmt)
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)
+ (!v4lconvert_supported_dst_fmt_only(data) &&
+ fmt->index < data->no_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))) {
+ if (v4lconvert_supported_dst_fmt_only(data) ||
+ !(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 (!v4lconvert_supported_dst_fmt_only(data))
+ i = fmt->index - data->no_formats;
+ else
+ i = fmt->index;
+
if (i >= no_faked_fmts) {
errno = EINVAL;
return -1;
@@ -333,7 +344,14 @@ int v4lconvert_try_format(struct v4lconvert_data *data,
int i, result;
unsigned int desired_width = dest_fmt->fmt.pix.width;
unsigned int desired_height = dest_fmt->fmt.pix.height;
- struct v4l2_format try_src, try_dest = *dest_fmt;
+ struct v4l2_format try_src, try_dest;
+
+ if (dest_fmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE &&
+ v4lconvert_supported_dst_fmt_only(data) &&
+ !v4lconvert_supported_dst_format(dest_fmt->fmt.pix.pixelformat))
+ dest_fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_RGB24;
+
+ try_dest = *dest_fmt;
/* Can we do conversion to the requested format & type? */
if (!v4lconvert_supported_dst_format(dest_fmt->fmt.pix.pixelformat) ||
@@ -398,19 +416,14 @@ int v4lconvert_needs_conversion(struct v4lconvert_data *data,
const struct v4l2_format *src_fmt, /* in */
const struct v4l2_format *dest_fmt) /* in */
{
- if(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)
- return 1; /* Formats differ */
-
- if (!(data->control_flags & (V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED)))
- return 0; /* Formats identical and we don't need flip */
+ if (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 ||
+ (v4lcontrol_needs_conversion(data->control) &&
+ v4lconvert_supported_dst_format(dest_fmt->fmt.pix.pixelformat)))
+ return 1;
- /* 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 */
+ return 0;
}
static int v4lconvert_processing_needs_double_conversion(
@@ -494,12 +507,9 @@ static int v4lconvert_convert_pixfmt(struct v4lconvert_data *data,
/* Check for (pixart) rotated JPEG */
if (header_width == height && header_height == width) {
if (!(data->control_flags & V4LCONTROL_ROTATED_90_JPEG)) {
- fprintf(stderr,
- "libv4lconvert: Unknown cam with 90° rotated JPEG, "
- "please report this to <hdegoede@redhat.com>\n");
- V4LCONVERT_ERR("JPEG needs 90 degree rotation\n");
- data->control_flags |= V4LCONTROL_ROTATED_90_JPEG;
- errno = EAGAIN;
+ V4LCONVERT_ERR("JPEG needs 90° rotation, please report "
+ "this to <hdegoede@redhat.com>\n");
+ errno = EIO;
return -1;
}
fmt->fmt.pix.width = header_width;
@@ -511,6 +521,13 @@ static int v4lconvert_convert_pixfmt(struct v4lconvert_data *data,
errno = EIO;
return -1;
}
+ } else if ((data->control_flags & V4LCONTROL_ROTATED_90_JPEG)) {
+ fprintf(stderr, "libv4lconvert: expected 90° rotated JPEG, but got "
+ "normal JPEG, please report this to <hdegoede@redhat.com>\n");
+ V4LCONVERT_ERR("expected 90° rotated JPEG, but got normal JPEG\n");
+ errno = EAGAIN;
+ data->control_flags &= ~V4LCONTROL_ROTATED_90_JPEG;
+ return -1;
}
components[0] = dest;
@@ -831,8 +848,18 @@ int v4lconvert_convert(struct v4lconvert_data *data,
struct v4l2_format my_src_fmt = *src_fmt;
struct v4l2_format my_dest_fmt = *dest_fmt;
- /* Special case when no conversion is needed */
- if (!v4lconvert_needs_conversion(data, src_fmt, dest_fmt)) {
+ processing = v4lprocessing_pre_processing(data->processing);
+
+ 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))) ||
+ /* 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)) {
int to_copy = MIN(dest_size, src_size);
memcpy(dest, src, to_copy);
return to_copy;
@@ -871,7 +898,6 @@ int v4lconvert_convert(struct v4lconvert_data *data,
return -1;
}
- processing = v4lprocessing_pre_processing(data->processing);
/* Sometimes we need foo -> rgb -> bar as video processing (whitebalance,
etc.) can only be done on rgb data */
@@ -1040,8 +1066,13 @@ static void v4lconvert_get_framesizes(struct v4lconvert_data *data,
int v4lconvert_enum_framesizes(struct v4lconvert_data *data,
struct v4l2_frmsizeenum *frmsize)
{
- if (!v4lconvert_supported_dst_format(frmsize->pixel_format))
+ if (!v4lconvert_supported_dst_format(frmsize->pixel_format)) {
+ if (v4lconvert_supported_dst_fmt_only(data)) {
+ errno = EINVAL;
+ return -1;
+ }
return syscall(SYS_ioctl, data->fd, VIDIOC_ENUM_FRAMESIZES, frmsize);
+ }
if (frmsize->index >= data->no_framesizes) {
errno = EINVAL;
@@ -1069,6 +1100,10 @@ int v4lconvert_enum_frameintervals(struct v4lconvert_data *data,
struct v4l2_format src_fmt, dest_fmt;
if (!v4lconvert_supported_dst_format(frmival->pixel_format)) {
+ if (v4lconvert_supported_dst_fmt_only(data)) {
+ errno = EINVAL;
+ return -1;
+ }
res = syscall(SYS_ioctl, data->fd, VIDIOC_ENUM_FRAMEINTERVALS, frmival);
if (res)
V4LCONVERT_ERR("%s\n", strerror(errno));