1 /* Aravis - Digital camera library
2  *
3  * Copyright © 2009-2010 Emmanuel Pacaud
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General
16  * Public License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  *
20  * Author: Emmanuel Pacaud <emmanuel@gnome.org>
21  */
22 
23 #include <arvmisc.h>
24 #include <arvdebug.h>
25 #include <string.h>
26 #include <math.h>
27 #include <stdio.h>
28 #include <zlib.h>
29 
30 /**
31  * SECTION: arvstatistic
32  * @short_description: An histogram tool
33  */
34 
35 typedef struct _ArvHistogram ArvHistogram;
36 
37 struct _ArvHistogram {
38 	char *		name;
39 
40 	guint64		and_more;
41 	guint64	 	and_less;
42 	guint64	 	last_seen_worst;
43 	int 	      	worst;
44 	int 	        best;
45 
46 	guint64 *	bins;
47 };
48 
49 struct _ArvStatistic {
50 	guint n_histograms;
51 	guint n_bins;
52 	guint bin_step;
53 	int offset;
54 
55 	guint64 counter;
56 
57 	ArvHistogram *histograms;
58 };
59 
60 static void
_arv_statistic_free(ArvStatistic * statistic)61 _arv_statistic_free (ArvStatistic *statistic)
62 {
63 	guint j;
64 
65 	if (statistic == NULL)
66 		return;
67 
68 	if (statistic->histograms != NULL) {
69 		for (j = 0; j < statistic->n_histograms && statistic->histograms[j].bins != NULL; j++) {
70 			if (statistic->histograms[j].name != NULL)
71 				g_free (statistic->histograms[j].name);
72 			g_free (statistic->histograms[j].bins);
73 		}
74 		g_free (statistic->histograms);
75 	}
76 
77 	g_free (statistic);
78 }
79 
80 /**
81  * arv_statistic_new: (skip)
82  * @n_histograms: number of histograms
83  * @n_bins: number of bins for each histogram
84  * @bin_step: bin step
85  * @offset: offset of the first bin
86  * Return value: a new #ArvStatistic structure
87  */
88 
89 ArvStatistic *
arv_statistic_new(unsigned int n_histograms,unsigned n_bins,unsigned int bin_step,int offset)90 arv_statistic_new (unsigned int n_histograms, unsigned n_bins, unsigned int bin_step, int offset)
91 {
92 	ArvStatistic *statistic;
93 	unsigned int i;
94 
95 	g_return_val_if_fail (n_histograms > 0, NULL);
96 	g_return_val_if_fail (n_bins > 0, NULL);
97 	g_return_val_if_fail (bin_step > 0, NULL);
98 
99 	statistic = g_new0 (ArvStatistic, 1);
100 
101 	statistic->n_histograms = n_histograms;
102 	statistic->n_bins = n_bins;
103 	statistic->bin_step = bin_step;
104 	statistic->offset = offset;
105 
106 	statistic->histograms = g_new (ArvHistogram, n_histograms);
107 
108 	for (i = 0; i < statistic->n_histograms; i++) {
109 		statistic->histograms[i].name = NULL;
110 		statistic->histograms[i].bins = g_new (guint64, statistic->n_bins);
111 	}
112 
113 	arv_statistic_reset (statistic);
114 
115 	return statistic;
116 }
117 
118 void
arv_statistic_free(ArvStatistic * statistic)119 arv_statistic_free (ArvStatistic *statistic)
120 {
121 	g_return_if_fail (statistic != NULL);
122 
123 	_arv_statistic_free (statistic);
124 }
125 
126 void
arv_statistic_reset(ArvStatistic * statistic)127 arv_statistic_reset (ArvStatistic *statistic)
128 {
129 	ArvHistogram *histogram;
130 	int i, j;
131 
132 	g_return_if_fail (statistic != NULL);
133 
134 	statistic->counter = 0;
135 
136 	for (j = 0; j < statistic->n_histograms; j++) {
137 		histogram = &statistic->histograms[j];
138 
139 		histogram->last_seen_worst = 0;
140 		histogram->best = 0x7fffffff;
141 		histogram->worst = 0x80000000;
142 		histogram->and_more = histogram->and_less = 0;
143 		for (i = 0; i < statistic->n_bins; i++)
144 			histogram->bins[i] = 0;
145 	}
146 }
147 
148 void
arv_statistic_set_name(ArvStatistic * statistic,unsigned int histogram_id,char const * name)149 arv_statistic_set_name (ArvStatistic *statistic, unsigned int histogram_id, char const *name)
150 {
151 	ArvHistogram *histogram;
152 	size_t length;
153 
154 	g_return_if_fail (statistic != NULL);
155 	g_return_if_fail (histogram_id < statistic->n_histograms);
156 
157 	histogram = &statistic->histograms[histogram_id];
158 
159 	if (histogram->name != NULL) {
160 		g_free (histogram->name);
161 		histogram->name = NULL;
162 	}
163 
164 	if (name == NULL)
165 		return;
166 
167 	length = strlen (name);
168 	if (length < 1)
169 		return;
170 
171 	histogram->name = g_malloc (length + 1);
172 	if (histogram->name == NULL)
173 		return;
174 
175 	memcpy (histogram->name, name, length + 1);
176 }
177 
178 gboolean
arv_statistic_fill(ArvStatistic * statistic,guint histogram_id,int value,guint64 counter)179 arv_statistic_fill (ArvStatistic *statistic, guint histogram_id, int value, guint64 counter)
180 {
181 	ArvHistogram *histogram;
182 	unsigned int class;
183 
184 	if (statistic == NULL)
185 		return FALSE;
186 	if (histogram_id >= statistic->n_histograms)
187 		return FALSE;
188 
189 	statistic->counter = counter;
190 
191 	histogram = &statistic->histograms[histogram_id];
192 
193 	if (histogram->best > value)
194 		histogram->best = value;
195 
196 	if (histogram->worst < value) {
197 		histogram->worst = value;
198 		histogram->last_seen_worst = counter;
199 	}
200 
201 	class = (value - statistic->offset) / statistic->bin_step;
202 
203 	if (value < statistic->offset)
204 		histogram->and_less++;
205 	else if (class >= statistic->n_bins)
206 		histogram->and_more++;
207 	else
208 		histogram->bins[class]++;
209 
210 	return TRUE;
211 }
212 
213 char *
arv_statistic_to_string(const ArvStatistic * statistic)214 arv_statistic_to_string (const ArvStatistic *statistic)
215 {
216 	int i, j, bin_max;
217 	gboolean max_found = FALSE;
218 	GString *string;
219 	char *str;
220 
221 	g_return_val_if_fail (statistic != NULL, NULL);
222 
223 	string = g_string_new ("");
224 
225 	bin_max = 0;
226 	for (i = statistic->n_bins - 1; i > 0 && !max_found; i--) {
227 		for (j = 0; j < statistic->n_histograms && !max_found; j++) {
228 			if (statistic->histograms[j].bins[i] != 0) {
229 				bin_max = i;
230 				max_found = TRUE;
231 			}
232 		}
233 	}
234 
235 	if (bin_max >= statistic->n_bins)
236 		bin_max = statistic->n_bins - 1;
237 
238 	for (j = 0; j < statistic->n_histograms; j++) {
239 		if (j == 0)
240 			g_string_append (string, "  bins  ");
241 		g_string_append_printf (string, ";%8.8s",
242 					statistic->histograms[j].name != NULL ?
243 					statistic->histograms[j].name :
244 					"  ----  ");
245 	}
246 	g_string_append (string, "\n");
247 
248 	for (i = 0; i <= bin_max; i++) {
249 		for (j = 0; j < statistic->n_histograms; j++) {
250 			if (j == 0)
251 				g_string_append_printf (string, "%8d", i * statistic->bin_step + statistic->offset);
252 			g_string_append_printf (string, ";%8Lu", (unsigned long long) statistic->histograms[j].bins[i]);
253 		}
254 		g_string_append (string, "\n");
255 	}
256 
257 	g_string_append (string, "-------------\n");
258 
259 	for (j = 0; j < statistic->n_histograms; j++) {
260 		if (j == 0)
261 			g_string_append_printf (string, ">=%6d", i * statistic->bin_step + statistic->offset);
262 		g_string_append_printf (string, ";%8Lu", (unsigned long long) statistic->histograms[j].and_more);
263 	}
264 	g_string_append (string, "\n");
265 
266 	for (j = 0; j < statistic->n_histograms; j++) {
267 		if (j == 0)
268 			g_string_append_printf (string, "< %6d", statistic->offset);
269 		g_string_append_printf (string, ";%8Lu", (unsigned long long) statistic->histograms[j].and_less);
270 	}
271 	g_string_append (string, "\n");
272 
273 	for (j = 0; j < statistic->n_histograms; j++) {
274 		if (j == 0)
275 			g_string_append (string, "min     ");
276 		if (statistic->histograms[j].best != 0x7fffffff)
277 			g_string_append_printf (string, ";%8d", statistic->histograms[j].best);
278 		else
279 			g_string_append_printf (string, ";%8s", "n/a");
280 	}
281 	g_string_append (string, "\n");
282 
283 	for (j = 0; j < statistic->n_histograms; j++) {
284 		if (j == 0)
285 			g_string_append (string, "max     ");
286 		if (statistic->histograms[j].worst != 0x80000000)
287 			g_string_append_printf (string, ";%8d", statistic->histograms[j].worst);
288 		else
289 			g_string_append_printf (string, ";%8s", "n/a");
290 	}
291 	g_string_append (string, "\n");
292 
293 	for (j = 0; j < statistic->n_histograms; j++) {
294 		if (j == 0)
295 			g_string_append (string, "last max\nat:     ");
296 		g_string_append_printf (string, ";%8Lu", (unsigned long long) statistic->histograms[j].last_seen_worst);
297 	}
298 	g_string_append (string, "\n");
299 
300 	g_string_append_printf (string, "Counter = %8Lu", (unsigned long long) statistic->counter);
301 
302 	str = string->str;
303 	g_string_free (string, FALSE);
304 
305 	return str;
306 }
307 
308 /**
309  * SECTION: arvvalue
310  * @short_description: An int64/double value storage
311  */
312 
313 ArvValue *
arv_value_new_double(double v_double)314 arv_value_new_double (double v_double)
315 {
316 	ArvValue *value = g_new (ArvValue, 1);
317 	value->type = G_TYPE_DOUBLE;
318 	value->data.v_double = v_double;
319 
320 	return value;
321 }
322 
323 ArvValue *
arv_value_new_int64(double v_int64)324 arv_value_new_int64 (double v_int64)
325 {
326 	ArvValue *value = g_new (ArvValue, 1);
327 	value->type = G_TYPE_INT64;
328 	value->data.v_int64 = v_int64;
329 
330 	return value;
331 }
332 
333 void
arv_value_free(ArvValue * value)334 arv_value_free (ArvValue *value)
335 {
336 	g_free (value);
337 }
338 
339 void
arv_value_copy(ArvValue * to,const ArvValue * from)340 arv_value_copy (ArvValue *to, const ArvValue *from)
341 {
342 	*to = *from;
343 }
344 
345 ArvValue *
arv_value_duplicate(const ArvValue * from)346 arv_value_duplicate (const ArvValue *from)
347 {
348 	ArvValue *value = g_new (ArvValue, 1);
349 
350 	if (from == NULL)
351 		return NULL;
352 
353 	*value = *from;
354 
355 	return value;
356 }
357 
358 GType
arv_value_get_type(void)359 arv_value_get_type (void)
360 {
361 	GType type_id = 0;
362 
363 	if (type_id == 0)
364 		type_id = g_boxed_type_register_static ("ArvValue",
365 							(GBoxedCopyFunc) arv_value_duplicate,
366 							(GBoxedFreeFunc) arv_value_free);
367 
368 	return type_id;
369 }
370 
371 void
arv_value_set_int64(ArvValue * value,gint64 v_int64)372 arv_value_set_int64 (ArvValue *value, gint64 v_int64)
373 {
374 	value->type = G_TYPE_INT64;
375 	value->data.v_int64 = v_int64;
376 }
377 
378 void
arv_value_set_double(ArvValue * value,double v_double)379 arv_value_set_double (ArvValue *value, double v_double)
380 {
381 	value->type = G_TYPE_DOUBLE;
382 	value->data.v_double = v_double;
383 }
384 
385 gint64
arv_value_get_int64(ArvValue * value)386 arv_value_get_int64 (ArvValue *value)
387 {
388 	if (value->type == G_TYPE_INT64)
389 		return value->data.v_int64;
390 	else
391 		return (gint64) value->data.v_double;
392 }
393 
394 double
arv_value_get_double(ArvValue * value)395 arv_value_get_double (ArvValue *value)
396 {
397 	if (value->type == G_TYPE_INT64)
398 		return (double) value->data.v_int64;
399 	else
400 		return value->data.v_double;
401 }
402 
403 gboolean
arv_value_holds_int64(ArvValue * value)404 arv_value_holds_int64 (ArvValue *value)
405 {
406 	return value->type == G_TYPE_INT64;
407 }
408 
409 double
arv_value_holds_double(ArvValue * value)410 arv_value_holds_double (ArvValue *value)
411 {
412 	return value->type == G_TYPE_DOUBLE;
413 }
414 
415 void
arv_copy_memory_with_endianess(void * to,size_t to_size,guint to_endianess,void * from,size_t from_size,guint from_endianess)416 arv_copy_memory_with_endianess (void *to, size_t to_size, guint to_endianess,
417 				void *from, size_t from_size, guint from_endianess)
418 {
419 	char *to_ptr;
420 	char *from_ptr;
421 	int i;
422 
423 	g_return_if_fail (to != NULL);
424 	g_return_if_fail (from != NULL);
425 
426 	if (to_endianess == G_LITTLE_ENDIAN &&
427 	    from_endianess == G_BIG_ENDIAN) {
428 		to_ptr = to;
429 		from_ptr = ((char *) from) + from_size - 1;
430 		if (to_size <= from_size) {
431 			for (i = 0; i < to_size; i++, to_ptr++, from_ptr--)
432 				*to_ptr = *from_ptr;
433 		} else {
434 			for (i = 0; i < from_size; i++, to_ptr++, from_ptr--)
435 				*to_ptr = *from_ptr;
436 			memset (((char *) to) + from_size, 0, to_size - from_size);
437 		}
438 	} else if (to_endianess == G_BIG_ENDIAN &&
439 		   from_endianess == G_LITTLE_ENDIAN) {
440 		to_ptr = ((char *) to) + to_size - 1;
441 		from_ptr = from;
442 		if (to_size <= from_size) {
443 			for (i = 0; i < to_size; i++, to_ptr--, from_ptr++)
444 				*to_ptr = *from_ptr;
445 		} else {
446 			for (i = 0; i < from_size; i++, to_ptr--, from_ptr++)
447 				*to_ptr = *from_ptr;
448 			memset (to, 0, to_size - from_size);
449 		}
450 	} else if (to_endianess == G_LITTLE_ENDIAN &&
451 		   from_endianess == G_LITTLE_ENDIAN) {
452 		if (to_size <= from_size)
453 			memcpy (to, from, to_size);
454 		else {
455 			memcpy (to, from, from_size);
456 			memset (((char *) to) + from_size, 0, to_size - from_size);
457 		}
458 	} else if (to_endianess == G_BIG_ENDIAN &&
459 		   from_endianess == G_BIG_ENDIAN) {
460 		if (to_size <= from_size)
461 			memcpy (to, ((char *) from) + from_size - to_size, to_size);
462 		else {
463 			memcpy (((char *) to) + to_size - from_size, from, from_size);
464 			memset (to, 0, to_size - from_size);
465 		}
466 	} else
467 		g_assert_not_reached ();
468 }
469 
470 #define ARV_DECOMPRESS_CHUNK 16384
471 
472 /**
473  * arv_decompress:
474  * @input_buffer: compressed data
475  * @input_buffer: size of compressed data
476  * @output_size: (out): placeholder for inflated data
477  * Return value: (transfer full): a newly allocated buffer
478  **/
479 
480 void *
arv_decompress(void * input_buffer,size_t input_size,size_t * output_size)481 arv_decompress (void *input_buffer, size_t input_size, size_t *output_size)
482 {
483 	z_stream stream;
484 	GByteArray *output;
485 	guchar z_stream_output[ARV_DECOMPRESS_CHUNK];
486 	unsigned have;
487 	int result;
488 
489 	g_return_val_if_fail (input_buffer != NULL, NULL);
490 	g_return_val_if_fail (input_size > 0, NULL);
491 
492 	/* allocate inflate state */
493 	stream.zalloc = Z_NULL;
494 	stream.zfree = Z_NULL;
495 	stream.opaque = Z_NULL;
496 	stream.avail_in = 0;
497 	stream.next_in = Z_NULL;
498 	stream.data_type = Z_UNKNOWN;
499 
500 	g_return_val_if_fail (inflateInit2(&stream, -MAX_WBITS) == Z_OK, NULL);
501 
502 	output = g_byte_array_new ();
503 
504 	/* decompress until deflate stream ends or end of file */
505 	do {
506 		stream.avail_in = MIN (input_size, ARV_DECOMPRESS_CHUNK);
507 		stream.next_in = input_buffer;
508 
509 		arv_debug_misc ("[Decompress] Input ptr = 0x%x - Chunk size = %d - %c",
510 				stream.next_in, stream.avail_in, *stream.next_in);
511 
512 		input_size -= stream.avail_in;
513 		input_buffer = ((char *) input_buffer) + stream.avail_in;
514 
515 		/* run inflate() on input until output buffer not full */
516 		do {
517 			stream.avail_out = ARV_DECOMPRESS_CHUNK;
518 			stream.next_out = z_stream_output;
519 			result = inflate(&stream, Z_NO_FLUSH);
520 			if (result == Z_STREAM_ERROR) {
521 				arv_warning_misc ("[Decompress] Z_STREAM_ERROR");
522 				goto CLEANUP;
523 			}
524 
525 			switch (result) {
526 				case Z_NEED_DICT:
527 					arv_warning_misc ("[Decompress] Z_NEED_DICT");
528 					goto CLEANUP;
529 				case Z_DATA_ERROR:
530 					arv_warning_misc ("[Decompress] Z_DATA_ERROR");
531 					goto CLEANUP;
532 				case Z_MEM_ERROR:
533 					arv_warning_misc ("[Decompress] Z_MEM_ERROR");
534 					goto CLEANUP;
535 			}
536 
537 			have = ARV_DECOMPRESS_CHUNK - stream.avail_out;
538 			g_byte_array_append (output, z_stream_output, have);
539 		} while (stream.avail_out == 0);
540 
541 		/* done when inflate() says it's done */
542 	} while (input_size > 0 && result != Z_STREAM_END);
543 
544 	/* clean up and return */
545 	inflateEnd(&stream);
546 
547 	if (result != Z_STREAM_END) {
548 		arv_warning_misc ("[Decompress] !Z_STREAM_END");
549 		g_byte_array_free (output, TRUE);
550 		if (output_size != NULL)
551 			*output_size = 0;
552 		return NULL;
553 	}
554 
555 	if (output_size != NULL)
556 		*output_size = output->len;
557 
558 	return g_byte_array_free (output, FALSE);
559 
560 CLEANUP:
561 
562 	if (output_size != NULL)
563 		*output_size = 0;
564 
565 	g_byte_array_free (output, TRUE);
566 	inflateEnd(&stream);
567 
568 	return NULL;
569 }
570 
571 /**
572  * SECTION: arvgst
573  * @short_description: Gstreamer utilities
574  */
575 
576 #define ARV_MAKE_FOURCC(a,b,c,d)        ((guint32)((a)|(b)<<8|(c)<<16|(d)<<24))
577 
578 typedef struct {
579 	ArvPixelFormat pixel_format;
580 	const char *gst_caps_string;
581 	const char *name;
582 	const char *format;
583 	const char *gst_0_10_caps_string;
584 	const char *name_0_10;
585 	int bpp;
586 	int depth;
587 	guint32 fourcc;
588 } ArvGstCapsInfos;
589 
590 ArvGstCapsInfos arv_gst_caps_infos[] = {
591 	{
592 		ARV_PIXEL_FORMAT_MONO_8,
593 		"video/x-raw, format=(string)GRAY8",
594 		"video/x-raw", 		"GRAY8",
595 		"video/x-raw-gray, bpp=(int)8, depth=(int)8",
596 		"video/x-raw-gray",	8,	8,	0
597 	},
598 	{
599 		ARV_PIXEL_FORMAT_MONO_16,
600 		"video/x-raw, format=(string)GRAY16_LE",
601 		"video/x-raw",		"GRAY16_LE",
602 		"video/x-raw-gray, bpp=(int)16, depth=(int)16",
603 		"video/x-raw-gray",	16,	16,	0
604 	},
605 	{
606 		ARV_PIXEL_FORMAT_MONO_12,
607 		"video/x-raw, format=(string)GRAY16_LE",
608 		"video/x-raw",		"GRAY16_LE",
609 		"video/x-raw-gray, bpp=(int)16, depth=(int)12",
610 		"video/x-raw-gray",	16,	12,	0
611 	},
612 	{
613 		ARV_PIXEL_FORMAT_MONO_12_PACKED,
614 		"video/x-raw, format=(string)GRAY16_LE",
615 		"video/x-raw",		"GRAY16_LE",
616 		"video/x-raw-gray, bpp=(int)12, depth=(int)12",
617 		"video/x-raw-gray",	12,	12,	0
618 	},
619 	{
620 		ARV_PIXEL_FORMAT_MONO_10,
621 		"video/x-raw, format=(string)GRAY16_LE",
622 		"video/x-raw", 		"GRAY16_LE",
623 		"video/x-raw-gray, bpp=(int)16, depth=(int)10",
624 		"video/x-raw-gray",	16,	10,	0
625 	},
626 	{
627 		ARV_PIXEL_FORMAT_BAYER_GR_8,
628 		"video/x-bayer, format=(string)grbg",
629 		"video/x-bayer",	"grbg",
630 		"video/x-raw-bayer, format=(string)grbg, bpp=(int)8, depth=(int)8",
631 		"video/x-raw-bayer",	8,	8,	ARV_MAKE_FOURCC ('g','r','b','g')
632 	},
633 	{
634 		ARV_PIXEL_FORMAT_BAYER_RG_8,
635 		"video/x-bayer, format=(string)rggb",
636 		"video/x-bayer",	"rggb",
637 		"video/x-raw-bayer, format=(string)rggb, bpp=(int)8, depth=(int)8",
638 		"video/x-raw-bayer",	8,	8,	ARV_MAKE_FOURCC ('r','g','g','b')
639 	},
640 	{
641 		ARV_PIXEL_FORMAT_BAYER_GB_8,
642 		"video/x-bayer, format=(string)gbrg",
643 		"video/x-bayer",	"gbrg",
644 		"video/x-raw-bayer, format=(string)gbrg, bpp=(int)8, depth=(int)8",
645 		"video/x-raw-bayer",	8,	8,	ARV_MAKE_FOURCC ('g','b','r','g')
646 	},
647 	{
648 		ARV_PIXEL_FORMAT_BAYER_BG_8,
649 		"video/x-bayer, format=(string)bggr",
650 		"video/x-bayer",	"bggr",
651 		"video/x-raw-bayer, format=(string)bggr, bpp=(int)8, depth=(int)8",
652 		"video/x-raw-bayer",	8,	8,	ARV_MAKE_FOURCC ('b','g','g','r')
653 	},
654 
655 /* Non 8bit bayer formats are not supported by gstreamer bayer plugin.
656  * This feature is discussed in bug https://bugzilla.gnome.org/show_bug.cgi?id=693666 .*/
657 
658 	{
659 		ARV_PIXEL_FORMAT_YUV_422_PACKED,
660 		"video/x-raw, format=(string)UYVY",
661 		"video/x-raw",		"UYVY",
662 		"video/x-raw-yuv, format=(fourcc)UYVY",
663 		"video/x-raw-yuv",	0,	0,	ARV_MAKE_FOURCC ('U','Y','V','Y')
664 	},
665 	{
666 		ARV_PIXEL_FORMAT_YUV_422_YUYV_PACKED,
667 		"video/x-raw, format=(string)YUY2",
668 		"video/x-raw", 		"YUY2",
669 		"video/x-raw-yuv, format=(fourcc)YUYU2",
670 		"video/x-raw-yuv",	0,	0,	ARV_MAKE_FOURCC ('Y','U','Y','2')
671 	},
672 	{
673 		ARV_PIXEL_FORMAT_RGB_8_PACKED,
674 		"video/x-raw, format=(string)RGB",
675 		"video/x-raw",		"RGB",
676 		"video/x-raw-rgb, format=(string)RGB, bpp=(int)24, depth=(int)24",
677 		"video/x-raw-rgb",	24,	24,	0
678 	},
679 	{
680 		ARV_PIXEL_FORMAT_CUSTOM_YUV_422_YUYV_PACKED,
681 		"video/x-raw, format=(string)YUY2",
682 		"video/x-raw",		"YUY2",
683 		"video/x-raw-yuv, format=(fourcc)YUYU2",
684 		"video/x-raw-yuv",	0,	0,	ARV_MAKE_FOURCC ('Y','U','Y','2')
685 	}
686 };
687 
688 /**
689  * arv_pixel_format_to_gst_caps_string:
690  * @pixel_format: a pixel format
691  * Return value: a gstreamer caps string describing the given @pixel_format.
692  */
693 
694 const char *
arv_pixel_format_to_gst_caps_string(ArvPixelFormat pixel_format)695 arv_pixel_format_to_gst_caps_string (ArvPixelFormat pixel_format)
696 {
697 	int i;
698 
699 	for (i = 0; i < G_N_ELEMENTS (arv_gst_caps_infos); i++)
700 		if (arv_gst_caps_infos[i].pixel_format == pixel_format)
701 			break;
702 
703 	if (i == G_N_ELEMENTS (arv_gst_caps_infos)) {
704 		arv_warning_misc ("[PixelFormat::to_gst_caps_string] 0x%08x not found", pixel_format);
705 		return NULL;
706 	}
707 
708 	arv_log_misc ("[PixelFormat::to_gst_caps_string] 0x%08x -> %s",
709 		      pixel_format, arv_gst_caps_infos[i].gst_caps_string);
710 
711 	return arv_gst_caps_infos[i].gst_caps_string;
712 }
713 
714 ArvPixelFormat
arv_pixel_format_from_gst_caps(const char * name,const char * format,int bpp,int depth)715 arv_pixel_format_from_gst_caps (const char *name, const char *format, int bpp, int depth)
716 {
717 	unsigned int i;
718 
719 	g_return_val_if_fail (name != NULL, 0);
720 
721 	for (i = 0; i < G_N_ELEMENTS (arv_gst_caps_infos); i++) {
722 		if (strcmp (name, arv_gst_caps_infos[i].name) != 0 ||
723 		    (depth > 0 && depth != arv_gst_caps_infos[i].depth) ||
724 		    (bpp > 0 && bpp != arv_gst_caps_infos[i].bpp))
725 			continue;
726 
727 		if (strcmp (name, "video/x-raw") == 0 &&
728 		    strcmp (format, arv_gst_caps_infos[i].format) == 0)
729 			return arv_gst_caps_infos[i].pixel_format;
730 
731 		if (strcmp (name, "video/x-bayer") == 0 &&
732 		    strcmp (format, arv_gst_caps_infos[i].format) == 0)
733 			return arv_gst_caps_infos[i].pixel_format;
734 	}
735 
736 	return 0;
737 }
738 
739 const char *
arv_pixel_format_to_gst_0_10_caps_string(ArvPixelFormat pixel_format)740 arv_pixel_format_to_gst_0_10_caps_string (ArvPixelFormat pixel_format)
741 {
742 	int i;
743 
744 	for (i = 0; i < G_N_ELEMENTS (arv_gst_caps_infos); i++)
745 		if (arv_gst_caps_infos[i].pixel_format == pixel_format)
746 			break;
747 
748 	if (i == G_N_ELEMENTS (arv_gst_caps_infos)) {
749 		arv_warning_misc ("[PixelFormat::to_gst_0_10_caps_string] 0x%08x not found", pixel_format);
750 		return NULL;
751 	}
752 
753 	arv_log_misc ("[PixelFormat::to_gst_0_10_caps_string] 0x%08x -> %s",
754 		      pixel_format, arv_gst_caps_infos[i].gst_0_10_caps_string);
755 
756 	return arv_gst_caps_infos[i].gst_0_10_caps_string;
757 }
758 
759 ArvPixelFormat
arv_pixel_format_from_gst_0_10_caps(const char * name,int bpp,int depth,guint32 fourcc)760 arv_pixel_format_from_gst_0_10_caps (const char *name, int bpp, int depth, guint32 fourcc)
761 {
762 	unsigned int i;
763 
764 	g_return_val_if_fail (name != NULL, 0);
765 
766 	for (i = 0; i < G_N_ELEMENTS (arv_gst_caps_infos); i++) {
767 		if (strcmp (name, arv_gst_caps_infos[i].name_0_10) != 0)
768 			continue;
769 
770 		if (strcmp (name, "video/x-raw-yuv") == 0 &&
771 		    (fourcc <= 0 || fourcc == arv_gst_caps_infos[i].fourcc))
772 			return arv_gst_caps_infos[i].pixel_format;
773 
774 		if ((depth <= 0 || depth == arv_gst_caps_infos[i].depth) &&
775 		    (bpp <= 0 || bpp == arv_gst_caps_infos[i].bpp) &&
776 		    fourcc == arv_gst_caps_infos[i].fourcc)
777 			return arv_gst_caps_infos[i].pixel_format;
778 	}
779 
780 	return 0;
781 }
782 
783 static struct {
784 	const char *vendor;
785 	const char *alias;
786 } vendor_aliases[] = {
787 	{ "The Imaging Source Europe GmbH",		"TIS"},
788 	{ "Point Grey Research",			"PointGrey"}
789 };
790 
791 /**
792  * arv_vendor_alias_lookup:
793  * @vendor: a vendor string
794  *
795  * Returns: vendor alias string if found, or @vendor if not found.
796  *
797  * Since: 0.6.0
798  */
799 
800 const char *
arv_vendor_alias_lookup(const char * vendor)801 arv_vendor_alias_lookup	(const char *vendor)
802 {
803 	int i;
804 
805 	if (vendor == NULL)
806 		return NULL;
807 
808 	for (i = 0; i < G_N_ELEMENTS (vendor_aliases); i++)
809 		if (g_strcmp0 (vendor_aliases[i].vendor, vendor) == 0)
810 			return vendor_aliases[i].alias;
811 
812 	return vendor;
813 }
814