diff options
author | Mauro Carvalho Chehab <mchehab+samsung@kernel.org> | 2018-07-24 09:49:09 -0300 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab+samsung@kernel.org> | 2018-07-24 11:19:19 -0300 |
commit | cbc8d0905488d9efe5c9ecb2e97076e27049c6b3 (patch) | |
tree | 51580318fbcd908b972f1fb74f90655afad41e81 /src/v4l.c | |
parent | 343b5eb4ae59dbf5583de087326fa3423c923595 (diff) |
Allow selecting the image resolution instead of "small/midium/large"resolution_improvement
The concept of small, midium, large is relative, as it depends on
whatever the camera supports.
Instead of using it, it is a way better to show a list of the
supported resolutions. That works fine for most cameras, with
uses a fixed set.
On cameras with a scale, the Kernel actually exports the resolution
range. On this case, let's present 4 resolutions between the
minimum and maximum one. That should be reasonable for most
usecases.
Nowadays, all drivers should be reporting resolutions via
VIDIOC_ENUM_FRAMESIZES. Yet, as one might run camorama with
very legacy kernels, provide backward support, using
small/midium/large resolutions just like before.
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
Diffstat (limited to 'src/v4l.c')
-rw-r--r-- | src/v4l.c | 68 |
1 files changed, 68 insertions, 0 deletions
@@ -2,6 +2,7 @@ #include<time.h> #include<errno.h> #include<gnome.h> +#include<stdlib.h> #include <sys/select.h> #include "support.h" @@ -20,6 +21,73 @@ void print_cam(cam *cam){ } +void insert_resolution(cam * cam, int x, int y) +{ + int i; + + try_set_win_info(cam, &x, &y); + for (i = 0; i++; i < cam->n_res) { + if (cam->res[i].x == x && cam->res[i].y == y) + return; + } + + cam->res = realloc(cam->res, (cam->n_res + 1) * sizeof(struct resolutions)); + + cam->res[cam->n_res].x = x; + cam->res[cam->n_res].y = y; + cam->n_res++; +} + +static int sort_func(const void *__b, + const void *__a) +{ + const struct resolutions *a = __a; + const struct resolutions *b = __b; + int r; + + r = b->x - a->x; + if (!r) + r = b->y - a->y; + + return r; +} + +void get_supported_resolutions(cam * cam) +{ + struct v4l2_fmtdesc fmt; + struct v4l2_frmsizeenum frmsize; + struct v4l2_frmivalenum frmival; + int i, x, y; + + fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + for (fmt.index = 0; + !v4l2_ioctl(cam->dev, VIDIOC_ENUM_FMT, &fmt); + fmt.index++) { + if (cam->pixformat != fmt.pixelformat) + continue; + + frmsize.pixel_format = fmt.pixelformat; + frmsize.index = 0; + while (!v4l2_ioctl(cam->dev, VIDIOC_ENUM_FRAMESIZES, &frmsize)) { + if (frmsize.type == V4L2_FRMSIZE_TYPE_DISCRETE) { + insert_resolution(cam, frmsize.discrete.width, + frmsize.discrete.height); + } else if (frmsize.type == V4L2_FRMSIZE_TYPE_STEPWISE) { + for (i = 0; i < 4; i++) { + x = frmsize.stepwise.min_width + + i * (frmsize.stepwise.max_width - frmsize.stepwise.min_width) / 4; + y = frmsize.stepwise.min_height + + i * (frmsize.stepwise.max_height - frmsize.stepwise.min_height) / 4; + insert_resolution(cam, x, y); + } + } + frmsize.index++; + } + } + qsort(cam->res, cam->n_res, sizeof(struct resolutions), sort_func); +} + void camera_cap(cam * cam) { char *msg; |