From cbc8d0905488d9efe5c9ecb2e97076e27049c6b3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 24 Jul 2018 09:49:09 -0300 Subject: Allow selecting the image resolution instead of "small/midium/large" 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 --- src/v4l.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) (limited to 'src/v4l.c') diff --git a/src/v4l.c b/src/v4l.c index f2eff32..5a00b13 100644 --- a/src/v4l.c +++ b/src/v4l.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #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; -- cgit v1.2.1