diff options
Diffstat (limited to 'v4l2-apps')
-rw-r--r-- | v4l2-apps/libv4l/ChangeLog | 1 | ||||
-rw-r--r-- | v4l2-apps/libv4l/TODO | 3 | ||||
-rw-r--r-- | v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c | 42 | ||||
-rw-r--r-- | v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.h | 12 | ||||
-rw-r--r-- | v4l2-apps/libv4l/libv4lconvert/flip.c | 27 | ||||
-rw-r--r-- | v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h | 5 | ||||
-rw-r--r-- | v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c | 65 |
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); |