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