1 /*
2 # (C) 2008-2011 Hans de Goede <hdegoede@redhat.com>
3
4 # This program is free software; you can redistribute it and/or modify
5 # it under the terms of the GNU Lesser General Public License as published by
6 # the Free Software Foundation; either version 2.1 of the License, or
7 # (at your option) any later version.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU Lesser General Public License for more details.
13 #
14 # You should have received a copy of the GNU Lesser General Public License
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
17 */
18
19 #ifdef ANDROID
20 #include <android-config.h>
21 #else
22 #include <config.h>
23 #endif
24 #include <errno.h>
25 #include <string.h>
26 #include <stdlib.h>
27 #include <unistd.h>
28 #include <sys/stat.h>
29 #include <sys/types.h>
30 #include "libv4lconvert.h"
31 #include "libv4lconvert-priv.h"
32 #include "libv4lsyscall-priv.h"
33
34 #define MIN(a, b) (((a) < (b)) ? (a) : (b))
35 #define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
36 #define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
37
set_bit(int nr,volatile unsigned long * addr)38 static inline void set_bit(int nr, volatile unsigned long *addr)
39 {
40 unsigned long mask = BIT_MASK(nr);
41 unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
42
43 *p |= mask;
44 }
45
clear_bit(int nr,volatile unsigned long * addr)46 static inline void clear_bit(int nr, volatile unsigned long *addr)
47 {
48 unsigned long mask = BIT_MASK(nr);
49 unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
50
51 *p &= ~mask;
52 }
53
test_bit(int nr,const volatile unsigned long * addr)54 static inline int test_bit(int nr, const volatile unsigned long *addr)
55 {
56 return 1UL & (addr[BIT_WORD(nr)] >> (nr & (BITS_PER_LONG-1)));
57 }
58
dev_init(int fd)59 static void *dev_init(int fd)
60 {
61 return NULL;
62 }
63
dev_close(void * dev_ops_priv)64 static void dev_close(void *dev_ops_priv)
65 {
66 }
67
dev_ioctl(void * dev_ops_priv,int fd,unsigned long cmd,void * arg)68 static int dev_ioctl(void *dev_ops_priv, int fd, unsigned long cmd, void *arg)
69 {
70 return SYS_IOCTL(fd, cmd, arg);
71 }
72
dev_read(void * dev_ops_priv,int fd,void * buf,size_t len)73 static ssize_t dev_read(void *dev_ops_priv, int fd, void *buf, size_t len)
74 {
75 return SYS_READ(fd, buf, len);
76 }
77
dev_write(void * dev_ops_priv,int fd,const void * buf,size_t len)78 static ssize_t dev_write(void *dev_ops_priv, int fd, const void *buf,
79 size_t len)
80 {
81 return SYS_WRITE(fd, buf, len);
82 }
83
84 static const struct libv4l_dev_ops default_dev_ops = {
85 .init = dev_init,
86 .close = dev_close,
87 .ioctl = dev_ioctl,
88 .read = dev_read,
89 .write = dev_write,
90 };
91
v4lconvert_get_default_dev_ops()92 const struct libv4l_dev_ops *v4lconvert_get_default_dev_ops()
93 {
94 return &default_dev_ops;
95 }
96
97 static void v4lconvert_get_framesizes(struct v4lconvert_data *data,
98 unsigned int pixelformat, int index);
99
100 /*
101 * Notes:
102 * 1) for proper functioning of v4lconvert_enum_fmt the first entries in
103 * supported_src_pixfmts must match with the entries in
104 * supported_dst_pixfmts.
105 * 2) The field needs_conversion should be zero, *except* for device-specific
106 * formats, where it doesn't make sense for applications to have their
107 * own decoders.
108 */
109 #define SUPPORTED_DST_PIXFMTS \
110 /* fourcc bpp rgb yuv needs */ \
111 /* rank rank conversion */ \
112 { V4L2_PIX_FMT_RGB24, 24, 1, 5, 0 }, \
113 { V4L2_PIX_FMT_BGR24, 24, 1, 5, 0 }, \
114 { V4L2_PIX_FMT_YUV420, 12, 6, 1, 0 }, \
115 { V4L2_PIX_FMT_YVU420, 12, 6, 1, 0 }
116
117 static const struct v4lconvert_pixfmt supported_src_pixfmts[] = {
118 SUPPORTED_DST_PIXFMTS,
119 /* packed rgb formats */
120 { V4L2_PIX_FMT_RGB565, 16, 4, 6, 0 },
121 { V4L2_PIX_FMT_BGR32, 32, 4, 6, 0 },
122 { V4L2_PIX_FMT_RGB32, 32, 4, 6, 0 },
123 { V4L2_PIX_FMT_XBGR32, 32, 4, 6, 0 },
124 { V4L2_PIX_FMT_XRGB32, 32, 4, 6, 0 },
125 { V4L2_PIX_FMT_ABGR32, 32, 4, 6, 0 },
126 { V4L2_PIX_FMT_ARGB32, 32, 4, 6, 0 },
127 /* yuv 4:2:2 formats */
128 { V4L2_PIX_FMT_YUYV, 16, 5, 4, 0 },
129 { V4L2_PIX_FMT_YVYU, 16, 5, 4, 0 },
130 { V4L2_PIX_FMT_UYVY, 16, 5, 4, 0 },
131 { V4L2_PIX_FMT_NV16, 16, 5, 4, 1 },
132 { V4L2_PIX_FMT_NV61, 16, 5, 4, 1 },
133 /* yuv 4:2:0 formats */
134 { V4L2_PIX_FMT_SPCA501, 12, 6, 3, 1 },
135 { V4L2_PIX_FMT_SPCA505, 12, 6, 3, 1 },
136 { V4L2_PIX_FMT_SPCA508, 12, 6, 3, 1 },
137 { V4L2_PIX_FMT_CIT_YYVYUY, 12, 6, 3, 1 },
138 { V4L2_PIX_FMT_KONICA420, 12, 6, 3, 1 },
139 { V4L2_PIX_FMT_SN9C20X_I420, 12, 6, 3, 1 },
140 { V4L2_PIX_FMT_M420, 12, 6, 3, 1 },
141 { V4L2_PIX_FMT_HM12, 12, 6, 3, 1 },
142 { V4L2_PIX_FMT_NV12, 12, 6, 3, 1 },
143 { V4L2_PIX_FMT_CPIA1, 0, 6, 3, 1 },
144 /* JPEG and variants */
145 { V4L2_PIX_FMT_MJPEG, 0, 7, 7, 0 },
146 { V4L2_PIX_FMT_JPEG, 0, 7, 7, 0 },
147 { V4L2_PIX_FMT_PJPG, 0, 7, 7, 1 },
148 { V4L2_PIX_FMT_JPGL, 0, 7, 7, 1 },
149 #ifdef HAVE_LIBV4LCONVERT_HELPERS
150 { V4L2_PIX_FMT_OV511, 0, 7, 7, 1 },
151 { V4L2_PIX_FMT_OV518, 0, 7, 7, 1 },
152 #endif
153 /* uncompressed bayer */
154 { V4L2_PIX_FMT_SBGGR8, 8, 8, 8, 0 },
155 { V4L2_PIX_FMT_SGBRG8, 8, 8, 8, 0 },
156 { V4L2_PIX_FMT_SGRBG8, 8, 8, 8, 0 },
157 { V4L2_PIX_FMT_SRGGB8, 8, 8, 8, 0 },
158 { V4L2_PIX_FMT_STV0680, 8, 8, 8, 1 },
159 { V4L2_PIX_FMT_SBGGR10P, 10, 8, 8, 1 },
160 { V4L2_PIX_FMT_SGBRG10P, 10, 8, 8, 1 },
161 { V4L2_PIX_FMT_SGRBG10P, 10, 8, 8, 1 },
162 { V4L2_PIX_FMT_SRGGB10P, 10, 8, 8, 1 },
163 { V4L2_PIX_FMT_SBGGR10, 16, 8, 8, 1 },
164 { V4L2_PIX_FMT_SGBRG10, 16, 8, 8, 1 },
165 { V4L2_PIX_FMT_SGRBG10, 16, 8, 8, 1 },
166 { V4L2_PIX_FMT_SRGGB10, 16, 8, 8, 1 },
167 { V4L2_PIX_FMT_SBGGR16, 16, 8, 8, 1 },
168 { V4L2_PIX_FMT_SGBRG16, 16, 8, 8, 1 },
169 { V4L2_PIX_FMT_SGRBG16, 16, 8, 8, 1 },
170 { V4L2_PIX_FMT_SRGGB16, 16, 8, 8, 1 },
171 /* compressed bayer */
172 { V4L2_PIX_FMT_SPCA561, 0, 9, 9, 1 },
173 { V4L2_PIX_FMT_SN9C10X, 0, 9, 9, 1 },
174 { V4L2_PIX_FMT_SN9C2028, 0, 9, 9, 1 },
175 { V4L2_PIX_FMT_PAC207, 0, 9, 9, 1 },
176 { V4L2_PIX_FMT_MR97310A, 0, 9, 9, 1 },
177 #ifdef HAVE_JPEG
178 { V4L2_PIX_FMT_JL2005BCD, 0, 9, 9, 1 },
179 #endif
180 { V4L2_PIX_FMT_SQ905C, 0, 9, 9, 1 },
181 /* special */
182 { V4L2_PIX_FMT_SE401, 0, 8, 9, 1 },
183 /* grey formats */
184 { V4L2_PIX_FMT_GREY, 8, 20, 20, 0 },
185 { V4L2_PIX_FMT_Y4, 8, 20, 20, 0 },
186 { V4L2_PIX_FMT_Y6, 8, 20, 20, 0 },
187 { V4L2_PIX_FMT_Y10BPACK, 10, 20, 20, 0 },
188 { V4L2_PIX_FMT_Y16, 16, 20, 20, 0 },
189 { V4L2_PIX_FMT_Y16_BE, 16, 20, 20, 0 },
190 /* hsv formats */
191 { V4L2_PIX_FMT_HSV32, 32, 5, 4, 0 },
192 { V4L2_PIX_FMT_HSV24, 24, 5, 4, 0 },
193 };
194
195 static const struct v4lconvert_pixfmt supported_dst_pixfmts[] = {
196 SUPPORTED_DST_PIXFMTS
197 };
198
199 /* List of well known resolutions which we can get by cropping somewhat larger
200 resolutions */
201 static const int v4lconvert_crop_res[][2] = {
202 /* low res VGA resolutions, can be made by software cropping SIF resolutions
203 for cam/drivers which do not support this in hardware */
204 { 320, 240 },
205 { 160, 120 },
206 /* Some CIF cams (with vv6410 sensor) have slightly larger then usual CIF
207 resolutions, make regular CIF resolutions available on these by sw crop */
208 { 352, 288 },
209 { 176, 144 },
210 };
211
v4lconvert_create(int fd)212 struct v4lconvert_data *v4lconvert_create(int fd)
213 {
214 return v4lconvert_create_with_dev_ops(fd, NULL, &default_dev_ops);
215 }
216
v4lconvert_create_with_dev_ops(int fd,void * dev_ops_priv,const struct libv4l_dev_ops * dev_ops)217 struct v4lconvert_data *v4lconvert_create_with_dev_ops(int fd, void *dev_ops_priv,
218 const struct libv4l_dev_ops *dev_ops)
219 {
220 int i, j;
221 struct v4lconvert_data *data = calloc(1, sizeof(struct v4lconvert_data));
222 struct v4l2_capability cap;
223 /*
224 * This keeps tracks of device-specific formats for which apps most
225 * likely don't know. If all a driver can offer are proprietary
226 * formats, a conversion is needed anyway. We can thus safely
227 * add software processing controls without much concern about a
228 * performance impact.
229 */
230 int always_needs_conversion = 1;
231
232 if (!data) {
233 fprintf(stderr, "libv4lconvert: error: out of memory!\n");
234 return NULL;
235 }
236
237 data->fd = fd;
238 data->dev_ops = dev_ops;
239 data->dev_ops_priv = dev_ops_priv;
240 data->decompress_pid = -1;
241 data->fps = 30;
242
243 /* Check supported formats */
244 for (i = 0; ; i++) {
245 struct v4l2_fmtdesc fmt = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE };
246
247 fmt.index = i;
248
249 if (data->dev_ops->ioctl(data->dev_ops_priv, data->fd,
250 VIDIOC_ENUM_FMT, &fmt))
251 break;
252
253 for (j = 0; j < ARRAY_SIZE(supported_src_pixfmts); j++)
254 if (fmt.pixelformat == supported_src_pixfmts[j].fmt)
255 break;
256
257 if (j < ARRAY_SIZE(supported_src_pixfmts)) {
258 set_bit(j, data->supported_src_formats);
259 v4lconvert_get_framesizes(data, fmt.pixelformat, j);
260 if (!supported_src_pixfmts[j].needs_conversion)
261 always_needs_conversion = 0;
262 } else
263 always_needs_conversion = 0;
264 }
265
266 data->no_formats = i;
267
268 /* Check if this cam has any special flags */
269 if (data->dev_ops->ioctl(data->dev_ops_priv, data->fd,
270 VIDIOC_QUERYCAP, &cap) == 0) {
271 if (!strcmp((char *)cap.driver, "uvcvideo"))
272 data->flags |= V4LCONVERT_IS_UVC;
273
274 if (cap.capabilities & V4L2_CAP_DEVICE_CAPS)
275 cap.capabilities = cap.device_caps;
276 if ((cap.capabilities & 0xff) & ~V4L2_CAP_VIDEO_CAPTURE)
277 always_needs_conversion = 0;
278 }
279
280 data->control = v4lcontrol_create(fd, dev_ops_priv, dev_ops,
281 always_needs_conversion);
282 if (!data->control) {
283 free(data);
284 return NULL;
285 }
286 data->bandwidth = v4lcontrol_get_bandwidth(data->control);
287 data->control_flags = v4lcontrol_get_flags(data->control);
288 if (data->control_flags & V4LCONTROL_FORCE_TINYJPEG)
289 data->flags |= V4LCONVERT_USE_TINYJPEG;
290
291 data->processing = v4lprocessing_create(fd, data->control);
292 if (!data->processing) {
293 v4lcontrol_destroy(data->control);
294 free(data);
295 return NULL;
296 }
297
298 return data;
299 }
300
v4lconvert_destroy(struct v4lconvert_data * data)301 void v4lconvert_destroy(struct v4lconvert_data *data)
302 {
303 if (!data)
304 return;
305
306 v4lprocessing_destroy(data->processing);
307 v4lcontrol_destroy(data->control);
308 if (data->tinyjpeg) {
309 unsigned char *comps[3] = { NULL, NULL, NULL };
310
311 tinyjpeg_set_components(data->tinyjpeg, comps, 3);
312 tinyjpeg_free(data->tinyjpeg);
313 }
314 #ifdef HAVE_JPEG
315 if (data->cinfo_initialized)
316 jpeg_destroy_decompress(&data->cinfo);
317 #endif // HAVE_JPEG
318 #ifdef HAVE_LIBV4LCONVERT_HELPERS
319 v4lconvert_helper_cleanup(data);
320 #endif
321 free(data->convert1_buf);
322 free(data->convert2_buf);
323 free(data->rotate90_buf);
324 free(data->flip_buf);
325 free(data->convert_pixfmt_buf);
326 free(data->previous_frame);
327 free(data);
328 }
329
v4lconvert_supported_dst_format(unsigned int pixelformat)330 int v4lconvert_supported_dst_format(unsigned int pixelformat)
331 {
332 int i;
333
334 for (i = 0; i < ARRAY_SIZE(supported_dst_pixfmts); i++)
335 if (supported_dst_pixfmts[i].fmt == pixelformat)
336 break;
337
338 return i != ARRAY_SIZE(supported_dst_pixfmts);
339 }
340
v4lconvert_supported_dst_fmt_only(struct v4lconvert_data * data)341 int v4lconvert_supported_dst_fmt_only(struct v4lconvert_data *data)
342 {
343 int i;
344
345 for (i = 0 ; i < ARRAY_SIZE(data->supported_src_formats); i++)
346 if (data->supported_src_formats[i])
347 break;
348 if (i == ARRAY_SIZE(data->supported_src_formats))
349 return 0;
350
351 return v4lcontrol_needs_conversion(data->control);
352 }
353
354 /* See libv4lconvert.h for description of in / out parameters */
v4lconvert_enum_fmt(struct v4lconvert_data * data,struct v4l2_fmtdesc * fmt)355 int v4lconvert_enum_fmt(struct v4lconvert_data *data, struct v4l2_fmtdesc *fmt)
356 {
357 int i, no_faked_fmts = 0;
358 unsigned int faked_fmts[ARRAY_SIZE(supported_dst_pixfmts)];
359
360 if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
361 (!v4lconvert_supported_dst_fmt_only(data) &&
362 fmt->index < data->no_formats))
363 return data->dev_ops->ioctl(data->dev_ops_priv, data->fd,
364 VIDIOC_ENUM_FMT, fmt);
365
366 for (i = 0; i < ARRAY_SIZE(supported_dst_pixfmts); i++)
367 if (v4lconvert_supported_dst_fmt_only(data) ||
368 !test_bit(i, data->supported_src_formats)) {
369 faked_fmts[no_faked_fmts] = supported_dst_pixfmts[i].fmt;
370 no_faked_fmts++;
371 }
372
373 if (!v4lconvert_supported_dst_fmt_only(data))
374 i = fmt->index - data->no_formats;
375 else
376 i = fmt->index;
377
378 if (i >= no_faked_fmts) {
379 errno = EINVAL;
380 return -1;
381 }
382
383 fmt->flags = V4L2_FMT_FLAG_EMULATED;
384 fmt->pixelformat = faked_fmts[i];
385 fmt->description[0] = faked_fmts[i] & 0xff;
386 fmt->description[1] = (faked_fmts[i] >> 8) & 0xff;
387 fmt->description[2] = (faked_fmts[i] >> 16) & 0xff;
388 fmt->description[3] = faked_fmts[i] >> 24;
389 fmt->description[4] = '\0';
390 memset(fmt->reserved, 0, sizeof(fmt->reserved));
391
392 return 0;
393 }
394
395 /* This function returns a value to rank (sort) source format by preference
396 when multiple source formats are available for a certain resolution, the
397 source format for which this function returns the lowest value wins.
398
399 This function uses the rgb_rank resp. yuv_rank values as a base when
400 converting to rgb32 resp. yuv420. The initial ranks range from 1 - 10,
401 the initial rank purely expresses the CPU cost of doing the conversion, the
402 ranking algorithm will give a penalty of 10 points if
403 (width * height * fps * bpp / 8) > bandwidth
404 thus disqualifying a src format which causes the bandwidth to be exceeded,
405 except when all of them cause this.
406
407 Note grey scale formats start at 20 rather than 1-10, because we want to
408 never autoselect them, unless they are the only choice */
v4lconvert_get_rank(struct v4lconvert_data * data,int src_index,int src_width,int src_height,unsigned int dest_pixelformat)409 static int v4lconvert_get_rank(struct v4lconvert_data *data,
410 int src_index, int src_width, int src_height,
411 unsigned int dest_pixelformat)
412 {
413 int needed, rank = 0;
414
415 switch (dest_pixelformat) {
416 case V4L2_PIX_FMT_RGB24:
417 case V4L2_PIX_FMT_BGR24:
418 rank = supported_src_pixfmts[src_index].rgb_rank;
419 break;
420 case V4L2_PIX_FMT_YUV420:
421 case V4L2_PIX_FMT_YVU420:
422 rank = supported_src_pixfmts[src_index].yuv_rank;
423 break;
424 }
425
426 /* So that if both rgb32 and bgr32 are supported, or both yuv420 and
427 yvu420 the right one wins */
428 if (supported_src_pixfmts[src_index].fmt == dest_pixelformat)
429 rank--;
430
431 /* check bandwidth needed */
432 needed = src_width * src_height * data->fps *
433 supported_src_pixfmts[src_index].bpp / 8;
434 if (data->bandwidth && needed > data->bandwidth)
435 rank += 10;
436 #if 0
437 printf("ranked: %c%c%c%c for %dx%d @ %d fps, needed: %d, bandwidth: %d, rank: %d\n",
438 supported_src_pixfmts[src_index].fmt & 0xff,
439 (supported_src_pixfmts[src_index].fmt >> 8) & 0xff,
440 (supported_src_pixfmts[src_index].fmt >> 16) & 0xff,
441 supported_src_pixfmts[src_index].fmt >> 24, src_width,
442 src_height, data->fps, needed, data->bandwidth, rank);
443 #endif
444 return rank;
445 }
446
447 /* Find out what format to use based on the (cached) results of enum
448 framesizes instead of doing a zillion try_fmt calls. This function
449 currently is intended for use with UVC cams only. This is esp.
450 important for UVC based cams as doing try_fmt there actually causes I/O */
v4lconvert_do_try_format_uvc(struct v4lconvert_data * data,struct v4l2_format * dest_fmt,struct v4l2_format * src_fmt)451 static int v4lconvert_do_try_format_uvc(struct v4lconvert_data *data,
452 struct v4l2_format *dest_fmt, struct v4l2_format *src_fmt)
453 {
454 int i, rank;
455 unsigned int closest_fmt_size_diff = -1;
456 int best_framesize = 0;/* Just use the first format if no small enough one */
457 int best_format = 0;
458 int best_rank = 100;
459
460 for (i = 0; i < data->no_framesizes; i++) {
461 if (data->framesizes[i].discrete.width <= dest_fmt->fmt.pix.width &&
462 data->framesizes[i].discrete.height <= dest_fmt->fmt.pix.height) {
463 int size_x_diff = dest_fmt->fmt.pix.width -
464 data->framesizes[i].discrete.width;
465 int size_y_diff = dest_fmt->fmt.pix.height -
466 data->framesizes[i].discrete.height;
467 unsigned int size_diff = size_x_diff * size_x_diff +
468 size_y_diff * size_y_diff;
469
470 if (size_diff < closest_fmt_size_diff) {
471 closest_fmt_size_diff = size_diff;
472 best_framesize = i;
473 }
474 }
475 }
476
477 for (i = 0; i < ARRAY_SIZE(supported_src_pixfmts); i++) {
478 /* is this format supported? */
479 if (!(data->framesize_supported_src_formats[best_framesize] &
480 (1ULL << i)))
481 continue;
482
483 /* Note the hardcoded use of discrete is based on this function
484 only getting called for uvc devices */
485 rank = v4lconvert_get_rank(data, i,
486 data->framesizes[best_framesize].discrete.width,
487 data->framesizes[best_framesize].discrete.height,
488 dest_fmt->fmt.pix.pixelformat);
489 if (rank < best_rank) {
490 best_rank = rank;
491 best_format = supported_src_pixfmts[i].fmt;
492 }
493 }
494
495 dest_fmt->fmt.pix.width = data->framesizes[best_framesize].discrete.width;
496 dest_fmt->fmt.pix.height = data->framesizes[best_framesize].discrete.height;
497 dest_fmt->fmt.pix.field = V4L2_FIELD_NONE; /* UVC has no fields */
498 /* Not pretty, the pwc driver doesn't fill these in try_fmt either though,
499 so we should be able to get away with this. */
500 dest_fmt->fmt.pix.bytesperline = 0;
501 dest_fmt->fmt.pix.sizeimage = 0;
502 dest_fmt->fmt.pix.colorspace = V4L2_COLORSPACE_DEFAULT;
503 dest_fmt->fmt.pix.priv = 0;
504
505 *src_fmt = *dest_fmt;
506 src_fmt->fmt.pix.pixelformat = best_format;
507
508 return 0;
509 }
510
v4lconvert_do_try_format(struct v4lconvert_data * data,struct v4l2_format * dest_fmt,struct v4l2_format * src_fmt)511 static int v4lconvert_do_try_format(struct v4lconvert_data *data,
512 struct v4l2_format *dest_fmt, struct v4l2_format *src_fmt)
513 {
514 int i, size_x_diff, size_y_diff, rank, best_rank = 0;
515 unsigned int size_diff, closest_fmt_size_diff = -1;
516 unsigned int desired_pixfmt = dest_fmt->fmt.pix.pixelformat;
517 struct v4l2_format try_fmt, closest_fmt = { .type = 0 };
518
519 if (data->flags & V4LCONVERT_IS_UVC)
520 return v4lconvert_do_try_format_uvc(data, dest_fmt, src_fmt);
521
522 for (i = 0; i < ARRAY_SIZE(supported_src_pixfmts); i++) {
523 /* is this format supported? */
524 if (!test_bit(i, data->supported_src_formats))
525 continue;
526
527 try_fmt = *dest_fmt;
528 try_fmt.fmt.pix.pixelformat = supported_src_pixfmts[i].fmt;
529 if (data->dev_ops->ioctl(data->dev_ops_priv, data->fd,
530 VIDIOC_TRY_FMT, &try_fmt))
531 continue;
532
533 if (try_fmt.fmt.pix.pixelformat !=
534 supported_src_pixfmts[i].fmt)
535 continue;
536
537 /* Did we get a better match than before? */
538 size_x_diff = (int)try_fmt.fmt.pix.width -
539 (int)dest_fmt->fmt.pix.width;
540 size_y_diff = (int)try_fmt.fmt.pix.height -
541 (int)dest_fmt->fmt.pix.height;
542 size_diff = size_x_diff * size_x_diff +
543 size_y_diff * size_y_diff;
544
545 rank = v4lconvert_get_rank(data, i,
546 try_fmt.fmt.pix.width,
547 try_fmt.fmt.pix.height,
548 desired_pixfmt);
549 if (size_diff < closest_fmt_size_diff ||
550 (size_diff == closest_fmt_size_diff && rank < best_rank)) {
551 closest_fmt = try_fmt;
552 closest_fmt_size_diff = size_diff;
553 best_rank = rank;
554 }
555 }
556
557 if (closest_fmt.type == 0)
558 return -1;
559
560 *dest_fmt = closest_fmt;
561 if (closest_fmt.fmt.pix.pixelformat != desired_pixfmt)
562 dest_fmt->fmt.pix.pixelformat = desired_pixfmt;
563 *src_fmt = closest_fmt;
564
565 return 0;
566 }
567
v4lconvert_fixup_fmt(struct v4l2_format * fmt)568 void v4lconvert_fixup_fmt(struct v4l2_format *fmt)
569 {
570 switch (fmt->fmt.pix.pixelformat) {
571 case V4L2_PIX_FMT_RGB24:
572 case V4L2_PIX_FMT_BGR24:
573 fmt->fmt.pix.bytesperline = fmt->fmt.pix.width * 3;
574 fmt->fmt.pix.sizeimage = fmt->fmt.pix.width * fmt->fmt.pix.height * 3;
575 break;
576 case V4L2_PIX_FMT_YUV420:
577 case V4L2_PIX_FMT_YVU420:
578 fmt->fmt.pix.bytesperline = fmt->fmt.pix.width;
579 fmt->fmt.pix.sizeimage = fmt->fmt.pix.width * fmt->fmt.pix.height * 3 / 2;
580 break;
581 }
582 }
583
584 /* See libv4lconvert.h for description of in / out parameters */
v4lconvert_try_format(struct v4lconvert_data * data,struct v4l2_format * dest_fmt,struct v4l2_format * src_fmt)585 int v4lconvert_try_format(struct v4lconvert_data *data,
586 struct v4l2_format *dest_fmt, struct v4l2_format *src_fmt)
587 {
588 int i, result;
589 unsigned int desired_width = dest_fmt->fmt.pix.width;
590 unsigned int desired_height = dest_fmt->fmt.pix.height;
591 struct v4l2_format try_src, try_dest, try2_src, try2_dest;
592
593 if (dest_fmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE &&
594 v4lconvert_supported_dst_fmt_only(data) &&
595 !v4lconvert_supported_dst_format(dest_fmt->fmt.pix.pixelformat))
596 dest_fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_RGB24;
597
598 try_dest = *dest_fmt;
599
600 /* Can we do conversion to the requested format & type? */
601 if (!v4lconvert_supported_dst_format(dest_fmt->fmt.pix.pixelformat) ||
602 dest_fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
603 v4lconvert_do_try_format(data, &try_dest, &try_src)) {
604 result = data->dev_ops->ioctl(data->dev_ops_priv, data->fd,
605 VIDIOC_TRY_FMT, dest_fmt);
606 if (src_fmt)
607 *src_fmt = *dest_fmt;
608 return result;
609 }
610
611 /* In case of a non exact resolution match, try again with a slightly larger
612 resolution as some weird devices are not able to crop of the number of
613 extra (border) pixels most sensors have compared to standard resolutions,
614 which we will then just crop off in software */
615 if (try_dest.fmt.pix.width != desired_width ||
616 try_dest.fmt.pix.height != desired_height) {
617 try2_dest = *dest_fmt;
618 try2_dest.fmt.pix.width = desired_width + 7;
619 try2_dest.fmt.pix.height = desired_height + 1;
620 result = v4lconvert_do_try_format(data, &try2_dest, &try2_src);
621 if (result == 0 &&
622 try2_dest.fmt.pix.width >= desired_width &&
623 try2_dest.fmt.pix.width <= desired_width + 7 &&
624 try2_dest.fmt.pix.height >= desired_height &&
625 try2_dest.fmt.pix.height <= desired_height + 1) {
626 /* Success! */
627 try2_dest.fmt.pix.width = desired_width;
628 try2_dest.fmt.pix.height = desired_height;
629 try_dest = try2_dest;
630 try_src = try2_src;
631 }
632 }
633
634 /* In case of a non exact resolution match, see if this is a well known
635 resolution some apps are hardcoded too and try to give the app what it
636 asked for by cropping a slightly larger resolution or adding a small
637 black border to a slightly smaller resolution */
638 if (try_dest.fmt.pix.width != desired_width ||
639 try_dest.fmt.pix.height != desired_height) {
640 for (i = 0; i < ARRAY_SIZE(v4lconvert_crop_res); i++) {
641 if (v4lconvert_crop_res[i][0] == desired_width &&
642 v4lconvert_crop_res[i][1] == desired_height) {
643 try2_dest = *dest_fmt;
644
645 /* Note these are chosen so that cropping to vga res just works for
646 vv6410 sensor cams, which have 356x292 and 180x148 */
647 try2_dest.fmt.pix.width = desired_width * 113 / 100;
648 try2_dest.fmt.pix.height = desired_height * 124 / 100;
649 result = v4lconvert_do_try_format(data, &try2_dest, &try2_src);
650 if (result == 0 &&
651 (/* Add a small black border of max 16 pixels */
652 (try2_dest.fmt.pix.width >= desired_width - 16 &&
653 try2_dest.fmt.pix.width <= desired_width &&
654 try2_dest.fmt.pix.height >= desired_height - 16 &&
655 try2_dest.fmt.pix.height <= desired_height) ||
656 /* Standard cropping to max 80% of actual width / height */
657 (try2_dest.fmt.pix.width >= desired_width &&
658 try2_dest.fmt.pix.width <= desired_width * 5 / 4 &&
659 try2_dest.fmt.pix.height >= desired_height &&
660 try2_dest.fmt.pix.height <= desired_height * 5 / 4) ||
661 /* Downscale 2x + cropping to max 80% of actual width / height */
662 (try2_dest.fmt.pix.width >= desired_width * 2 &&
663 try2_dest.fmt.pix.width <= desired_width * 5 / 2 &&
664 try2_dest.fmt.pix.height >= desired_height * 2 &&
665 try2_dest.fmt.pix.height <= desired_height * 5 / 2))) {
666 /* Success! */
667 try2_dest.fmt.pix.width = desired_width;
668 try2_dest.fmt.pix.height = desired_height;
669 try_dest = try2_dest;
670 try_src = try2_src;
671 }
672 break;
673 }
674 }
675 }
676
677 /* Some applications / libs (*cough* gstreamer *cough*) will not work
678 correctly with planar YUV formats when the width is not a multiple of 8
679 or the height is not a multiple of 2. With RGB formats these apps require
680 the width to be a multiple of 4. We apply the same rounding to all
681 formats to not end up with 2 close but different resolutions. */
682 try_dest.fmt.pix.width &= ~7;
683 try_dest.fmt.pix.height &= ~1;
684
685 /* Are we converting / cropping ? */
686 if (try_src.fmt.pix.width != try_dest.fmt.pix.width ||
687 try_src.fmt.pix.height != try_dest.fmt.pix.height ||
688 try_src.fmt.pix.pixelformat != try_dest.fmt.pix.pixelformat)
689 v4lconvert_fixup_fmt(&try_dest);
690
691 *dest_fmt = try_dest;
692 if (src_fmt)
693 *src_fmt = try_src;
694
695 return 0;
696 }
697
698 /* Is conversion necessary ? */
v4lconvert_needs_conversion(struct v4lconvert_data * data,const struct v4l2_format * src_fmt,const struct v4l2_format * dest_fmt)699 int v4lconvert_needs_conversion(struct v4lconvert_data *data,
700 const struct v4l2_format *src_fmt, /* in */
701 const struct v4l2_format *dest_fmt) /* in */
702 {
703 if (src_fmt->fmt.pix.width != dest_fmt->fmt.pix.width ||
704 src_fmt->fmt.pix.height != dest_fmt->fmt.pix.height ||
705 src_fmt->fmt.pix.pixelformat != dest_fmt->fmt.pix.pixelformat ||
706 (v4lcontrol_needs_conversion(data->control) &&
707 v4lconvert_supported_dst_format(dest_fmt->fmt.pix.pixelformat)))
708 return 1;
709
710 return 0;
711 }
712
v4lconvert_processing_needs_double_conversion(unsigned int src_pix_fmt,unsigned int dest_pix_fmt)713 static int v4lconvert_processing_needs_double_conversion(
714 unsigned int src_pix_fmt, unsigned int dest_pix_fmt)
715 {
716 switch (src_pix_fmt) {
717 case V4L2_PIX_FMT_RGB24:
718 case V4L2_PIX_FMT_BGR24:
719 case V4L2_PIX_FMT_SPCA561:
720 case V4L2_PIX_FMT_SN9C10X:
721 case V4L2_PIX_FMT_PAC207:
722 case V4L2_PIX_FMT_MR97310A:
723 #ifdef HAVE_JPEG
724 case V4L2_PIX_FMT_JL2005BCD:
725 #endif
726 case V4L2_PIX_FMT_SN9C2028:
727 case V4L2_PIX_FMT_SQ905C:
728 case V4L2_PIX_FMT_SBGGR8:
729 case V4L2_PIX_FMT_SGBRG8:
730 case V4L2_PIX_FMT_SGRBG8:
731 case V4L2_PIX_FMT_SRGGB8:
732 case V4L2_PIX_FMT_SBGGR10P:
733 case V4L2_PIX_FMT_SGBRG10P:
734 case V4L2_PIX_FMT_SGRBG10P:
735 case V4L2_PIX_FMT_SRGGB10P:
736 case V4L2_PIX_FMT_SBGGR10:
737 case V4L2_PIX_FMT_SGBRG10:
738 case V4L2_PIX_FMT_SGRBG10:
739 case V4L2_PIX_FMT_SRGGB10:
740 case V4L2_PIX_FMT_SBGGR16:
741 case V4L2_PIX_FMT_SGBRG16:
742 case V4L2_PIX_FMT_SGRBG16:
743 case V4L2_PIX_FMT_SRGGB16:
744 case V4L2_PIX_FMT_STV0680:
745 return 0;
746 }
747 switch (dest_pix_fmt) {
748 case V4L2_PIX_FMT_RGB24:
749 case V4L2_PIX_FMT_BGR24:
750 return 0;
751 }
752
753 return 1;
754 }
755
v4lconvert_alloc_buffer(int needed,unsigned char ** buf,int * buf_size)756 unsigned char *v4lconvert_alloc_buffer(int needed,
757 unsigned char **buf, int *buf_size)
758 {
759 if (*buf_size < needed) {
760 free(*buf);
761 *buf = malloc(needed);
762 if (*buf == NULL) {
763 *buf_size = 0;
764 return NULL;
765 }
766 *buf_size = needed;
767 }
768 return *buf;
769 }
770
v4lconvert_oom_error(struct v4lconvert_data * data)771 int v4lconvert_oom_error(struct v4lconvert_data *data)
772 {
773 V4LCONVERT_ERR("could not allocate memory\n");
774 errno = ENOMEM;
775 return -1;
776 }
777
v4lconvert_convert_pixfmt(struct v4lconvert_data * data,unsigned char * src,int src_size,unsigned char * dest,int dest_size,struct v4l2_format * fmt,unsigned int dest_pix_fmt)778 static int v4lconvert_convert_pixfmt(struct v4lconvert_data *data,
779 unsigned char *src, int src_size, unsigned char *dest, int dest_size,
780 struct v4l2_format *fmt, unsigned int dest_pix_fmt)
781 {
782 int result = 0;
783 unsigned int src_pix_fmt = fmt->fmt.pix.pixelformat;
784 unsigned int width = fmt->fmt.pix.width;
785 unsigned int height = fmt->fmt.pix.height;
786 unsigned int bytesperline = fmt->fmt.pix.bytesperline;
787
788 switch (src_pix_fmt) {
789 /* JPG and variants */
790 case V4L2_PIX_FMT_MJPEG:
791 case V4L2_PIX_FMT_JPEG:
792 #ifdef HAVE_JPEG
793 if (data->flags & V4LCONVERT_USE_TINYJPEG) {
794 #endif // HAVE_JPEG
795 result = v4lconvert_decode_jpeg_tinyjpeg(data,
796 src, src_size, dest,
797 fmt, dest_pix_fmt, 0);
798 #ifdef HAVE_JPEG
799 } else {
800 result = v4lconvert_decode_jpeg_libjpeg(data,
801 src, src_size, dest,
802 fmt, dest_pix_fmt);
803 if (result == -1 && errno == EOPNOTSUPP) {
804 /* Fall back to tinyjpeg */
805 jpeg_destroy_decompress(&data->cinfo);
806 data->cinfo_initialized = 0;
807 data->flags |= V4LCONVERT_USE_TINYJPEG;
808 result = v4lconvert_decode_jpeg_tinyjpeg(data,
809 src, src_size, dest,
810 fmt, dest_pix_fmt, 0);
811 }
812 }
813 #endif // HAVE_JPEG
814 break;
815 case V4L2_PIX_FMT_PJPG:
816 result = v4lconvert_decode_jpeg_tinyjpeg(data, src, src_size,
817 dest, fmt, dest_pix_fmt,
818 TINYJPEG_FLAGS_PIXART_JPEG);
819 break;
820 case V4L2_PIX_FMT_JPGL:
821 result = v4lconvert_decode_jpgl(src, src_size, dest_pix_fmt,
822 dest, width, height);
823 break;
824
825 /* Custom cam specific YUV formats */
826 case V4L2_PIX_FMT_SPCA501:
827 case V4L2_PIX_FMT_SPCA505:
828 case V4L2_PIX_FMT_SPCA508:
829 case V4L2_PIX_FMT_CIT_YYVYUY:
830 case V4L2_PIX_FMT_KONICA420:
831 case V4L2_PIX_FMT_M420:
832 case V4L2_PIX_FMT_SN9C20X_I420:
833 case V4L2_PIX_FMT_CPIA1:
834 case V4L2_PIX_FMT_OV511:
835 case V4L2_PIX_FMT_OV518: {
836 unsigned char *d;
837 int d_size;
838 int yvu = 0;
839
840 if (dest_pix_fmt != V4L2_PIX_FMT_YUV420 &&
841 dest_pix_fmt != V4L2_PIX_FMT_YVU420) {
842 d = v4lconvert_alloc_buffer(width * height * 3 / 2,
843 &data->convert_pixfmt_buf, &data->convert_pixfmt_buf_size);
844 if (!d)
845 return v4lconvert_oom_error(data);
846 d_size = width * height * 3 / 2;
847 } else {
848 d = dest;
849 d_size = dest_size;
850 }
851
852 if (dest_pix_fmt == V4L2_PIX_FMT_YVU420)
853 yvu = 1;
854
855 switch (src_pix_fmt) {
856 case V4L2_PIX_FMT_SPCA501:
857 v4lconvert_spca501_to_yuv420(src, d, width, height, yvu);
858 break;
859 case V4L2_PIX_FMT_SPCA505:
860 v4lconvert_spca505_to_yuv420(src, d, width, height, yvu);
861 break;
862 case V4L2_PIX_FMT_SPCA508:
863 v4lconvert_spca508_to_yuv420(src, d, width, height, yvu);
864 break;
865 case V4L2_PIX_FMT_CIT_YYVYUY:
866 v4lconvert_cit_yyvyuy_to_yuv420(src, d, width, height, yvu);
867 break;
868 case V4L2_PIX_FMT_KONICA420:
869 v4lconvert_konica_yuv420_to_yuv420(src, d, width, height, yvu);
870 break;
871 case V4L2_PIX_FMT_M420:
872 v4lconvert_m420_to_yuv420(src, d, width, height, yvu);
873 break;
874 case V4L2_PIX_FMT_SN9C20X_I420:
875 v4lconvert_sn9c20x_to_yuv420(src, d, width, height, yvu);
876 break;
877 case V4L2_PIX_FMT_CPIA1:
878 if (v4lconvert_cpia1_to_yuv420(data, src, src_size, d,
879 width, height, yvu)) {
880 /* Corrupt frame, better get another one */
881 errno = EAGAIN;
882 return -1;
883 }
884 break;
885 #ifdef HAVE_LIBV4LCONVERT_HELPERS
886 case V4L2_PIX_FMT_OV511:
887 if (v4lconvert_helper_decompress(data, LIBV4LCONVERT_PRIV_DIR "/ov511-decomp",
888 src, src_size, d, d_size, width, height, yvu)) {
889 /* Corrupt frame, better get another one */
890 errno = EAGAIN;
891 return -1;
892 }
893 break;
894 case V4L2_PIX_FMT_OV518:
895 if (v4lconvert_helper_decompress(data, LIBV4LCONVERT_PRIV_DIR "/ov518-decomp",
896 src, src_size, d, d_size, width, height, yvu)) {
897 /* Corrupt frame, better get another one */
898 errno = EAGAIN;
899 return -1;
900 }
901 break;
902 #endif
903 }
904
905 switch (dest_pix_fmt) {
906 case V4L2_PIX_FMT_RGB24:
907 v4lconvert_yuv420_to_rgb24(data->convert_pixfmt_buf, dest, width,
908 height, yvu);
909 break;
910 case V4L2_PIX_FMT_BGR24:
911 v4lconvert_yuv420_to_bgr24(data->convert_pixfmt_buf, dest, width,
912 height, yvu);
913 break;
914 }
915 break;
916 }
917
918 /* Conexant cx2341x raw video macroblock format */
919 case V4L2_PIX_FMT_HM12:
920 switch (dest_pix_fmt) {
921 case V4L2_PIX_FMT_RGB24:
922 v4lconvert_hm12_to_rgb24(src, dest, width, height);
923 break;
924 case V4L2_PIX_FMT_BGR24:
925 v4lconvert_hm12_to_bgr24(src, dest, width, height);
926 break;
927 case V4L2_PIX_FMT_YUV420:
928 v4lconvert_hm12_to_yuv420(src, dest, width, height, 0);
929 break;
930 case V4L2_PIX_FMT_YVU420:
931 v4lconvert_hm12_to_yuv420(src, dest, width, height, 1);
932 break;
933 }
934 break;
935
936 /* NV12 formats */
937 case V4L2_PIX_FMT_NV12:
938 switch (dest_pix_fmt) {
939 case V4L2_PIX_FMT_RGB24:
940 v4lconvert_nv12_to_rgb24(src, dest, width, height, 0);
941 break;
942 case V4L2_PIX_FMT_BGR24:
943 v4lconvert_nv12_to_rgb24(src, dest, width, height, 1);
944 break;
945 case V4L2_PIX_FMT_YUV420:
946 v4lconvert_nv12_to_yuv420(src, dest, width, height, 0);
947 break;
948 case V4L2_PIX_FMT_YVU420:
949 v4lconvert_nv12_to_yuv420(src, dest, width, height, 1);
950 break;
951 }
952 break;
953
954 /* compressed bayer formats */
955 case V4L2_PIX_FMT_SPCA561:
956 case V4L2_PIX_FMT_SN9C10X:
957 case V4L2_PIX_FMT_PAC207:
958 case V4L2_PIX_FMT_MR97310A:
959 #ifdef HAVE_JPEG
960 case V4L2_PIX_FMT_JL2005BCD:
961 #endif
962 case V4L2_PIX_FMT_SN9C2028:
963 case V4L2_PIX_FMT_SQ905C:
964 case V4L2_PIX_FMT_STV0680: { /* Not compressed but needs some shuffling */
965 unsigned char *tmpbuf;
966 struct v4l2_format tmpfmt = *fmt;
967
968 tmpbuf = v4lconvert_alloc_buffer(width * height,
969 &data->convert_pixfmt_buf, &data->convert_pixfmt_buf_size);
970 if (!tmpbuf)
971 return v4lconvert_oom_error(data);
972
973 switch (src_pix_fmt) {
974 case V4L2_PIX_FMT_SPCA561:
975 v4lconvert_decode_spca561(src, tmpbuf, width, height);
976 tmpfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_SGBRG8;
977 break;
978 case V4L2_PIX_FMT_SN9C10X:
979 v4lconvert_decode_sn9c10x(src, tmpbuf, width, height);
980 tmpfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_SBGGR8;
981 break;
982 case V4L2_PIX_FMT_PAC207:
983 if (v4lconvert_decode_pac207(data, src, src_size, tmpbuf,
984 width, height)) {
985 /* Corrupt frame, better get another one */
986 errno = EAGAIN;
987 return -1;
988 }
989 tmpfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_SBGGR8;
990 break;
991 case V4L2_PIX_FMT_MR97310A:
992 if (v4lconvert_decode_mr97310a(data, src, src_size, tmpbuf,
993 width, height)) {
994 /* Corrupt frame, better get another one */
995 errno = EAGAIN;
996 return -1;
997 }
998 tmpfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_SBGGR8;
999 break;
1000 #ifdef HAVE_JPEG
1001 case V4L2_PIX_FMT_JL2005BCD:
1002 if (v4lconvert_decode_jl2005bcd(data, src, src_size,
1003 tmpbuf,
1004 width, height)) {
1005 /* Corrupt frame, better get another one */
1006 errno = EAGAIN;
1007 return -1;
1008 }
1009 tmpfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_SRGGB8;
1010 break;
1011 #endif
1012 case V4L2_PIX_FMT_SN9C2028:
1013 v4lconvert_decode_sn9c2028(src, tmpbuf, width, height);
1014 tmpfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_SBGGR8;
1015 break;
1016 case V4L2_PIX_FMT_SQ905C:
1017 v4lconvert_decode_sq905c(src, tmpbuf, width, height);
1018 tmpfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_SRGGB8;
1019 break;
1020 case V4L2_PIX_FMT_STV0680:
1021 v4lconvert_decode_stv0680(src, tmpbuf, width, height);
1022 tmpfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_SRGGB8;
1023 break;
1024 }
1025 /* Do processing on the tmp buffer, because doing it on bayer data is
1026 cheaper, and bayer == rgb and our dest_fmt may be yuv */
1027 tmpfmt.fmt.pix.bytesperline = width;
1028 tmpfmt.fmt.pix.sizeimage = width * height;
1029 v4lprocessing_processing(data->processing, tmpbuf, &tmpfmt);
1030 /* Deliberate fall through to raw bayer fmt code! */
1031 src_pix_fmt = tmpfmt.fmt.pix.pixelformat;
1032 src = tmpbuf;
1033 src_size = width * height;
1034 /* fall through */
1035 }
1036
1037 /* Raw bayer formats */
1038 case V4L2_PIX_FMT_SBGGR10P:
1039 case V4L2_PIX_FMT_SGBRG10P:
1040 case V4L2_PIX_FMT_SGRBG10P:
1041 case V4L2_PIX_FMT_SRGGB10P: {
1042 int b10format = 1;
1043
1044 switch (src_pix_fmt) {
1045 case V4L2_PIX_FMT_SBGGR10P:
1046 src_pix_fmt = V4L2_PIX_FMT_SBGGR8;
1047 break;
1048 case V4L2_PIX_FMT_SGBRG10P:
1049 src_pix_fmt = V4L2_PIX_FMT_SGBRG8;
1050 break;
1051 case V4L2_PIX_FMT_SGRBG10P:
1052 src_pix_fmt = V4L2_PIX_FMT_SGRBG8;
1053 break;
1054 case V4L2_PIX_FMT_SRGGB10P:
1055 src_pix_fmt = V4L2_PIX_FMT_SRGGB8;
1056 break;
1057 default:
1058 b10format = 0;
1059 break;
1060 }
1061
1062 if (b10format) {
1063 if (src_size < ((width * height * 10)/8)) {
1064 V4LCONVERT_ERR
1065 ("short raw bayer10 data frame\n");
1066 errno = EPIPE;
1067 result = -1;
1068 break;
1069 }
1070 v4lconvert_bayer10p_to_bayer8(src, src, width, height);
1071 bytesperline = width;
1072 }
1073 }
1074
1075 case V4L2_PIX_FMT_SBGGR10:
1076 case V4L2_PIX_FMT_SGBRG10:
1077 case V4L2_PIX_FMT_SGRBG10:
1078 case V4L2_PIX_FMT_SRGGB10: {
1079 int b10format = 1;
1080
1081 switch (src_pix_fmt) {
1082 case V4L2_PIX_FMT_SBGGR10:
1083 src_pix_fmt = V4L2_PIX_FMT_SBGGR8;
1084 break;
1085 case V4L2_PIX_FMT_SGBRG10:
1086 src_pix_fmt = V4L2_PIX_FMT_SGBRG8;
1087 break;
1088 case V4L2_PIX_FMT_SGRBG10:
1089 src_pix_fmt = V4L2_PIX_FMT_SGRBG8;
1090 break;
1091 case V4L2_PIX_FMT_SRGGB10:
1092 src_pix_fmt = V4L2_PIX_FMT_SRGGB8;
1093 break;
1094 default:
1095 b10format = 0;
1096 break;
1097 }
1098
1099 if (b10format) {
1100 if (src_size < (width * height * 2)) {
1101 V4LCONVERT_ERR
1102 ("short raw bayer10 data frame\n");
1103 errno = EPIPE;
1104 result = -1;
1105 break;
1106 }
1107 v4lconvert_bayer10_to_bayer8(src, src, width, height);
1108 bytesperline = width;
1109 }
1110 }
1111
1112 case V4L2_PIX_FMT_SBGGR16:
1113 case V4L2_PIX_FMT_SGBRG16:
1114 case V4L2_PIX_FMT_SGRBG16:
1115 case V4L2_PIX_FMT_SRGGB16: {
1116 int b16format = 1;
1117
1118 switch (src_pix_fmt) {
1119 case V4L2_PIX_FMT_SBGGR16:
1120 src_pix_fmt = V4L2_PIX_FMT_SBGGR8;
1121 break;
1122 case V4L2_PIX_FMT_SGBRG16:
1123 src_pix_fmt = V4L2_PIX_FMT_SGBRG8;
1124 break;
1125 case V4L2_PIX_FMT_SGRBG16:
1126 src_pix_fmt = V4L2_PIX_FMT_SGRBG8;
1127 break;
1128 case V4L2_PIX_FMT_SRGGB16:
1129 src_pix_fmt = V4L2_PIX_FMT_SRGGB8;
1130 break;
1131 default:
1132 b16format = 0;
1133 break;
1134 }
1135
1136 if (b16format) {
1137 if (src_size < ((width * height * 2))) {
1138 V4LCONVERT_ERR
1139 ("short raw bayer16 data frame\n");
1140 errno = EPIPE;
1141 result = -1;
1142 break;
1143 }
1144 v4lconvert_bayer16_to_bayer8(src, src, width, height);
1145 bytesperline = width;
1146 }
1147 }
1148
1149 /* Fall-through*/
1150 case V4L2_PIX_FMT_SBGGR8:
1151 case V4L2_PIX_FMT_SGBRG8:
1152 case V4L2_PIX_FMT_SGRBG8:
1153 case V4L2_PIX_FMT_SRGGB8:
1154 if (src_size < (width * height)) {
1155 V4LCONVERT_ERR("short raw bayer data frame\n");
1156 errno = EPIPE;
1157 result = -1;
1158 }
1159 switch (dest_pix_fmt) {
1160 case V4L2_PIX_FMT_RGB24:
1161 v4lconvert_bayer_to_rgb24(src, dest, width, height, bytesperline, src_pix_fmt);
1162 break;
1163 case V4L2_PIX_FMT_BGR24:
1164 v4lconvert_bayer_to_bgr24(src, dest, width, height, bytesperline, src_pix_fmt);
1165 break;
1166 case V4L2_PIX_FMT_YUV420:
1167 v4lconvert_bayer_to_yuv420(src, dest, width, height, bytesperline, src_pix_fmt, 0);
1168 break;
1169 case V4L2_PIX_FMT_YVU420:
1170 v4lconvert_bayer_to_yuv420(src, dest, width, height, bytesperline, src_pix_fmt, 1);
1171 break;
1172 }
1173 break;
1174
1175 case V4L2_PIX_FMT_SE401: {
1176 unsigned char *d = NULL;
1177
1178 switch (dest_pix_fmt) {
1179 case V4L2_PIX_FMT_RGB24:
1180 d = dest;
1181 break;
1182 case V4L2_PIX_FMT_BGR24:
1183 case V4L2_PIX_FMT_YUV420:
1184 case V4L2_PIX_FMT_YVU420:
1185 d = v4lconvert_alloc_buffer(width * height * 3,
1186 &data->convert_pixfmt_buf,
1187 &data->convert_pixfmt_buf_size);
1188 if (!d)
1189 return v4lconvert_oom_error(data);
1190
1191 fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_RGB24;
1192 v4lconvert_fixup_fmt(fmt);
1193 break;
1194 default:
1195 V4LCONVERT_ERR("Unknown destination format in conversion\n");
1196 errno = EINVAL;
1197 return -1;
1198 }
1199
1200 result = v4lconvert_se401_to_rgb24(data, src, src_size, d,
1201 width, height);
1202 switch (dest_pix_fmt) {
1203 case V4L2_PIX_FMT_BGR24:
1204 v4lconvert_swap_rgb(d, dest, width, height);
1205 break;
1206 case V4L2_PIX_FMT_YUV420:
1207 v4lconvert_rgb24_to_yuv420(d, dest, fmt, 0, 0, 3);
1208 break;
1209 case V4L2_PIX_FMT_YVU420:
1210 v4lconvert_rgb24_to_yuv420(d, dest, fmt, 0, 1, 3);
1211 break;
1212 }
1213 break;
1214 }
1215
1216 case V4L2_PIX_FMT_Y16:
1217 case V4L2_PIX_FMT_Y16_BE:
1218 if (src_size < (width * height * 2)) {
1219 V4LCONVERT_ERR("short y16 data frame\n");
1220 errno = EPIPE;
1221 result = -1;
1222 }
1223 switch (dest_pix_fmt) {
1224 case V4L2_PIX_FMT_RGB24:
1225 case V4L2_PIX_FMT_BGR24:
1226 v4lconvert_y16_to_rgb24(src, dest, width, height,
1227 src_pix_fmt == V4L2_PIX_FMT_Y16);
1228 break;
1229 case V4L2_PIX_FMT_YUV420:
1230 case V4L2_PIX_FMT_YVU420:
1231 v4lconvert_y16_to_yuv420(src, dest, fmt,
1232 src_pix_fmt == V4L2_PIX_FMT_Y16);
1233 break;
1234 }
1235 break;
1236
1237 case V4L2_PIX_FMT_GREY:
1238 case V4L2_PIX_FMT_Y4:
1239 case V4L2_PIX_FMT_Y6:
1240 if (src_size < (width * height)) {
1241 V4LCONVERT_ERR("short grey data frame\n");
1242 errno = EPIPE;
1243 result = -1;
1244 }
1245 switch (dest_pix_fmt) {
1246 case V4L2_PIX_FMT_RGB24:
1247 case V4L2_PIX_FMT_BGR24:
1248 v4lconvert_grey_to_rgb24(src, dest, width, height);
1249 break;
1250 case V4L2_PIX_FMT_YUV420:
1251 case V4L2_PIX_FMT_YVU420:
1252 v4lconvert_grey_to_yuv420(src, dest, fmt);
1253 break;
1254 }
1255 break;
1256
1257 case V4L2_PIX_FMT_Y10BPACK:
1258 if (src_size < (width * height * 10 / 8)) {
1259 V4LCONVERT_ERR("short y10b data frame\n");
1260 errno = EPIPE;
1261 result = -1;
1262 }
1263 switch (dest_pix_fmt) {
1264 case V4L2_PIX_FMT_RGB24:
1265 case V4L2_PIX_FMT_BGR24:
1266 result = v4lconvert_y10b_to_rgb24(data, src, dest,
1267 width, height);
1268 break;
1269 case V4L2_PIX_FMT_YUV420:
1270 case V4L2_PIX_FMT_YVU420:
1271 result = v4lconvert_y10b_to_yuv420(data, src, dest,
1272 width, height);
1273 break;
1274 }
1275 break;
1276
1277 case V4L2_PIX_FMT_RGB565:
1278 if (src_size < (width * height * 2)) {
1279 V4LCONVERT_ERR("short rgb565 data frame\n");
1280 errno = EPIPE;
1281 result = -1;
1282 }
1283 switch (dest_pix_fmt) {
1284 case V4L2_PIX_FMT_RGB24:
1285 v4lconvert_rgb565_to_rgb24(src, dest, width, height);
1286 break;
1287 case V4L2_PIX_FMT_BGR24:
1288 v4lconvert_rgb565_to_bgr24(src, dest, width, height);
1289 break;
1290 case V4L2_PIX_FMT_YUV420:
1291 v4lconvert_rgb565_to_yuv420(src, dest, fmt, 0);
1292 break;
1293 case V4L2_PIX_FMT_YVU420:
1294 v4lconvert_rgb565_to_yuv420(src, dest, fmt, 1);
1295 break;
1296 }
1297 break;
1298
1299 case V4L2_PIX_FMT_RGB24:
1300 if (src_size < (width * height * 3)) {
1301 V4LCONVERT_ERR("short rgb24 data frame\n");
1302 errno = EPIPE;
1303 result = -1;
1304 }
1305 switch (dest_pix_fmt) {
1306 case V4L2_PIX_FMT_RGB24:
1307 memcpy(dest, src, width * height * 3);
1308 break;
1309 case V4L2_PIX_FMT_BGR24:
1310 v4lconvert_swap_rgb(src, dest, width, height);
1311 break;
1312 case V4L2_PIX_FMT_YUV420:
1313 v4lconvert_rgb24_to_yuv420(src, dest, fmt, 0, 0, 3);
1314 break;
1315 case V4L2_PIX_FMT_YVU420:
1316 v4lconvert_rgb24_to_yuv420(src, dest, fmt, 0, 1, 3);
1317 break;
1318 }
1319 break;
1320
1321 case V4L2_PIX_FMT_BGR24:
1322 if (src_size < (width * height * 3)) {
1323 V4LCONVERT_ERR("short bgr24 data frame\n");
1324 errno = EPIPE;
1325 result = -1;
1326 }
1327 switch (dest_pix_fmt) {
1328 case V4L2_PIX_FMT_RGB24:
1329 v4lconvert_swap_rgb(src, dest, width, height);
1330 break;
1331 case V4L2_PIX_FMT_BGR24:
1332 memcpy(dest, src, width * height * 3);
1333 break;
1334 case V4L2_PIX_FMT_YUV420:
1335 v4lconvert_rgb24_to_yuv420(src, dest, fmt, 1, 0, 3);
1336 break;
1337 case V4L2_PIX_FMT_YVU420:
1338 v4lconvert_rgb24_to_yuv420(src, dest, fmt, 1, 1, 3);
1339 break;
1340 }
1341 break;
1342
1343 case V4L2_PIX_FMT_RGB32:
1344 case V4L2_PIX_FMT_XRGB32:
1345 case V4L2_PIX_FMT_ARGB32:
1346 if (src_size < (width * height * 4)) {
1347 V4LCONVERT_ERR("short rgb32 data frame\n");
1348 errno = EPIPE;
1349 result = -1;
1350 }
1351 src++;
1352 switch (dest_pix_fmt) {
1353 case V4L2_PIX_FMT_RGB24:
1354 v4lconvert_rgb32_to_rgb24(src, dest, width, height, 0);
1355 break;
1356 case V4L2_PIX_FMT_BGR24:
1357 v4lconvert_rgb32_to_rgb24(src, dest, width, height, 1);
1358 break;
1359 case V4L2_PIX_FMT_YUV420:
1360 v4lconvert_rgb24_to_yuv420(src, dest, fmt, 0, 0, 4);
1361 break;
1362 case V4L2_PIX_FMT_YVU420:
1363 v4lconvert_rgb24_to_yuv420(src, dest, fmt, 0, 1, 4);
1364 break;
1365 }
1366 break;
1367
1368 case V4L2_PIX_FMT_BGR32:
1369 case V4L2_PIX_FMT_XBGR32:
1370 case V4L2_PIX_FMT_ABGR32:
1371 if (src_size < (width * height * 4)) {
1372 V4LCONVERT_ERR("short bgr32 data frame\n");
1373 errno = EPIPE;
1374 result = -1;
1375 }
1376 switch (dest_pix_fmt) {
1377 case V4L2_PIX_FMT_RGB24:
1378 v4lconvert_rgb32_to_rgb24(src, dest, width, height, 1);
1379 break;
1380 case V4L2_PIX_FMT_BGR24:
1381 v4lconvert_rgb32_to_rgb24(src, dest, width, height, 0);
1382 break;
1383 case V4L2_PIX_FMT_YUV420:
1384 v4lconvert_rgb24_to_yuv420(src, dest, fmt, 1, 0, 4);
1385 break;
1386 case V4L2_PIX_FMT_YVU420:
1387 v4lconvert_rgb24_to_yuv420(src, dest, fmt, 1, 1, 4);
1388 break;
1389 }
1390 break;
1391
1392 case V4L2_PIX_FMT_YUV420:
1393 if (src_size < (width * height * 3 / 2)) {
1394 V4LCONVERT_ERR("short yuv420 data frame\n");
1395 errno = EPIPE;
1396 result = -1;
1397 }
1398 switch (dest_pix_fmt) {
1399 case V4L2_PIX_FMT_RGB24:
1400 v4lconvert_yuv420_to_rgb24(src, dest, width,
1401 height, 0);
1402 break;
1403 case V4L2_PIX_FMT_BGR24:
1404 v4lconvert_yuv420_to_bgr24(src, dest, width,
1405 height, 0);
1406 break;
1407 case V4L2_PIX_FMT_YUV420:
1408 memcpy(dest, src, width * height * 3 / 2);
1409 break;
1410 case V4L2_PIX_FMT_YVU420:
1411 v4lconvert_swap_uv(src, dest, fmt);
1412 break;
1413 }
1414 break;
1415
1416 case V4L2_PIX_FMT_YVU420:
1417 if (src_size < (width * height * 3 / 2)) {
1418 V4LCONVERT_ERR("short yvu420 data frame\n");
1419 errno = EPIPE;
1420 result = -1;
1421 }
1422 switch (dest_pix_fmt) {
1423 case V4L2_PIX_FMT_RGB24:
1424 v4lconvert_yuv420_to_rgb24(src, dest, width,
1425 height, 1);
1426 break;
1427 case V4L2_PIX_FMT_BGR24:
1428 v4lconvert_yuv420_to_bgr24(src, dest, width,
1429 height, 1);
1430 break;
1431 case V4L2_PIX_FMT_YUV420:
1432 v4lconvert_swap_uv(src, dest, fmt);
1433 break;
1434 case V4L2_PIX_FMT_YVU420:
1435 memcpy(dest, src, width * height * 3 / 2);
1436 break;
1437 }
1438 break;
1439
1440 case V4L2_PIX_FMT_NV16: {
1441 unsigned char *tmpbuf;
1442
1443 tmpbuf = v4lconvert_alloc_buffer(width * height * 2,
1444 &data->convert_pixfmt_buf, &data->convert_pixfmt_buf_size);
1445 if (!tmpbuf)
1446 return v4lconvert_oom_error(data);
1447
1448 v4lconvert_nv16_to_yuyv(src, tmpbuf, width, height);
1449 src_pix_fmt = V4L2_PIX_FMT_YUYV;
1450 src = tmpbuf;
1451 bytesperline = bytesperline * 2;
1452 /* fall through */
1453 }
1454 case V4L2_PIX_FMT_YUYV:
1455 if (src_size < (width * height * 2)) {
1456 V4LCONVERT_ERR("short yuyv data frame\n");
1457 errno = EPIPE;
1458 result = -1;
1459 }
1460 switch (dest_pix_fmt) {
1461 case V4L2_PIX_FMT_RGB24:
1462 v4lconvert_yuyv_to_rgb24(src, dest, width, height, bytesperline);
1463 break;
1464 case V4L2_PIX_FMT_BGR24:
1465 v4lconvert_yuyv_to_bgr24(src, dest, width, height, bytesperline);
1466 break;
1467 case V4L2_PIX_FMT_YUV420:
1468 v4lconvert_yuyv_to_yuv420(src, dest, width, height, bytesperline, 0);
1469 break;
1470 case V4L2_PIX_FMT_YVU420:
1471 v4lconvert_yuyv_to_yuv420(src, dest, width, height, bytesperline, 1);
1472 break;
1473 }
1474 break;
1475
1476 case V4L2_PIX_FMT_NV61: {
1477 unsigned char *tmpbuf;
1478
1479 tmpbuf = v4lconvert_alloc_buffer(width * height * 2,
1480 &data->convert_pixfmt_buf, &data->convert_pixfmt_buf_size);
1481 if (!tmpbuf)
1482 return v4lconvert_oom_error(data);
1483
1484 /* Note NV61 is NV16 with U and V swapped so this becomes yvyu. */
1485 v4lconvert_nv16_to_yuyv(src, tmpbuf, width, height);
1486 src_pix_fmt = V4L2_PIX_FMT_YVYU;
1487 src = tmpbuf;
1488 bytesperline = bytesperline * 2;
1489 /* fall through */
1490 }
1491 case V4L2_PIX_FMT_YVYU:
1492 if (src_size < (width * height * 2)) {
1493 V4LCONVERT_ERR("short yvyu data frame\n");
1494 errno = EPIPE;
1495 result = -1;
1496 }
1497 switch (dest_pix_fmt) {
1498 case V4L2_PIX_FMT_RGB24:
1499 v4lconvert_yvyu_to_rgb24(src, dest, width, height, bytesperline);
1500 break;
1501 case V4L2_PIX_FMT_BGR24:
1502 v4lconvert_yvyu_to_bgr24(src, dest, width, height, bytesperline);
1503 break;
1504 case V4L2_PIX_FMT_YUV420:
1505 /* Note we use yuyv_to_yuv420 not v4lconvert_yvyu_to_yuv420,
1506 with the last argument reversed to make it have as we want */
1507 v4lconvert_yuyv_to_yuv420(src, dest, width, height, bytesperline, 1);
1508 break;
1509 case V4L2_PIX_FMT_YVU420:
1510 v4lconvert_yuyv_to_yuv420(src, dest, width, height, bytesperline, 0);
1511 break;
1512 }
1513 break;
1514
1515 case V4L2_PIX_FMT_UYVY:
1516 if (src_size < (width * height * 2)) {
1517 V4LCONVERT_ERR("short uyvy data frame\n");
1518 errno = EPIPE;
1519 result = -1;
1520 }
1521 switch (dest_pix_fmt) {
1522 case V4L2_PIX_FMT_RGB24:
1523 v4lconvert_uyvy_to_rgb24(src, dest, width, height, bytesperline);
1524 break;
1525 case V4L2_PIX_FMT_BGR24:
1526 v4lconvert_uyvy_to_bgr24(src, dest, width, height, bytesperline);
1527 break;
1528 case V4L2_PIX_FMT_YUV420:
1529 v4lconvert_uyvy_to_yuv420(src, dest, width, height, bytesperline, 0);
1530 break;
1531 case V4L2_PIX_FMT_YVU420:
1532 v4lconvert_uyvy_to_yuv420(src, dest, width, height, bytesperline, 1);
1533 break;
1534 }
1535 break;
1536 case V4L2_PIX_FMT_HSV24:
1537 if (src_size < (width * height * 3)) {
1538 V4LCONVERT_ERR("short hsv24 data frame\n");
1539 errno = EPIPE;
1540 result = -1;
1541 }
1542 switch (dest_pix_fmt) {
1543 case V4L2_PIX_FMT_RGB24:
1544 v4lconvert_hsv_to_rgb24(src, dest, width, height, 0,
1545 24, fmt->fmt.pix.hsv_enc);
1546 break;
1547 case V4L2_PIX_FMT_BGR24:
1548 v4lconvert_hsv_to_rgb24(src, dest, width, height, 1,
1549 24, fmt->fmt.pix.hsv_enc);
1550 break;
1551 case V4L2_PIX_FMT_YUV420:
1552 v4lconvert_hsv_to_rgb24(src, dest, width, height, 0,
1553 24, fmt->fmt.pix.hsv_enc);
1554 v4lconvert_rgb24_to_yuv420(src, dest, fmt, 0, 0, 3);
1555 break;
1556 case V4L2_PIX_FMT_YVU420:
1557 v4lconvert_hsv_to_rgb24(src, dest, width, height, 0,
1558 24, fmt->fmt.pix.hsv_enc);
1559 v4lconvert_rgb24_to_yuv420(src, dest, fmt, 0, 1, 3);
1560 break;
1561 }
1562
1563 break;
1564
1565 case V4L2_PIX_FMT_HSV32:
1566 if (src_size < (width * height * 4)) {
1567 V4LCONVERT_ERR("short hsv32 data frame\n");
1568 errno = EPIPE;
1569 result = -1;
1570 }
1571 switch (dest_pix_fmt) {
1572 case V4L2_PIX_FMT_RGB24:
1573 v4lconvert_hsv_to_rgb24(src, dest, width, height, 0,
1574 32, fmt->fmt.pix.hsv_enc);
1575 break;
1576 case V4L2_PIX_FMT_BGR24:
1577 v4lconvert_hsv_to_rgb24(src, dest, width, height, 1,
1578 32, fmt->fmt.pix.hsv_enc);
1579 break;
1580 case V4L2_PIX_FMT_YUV420:
1581 v4lconvert_hsv_to_rgb24(src, dest, width, height, 0,
1582 32, fmt->fmt.pix.hsv_enc);
1583 v4lconvert_rgb24_to_yuv420(src, dest, fmt, 0, 0, 3);
1584 break;
1585 case V4L2_PIX_FMT_YVU420:
1586 v4lconvert_hsv_to_rgb24(src, dest, width, height, 0,
1587 32, fmt->fmt.pix.hsv_enc);
1588 v4lconvert_rgb24_to_yuv420(src, dest, fmt, 0, 1, 3);
1589 break;
1590 }
1591
1592 break;
1593
1594
1595
1596 default:
1597 V4LCONVERT_ERR("Unknown src format in conversion\n");
1598 errno = EINVAL;
1599 return -1;
1600 }
1601
1602 fmt->fmt.pix.pixelformat = dest_pix_fmt;
1603 v4lconvert_fixup_fmt(fmt);
1604
1605 return result;
1606 }
1607
v4lconvert_convert(struct v4lconvert_data * data,const struct v4l2_format * src_fmt,const struct v4l2_format * dest_fmt,unsigned char * src,int src_size,unsigned char * dest,int dest_size)1608 int v4lconvert_convert(struct v4lconvert_data *data,
1609 const struct v4l2_format *src_fmt, /* in */
1610 const struct v4l2_format *dest_fmt, /* in */
1611 unsigned char *src, int src_size, unsigned char *dest, int dest_size)
1612 {
1613 int res, dest_needed, temp_needed, processing, convert = 0;
1614 int rotate90, vflip, hflip, crop;
1615 unsigned char *convert1_dest = dest;
1616 int convert1_dest_size = dest_size;
1617 unsigned char *convert2_src = src, *convert2_dest = dest;
1618 int convert2_dest_size = dest_size;
1619 unsigned char *rotate90_src = src, *rotate90_dest = dest;
1620 unsigned char *flip_src = src, *flip_dest = dest;
1621 unsigned char *crop_src = src;
1622 struct v4l2_format my_src_fmt = *src_fmt;
1623 struct v4l2_format my_dest_fmt = *dest_fmt;
1624
1625 processing = v4lprocessing_pre_processing(data->processing);
1626 rotate90 = data->control_flags & V4LCONTROL_ROTATED_90_JPEG;
1627 hflip = v4lcontrol_get_ctrl(data->control, V4LCONTROL_HFLIP);
1628 vflip = v4lcontrol_get_ctrl(data->control, V4LCONTROL_VFLIP);
1629 crop = my_dest_fmt.fmt.pix.width != my_src_fmt.fmt.pix.width ||
1630 my_dest_fmt.fmt.pix.height != my_src_fmt.fmt.pix.height;
1631
1632 if (/* If no conversion/processing is needed */
1633 (src_fmt->fmt.pix.pixelformat == dest_fmt->fmt.pix.pixelformat &&
1634 !processing && !rotate90 && !hflip && !vflip && !crop) ||
1635 /* or if we should do processing/rotating/flipping but the app tries to
1636 use the native cam format, we just return an unprocessed frame copy */
1637 !v4lconvert_supported_dst_format(dest_fmt->fmt.pix.pixelformat)) {
1638 int to_copy = MIN(dest_size, src_size);
1639 memcpy(dest, src, to_copy);
1640 return to_copy;
1641 }
1642
1643 /* sanity check, is the dest buffer large enough? */
1644 switch (my_dest_fmt.fmt.pix.pixelformat) {
1645 case V4L2_PIX_FMT_RGB24:
1646 case V4L2_PIX_FMT_BGR24:
1647 dest_needed = my_dest_fmt.fmt.pix.width * my_dest_fmt.fmt.pix.height * 3;
1648 temp_needed = my_src_fmt.fmt.pix.width * my_src_fmt.fmt.pix.height * 3;
1649 break;
1650 case V4L2_PIX_FMT_YUV420:
1651 case V4L2_PIX_FMT_YVU420:
1652 dest_needed =
1653 my_dest_fmt.fmt.pix.width * my_dest_fmt.fmt.pix.height * 3 / 2;
1654 temp_needed =
1655 my_src_fmt.fmt.pix.width * my_src_fmt.fmt.pix.height * 3 / 2;
1656 break;
1657 default:
1658 V4LCONVERT_ERR("Unknown dest format in conversion\n");
1659 errno = EINVAL;
1660 return -1;
1661 }
1662
1663 if (dest_size < dest_needed) {
1664 V4LCONVERT_ERR("destination buffer too small (%d < %d)\n",
1665 dest_size, dest_needed);
1666 errno = EFAULT;
1667 return -1;
1668 }
1669
1670
1671 /* Sometimes we need foo -> rgb -> bar as video processing (whitebalance,
1672 etc.) can only be done on rgb data */
1673 if (processing && v4lconvert_processing_needs_double_conversion(
1674 my_src_fmt.fmt.pix.pixelformat,
1675 my_dest_fmt.fmt.pix.pixelformat))
1676 convert = 2;
1677 else if (my_dest_fmt.fmt.pix.pixelformat !=
1678 my_src_fmt.fmt.pix.pixelformat ||
1679 /* Special case if we do not need to do conversion, but we
1680 are not doing any other step involving copying either,
1681 force going through convert_pixfmt to copy the data from
1682 source to dest */
1683 (!rotate90 && !hflip && !vflip && !crop))
1684 convert = 1;
1685
1686 /* convert_pixfmt (only if convert == 2) -> processing -> convert_pixfmt ->
1687 rotate -> flip -> crop, all steps are optional */
1688 if (convert == 2) {
1689 convert1_dest = v4lconvert_alloc_buffer(
1690 my_src_fmt.fmt.pix.width * my_src_fmt.fmt.pix.height * 3,
1691 &data->convert1_buf, &data->convert1_buf_size);
1692 if (!convert1_dest)
1693 return v4lconvert_oom_error(data);
1694
1695 convert1_dest_size =
1696 my_src_fmt.fmt.pix.width * my_src_fmt.fmt.pix.height * 3;
1697 convert2_src = convert1_dest;
1698 }
1699
1700 if (convert && (rotate90 || hflip || vflip || crop)) {
1701 convert2_dest = v4lconvert_alloc_buffer(temp_needed,
1702 &data->convert2_buf, &data->convert2_buf_size);
1703 if (!convert2_dest)
1704 return v4lconvert_oom_error(data);
1705
1706 convert2_dest_size = temp_needed;
1707 rotate90_src = flip_src = crop_src = convert2_dest;
1708 }
1709
1710 if (rotate90 && (hflip || vflip || crop)) {
1711 rotate90_dest = v4lconvert_alloc_buffer(temp_needed,
1712 &data->rotate90_buf, &data->rotate90_buf_size);
1713 if (!rotate90_dest)
1714 return v4lconvert_oom_error(data);
1715
1716 flip_src = crop_src = rotate90_dest;
1717 }
1718
1719 if ((vflip || hflip) && crop) {
1720 flip_dest = v4lconvert_alloc_buffer(temp_needed, &data->flip_buf,
1721 &data->flip_buf_size);
1722 if (!flip_dest)
1723 return v4lconvert_oom_error(data);
1724
1725 crop_src = flip_dest;
1726 }
1727
1728 /* Done setting sources / dest and allocating intermediate buffers,
1729 real conversion / processing / ... starts here. */
1730 if (convert == 2) {
1731 res = v4lconvert_convert_pixfmt(data, src, src_size,
1732 convert1_dest, convert1_dest_size,
1733 &my_src_fmt,
1734 V4L2_PIX_FMT_RGB24);
1735 if (res)
1736 return res;
1737
1738 src_size = my_src_fmt.fmt.pix.sizeimage;
1739 }
1740
1741 if (processing)
1742 v4lprocessing_processing(data->processing, convert2_src, &my_src_fmt);
1743
1744 if (convert) {
1745 res = v4lconvert_convert_pixfmt(data, convert2_src, src_size,
1746 convert2_dest, convert2_dest_size,
1747 &my_src_fmt,
1748 my_dest_fmt.fmt.pix.pixelformat);
1749 if (res)
1750 return res;
1751
1752 src_size = my_src_fmt.fmt.pix.sizeimage;
1753
1754 /* We call processing here again in case the source format was not
1755 rgb, but the dest is. v4lprocessing checks it self it only actually
1756 does the processing once per frame. */
1757 if (processing)
1758 v4lprocessing_processing(data->processing, convert2_dest, &my_src_fmt);
1759 }
1760
1761 if (rotate90)
1762 v4lconvert_rotate90(rotate90_src, rotate90_dest, &my_src_fmt);
1763
1764 if (hflip || vflip)
1765 v4lconvert_flip(flip_src, flip_dest, &my_src_fmt, hflip, vflip);
1766
1767 if (crop)
1768 v4lconvert_crop(crop_src, dest, &my_src_fmt, &my_dest_fmt);
1769
1770 return dest_needed;
1771 }
1772
v4lconvert_get_error_message(struct v4lconvert_data * data)1773 const char *v4lconvert_get_error_message(struct v4lconvert_data *data)
1774 {
1775 return data->error_msg;
1776 }
1777
v4lconvert_get_framesizes(struct v4lconvert_data * data,unsigned int pixelformat,int index)1778 static void v4lconvert_get_framesizes(struct v4lconvert_data *data,
1779 unsigned int pixelformat, int index)
1780 {
1781 int i, j, match;
1782 struct v4l2_frmsizeenum frmsize = { .pixel_format = pixelformat };
1783
1784 for (i = 0; ; i++) {
1785 frmsize.index = i;
1786 if (data->dev_ops->ioctl(data->dev_ops_priv, data->fd,
1787 VIDIOC_ENUM_FRAMESIZES, &frmsize))
1788 break;
1789
1790 /* We got a framesize, check we don't have the same one already */
1791 match = 0;
1792 for (j = 0; j < data->no_framesizes; j++) {
1793 if (frmsize.type != data->framesizes[j].type)
1794 continue;
1795
1796 switch (frmsize.type) {
1797 case V4L2_FRMSIZE_TYPE_DISCRETE:
1798 if (!memcmp(&frmsize.discrete, &data->framesizes[j].discrete,
1799 sizeof(frmsize.discrete)))
1800 match = 1;
1801 break;
1802 case V4L2_FRMSIZE_TYPE_CONTINUOUS:
1803 case V4L2_FRMSIZE_TYPE_STEPWISE:
1804 if (!memcmp(&frmsize.stepwise, &data->framesizes[j].stepwise,
1805 sizeof(frmsize.stepwise)))
1806 match = 1;
1807 break;
1808 }
1809 if (match)
1810 break;
1811 }
1812 /* Add this framesize if it is not already in our list */
1813 if (!match) {
1814 if (data->no_framesizes == V4LCONVERT_MAX_FRAMESIZES) {
1815 fprintf(stderr, "libv4lconvert: warning more framesizes than I can handle!\n");
1816 return;
1817 }
1818 data->framesizes[data->no_framesizes].type = frmsize.type;
1819 data->framesize_supported_src_formats[data->no_framesizes] = 1ULL << index;
1820
1821 switch (frmsize.type) {
1822 case V4L2_FRMSIZE_TYPE_DISCRETE:
1823 data->framesizes[data->no_framesizes].discrete = frmsize.discrete;
1824 break;
1825 case V4L2_FRMSIZE_TYPE_CONTINUOUS:
1826 case V4L2_FRMSIZE_TYPE_STEPWISE:
1827 data->framesizes[data->no_framesizes].stepwise = frmsize.stepwise;
1828 break;
1829 }
1830 data->no_framesizes++;
1831 } else {
1832 data->framesize_supported_src_formats[j] |= 1ULL << index;
1833 }
1834 }
1835 }
1836
v4lconvert_enum_framesizes(struct v4lconvert_data * data,struct v4l2_frmsizeenum * frmsize)1837 int v4lconvert_enum_framesizes(struct v4lconvert_data *data,
1838 struct v4l2_frmsizeenum *frmsize)
1839 {
1840 if (!v4lconvert_supported_dst_format(frmsize->pixel_format)) {
1841 if (v4lconvert_supported_dst_fmt_only(data)) {
1842 errno = EINVAL;
1843 return -1;
1844 }
1845 return data->dev_ops->ioctl(data->dev_ops_priv, data->fd,
1846 VIDIOC_ENUM_FRAMESIZES, frmsize);
1847 }
1848
1849 if (frmsize->index >= data->no_framesizes) {
1850 errno = EINVAL;
1851 return -1;
1852 }
1853
1854 frmsize->type = data->framesizes[frmsize->index].type;
1855 memset(frmsize->reserved, 0, sizeof(frmsize->reserved));
1856 switch (frmsize->type) {
1857 case V4L2_FRMSIZE_TYPE_DISCRETE:
1858 frmsize->discrete = data->framesizes[frmsize->index].discrete;
1859 /* Apply the same rounding algorithm as v4lconvert_try_format */
1860 frmsize->discrete.width &= ~7;
1861 frmsize->discrete.height &= ~1;
1862 break;
1863 case V4L2_FRMSIZE_TYPE_CONTINUOUS:
1864 case V4L2_FRMSIZE_TYPE_STEPWISE:
1865 frmsize->stepwise = data->framesizes[frmsize->index].stepwise;
1866 break;
1867 }
1868
1869 return 0;
1870 }
1871
v4lconvert_enum_frameintervals(struct v4lconvert_data * data,struct v4l2_frmivalenum * frmival)1872 int v4lconvert_enum_frameintervals(struct v4lconvert_data *data,
1873 struct v4l2_frmivalenum *frmival)
1874 {
1875 int res;
1876 struct v4l2_format src_fmt, dest_fmt;
1877
1878 if (!v4lconvert_supported_dst_format(frmival->pixel_format)) {
1879 if (v4lconvert_supported_dst_fmt_only(data)) {
1880 errno = EINVAL;
1881 return -1;
1882 }
1883 res = data->dev_ops->ioctl(data->dev_ops_priv, data->fd,
1884 VIDIOC_ENUM_FRAMEINTERVALS, frmival);
1885 if (res)
1886 V4LCONVERT_ERR("%s\n", strerror(errno));
1887 return res;
1888 }
1889
1890 /* Check which format we will be using to convert to frmival->pixel_format */
1891 memset(&dest_fmt, 0, sizeof(dest_fmt));
1892 dest_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1893 dest_fmt.fmt.pix.pixelformat = frmival->pixel_format;
1894 dest_fmt.fmt.pix.width = frmival->width;
1895 dest_fmt.fmt.pix.height = frmival->height;
1896 res = v4lconvert_try_format(data, &dest_fmt, &src_fmt);
1897 if (res) {
1898 V4LCONVERT_ERR("trying format: %s\n", strerror(errno));
1899 return res;
1900 }
1901
1902 /* Check the requested format is supported exactly as requested */
1903 if (dest_fmt.fmt.pix.pixelformat != frmival->pixel_format ||
1904 dest_fmt.fmt.pix.width != frmival->width ||
1905 dest_fmt.fmt.pix.height != frmival->height) {
1906 int frmival_pixformat = frmival->pixel_format;
1907 int dest_pixformat = dest_fmt.fmt.pix.pixelformat;
1908
1909 V4LCONVERT_ERR("Could not find matching framesize for: %c%c%c%c %dx%d "
1910 "closest match: %c%c%c%c %dx%d\n",
1911 frmival_pixformat & 0xff,
1912 (frmival_pixformat >> 8) & 0xff,
1913 (frmival_pixformat >> 16) & 0xff,
1914 frmival_pixformat >> 24,
1915 frmival->width, frmival->height,
1916 dest_pixformat & 0xff,
1917 (dest_pixformat >> 8) & 0xff,
1918 (dest_pixformat >> 16) & 0xff,
1919 dest_pixformat >> 24,
1920 dest_fmt.fmt.pix.width , dest_fmt.fmt.pix.height);
1921 errno = EINVAL;
1922 return -1;
1923 }
1924
1925 /* Enumerate the frameintervals of the source format we will be using */
1926 frmival->pixel_format = src_fmt.fmt.pix.pixelformat;
1927 frmival->width = src_fmt.fmt.pix.width;
1928 frmival->height = src_fmt.fmt.pix.height;
1929 res = data->dev_ops->ioctl(data->dev_ops_priv, data->fd,
1930 VIDIOC_ENUM_FRAMEINTERVALS, frmival);
1931 if (res) {
1932 int dest_pixfmt = dest_fmt.fmt.pix.pixelformat;
1933 int src_pixfmt = src_fmt.fmt.pix.pixelformat;
1934
1935 V4LCONVERT_ERR("Could not enum frameival index: %d for: %c%c%c%c %dx%d "
1936 "using src: %c%c%c%c %dx%d, error: %s\n",
1937 frmival->index,
1938 dest_pixfmt & 0xff,
1939 (dest_pixfmt >> 8) & 0xff,
1940 (dest_pixfmt >> 16) & 0xff,
1941 dest_pixfmt >> 24,
1942 dest_fmt.fmt.pix.width , dest_fmt.fmt.pix.height,
1943 src_pixfmt & 0xff,
1944 (src_pixfmt >> 8) & 0xff,
1945 (src_pixfmt >> 16) & 0xff,
1946 src_pixfmt >> 24,
1947 src_fmt.fmt.pix.width, src_fmt.fmt.pix.height, strerror(errno));
1948 }
1949
1950 /* Restore the requested format in the frmival struct */
1951 frmival->pixel_format = dest_fmt.fmt.pix.pixelformat;
1952 frmival->width = dest_fmt.fmt.pix.width;
1953 frmival->height = dest_fmt.fmt.pix.height;
1954
1955 return res;
1956 }
1957
v4lconvert_vidioc_queryctrl(struct v4lconvert_data * data,void * arg)1958 int v4lconvert_vidioc_queryctrl(struct v4lconvert_data *data, void *arg)
1959 {
1960 return v4lcontrol_vidioc_queryctrl(data->control, arg);
1961 }
1962
v4lconvert_vidioc_g_ctrl(struct v4lconvert_data * data,void * arg)1963 int v4lconvert_vidioc_g_ctrl(struct v4lconvert_data *data, void *arg)
1964 {
1965 return v4lcontrol_vidioc_g_ctrl(data->control, arg);
1966 }
1967
v4lconvert_vidioc_s_ctrl(struct v4lconvert_data * data,void * arg)1968 int v4lconvert_vidioc_s_ctrl(struct v4lconvert_data *data, void *arg)
1969 {
1970 return v4lcontrol_vidioc_s_ctrl(data->control, arg);
1971 }
1972
v4lconvert_vidioc_g_ext_ctrls(struct v4lconvert_data * data,void * arg)1973 int v4lconvert_vidioc_g_ext_ctrls(struct v4lconvert_data *data, void *arg)
1974 {
1975 return v4lcontrol_vidioc_g_ext_ctrls(data->control, arg);
1976 }
1977
v4lconvert_vidioc_try_ext_ctrls(struct v4lconvert_data * data,void * arg)1978 int v4lconvert_vidioc_try_ext_ctrls(struct v4lconvert_data *data, void *arg)
1979 {
1980 return v4lcontrol_vidioc_try_ext_ctrls(data->control, arg);
1981 }
1982
v4lconvert_vidioc_s_ext_ctrls(struct v4lconvert_data * data,void * arg)1983 int v4lconvert_vidioc_s_ext_ctrls(struct v4lconvert_data *data, void *arg)
1984 {
1985 return v4lcontrol_vidioc_s_ext_ctrls(data->control, arg);
1986 }
1987
v4lconvert_get_fps(struct v4lconvert_data * data)1988 int v4lconvert_get_fps(struct v4lconvert_data *data)
1989 {
1990 return data->fps;
1991 }
1992
v4lconvert_set_fps(struct v4lconvert_data * data,int fps)1993 void v4lconvert_set_fps(struct v4lconvert_data *data, int fps)
1994 {
1995 data->fps = fps;
1996 }
1997