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