root/v4l2-apps/test/pixfmt-test.c

Revision 8136:aef02567c2d9, 41.2 kB (checked in by Mauro Carvalho Chehab <mchehab@infradead.org>, 1 year ago)

Added the SBGGR16 format and fixed two memory leaks on pixfmt-test.

From: Michael Schimek <mschimek@gmx.at>

Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>

Line 
1 /*
2     V4L2 pixfmt test
3
4     Copyright (C) 2007, 2008 Michael H. Schimek <mschimek@gmx.at>
5
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */
20
21 #define _GNU_SOURCE 1
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <stdbool.h>
26 #include <stdarg.h>
27 #include <string.h>
28 #include <inttypes.h>
29 #include <assert.h>
30
31 #include <getopt.h>             /* getopt_long() */
32
33 #include <fcntl.h>              /* low-level i/o */
34 #include <unistd.h>
35 #include <errno.h>
36 #include <sys/stat.h>
37 #include <sys/types.h>
38 #include <sys/time.h>
39 #include <sys/mman.h>
40 #include <sys/ioctl.h>
41
42 #include <asm/types.h>          /* for videodev2.h */
43
44 #include <linux/videodev2.h>
45
46 #include <X11/Xlib.h>
47 #include <X11/keysym.h>
48 #include <X11/Xutil.h>
49
50 #undef MAX
51 #define MAX(x, y) ({                                                    \
52         __typeof__ (x) _x = (x);                                        \
53         __typeof__ (y) _y = (y);                                        \
54         (void)(&_x == &_y); /* alert when type mismatch */              \
55         (_x > _y) ? _x : _y;                                            \
56 })
57
58 #define N_ELEMENTS(array) (sizeof (array) / sizeof ((array)[0]))
59 #define CLEAR(var) memset (&(var), 0, sizeof (var))
60
61 typedef enum {
62         /* Packed RGB formats. */
63
64                                 /* in memory */
65         BGRA8888_LE = 1,        /* bbbbbbbb gggggggg rrrrrrrr aaaaaaaa */
66         BGRA8888_BE,            /* aaaaaaaa rrrrrrrr gggggggg bbbbbbbb */
67         RGBA8888_LE,            /* rrrrrrrr gggggggg bbbbbbbb aaaaaaaa */
68         RGBA8888_BE,            /* aaaaaaaa bbbbbbbb gggggggg rrrrrrrr */
69
70         BGR888_LE,              /* bbbbbbbb gggggggg rrrrrrrr */
71         BGR888_BE,              /* rrrrrrrr gggggggg bbbbbbbb */
72
73         BGR565_LE,              /* gggbbbbb rrrrrggg */
74         BGR565_BE,              /* rrrrrggg gggbbbbb */
75         RGB565_LE,              /* gggrrrrr bbbbbggg */
76         RGB565_BE,              /* bbbbbggg gggrrrrr */
77
78         BGRA5551_LE,            /* gggbbbbb arrrrrgg */
79         BGRA5551_BE,            /* arrrrrgg gggbbbbb */
80         RGBA5551_LE,            /* gggrrrrr abbbbbgg */
81         RGBA5551_BE,            /* abbbbbgg gggrrrrr */
82
83         ABGR1555_LE,            /* ggbbbbba rrrrrggg */
84         ABGR1555_BE,            /* rrrrrggg ggbbbbba */
85         ARGB1555_LE,            /* ggrrrrra bbbbbggg */
86         ARGB1555_BE,            /* bbbbbggg ggrrrrra */
87
88         BGRA4444_LE,            /* ggggbbbb aaaarrrr */
89         BGRA4444_BE,            /* aaaarrrr ggggbbbb */
90         RGBA4444_LE,            /* ggggrrrr aaaabbbb */
91         RGBA4444_BE,            /* aaaabbbb ggggrrrr */
92
93         ABGR4444_LE,            /* bbbbaaaa rrrrgggg */
94         ABGR4444_BE,            /* rrrrgggg bbbbaaaa */
95         ARGB4444_LE,            /* rrrraaaa bbbbgggg */
96         ARGB4444_BE,            /* bbbbgggg rrrraaaa */
97
98         BGR233,                 /* rrrgggbb */
99         RGB332,                 /* bbgggrrr */
100
101         /* Bayer formats. */
102
103         BGGR8,                  /* bbbbbbbb gggggggg */
104                                 /* gggggggg rrrrrrrr */
105         GBRG8,                  /* gggggggg bbbbbbbb */
106                                 /* rrrrrrrr gggggggg */
107         RGGB8,                  /* rrrrrrrr gggggggg */
108                                 /* gggggggg bbbbbbbb */
109         GRBG8,                  /* gggggggg rrrrrrrr */
110                                 /* bbbbbbbb gggggggg */
111
112         BGGR16,                 /* b7...b0 b15...b8 g7...g0 g15...g8 */
113                                 /* g7...g0 g15...g8 r7...r0 r15...r8 */
114         GBRG16,                 /* g7...g0 g15...g8 b7...b0 b15...b8 */
115                                 /* r7...r0 r15...r8 g7...g0 g15...g8 */
116         RGGB16,                 /* r7...r0 r15...r8 g7...g0 g15...g8 */
117                                 /* g7...g0 g15...g8 b7...b0 b15...b8 */
118         GRBG16,                 /* g7...g0 g15...g8 r7...r0 r15...r8 */
119                                 /* b7...b0 b15...b8 g7...g0 g15...g8 */
120 } pixfmt;
121
122 /* A pixfmt set would be nicer, but I doubt all
123    YUV and RGB formats will fit in 64 bits. */
124 typedef enum {
125         PACKED_RGB      = (1 << 0),
126         BAYER           = (1 << 1)
127 } pixfmt_class;
128
129 typedef enum {
130         LE = 1,
131         BE
132 } byte_order;
133
134 typedef struct {
135         /* Our name for this format. */
136         const char *            name;
137
138         /* V4L2's name "V4L2_PIX_FMT_..." or NULL. */
139         const char *            v4l2_fourcc_name;
140
141         /* Our ID for this format. */
142         pixfmt                  pixfmt;
143
144         /* Same pixfmt with opposite byte order.
145            Applies only to packed RGB formats. */
146         pixfmt                  pixfmt_opposite_byte_order;
147
148         /* Same pixfmt with red and blue bits swapped.
149            Applies only to RGB formats. */
150         pixfmt                  pixfmt_swap_red_blue;
151
152         /* Same pixfmt with alpha bits at the other end.
153            Applies only to packed RGB formats. */
154         pixfmt                  pixfmt_opposite_alpha;
155
156         pixfmt_class            pixfmt_class;
157
158         /* V4L2's FOURCC or 0. */
159         uint32_t                v4l2_fourcc;
160
161         /* LE or BE. Applies only to packed RGB formats. */
162         byte_order              byte_order;
163
164         /* Applies only to RGB formats. */
165         uint8_t                 bits_per_pixel;
166
167         /* Number of blue, green and red bits per pixel.
168            Applies only to RGB formats. */
169         uint8_t                 color_depth;
170
171         /* Blue, green, red, alpha bit masks.
172            Applies only to packed RGB formats. */
173         uint32_t                mask[4];
174
175         /* Number of blue, green, red, alpha bits.
176            Applies only to packed RGB formats. */
177         uint8_t                 n_bits[4];
178
179         /* Number of zero bits above the blue, green, red, alpha MSB.
180            E.g. 0x80001234 -> 0, 0x00000001 -> 31, 0 -> 32.
181            Applies only to packed RGB formats. */
182         uint8_t                 shr[4];
183
184 } pixel_format;
185
186 /* Population count in 32 bit constant, e.g. 0x70F -> 7. */
187 #define PC32b(m) ((m) - (((m) >> 1) & 0x55555555))
188 #define PC32a(m) ((PC32b (m) & 0x33333333) + ((PC32b (m) >> 2) & 0x33333333))
189 #define PC32(m) ((((uint64_t)((PC32a (m) & 0x0F0F0F0F)                  \
190                               + ((PC32a (m) >> 4) & 0x0F0F0F0F))        \
191                    * 0x01010101) >> 24) & 0xFF)
192
193 /* Find first set bit in 32 bit constant, see man 3 ffs(). */
194 #define FFS2(m) ((m) & 0x2 ? 2 : (m))
195 #define FFS4(m) ((m) & 0xC ? 2 + FFS2 ((m) >> 2) : FFS2 (m))
196 #define FFS8(m) ((m) & 0xF0 ? 4 + FFS4 ((m) >> 4) : FFS4 (m))
197 #define FFS16(m) ((m) & 0xFF00 ? 8 + FFS8 ((m) >> 8) : FFS8 (m))
198 #define FFS32(m) ((m) & 0xFFFF0000 ? 16 + FFS16 ((m) >> 16) : FFS16 (m))
199
200 #define PF_RGB(tn, vn, pf, pfxbo, pfxrb, pfxa, vpf, bo, b, g, r, a)     \
201         [pf] = {                                                        \
202                 .name = tn,                                             \
203                 .v4l2_fourcc_name = (0 == vpf) ? NULL : vn,             \
204                 .pixfmt = pf,                                           \
205                 .pixfmt_opposite_byte_order = pfxbo,                    \
206                 .pixfmt_swap_red_blue = pfxrb,                          \
207                 .pixfmt_opposite_alpha = pfxa,                          \
208                 .pixfmt_class = PACKED_RGB,                             \
209                 .v4l2_fourcc = vpf,                                     \
210                 .byte_order = bo,                                       \
211                 .bits_per_pixel = PC32 ((b) | (g) | (r) | (a)),         \
212                 .color_depth = PC32 ((b) | (g) | (r)),                  \
213                 .mask = { b, g, r, a },                                 \
214                 .n_bits = { PC32 (b), PC32 (g), PC32 (r), PC32 (a) },   \
215                 .shr = { 32 - FFS32 (b), 32 - FFS32 (g),                \
216                          32 - FFS32 (r), 32 - FFS32 (a) }               \
217         }
218
219 #define PF_RGB8(pf, pfxrb, vpf, b, g, r, a)                             \
220         PF_RGB (# pf, # vpf, pf, pf, pfxrb, 0, vpf, LE, b, g, r, a)
221
222 #define PF_RGB16(fmt, bo, pfxrb, pfxa, vpf, b, g, r, a)                 \
223         PF_RGB (# fmt "_" # bo, # vpf,                                  \
224                 fmt ## _ ## bo,                                         \
225                 (bo == LE) ? fmt ## _ ## BE : fmt ## _ ## LE,           \
226                 pfxrb, pfxa, vpf, bo, b, g, r, a)
227
228 #define PF_RGB24 PF_RGB16
229 #define PF_RGB32 PF_RGB16
230
231 #define PF_BAYER(pf, pfxrb, bpp, vpf)                                   \
232         [pf] = {                                                        \
233                 .name = # pf,                                           \
234                 .v4l2_fourcc_name = (0 == vpf) ? NULL : # vpf,          \
235                 .pixfmt = pf,                                           \
236                 .pixfmt_opposite_byte_order = pf,                       \
237                 .pixfmt_swap_red_blue = pfxrb,                          \
238                 .pixfmt_opposite_alpha = pf,                            \
239                 .pixfmt_class = BAYER,                                  \
240                 .v4l2_fourcc = vpf,                                     \
241                 .byte_order = LE,                                       \
242                 .bits_per_pixel = bpp,                                  \
243                 .color_depth = bpp * 3 /* sort of */                    \
244         }
245
246 static const pixel_format
247 pixel_formats [] = {
248         PF_RGB32 (BGRA8888, LE, RGBA8888_LE, RGBA8888_BE,
249                   V4L2_PIX_FMT_BGR32, 0xFF, 0xFF00, 0xFF0000, 0xFF000000),
250         PF_RGB32 (BGRA8888, BE, RGBA8888_BE, RGBA8888_LE,
251                   V4L2_PIX_FMT_RGB32, 0xFF, 0xFF00, 0xFF0000, 0xFF000000),
252         PF_RGB32 (RGBA8888, LE, BGRA8888_LE, BGRA8888_BE,
253                   0, 0xFF0000, 0xFF00, 0xFF, 0xFF000000),
254         PF_RGB32 (RGBA8888, BE, BGRA8888_BE, BGRA8888_LE,
255                   0, 0xFF0000, 0xFF00, 0xFF, 0xFF000000),
256
257         PF_RGB24 (BGR888, LE, BGR888_BE, 0,
258                   V4L2_PIX_FMT_BGR24, 0xFF, 0xFF00, 0xFF0000, 0),
259         PF_RGB24 (BGR888, BE, BGR888_LE, 0,
260                   V4L2_PIX_FMT_RGB24, 0xFF, 0xFF00, 0xFF0000, 0),
261
262         PF_RGB16 (BGR565, LE, RGB565_LE, 0,
263                   V4L2_PIX_FMT_RGB565, 0x001F, 0x07E0, 0xF800, 0),
264         PF_RGB16 (BGR565, BE, RGB565_BE, 0,
265                   V4L2_PIX_FMT_RGB565X, 0x001F, 0x07E0, 0xF800, 0),
266         PF_RGB16 (RGB565, LE, BGR565_LE, 0, 0, 0xF800, 0x07E0, 0x001F, 0),
267         PF_RGB16 (RGB565, BE, BGR565_BE, 0, 0, 0xF800, 0x07E0, 0x001F, 0),
268
269         PF_RGB16 (BGRA5551, LE, RGBA5551_LE, ABGR1555_LE,
270                   V4L2_PIX_FMT_RGB555, 0x001F, 0x03E0, 0x7C00, 0x8000),
271         PF_RGB16 (BGRA5551, BE, RGBA5551_BE, ABGR1555_BE,
272                   V4L2_PIX_FMT_RGB555X, 0x001F, 0x03E0, 0x7C00, 0x8000),
273         PF_RGB16 (RGBA5551, LE, BGRA5551_LE, ARGB1555_LE,
274                   0, 0x7C00, 0x03E0, 0x001F, 0x8000),
275         PF_RGB16 (RGBA5551, BE, BGRA5551_BE, ARGB1555_BE,
276                   0, 0x7C00, 0x03E0, 0x001F, 0x8000),
277
278         PF_RGB16 (ABGR1555, LE, ARGB1555_LE, BGRA5551_LE,
279                   0, 0x003E, 0x07C0, 0xF800, 0x0001),
280         PF_RGB16 (ABGR1555, BE, ARGB1555_BE, BGRA5551_BE,
281                   0, 0x003E, 0x07C0, 0xF800, 0x0001),
282         PF_RGB16 (ARGB1555, LE, ABGR1555_LE, RGBA5551_LE,
283                   0, 0xF800, 0x07C0, 0x003E, 0x0001),
284         PF_RGB16 (ARGB1555, BE, ABGR1555_BE, RGBA5551_BE,
285                   0, 0xF800, 0x07C0, 0x003E, 0x0001),
286
287         PF_RGB16 (BGRA4444, LE, RGBA4444_LE, ABGR4444_LE,
288                   V4L2_PIX_FMT_RGB444, 0x000F, 0x00F0, 0x0F00, 0xF000),
289         PF_RGB16 (BGRA4444, BE, RGBA4444_BE, ABGR4444_BE,
290                   0, 0x000F, 0x00F0, 0x0F00, 0xF000),
291         PF_RGB16 (RGBA4444, LE, BGRA4444_LE, ARGB4444_LE,
292                   0, 0x0F00, 0x00F0, 0x000F, 0xF000),
293         PF_RGB16 (RGBA4444, BE, BGRA4444_BE, ARGB4444_BE,
294                   0, 0x0F00, 0x00F0, 0x000F, 0xF000),
295
296         PF_RGB16 (ABGR4444, LE, ARGB4444_LE, BGRA4444_LE,
297                   0, 0x00F0, 0x0F00, 0xF000, 0x000F),
298         PF_RGB16 (ABGR4444, BE, ARGB4444_BE, BGRA4444_BE,
299                   0, 0x00F0, 0x0F00, 0xF000, 0x000F),
300         PF_RGB16 (ARGB4444, LE, ABGR4444_LE, RGBA4444_LE,
301                   0, 0xF000, 0x0F00, 0x00F0, 0x000F),
302         PF_RGB16 (ARGB4444, BE, ABGR4444_BE, RGBA4444_BE,
303                   0, 0xF000, 0x0F00, 0x00F0, 0x000F),
304
305         PF_RGB8 (BGR233, RGB332,
306                  V4L2_PIX_FMT_RGB332, 0x03, 0x1C, 0xE0, 0),
307         PF_RGB8 (RGB332, BGR233,
308                  0, 0xE0, 0x1C, 0x03, 0),
309
310         PF_BAYER (BGGR8, RGGB8, 8, V4L2_PIX_FMT_SBGGR8),
311         PF_BAYER (RGGB8, BGGR8, 8, 0),
312         PF_BAYER (GBRG8, GRBG8, 8, 0),
313         PF_BAYER (GRBG8, GBRG8, 8, 0),
314
315         PF_BAYER (BGGR16, RGGB16, 16, V4L2_PIX_FMT_SBGGR16),
316         PF_BAYER (RGGB16, BGGR16, 16, 0),
317         PF_BAYER (GBRG16, GRBG16, 16, 0),
318         PF_BAYER (GRBG16, GBRG16, 16, 0),
319 };
320
321 static const pixel_format *
322 find_v4l2_fourcc                (uint32_t               fourcc)
323 {
324         const pixel_format *pf;
325
326         for (pf = pixel_formats;
327              pf < pixel_formats + N_ELEMENTS (pixel_formats); ++pf) {
328                 if (fourcc == pf->v4l2_fourcc)
329                         return pf;
330         }
331
332         return NULL;
333 }
334
335 static const pixel_format *
336 next_converter                  (const pixel_format *   pf)
337 {
338         const pixel_format *next_pf;
339
340         if (NULL == pf)
341                 pf = pixel_formats;
342         else
343                 pf = pixel_formats + pf->pixfmt;
344
345         next_pf = pf;
346
347         for (;;) {
348                 if (++next_pf >= pixel_formats + N_ELEMENTS (pixel_formats))
349                         next_pf = pixel_formats;
350
351                 if (next_pf == pf)
352                         break;
353
354                 if (0 == next_pf->pixfmt)
355                         continue;
356
357                 if (pf->pixfmt_class == next_pf->pixfmt_class
358                     && pf->bits_per_pixel == next_pf->bits_per_pixel)
359                         break;
360         }
361
362         return next_pf;
363 }
364
365 typedef enum {
366         IO_METHOD_READ = 1,
367         IO_METHOD_MMAP,
368 } io_methods;
369
370 typedef struct {
371         void *                  start;
372         size_t                  length;
373 } io_buffer;
374
375 #define VERSION "1.0"
376
377 static const char *             my_name;
378
379 static const char *             dev_name = "/dev/video";
380
381 static int                      dev_fd;
382 static v4l2_std_id              std_id;
383 static io_methods               io_method;
384 static struct v4l2_format       fmt;
385 static io_buffer *              buffers;
386 static unsigned int             n_buffers;
387
388 static Display *                display;
389 static int                      screen;
390 static Window                   window;
391 static GC                       gc;
392 static Atom                     xa_delete_window;
393
394 static XImage *                 ximage;
395 static const pixel_format *     ximage_pf;
396
397 static void
398 error_exit                      (const char *           templ,
399                                  ...)
400 {
401         va_list ap;
402
403         fprintf (stderr, "%s: ", my_name);
404         va_start (ap, templ);
405         vfprintf (stderr, templ, ap);
406         va_end (ap);
407
408         exit (EXIT_FAILURE);
409 }
410
411 static void
412 errno_exit                      (const char *           s)
413 {
414         error_exit ("%s error %d, %s\n",
415                     s, errno, strerror (errno));
416 }
417
418 static void
419 write_rgb_pixel                 (uint8_t *              dst,
420                                  const pixel_format *   dst_pf,
421                                  unsigned int           b,
422                                  unsigned int           g,
423                                  unsigned int           r,
424                                  unsigned int           depth)
425 {
426         unsigned int dst_pixel;
427         unsigned int shl;
428
429         shl = 32 - depth;
430         dst_pixel  = ((b << shl) >> dst_pf->shr[0]) & dst_pf->mask[0];
431         dst_pixel |= ((g << shl) >> dst_pf->shr[1]) & dst_pf->mask[1];
432         dst_pixel |= ((r << shl) >> dst_pf->shr[2]) & dst_pf->mask[2];
433
434         switch (dst_pf->byte_order * 256 + dst_pf->bits_per_pixel) {
435         case LE * 256 + 32:
436                 dst[3] = dst_pixel >> 24;
437                 /* fall through */
438         case LE * 256 + 24:
439                 dst[2] = dst_pixel >> 16;
440         case LE * 256 + 16:
441                 dst[1] = dst_pixel >> 8;
442         case LE * 256 + 8:
443                 dst[0] = dst_pixel;
444                 break;
445
446         case BE * 256 + 32:
447                 *dst++ = dst_pixel >> 24;
448         case BE * 256 + 24:
449                 *dst++ = dst_pixel >> 16;
450         case BE * 256 + 16:
451                 *dst++ = dst_pixel >> 8;
452         case BE * 256 + 8:
453                 *dst = dst_pixel;
454                 break;
455
456         default:
457                 assert (0);
458                 break;
459         }
460 }
461
462 static void
463 convert_bayer8_image            (uint8_t *              dst,
464                                  const pixel_format *   dst_pf,
465                                  unsigned long          dst_bpl,
466                                  const uint8_t *        src,
467                                  const pixel_format *   src_pf,
468                                  unsigned long          src_bpl,
469                                  unsigned int           width,
470                                  unsigned int           height)
471 {
472         unsigned long dst_padding;
473         unsigned int tile;
474         unsigned int y;
475
476         assert (PACKED_RGB == dst_pf->pixfmt_class);
477         assert (BAYER == src_pf->pixfmt_class);
478
479         assert (width >= 2 && 0 == (width & 1));
480         assert (height >= 2 && 0 == (height & 1));
481
482         dst_padding = dst_bpl - width * (dst_pf->bits_per_pixel >> 3);
483         assert ((long) dst_padding >= 0);
484
485         switch (src_pf->pixfmt) {
486         case BGGR8:
487                 tile = 0;
488                 break;
489
490         case GBRG8:
491                 tile = 1;
492                 break;
493
494         case RGGB8:
495                 tile = 2;
496                 break;
497
498         case GRBG8:
499                 tile = 3;
500                 break;
501
502         default:
503                 assert (0);
504                 break;
505         }
506
507         for (y = 0; y < height; ++y) {
508                 const uint8_t *srcm;
509                 const uint8_t *srcp;
510                 unsigned int x;
511
512                 srcm = srcp = src - src_bpl;
513
514                 if (0 == y)
515                         srcm += src_bpl * 2;
516
517                 if (y != height - 1)
518                         srcp += src_bpl * 2;
519
520                 for (x = 0; x < width; ++x) {
521                         int xm, xp;
522
523                         xm = (((0 == x) - 1) | 1) + x;
524                         xp = (((x != width - 1) - 1) | 1) + x;
525
526                         switch (tile) {
527                         case 0: /* BG
528                                    GR */
529                                 write_rgb_pixel (dst, dst_pf,
530                                                  /* b */ src[x],
531                                                  /* g */ (src[xm] +
532                                                           src[xp] +
533                                                           srcm[x] +
534                                                           srcp[x] + 2) >> 2,
535                                                  /* r */ (srcm[xm] +
536                                                           srcm[xp] +
537                                                           srcp[xm] +
538                                                           srcp[xp] + 2) >> 2,
539                                                  /* depth */ 8);
540                                 break;
541
542                         case 1: /* GB
543                                    RG */
544                                 write_rgb_pixel (dst, dst_pf,
545                                                  /* b */ (src[xm] +
546                                                           src[xp] + 1) >> 1,
547                                                  /* g */ src[x],
548                                                  /* r */ (srcm[x] +
549                                                           srcp[x] + 1) >> 1,
550                                                  /* depth */ 8);
551                                 break;
552
553                         case 2: /* GR
554                                    BG */
555                                 write_rgb_pixel (dst, dst_pf,
556                                                  /* b */ (srcm[x] +
557                                                           srcp[x] + 1) >> 1,
558                                                  /* g */ src[x],
559                                                  /* r */ (src[xm] +
560                                                           src[xp] + 1) >> 1,
561                                                  /* depth */ 8);
562                                 break;
563
564                         case 3: /* RG
565                                    GB */
566                                 write_rgb_pixel (dst, dst_pf,
567                                                  /* b */ (srcm[xm] +
568                                                           srcm[xp] +
569                                                           srcp[xm] +
570                                                           srcp[xp] + 2) >> 2,
571                                                  /* g */ (src[xm] +
572                                                           src[xp] +
573                                                           srcm[x] +
574                                                           srcp[x] + 2) >> 2,
575                                                  /* r */ src[x],
576                                                  /* depth */ 8);
577                                 break;
578
579                         default:
580                                 assert (0);
581                                 break;
582                         }
583
584                         tile ^= 1;
585
586                         dst += dst_pf->bits_per_pixel >> 3;
587                 }
588
589                 tile ^= 2;
590
591                 dst += dst_padding;
592                 src += src_bpl;
593         }
594 }
595
596 static void
597 convert_bayer16_image           (uint8_t *              dst,
598                                  const pixel_format *   dst_pf,
599                                  unsigned long          dst_bpl,
600                                  const uint16_t *       src,
601                                  const pixel_format *   src_pf,
602                                  unsigned long          src_bpl,
603                                  unsigned int           width,
604                                  unsigned int           height)
605 {
606         unsigned long dst_padding;
607         unsigned int tile;
608         unsigned int y;
609
610         assert (PACKED_RGB == dst_pf->pixfmt_class);
611         assert (BAYER == src_pf->pixfmt_class);
612
613         assert (width >= 2 && 0 == (width & 1));
614         assert (height >= 2 && 0 == (height & 1));
615
616         dst_padding = dst_bpl - width * (dst_pf->bits_per_pixel >> 3);
617         assert ((long) dst_padding >= 0);
618
619         switch (src_pf->pixfmt) {
620         case BGGR16:
621                 tile = 0;
622                 break;
623
624         case GBRG16:
625                 tile = 1;
626                 break;
627
628         case RGGB16:
629                 tile = 2;
630                 break;
631
632         case GRBG16:
633                 tile = 3;
634                 break;
635
636         default:
637                 assert (0);
638                 break;
639         }
640
641         for (y = 0; y < height; ++y) {
642                 const uint16_t *srcm;
643                 const uint16_t *srcp;
644                 unsigned int x;
645
646                 srcm = srcp = (const uint16_t *)
647                         ((char *) src - src_bpl);
648
649                 if (0 == y)
650                         srcm = (const uint16_t *)
651                                 ((char *) srcm + src_bpl * 2);
652
653                 if (y != height - 1)
654                         srcp = (const uint16_t *)
655                                 ((char *) srcp + src_bpl * 2);
656
657                 for (x = 0; x < width; ++x) {
658                         int xm, xp;
659
660                         xm = (((0 == x) - 1) | 1) + x;
661                         xp = (((x != width - 1) - 1) | 1) + x;
662
663                         switch (tile) {
664                         case 0: /* BG
665                                    GR */
666                                 write_rgb_pixel (dst, dst_pf,
667                                                  /* b */ src[x],
668                                                  /* g */ (src[xm] +
669                                                           src[xp] +
670                                                           srcm[x] +
671                                                           srcp[x] + 2) >> 2,
672                                                  /* r */ (srcm[xm] +
673                                                           srcm[xp] +
674                                                           srcp[xm] +
675                                                           srcp[xp] + 2) >> 2,
676                                                  /* depth */ 10);
677                                 break;
678
679                         case 1: /* GB
680                                    RG */
681                                 write_rgb_pixel (dst, dst_pf,
682                                                  /* b */ (src[xm] +
683                                                           src[xp] + 1) >> 1,
684                                                  /* g */ src[x],
685                                                  /* r */ (srcm[x] +
686                                                           srcp[x] + 1) >> 1,
687                                                  /* depth */ 10);
688                                 break;
689
690                         case 2: /* GR
691                                    BG */
692                                 write_rgb_pixel (dst, dst_pf,
693                                                  /* b */ (srcm[x] +
694                                                           srcp[x] + 1) >> 1,
695                                                  /* g */ src[x],
696                                                  /* r */ (src[xm] +
697                                                           src[xp] + 1) >> 1,
698                                                  /* depth */ 10);
699                                 break;
700
701                         case 3: /* RG
702                                    GB */
703                                 write_rgb_pixel (dst, dst_pf,
704                                                  /* b */ (srcm[xm] +
705                                                           srcm[xp] +
706                                                           srcp[xm] +
707                                                           srcp[xp] + 2) >> 2,
708                                                  /* g */ (src[xm] +
709                                                           src[xp] +
710                                                           srcm[x] +
711                                                           srcp[x] + 2) >> 2,
712                                                  /* r */ src[x],
713                                                  /* depth */ 10);
714                                 break;
715
716                         default:
717                                 assert (0);
718                                 break;
719                         }
720
721                         tile ^= 1;
722
723                         dst += dst_pf->bits_per_pixel >> 3;
724                 }
725
726                 tile ^= 2;
727
728                 dst += dst_padding;
729                 src = (const uint16_t *)((char *) src + src_bpl);
730         }
731 }
732
733 static void
734 convert_packed_rgb_pixel        (uint8_t *              dst,
735                                  const pixel_format *   dst_pf,
736                                  const uint8_t *        src,
737                                  const pixel_format *   src_pf)
738 {
739         uint32_t dst_pixel;
740         uint32_t src_pixel;
741         unsigned int i;
742
743         src_pixel = 0;
744
745         switch (src_pf->byte_order * 256 + src_pf->bits_per_pixel) {
746         case LE * 256 + 32:
747                 src_pixel = src[3] << 24;
748                 /* fall through */
749         case LE * 256 + 24:
750                 src_pixel |= src[2] << 16;
751         case LE * 256 + 16:
752                 src_pixel |= src[1] << 8;
753         case LE * 256 + 8:
754                 src_pixel |= src[0];
755                 break;
756
757         case BE * 256 + 32:
758                 src_pixel = *src++ << 24;
759         case BE * 256 + 24:
760                 src_pixel |= *src++ << 16;
761         case BE * 256 + 16:
762                 src_pixel |= *src++ << 8;
763         case BE * 256 + 8:
764                 src_pixel |= *src;
765                 break;
766
767         default:
768                 assert (0);
769                 break;
770         }
771
772         dst_pixel = 0;
773
774         for (i = 0; i < 3; ++i) {
775                 unsigned int c;
776
777                 c = (src_pixel & src_pf->mask[i]) << src_pf->shr[i];
778
779                 /* XXX Check if CPU supports only signed right shift. */
780                 c |= c >> src_pf->n_bits[i];
781                 c |= c >> (src_pf->n_bits[i] * 2);
782
783                 dst_pixel |= (c >> dst_pf->shr[i]) & dst_pf->mask[i];
784         }
785
786         switch (dst_pf->byte_order * 256 + dst_pf->bits_per_pixel) {
787         case LE * 256 + 32:
788                 dst[3] = dst_pixel >> 24;
789                 /* fall through */
790         case LE * 256 + 24:
791                 dst[2] = dst_pixel >> 16;
792         case LE * 256 + 16:
793                 dst[1] = dst_pixel >> 8;
794         case LE * 256 + 8:
795                 dst[0] = dst_pixel;
796                 break;
797
798         case BE * 256 + 32:
799                 *dst++ = dst_pixel >> 24;
800         case BE * 256 + 24:
801                 *dst++ = dst_pixel >> 16;
802         case BE * 256 + 16:
803                 *dst++ = dst_pixel >> 8;
804         case BE * 256 + 8:
805                 *dst = dst_pixel;
806                 break;
807
808         default:
809                 assert (0);
810                 break;
811         }
812 }
813
814 static void
815 convert_rgb_image               (uint8_t *              dst,
816                                  const pixel_format *   dst_pf,
817                                  unsigned long          dst_bpl,
818                                  const uint8_t *        src,
819                                  const pixel_format *   src_pf,
820                                  unsigned long          src_bpl,
821                                  unsigned int           width,
822                                  unsigned int           height)
823 {
824         unsigned long dst_padding;
825         unsigned long src_padding;
826
827         assert (PACKED_RGB == dst_pf->pixfmt_class);
828
829         if (BAYER == src_pf->pixfmt_class) {
830                 if (8 == src_pf->bits_per_pixel) {
831                         convert_bayer8_image (dst, dst_pf, dst_bpl,
832                                               src, src_pf, src_bpl,
833                                               width, height);
834                 } else {
835                         convert_bayer16_image (dst, dst_pf, dst_bpl,
836                                                (const uint16_t *) src,
837                                                src_pf, src_bpl,
838                                                width, height);
839                 }
840                 return;
841         }
842
843         assert (width > 0);
844         assert (height > 0);
845
846         dst_padding = dst_bpl - width * (dst_pf->bits_per_pixel >> 3);
847         src_padding = src_bpl - width * (src_pf->bits_per_pixel >> 3);
848
849         assert ((long)(dst_padding | src_padding) >= 0);
850
851         do {
852                 unsigned int count = width;
853
854                 do {
855                         convert_packed_rgb_pixel (dst, dst_pf, src, src_pf);
856
857                         dst += dst_pf->bits_per_pixel >> 3;
858                         src += src_pf->bits_per_pixel >> 3;
859                 } while (--count > 0);
860
861                 dst += dst_padding;
862                 src += src_padding;
863         } while (--height > 0);
864 }
865
866 typedef enum {
867         NEXT_FORMAT = 1,
868         NEXT_CONVERTER
869 } my_event;
870
871 static my_event
872 x_event                         (void)
873 {
874         while (XPending (display)) {
875                 XEvent event;
876                 int key;
877
878                 XNextEvent (display, &event);
879
880                 switch (event.type) {
881                 case KeyPress:
882                         key = XLookupKeysym (&event.xkey, 0);
883
884                         switch (key) {
885                         case 'n':
886                                 return NEXT_FORMAT;
887
888                         case 'c':
889                                 if (event.xkey.state & ControlMask)
890                                         exit (EXIT_SUCCESS);
891                                 return NEXT_CONVERTER;
892
893                         case 'q':
894                                 exit (EXIT_SUCCESS);
895
896                         default:
897                                 break;
898                         }
899
900                         break;
901
902                 case ClientMessage:
903                         /* We requested only delete_window messages. */
904                         exit (EXIT_SUCCESS);
905
906                 default:
907                         break;
908                 }
909         }
910
911         return 0;
912 }
913
914 static XImage *
915 create_ximage                   (const pixel_format **  pf,
916                                  unsigned int           width,
917                                  unsigned int           height)
918 {
919         XImage *xi;
920         unsigned int image_size;
921         unsigned int i;
922
923         assert (NULL != display);
924
925         xi = XCreateImage (display,
926                                DefaultVisual (display, screen),
927                                DefaultDepth (display, screen),
928                                ZPixmap,
929                                /* offset */ 0,
930                                /* data */ NULL,
931                                width,
932                                height,
933                                /* bitmap_pad (n/a) */ 8,
934                                /* bytes_per_line: auto */ 0);
935         if (NULL == xi) {
936                 error_exit ("Cannot allocate XImage.\n");
937         }
938
939         for (i = 0; i < N_ELEMENTS (pixel_formats); ++i) {
940                 if (PACKED_RGB != pixel_formats[i].pixfmt_class)
941                         continue;
942                 if ((LSBFirst == xi->byte_order)
943                     != (LE == pixel_formats[i].byte_order))
944                         continue;
945                 if (xi->bits_per_pixel
946                     != pixel_formats[i].bits_per_pixel)
947                         continue;
948                 if (xi->blue_mask != pixel_formats[i].mask[0])
949                         continue;
950                 if (xi->green_mask != pixel_formats[i].mask[1])
951                         continue;
952                 if (xi->red_mask != pixel_formats[i].mask[2])
953                         continue;
954                 break;
955         }
956
957         if (i >= N_ELEMENTS (pixel_formats)) {
958                 error_exit ("Unknown XImage pixel format "
959                             "(bpp=%u %s b=0x%08x g=0x%08x r=0x%08x).\n",
960                             xi->bits_per_pixel,
961                             (LSBFirst == xi->byte_order) ?
962                             "LSBFirst" : "MSBFirst",
963                             xi->blue_mask,
964                             xi->green_mask,
965                             xi->red_mask);
966         }
967
968         if (NULL != pf)
969                 *pf = pixel_formats + i;
970
971         image_size = (xi->bytes_per_line * xi->height);
972
973         xi->data = malloc (image_size);
974         if (NULL == xi->data) {
975                 error_exit ("Cannot allocate XImage data (%u bytes).\n",
976                             image_size);
977                 exit (EXIT_FAILURE);
978         }
979
980         return xi;
981 }
982
983 static void
984 resize_window                   (unsigned int           image_width,
985                                  unsigned int           image_height,
986                                  unsigned int           text_width,
987                                  unsigned int           text_height)
988 {
989         assert (0 != window);
990
991         XResizeWindow (display, window,
992                        MAX (image_width, text_width),
993                        image_height + text_height);
994
995         if (NULL != ximage) {
996                 free (ximage->data);
997                 ximage->data = NULL;
998
999                 XDestroyImage (ximage);
1000         }
1001
1002         ximage = create_ximage (&ximage_pf, image_width, image_height);
1003 }
1004
1005 static const char *
1006 pixel_format_bit_string         (const pixel_format *   pf)
1007 {
1008         static char buf[64];
1009         char *d;
1010         unsigned int i;
1011
1012         if (PACKED_RGB != pf->pixfmt_class)
1013                 return NULL;
1014
1015         d = buf;
1016
1017         for (i = 0; i < pf->bits_per_pixel; i += 8) {
1018                 unsigned int ii;
1019                 int j;
1020
1021                 if (0 != i)
1022                         *d++ = ' ';
1023
1024                 ii = i;
1025                 if (BE == pf->byte_order)
1026                         ii = pf->bits_per_pixel - i - 8;
1027
1028                 for (j = 7; j >= 0; --j) {
1029                         unsigned int k;
1030
1031                         for (k = 0; k < 4; ++k) {
1032                                 if (pf->mask[k] & (1 << (ii + j))) {
1033                                         *d++ = "bgra"[k];
1034                                         break;
1035                                 }
1036                         }
1037                 }
1038         }
1039
1040         *d = 0;
1041
1042         return buf;
1043 }
1044
1045 static void
1046 display_image                   (const uint8_t *        image,
1047                                  uint32_t               v4l2_fourcc,
1048                                  const pixel_format *   image_pf,
1049                                  unsigned long          image_bpl,
1050                                  unsigned int           image_width,
1051                                  unsigned int           image_height)
1052 {
1053         XWindowAttributes wa;
1054         XFontStruct *font;
1055         unsigned int text_height;
1056         XTextItem xti;
1057         const char *v4l2_fourcc_name;
1058         unsigned int i;
1059
1060         assert (NULL != ximage);
1061
1062         if (!XGetWindowAttributes (display, window, &wa)) {
1063                 error_exit ("Cannot determine current X11 window size.\n");
1064         }
1065
1066         font = XQueryFont (display, XGContextFromGC (gc));
1067         text_height = font->max_bounds.ascent + font->max_bounds.descent;
1068
1069         if (image_width > (unsigned int) ximage->width
1070             || image_width != (unsigned int) wa.width
1071             || image_height > (unsigned int) ximage->height
1072             || image_height + text_height != (unsigned int) wa.height) {
1073                 resize_window (image_width,
1074                                image_height,
1075                                /* text_width */ image_width,
1076                                text_height);
1077         }
1078
1079         convert_rgb_image ((uint8_t *) ximage->data,
1080                            ximage_pf,
1081                            ximage->bytes_per_line,
1082                            image,
1083                            image_pf,
1084                            image_bpl,
1085                            image_width,
1086                            image_height);
1087
1088         XPutImage (display,
1089                    window,
1090                    gc,
1091                    ximage,
1092                    /* src_x */ 0,
1093                    /* src_y */ 0,
1094                    /* dst_x */ 0,
1095                    /* dst_y */ 0,
1096                    /* width */ image_width,
1097                    /* height */ image_height);
1098
1099
1100         XSetForeground (display, gc, XBlackPixel (display, screen));
1101
1102         XFillRectangle (display,
1103                         window,
1104                         gc,
1105                         /* x */ 0,
1106                         /* y */ image_height,
1107                         wa.width,
1108                         text_height);
1109
1110         XSetForeground (display, gc, XWhitePixel (display, screen));
1111
1112         v4l2_fourcc_name = "?";
1113
1114         for (i = 0; i < N_ELEMENTS (pixel_formats); ++i) {
1115                 if (v4l2_fourcc == pixel_formats[i].v4l2_fourcc) {
1116                         v4l2_fourcc_name = pixel_formats[i].v4l2_fourcc_name;
1117                         break;
1118                 }
1119         }
1120
1121
1122         CLEAR (xti);
1123
1124         if (PACKED_RGB == image_pf->pixfmt_class) {
1125                 xti.nchars = asprintf (&xti.chars,
1126                                        "Format %s, converter %s (%s)",
1127                                        v4l2_fourcc_name,
1128                                        image_pf->name,
1129                                        pixel_format_bit_string (image_pf));
1130         } else {
1131                 xti.nchars = asprintf (&xti.chars,
1132                                        "Format %s, converter %s",
1133                                        v4l2_fourcc_name,
1134                                        image_pf->name);
1135         }
1136
1137         if (xti.nchars < 0) {
1138                 error_exit ("Cannot allocate text buffer.\n");
1139         }
1140
1141         XDrawText (display, window, gc,
1142                    /* x */ 4,
1143                    /* y */ image_height + font->max_bounds.ascent,
1144                    &xti,
1145                    /* n_items */ 1);
1146
1147         free (xti.chars);
1148
1149         XFreeFontInfo (/* names */ NULL, font, 1);
1150 }
1151
1152 static void
1153 open_window                     (unsigned int           width,
1154                                  unsigned int           height)
1155 {
1156         GC default_gc;
1157         XFontStruct *font;
1158         unsigned int text_height;
1159
1160         display = XOpenDisplay (NULL);
1161         if (NULL == display) {
1162                 error_exit ("Cannot open X11 display.\n");
1163         }
1164
1165         screen = DefaultScreen (display);
1166
1167         default_gc = XDefaultGC (display, screen);
1168         font = XQueryFont (display, XGContextFromGC (default_gc));
1169         text_height = font->max_bounds.ascent + font->max_bounds.descent;
1170
1171         window = XCreateSimpleWindow (display,
1172                                       RootWindow (display, screen),
1173                                       /* x */ 0,
1174                                       /* y */ 0,
1175                                       width,
1176                                       height + text_height,
1177                                       /* border width */ 2,
1178                                       /* foreground */
1179                                       XWhitePixel (display, screen),
1180                                       /* background */
1181                                       XBlackPixel (display, screen));
1182         if (0 == window) {
1183                 error_exit ("Cannot open X11 window.\n");
1184         }
1185
1186         gc = XCreateGC (display, window,
1187                         /* valuemask */ 0,
1188                         /* values */ NULL);
1189
1190         XSetFunction (display, gc, GXcopy);
1191         XSetFillStyle (display, gc, FillSolid);
1192
1193         ximage = create_ximage (&ximage_pf, width, height);
1194
1195         XSelectInput (display, window,
1196                       (KeyPressMask |
1197                        ExposureMask |
1198                        StructureNotifyMask));
1199
1200         xa_delete_window = XInternAtom (display, "WM_DELETE_WINDOW",
1201                                         /* only_if_exists */ False);
1202
1203         XSetWMProtocols (display, window, &xa_delete_window, /* count */ 1);
1204
1205         XStoreName (display, window,
1206                     "V4L2 Pixfmt Test - "
1207                     "Press [n] for next format, [c] for next converter");
1208
1209         XMapWindow (display, window);
1210
1211         XSync (display, /* discard all events */ False);
1212 }
1213
1214 static int
1215 xioctl                          (int                    fd,
1216                                  int                    request,
1217                                  void *                 arg)
1218 {
1219         int r;
1220
1221         do r = ioctl (fd, request, arg);
1222         while (-1 == r && EINTR == errno);
1223
1224         return r;
1225 }
1226
1227 static bool
1228 read_and_display_frame          (const pixel_format *   conv_pf)
1229 {
1230         struct v4l2_buffer buf;
1231
1232         switch (io_method) {
1233         case IO_METHOD_READ:
1234                 if (-1 == read (dev_fd, buffers[0].start,
1235                                 buffers[0].length)) {
1236                         switch (errno) {
1237                         case EAGAIN:
1238                                 return false;
1239
1240                         default:
1241                                 errno_exit ("read");
1242                         }
1243                 }
1244
1245                 display_image (buffers[0].start,
1246                                fmt.fmt.pix.pixelformat,
1247                                conv_pf,
1248                                fmt.fmt.pix.bytesperline,
1249                                fmt.fmt.pix.width,
1250                                fmt.fmt.pix.height);
1251
1252                 break;
1253
1254         case IO_METHOD_MMAP:
1255                 CLEAR (buf);
1256
1257                 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1258                 buf.memory = V4L2_MEMORY_MMAP;
1259
1260                 if (-1 == xioctl (dev_fd, VIDIOC_DQBUF, &buf)) {
1261                         switch (errno) {
1262                         case EAGAIN:
1263                                 return false;
1264
1265                         case EIO:
1266                                 /* Could ignore EIO, see spec. */
1267
1268                                 /* fall through */
1269
1270                         default:
1271                                 errno_exit ("VIDIOC_DQBUF");
1272                         }
1273                 }
1274
1275                 assert (buf.index < n_buffers);
1276
1277                 display_image (buffers[buf.index].start,
1278                                fmt.fmt.pix.pixelformat,
1279                                conv_pf,
1280                                fmt.fmt.pix.bytesperline,
1281                                fmt.fmt.pix.width,
1282                                fmt.fmt.pix.height);
1283
1284                 if (-1 == xioctl (dev_fd, VIDIOC_QBUF, &buf))
1285                         errno_exit ("VIDIOC_QBUF");
1286
1287                 break;
1288         }
1289
1290         return true;
1291 }
1292
1293 static void
1294 wait_for_next_frame             (void)
1295 {
1296         for (;;) {
1297                 struct timeval timeout;
1298                 fd_set fds;
1299                 int r;
1300
1301                 FD_ZERO (&fds);
1302                 FD_SET (dev_fd, &fds);
1303
1304                 timeout.tv_sec = 2;
1305                 timeout.tv_usec = 0;
1306
1307                 r = select (dev_fd + 1, &fds, NULL, NULL, &timeout);
1308                 if (-1 == r) {
1309                         if (EINTR == errno)
1310                                 continue;
1311
1312                         errno_exit ("select");
1313                 } else if (0 == r) {
1314                         error_exit ("select timeout.\n");
1315                 } else {
1316                         break;
1317                 }
1318         }
1319 }
1320
1321 static void
1322 flush_capture_queue             (void)
1323 {
1324         struct v4l2_buffer buf;
1325
1326         for (;;) {
1327                 switch (io_method) {
1328                 case IO_METHOD_READ:
1329                         /* Nothing to do. */
1330                         return;
1331
1332                 case IO_METHOD_MMAP:
1333                         CLEAR (buf);
1334
1335                         buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1336                         buf.memory = V4L2_MEMORY_MMAP;
1337
1338                         if (-1 == xioctl (dev_fd, VIDIOC_DQBUF, &buf)) {
1339                                 switch (errno) {
1340                                 case EAGAIN:
1341                                         return;
1342
1343                                 default:
1344                                         errno_exit ("VIDIOC_DQBUF");
1345                                 }
1346                         }
1347
1348                         if (-1 == xioctl (dev_fd, VIDIOC_QBUF, &buf))
1349                                 errno_exit ("VIDIOC_QBUF");
1350
1351                         break;
1352
1353                 default:
1354                         assert (0);
1355                         break;
1356                 }
1357         }
1358 }
1359
1360 static void
1361 capture_loop                    (void)
1362 {
1363         const pixel_format *conv_pf;
1364
1365         conv_pf = find_v4l2_fourcc (fmt.fmt.pix.pixelformat);
1366         assert (NULL != conv_pf);
1367
1368         for (;;) {
1369                 /* Remove images from the capture queue if
1370                    we can't display them fast enough. */
1371                 flush_capture_queue ();
1372
1373                 do {
1374                         wait_for_next_frame ();
1375                 } while (!read_and_display_frame (conv_pf));
1376
1377                 switch (x_event ()) {
1378                 case NEXT_CONVERTER:
1379                         conv_pf = next_converter (conv_pf);
1380                         break;
1381
1382                 case NEXT_FORMAT:
1383                         return;
1384
1385                 default:
1386                         break;
1387                 }
1388         }
1389 }
1390
1391 static void
1392 stop_capturing                  (void)
1393 {
1394         enum v4l2_buf_type type;
1395
1396         switch (io_method) {
1397         case IO_METHOD_READ:
1398                 /* Nothing to do. */
1399                 break;
1400
1401         case IO_METHOD_MMAP:
1402                 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1403
1404                 if (-1 == xioctl (dev_fd, VIDIOC_STREAMOFF, &type))
1405                         errno_exit ("VIDIOC_STREAMOFF");
1406
1407                 break;
1408         }
1409 }
1410
1411 static void
1412 start_capturing                 (void)
1413 {
1414         unsigned int i;
1415         enum v4l2_buf_type type;
1416
1417         switch (io_method) {
1418         case IO_METHOD_READ:
1419                 /* Nothing to do. */
1420                 break;
1421
1422         case IO_METHOD_MMAP:
1423                 for (i = 0; i < n_buffers; ++i) {
1424                         struct v4l2_buffer buf;
1425
1426                         CLEAR (buf);
1427
1428                         buf.type        = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1429                         buf.memory      = V4L2_MEMORY_MMAP;
1430                         buf.index       = i;
1431
1432                         if (-1 == xioctl (dev_fd, VIDIOC_QBUF, &buf))
1433                                 errno_exit ("VIDIOC_QBUF");
1434                 }
1435
1436                 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1437
1438                 if (-1 == xioctl (dev_fd, VIDIOC_STREAMON, &type))
1439                         errno_exit ("VIDIOC_STREAMON");
1440
1441                 break;
1442
1443         default:
1444                 assert (0);
1445                 break;
1446         }
1447 }
1448
1449 static void
1450 free_io_buffers                 (void)
1451 {
1452         unsigned int i;
1453
1454         switch (io_method) {
1455         case IO_METHOD_READ:
1456                 free (buffers[0].start);
1457                 break;
1458
1459         case IO_METHOD_MMAP:
1460                 for (i = 0; i < n_buffers; ++i) {
1461                         if (-1 == munmap (buffers[i].start,
1462                                           buffers[i].length)) {
1463                                 errno_exit ("munmap");
1464                         }
1465                 }
1466
1467                 break;
1468
1469         default:
1470                 assert (0);
1471                 break;
1472         }
1473
1474         free (buffers);
1475         buffers = NULL;
1476 }
1477
1478 static void
1479 init_read_io                    (unsigned int           buffer_size)
1480 {
1481         buffers = calloc (1, sizeof (*buffers));
1482
1483         if (NULL == buffers) {
1484                 error_exit ("Cannot allocate capture buffer (%u bytes).\n",
1485                             sizeof (*buffers));
1486         }
1487
1488         buffers[0].length = buffer_size;
1489         buffers[0].start = malloc (buffer_size);
1490
1491         if (NULL == buffers[0].start) {
1492                 error_exit ("Cannot allocate capture buffer (%u bytes).\n",
1493                             buffer_size);
1494         }
1495 }
1496
1497 static void
1498 init_mmap_io                    (void)
1499 {
1500         struct v4l2_requestbuffers req;
1501
1502         CLEAR (req);
1503
1504         req.count       = 4;
1505         req.type        = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1506         req.memory      = V4L2_MEMORY_MMAP;
1507
1508         if (-1 == xioctl (dev_fd, VIDIOC_REQBUFS, &req)) {
1509                 if (EINVAL == errno) {
1510                         error_exit ("%s does not support "
1511                                     "memory mapping.\n", dev_name);
1512                 } else {
1513                         errno_exit ("VIDIOC_REQBUFS");
1514                 }
1515         }
1516
1517         if (req.count < 2) {
1518                 error_exit ("Insufficient buffer memory on %s.\n",
1519                             dev_name);
1520         }
1521
1522         buffers = calloc (req.count, sizeof (*buffers));
1523         if (NULL == buffers) {
1524                 error_exit ("Cannot allocate capture buffer (%u bytes).\n",
1525                             req.count * sizeof (*buffers));
1526         }
1527
1528         for (n_buffers = 0; n_buffers < req.count; ++n_buffers) {
1529                 struct v4l2_buffer buf;
1530
1531                 CLEAR (buf);
1532
1533                 buf.type        = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1534                 buf.memory      = V4L2_MEMORY_MMAP;
1535                 buf.index       = n_buffers;
1536
1537                 if (-1 == xioctl (dev_fd, VIDIOC_QUERYBUF, &buf))
1538                         errno_exit ("VIDIOC_QUERYBUF");
1539
1540                 buffers[n_buffers].length = buf.length;
1541                 buffers[n_buffers].start =
1542                         mmap (NULL /* start anywhere */,
1543                               buf.length,
1544                               PROT_READ | PROT_WRITE /* required */,
1545                               MAP_SHARED /* recommended */,
1546                               dev_fd, buf.m.offset);
1547
1548                 if (MAP_FAILED == buffers[n_buffers].start)
1549                         errno_exit ("mmap");
1550         }
1551 }
1552
1553 static void
1554 mainloop                        (void)
1555 {
1556         bool checked_formats[N_ELEMENTS (pixel_formats)];
1557
1558         CLEAR (checked_formats);
1559
1560         for (;;) {
1561                 const pixel_format *pf;
1562                 const pixel_format *actual_pf;
1563                 unsigned int width;
1564                 unsigned int height;
1565                 unsigned int min_bpl;
1566                 unsigned int min_size;
1567                 unsigned int i;
1568
1569                 for (i = 0; i < N_ELEMENTS (pixel_formats); ++i) {
1570                         if (checked_formats[i])
1571                                 continue;
1572                         checked_formats[i] = true;
1573                         if (0 != pixel_formats[i].v4l2_fourcc)
1574                                 break;
1575                 }
1576
1577                 if (i >= N_ELEMENTS (pixel_formats))
1578                         return; /* all done */
1579
1580                 pf = pixel_formats + i;
1581
1582                 CLEAR (fmt);
1583
1584                 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1585
1586                 height = 480;
1587                 if (std_id & V4L2_STD_625_50)
1588                         height = 576;
1589
1590                 width = height * 4 / 3;
1591
1592                 fmt.fmt.pix.width = width;
1593                 fmt.fmt.pix.height = height;
1594
1595                 fmt.fmt.pix.pixelformat = pf->v4l2_fourcc;
1596
1597                 fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
1598
1599                 if (-1 == xioctl (dev_fd, VIDIOC_S_FMT, &fmt)) {
1600                         if (EINVAL != errno) {
1601                                 errno_exit ("VIDIOC_S_FMT");
1602                         }
1603
1604                         fprintf (stderr, "Format %s %ux%u "
1605                                  "not supported by driver.\n",
1606                                  pf->v4l2_fourcc_name,
1607                                  width,
1608                                  height);
1609
1610                         continue;
1611                 }
1612
1613                 actual_pf = find_v4l2_fourcc (fmt.fmt.pix.pixelformat);
1614                 if (0 == actual_pf) {
1615                         fprintf (stderr,
1616                                  "Requested pixelformat %s, driver "
1617                                  "returned unknown pixelformat 0x%08x.\n",
1618                                  pf->v4l2_fourcc_name,
1619                                  fmt.fmt.pix.pixelformat);
1620                         continue;
1621                 } else if (pf != actual_pf) {
1622                         /* Some drivers change pixelformat. */
1623                         checked_formats[actual_pf->pixfmt] = true;
1624                         pf = actual_pf;
1625                 }
1626
1627                 min_bpl = (fmt.fmt.pix.width * pf->bits_per_pixel) >> 3;
1628
1629                 if (fmt.fmt.pix.bytesperline < min_bpl) {
1630                         error_exit ("Driver returned fmt.pix.pixelformat=%s "
1631                                     "width=%u height=%u bytesperline=%u. "
1632                                     "Expected bytesperline >= %u.\n",
1633                                     pf->v4l2_fourcc_name,
1634                                     fmt.fmt.pix.width,
1635                                     fmt.fmt.pix.height,
1636                                     fmt.fmt.pix.bytesperline,
1637                                     min_bpl);
1638                         continue;
1639                 }
1640
1641                 min_size = (fmt.fmt.pix.height - 1)
1642                         * MAX (min_bpl, fmt.fmt.pix.bytesperline)
1643                         + min_bpl;
1644
1645                 if (fmt.fmt.pix.sizeimage < min_size) {
1646                         error_exit ("Driver returned fmt.pix.pixelformat=%s "
1647                                     "width=%u height=%u bytesperline=%u "
1648                                     "size=%u. Expected size >= %u.\n",
1649                                     pf->v4l2_fourcc_name,
1650                                     fmt.fmt.pix.width,
1651                                     fmt.fmt.pix.height,
1652                                     fmt.fmt.pix.bytesperline,
1653                                     fmt.fmt.pix.sizeimage,
1654                                     min_size);
1655                         continue;
1656                 }
1657
1658                 if (0 == window) {
1659                         open_window (fmt.fmt.pix.width,
1660                                      fmt.fmt.pix.height);
1661                 }
1662
1663                 switch (io_method) {
1664                 case IO_METHOD_READ:
1665                         init_read_io (fmt.fmt.pix.sizeimage);
1666                         break;
1667
1668                 case IO_METHOD_MMAP:
1669                         init_mmap_io ();
1670                         break;
1671                 }
1672
1673                 start_capturing ();
1674
1675                 capture_loop ();
1676
1677                 stop_capturing ();
1678
1679                 free_io_buffers ();
1680         }
1681 }
1682
1683 static void
1684 init_device                     (void)
1685 {
1686         struct v4l2_capability cap;
1687         struct v4l2_cropcap cropcap;
1688         struct v4l2_crop crop;
1689
1690         if (-1 == xioctl (dev_fd, VIDIOC_QUERYCAP, &cap)) {
1691                 if (EINVAL == errno) {
1692                         error_exit ("%s is not a V4L2 device.\n");
1693                 } else {
1694                         errno_exit ("VIDIOC_QUERYCAP");
1695                 }
1696         }
1697
1698         switch (io_method) {
1699         case 0:
1700                 if (cap.capabilities & V4L2_CAP_STREAMING) {
1701                         io_method = IO_METHOD_MMAP;
1702                 } else if (cap.capabilities & V4L2_CAP_READWRITE) {
1703                         io_method = IO_METHOD_READ;
1704                 } else {
1705                         error_exit ("%s does not support reading or "
1706                                     "streaming.\n");
1707                 }
1708
1709                 break;
1710
1711         case IO_METHOD_READ:
1712                 if (0 == (cap.capabilities & V4L2_CAP_READWRITE)) {
1713                         error_exit ("%s does not support read i/o.\n");
1714                 }
1715
1716                 break;
1717
1718         case IO_METHOD_MMAP:
1719                 if (0 == (cap.capabilities & V4L2_CAP_STREAMING)) {
1720                         error_exit ("%s does not support streaming i/o.\n");
1721                 }
1722
1723                 break;
1724
1725         default:
1726                 assert (0);
1727                 break;
1728         }
1729
1730         CLEAR (cropcap);
1731
1732         cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1733
1734         if (0 == xioctl (dev_fd, VIDIOC_CROPCAP, &cropcap)) {
1735                 crop.type = cropcap.type;
1736                 crop.c = cropcap.defrect; /* reset to default */
1737
1738                 /* Errors ignored. */
1739                 xioctl (dev_fd, VIDIOC_S_CROP, &crop);
1740         } else {
1741                 /* Errors ignored. */
1742         }
1743
1744         if (-1 == xioctl (dev_fd, VIDIOC_G_STD, &std_id))
1745                 errno_exit ("VIDIOC_G_STD");
1746 }
1747
1748 static void
1749 open_device                     (void)
1750 {
1751         struct stat st;
1752
1753         if (-1 == stat (dev_name, &st)) {
1754                 error_exit ("Cannot identify '%s'. %s.\n",
1755                             dev_name, strerror (errno));
1756         }
1757
1758         if (!S_ISCHR (st.st_mode)) {
1759                 error_exit ("%s is not a device file.\n", dev_name);
1760         }
1761
1762         dev_fd = open (dev_name, O_RDWR /* required */ | O_NONBLOCK, 0);
1763         if (-1 == dev_fd) {
1764                 error_exit ("Cannot open %s. %s.\n",
1765                             dev_name, strerror (errno));
1766         }
1767 }
1768
1769 static void
1770 self_test                       (void)
1771 {
1772         const pixel_format *pf;
1773
1774         assert (0 == pixel_formats[0].pixfmt);
1775         assert (N_ELEMENTS (pixel_formats) > 0);
1776
1777         for (pf = pixel_formats + 1;
1778              pf < pixel_formats + N_ELEMENTS (pixel_formats); ++pf) {
1779                 const pixel_format *pf2;
1780                 unsigned int i;
1781
1782 #define pf_assert(expr)                                                 \
1783 do {                                                                    \
1784         if (!(expr)) {                                                  \
1785                 error_exit ("Assertion %s failed in "                   \
1786                             "pixel_format[%d = %s].\n",                 \
1787                             #expr, (int)(pf - pixel_formats),           \
1788                             pf->name ? pf->name : "?");                 \
1789         }                                                               \
1790 } while (0)
1791
1792                 pf_assert (0 != pf->pixfmt);
1793                 pf_assert (NULL != pf->name);
1794
1795                 pf_assert ((0 == pf->v4l2_fourcc)
1796                            == (NULL == pf->v4l2_fourcc_name));
1797
1798                 pf_assert (0 != pf->pixfmt_swap_red_blue);
1799
1800                 pf_assert (LE == pf->byte_order
1801                            || BE == pf->byte_order);
1802
1803                 pf_assert (PACKED_RGB == pf->pixfmt_class
1804                            || BAYER == pf->pixfmt_class);
1805
1806                 if (PACKED_RGB == pf->pixfmt_class) {
1807                         pf_assert (pf->color_depth == (pf->n_bits[0] +
1808                                                        pf->n_bits[1] +
1809                                                        pf->n_bits[2]));
1810
1811                         pf_assert (pf->bits_per_pixel == (pf->n_bits[0] +
1812                                                           pf->n_bits[1] +
1813                                                           pf->n_bits[2] +
1814                                                           pf->n_bits[3]));
1815
1816                         pf_assert (0 != pf->pixfmt_opposite_byte_order);
1817
1818                         if (0 != pf->mask[3]) /* has alpha */
1819                                 pf_assert (0 != pf->pixfmt_opposite_alpha);
1820                         else
1821                                 pf_assert (0 == pf->pixfmt_opposite_alpha);
1822
1823                         for (i = 0; i < N_ELEMENTS (pf->mask); ++i) {
1824                                 pf_assert (pf->n_bits[i] + pf->shr[i] <= 32);
1825                                 pf_assert (pf->mask[i]
1826                                            == (((1u << pf->n_bits[i]) - 1)
1827                                                << (32 - pf->n_bits[i]
1828                                                    - pf->shr[i])));
1829                         }
1830                 }
1831
1832                 for (pf2 = pf + 1;
1833                      pf2 < pixel_formats + N_ELEMENTS (pixel_formats);
1834                      ++pf2) {
1835                         if (pf->pixfmt == pf2->pixfmt
1836                             || 0 == strcmp (pf->name, pf2->name)) {
1837                                 error_exit ("Assertion failure: pixfmt "
1838                                             "%u (%s) twice in "
1839                                             "pixel_formats[] table.\n",
1840                                             pf->pixfmt, pf->name);
1841                         }
1842
1843                         if (0 != pf->v4l2_fourcc
1844                             && 0 != pf2->v4l2_fourcc
1845                             && (pf->v4l2_fourcc == pf2->v4l2_fourcc
1846                                 || 0 == strcmp (pf->v4l2_fourcc_name,
1847                                                 pf2->v4l2_fourcc_name))) {
1848                                 error_exit ("Assertion failure: V4L2 "
1849                                             "fourcc 0x%08x (%s) twice in "
1850                                             "pixel_formats[] table.\n",
1851                                             pf->v4l2_fourcc,
1852                                             pf->v4l2_fourcc_name);
1853                         }
1854                 }
1855
1856 #undef pf_assert
1857
1858         }
1859
1860         /* XXX Should also test the converters here. */
1861 }
1862
1863 static void
1864 usage                           (FILE *                 fp,
1865                                  int                    argc,
1866                                  char **                argv)
1867 {
1868         fprintf (fp, "\
1869 V4L2 pixfmt test " VERSION "\n\
1870 Copyright (C) 2007 Michael H. Schimek\n\
1871 This program is licensed under GPL 2 or later. NO WARRANTIES.\n\n\
1872 Usage: %s [options]\n\n\
1873 Options:\n\
1874 -d | --device name  Video device name [%s]\n\
1875 -h | --help         Print this message\n\
1876 -m | --mmap         Use memory mapped buffers (auto)\n\
1877 -r | --read         Use read() calls (auto)\n\
1878 ",
1879                  my_name, dev_name);
1880 }
1881
1882 static const char short_options [] = "d:hmr";
1883
1884 static const struct option
1885 long_options [] = {
1886         { "device",     required_argument,      NULL,           'd' },
1887         { "help",       no_argument,            NULL,           'h' },
1888         { "mmap",       no_argument,            NULL,           'm' },
1889         { "read",       no_argument,            NULL,           'r' },
1890         { "usage",      no_argument,            NULL,           'h' },
1891         { 0, 0, 0, 0 }
1892 };
1893
1894 int
1895 main                            (int                    argc,
1896                                  char **                argv)
1897 {
1898         my_name = argv[0];
1899
1900         self_test ();
1901
1902         for (;;) {
1903                 int opt_index;
1904                 int c;
1905
1906                 c = getopt_long (argc, argv,
1907                                  short_options, long_options,
1908                                  &opt_index);
1909
1910                 if (-1 == c)
1911                         break;
1912
1913                 switch (c) {
1914                 case 0: /* getopt_long() flag */
1915                         break;
1916
1917                 case 'd':
1918                         dev_name = optarg;
1919                         break;
1920
1921                 case 'h':
1922                         usage (stdout, argc, argv);
1923                         exit (EXIT_SUCCESS);
1924
1925                 case 'm':
1926                         io_method = IO_METHOD_MMAP;
1927                         break;
1928
1929                 case 'r':
1930                         io_method = IO_METHOD_READ;
1931                         break;
1932
1933                 default:
1934                         usage (stderr, argc, argv);
1935                         exit (EXIT_FAILURE);
1936                 }
1937         }
1938
1939         open_device ();
1940
1941         init_device ();
1942
1943         mainloop ();
1944
1945         exit (EXIT_SUCCESS);
1946
1947         return 0;
1948 }
Note: See TracBrowser for help on using the browser.