Skip to content

Commit 3fe27eb

Browse files
authored
Support image cropping (#10)
This patch configures predefined the v4l2_rect_set_min_size() and v4l2_rect_set_max_size() for image cropping. It defaults to the Four-Thirds system which is usually in cropping. To check the functionality, use the following command: $ sudo v4l2-ctl -d /dev/video2 --all ... Video input : 0 (vcam_in 0: ok) Format Video Capture: Width/Height : 480/360 Pixel Format : 'RGB3' (24-bit RGB 8-8-8) Field : None Bytes per Line : 1920 Size Image : 921600
1 parent b10c3ff commit 3fe27eb

File tree

4 files changed

+78
-8
lines changed

4 files changed

+78
-8
lines changed

README.md

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,10 @@ Expectedly, two device nodes will be created in `/dev`:
3939
* videoX - V4L2 device;
4040
* vcamctl - Control device for virtual camera(s), used by control utility `vcam-util`;
4141

42-
In `/proc` directory, device file `fbX` will be created.
42+
In `/proc` directory, device file `vcamfbX` will be created.
4343

4444
The device if initialy configured to process 640x480 RGB24 image format.
45-
By writing 640x480 RGB24 raw frame data to `/proc/fbX` file the resulting
45+
By writing 640x480 RGB24 raw frame data to `/proc/vcamfbX` file the resulting
4646
video stream will appear on corresponding `/dev/videoX` V4L2 device(s).
4747

4848
Run `vcam-util --help` for more information about how to configure, add or
@@ -85,6 +85,13 @@ Driver Info:
8585
Device Capabilities
8686
```
8787

88+
Available parameters in the `module.c`:
89+
* `devices_max` - Maximal number of devices. The default is 8.
90+
* `create_devices` - Number of devices to be created during initialization. The default is 1.
91+
* `allow_pix_conversion` - Allow pixel format conversion from RGB24 to YUYV. The default is OFF.
92+
* `allow_scaling` - Allow image scaling from 480p to 720p. The default is OFF.
93+
* `allow_cropping` - Allow image cropping in Four-Thirds system. The default is OFF.
94+
8895
## Related Projects
8996

9097
* [akvcam](https://github.com/webcamoid/akvcam)

device.c

Lines changed: 61 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <linux/time.h>
55
#include <linux/version.h>
66
#include <media/v4l2-image-sizes.h>
7+
#include <media/v4l2-rect.h>
78
#include <media/videobuf2-core.h>
89
#include <media/videobuf2-vmalloc.h>
910

@@ -14,6 +15,7 @@
1415
extern const char *vcam_dev_name;
1516
extern unsigned char allow_pix_conversion;
1617
extern unsigned char allow_scaling;
18+
extern unsigned char allow_cropping;
1719

1820
struct __attribute__((__packed__)) rgb_struct {
1921
unsigned char r, g, b;
@@ -118,8 +120,13 @@ static int vcam_g_fmt_vid_cap(struct file *file,
118120
struct v4l2_format *f)
119121
{
120122
struct vcam_device *dev = (struct vcam_device *) video_drvdata(file);
121-
memcpy(&f->fmt.pix, &dev->output_format, sizeof(struct v4l2_pix_format));
122-
123+
if (dev->conv_crop_on) {
124+
memcpy(&f->fmt.pix, &dev->crop_output_format,
125+
sizeof(struct v4l2_pix_format));
126+
} else {
127+
memcpy(&f->fmt.pix, &dev->output_format,
128+
sizeof(struct v4l2_pix_format));
129+
}
123130
return 0;
124131
}
125132

@@ -158,18 +165,59 @@ static int vcam_try_fmt_vid_cap(struct file *file,
158165
vcam_sizes, n_avail, width, height, vcam_sizes[n_avail - 1].width,
159166
vcam_sizes[n_avail - 1].height);
160167
#else
161-
const struct v4l2_discrete_probe vcam_probe = {
162-
vcam_sizes, ARRAY_SIZE(vcam_sizes)};
168+
const struct v4l2_discrete_probe vcam_probe = {vcam_sizes, n_avail};
163169

164170
const struct v4l2_frmsize_discrete *sz =
165171
v4l2_find_nearest_format(&vcam_probe, vcam_sizes[n_avail - 1].width,
166172
vcam_sizes[n_avail - 1].height);
167173
#endif
168174
f->fmt.pix.width = sz->width;
169175
f->fmt.pix.height = sz->height;
176+
dev->output_format.width = sz->width;
177+
dev->output_format.height = sz->height;
178+
179+
/* set the output_format on YUYV or SRGB*/
180+
if (dev->output_format.pixelformat == V4L2_PIX_FMT_YUYV) {
181+
dev->output_format.bytesperline = dev->output_format.width << 1;
182+
dev->output_format.colorspace = V4L2_COLORSPACE_SMPTE170M;
183+
} else {
184+
dev->output_format.bytesperline = dev->output_format.width * 3;
185+
dev->output_format.colorspace = V4L2_COLORSPACE_SRGB;
186+
}
187+
dev->output_format.sizeimage =
188+
dev->output_format.bytesperline * dev->output_format.height;
170189
vcam_update_format_cap(dev, false);
171190
}
172191

192+
if (dev->conv_crop_on) {
193+
/* set the rectangular size for the cropping */
194+
struct v4l2_rect *crop = &dev->crop_cap;
195+
struct v4l2_rect r = {0, 0, f->fmt.pix.width, f->fmt.pix.height};
196+
struct v4l2_rect min_r = {0, 0, r.width * 3 / 4, r.height * 3 / 4};
197+
struct v4l2_rect max_r = {0, 0, r.width, r.height};
198+
v4l2_rect_set_min_size(crop, &min_r);
199+
v4l2_rect_set_max_size(crop, &max_r);
200+
dev->crop_output_format = dev->output_format;
201+
dev->crop_output_format.width = crop->width;
202+
dev->crop_output_format.height = crop->height;
203+
pr_debug("Output crop is %d", dev->conv_crop_on);
204+
205+
/* set the cropping v4l2_format on YUYV or SRGB */
206+
f->fmt.pix.width = dev->crop_output_format.width;
207+
f->fmt.pix.height = dev->crop_output_format.height;
208+
f->fmt.pix.field = V4L2_FIELD_NONE;
209+
if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) {
210+
f->fmt.pix.bytesperline = dev->output_format.width << 1;
211+
f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
212+
} else {
213+
f->fmt.pix.bytesperline = dev->output_format.width * 3;
214+
f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
215+
}
216+
f->fmt.pix.sizeimage =
217+
f->fmt.pix.bytesperline * dev->output_format.height;
218+
return 0;
219+
}
220+
173221
f->fmt.pix.field = V4L2_FIELD_NONE;
174222
if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) {
175223
f->fmt.pix.bytesperline = f->fmt.pix.width << 1;
@@ -199,7 +247,12 @@ static int vcam_s_fmt_vid_cap(struct file *file,
199247
if (ret < 0)
200248
return ret;
201249

202-
dev->output_format = f->fmt.pix;
250+
if (dev->conv_crop_on) {
251+
dev->crop_output_format = f->fmt.pix;
252+
} else {
253+
dev->output_format = f->fmt.pix;
254+
}
255+
203256
pr_debug("Resolution set to %dx%d\n", dev->output_format.width,
204257
dev->output_format.height);
205258
return 0;
@@ -836,6 +889,7 @@ struct vcam_device *create_vcam_device(size_t idx,
836889
/* Setup conversion capabilities */
837890
vcam->conv_res_on = (bool) allow_scaling;
838891
vcam->conv_pixfmt_on = (bool) allow_pix_conversion;
892+
vcam->conv_crop_on = (bool) allow_cropping;
839893

840894
/* Alloc and set initial format */
841895
if (vcam->conv_pixfmt_on) {
@@ -871,7 +925,8 @@ struct vcam_device *create_vcam_device(size_t idx,
871925
framebuffer_failure:
872926
destroy_framebuffer(vcam->vcam_fb_fname);
873927
video_regdev_failure:
874-
/* TODO: vb2 deinit */
928+
video_unregister_device(&vcam->vdev);
929+
video_device_release(&vcam->vdev);
875930
vb2_out_init_failed:
876931
v4l2_device_unregister(&vcam->v4l2_dev);
877932
v4l2_registration_failure:

device.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,9 +82,13 @@ struct vcam_device {
8282
struct v4l2_pix_format output_format;
8383
struct v4l2_pix_format input_format;
8484

85+
struct v4l2_pix_format crop_output_format;
86+
struct v4l2_rect crop_cap;
87+
8588
/* Conversion switches */
8689
bool conv_pixfmt_on;
8790
bool conv_res_on;
91+
bool conv_crop_on;
8892
};
8993

9094
struct vcam_device *create_vcam_device(size_t idx,

module.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ unsigned short devices_max = 8;
1515
unsigned short create_devices = 1;
1616
unsigned char allow_pix_conversion = 0;
1717
unsigned char allow_scaling = 0;
18+
unsigned char allow_cropping = 0;
1819

1920
module_param(devices_max, ushort, 0);
2021
MODULE_PARM_DESC(devices_max, "Maximal number of devices\n");
@@ -30,6 +31,9 @@ MODULE_PARM_DESC(allow_pix_conversion,
3031
module_param(allow_scaling, byte, 0);
3132
MODULE_PARM_DESC(allow_scaling, "Allow image scaling by default\n");
3233

34+
module_param(allow_cropping, byte, 0);
35+
MODULE_PARM_DESC(allow_cropping, "Allow image cropping by default\n");
36+
3337
const char *vcam_dev_name = VCAM_DEV_NAME;
3438

3539
static int __init vcam_init(void)

0 commit comments

Comments
 (0)