|
4 | 4 | #include <linux/time.h>
|
5 | 5 | #include <linux/version.h>
|
6 | 6 | #include <media/v4l2-image-sizes.h>
|
| 7 | +#include <media/v4l2-rect.h> |
7 | 8 | #include <media/videobuf2-core.h>
|
8 | 9 | #include <media/videobuf2-vmalloc.h>
|
9 | 10 |
|
|
14 | 15 | extern const char *vcam_dev_name;
|
15 | 16 | extern unsigned char allow_pix_conversion;
|
16 | 17 | extern unsigned char allow_scaling;
|
| 18 | +extern unsigned char allow_cropping; |
17 | 19 |
|
18 | 20 | struct __attribute__((__packed__)) rgb_struct {
|
19 | 21 | unsigned char r, g, b;
|
@@ -118,8 +120,13 @@ static int vcam_g_fmt_vid_cap(struct file *file,
|
118 | 120 | struct v4l2_format *f)
|
119 | 121 | {
|
120 | 122 | 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 | + } |
123 | 130 | return 0;
|
124 | 131 | }
|
125 | 132 |
|
@@ -158,18 +165,59 @@ static int vcam_try_fmt_vid_cap(struct file *file,
|
158 | 165 | vcam_sizes, n_avail, width, height, vcam_sizes[n_avail - 1].width,
|
159 | 166 | vcam_sizes[n_avail - 1].height);
|
160 | 167 | #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}; |
163 | 169 |
|
164 | 170 | const struct v4l2_frmsize_discrete *sz =
|
165 | 171 | v4l2_find_nearest_format(&vcam_probe, vcam_sizes[n_avail - 1].width,
|
166 | 172 | vcam_sizes[n_avail - 1].height);
|
167 | 173 | #endif
|
168 | 174 | f->fmt.pix.width = sz->width;
|
169 | 175 | 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; |
170 | 189 | vcam_update_format_cap(dev, false);
|
171 | 190 | }
|
172 | 191 |
|
| 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 | + |
173 | 221 | f->fmt.pix.field = V4L2_FIELD_NONE;
|
174 | 222 | if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) {
|
175 | 223 | f->fmt.pix.bytesperline = f->fmt.pix.width << 1;
|
@@ -199,7 +247,12 @@ static int vcam_s_fmt_vid_cap(struct file *file,
|
199 | 247 | if (ret < 0)
|
200 | 248 | return ret;
|
201 | 249 |
|
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 | + |
203 | 256 | pr_debug("Resolution set to %dx%d\n", dev->output_format.width,
|
204 | 257 | dev->output_format.height);
|
205 | 258 | return 0;
|
@@ -836,6 +889,7 @@ struct vcam_device *create_vcam_device(size_t idx,
|
836 | 889 | /* Setup conversion capabilities */
|
837 | 890 | vcam->conv_res_on = (bool) allow_scaling;
|
838 | 891 | vcam->conv_pixfmt_on = (bool) allow_pix_conversion;
|
| 892 | + vcam->conv_crop_on = (bool) allow_cropping; |
839 | 893 |
|
840 | 894 | /* Alloc and set initial format */
|
841 | 895 | if (vcam->conv_pixfmt_on) {
|
@@ -871,7 +925,8 @@ struct vcam_device *create_vcam_device(size_t idx,
|
871 | 925 | framebuffer_failure:
|
872 | 926 | destroy_framebuffer(vcam->vcam_fb_fname);
|
873 | 927 | video_regdev_failure:
|
874 |
| - /* TODO: vb2 deinit */ |
| 928 | + video_unregister_device(&vcam->vdev); |
| 929 | + video_device_release(&vcam->vdev); |
875 | 930 | vb2_out_init_failed:
|
876 | 931 | v4l2_device_unregister(&vcam->v4l2_dev);
|
877 | 932 | v4l2_registration_failure:
|
|
0 commit comments