1 // SPDX-License-Identifier: LGPL-2.1-only
2 /*
3 * Copyright 2018 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
4 */
5
6 #include <unistd.h>
7 #include <stdlib.h>
8 #include <stdio.h>
9 #include <string.h>
10 #include <inttypes.h>
11 #include <sys/types.h>
12 #include <sys/stat.h>
13 #include <fcntl.h>
14 #include <ctype.h>
15 #include <errno.h>
16 #include <sys/ioctl.h>
17 #include <sys/time.h>
18 #include <sys/types.h>
19 #include <dirent.h>
20
21 #include <v4l2-info.h>
22
23 #include <fstream>
24
num2s(unsigned num,bool is_hex=true)25 static std::string num2s(unsigned num, bool is_hex = true)
26 {
27 char buf[16];
28
29 if (is_hex)
30 sprintf(buf, "0x%08x", num);
31 else
32 sprintf(buf, "%u", num);
33 return buf;
34 }
35
36 typedef struct {
37 unsigned flag;
38 const char *str;
39 } flag_def;
40
flags2s(unsigned val,const flag_def * def)41 static std::string flags2s(unsigned val, const flag_def *def)
42 {
43 std::string s;
44
45 while (def->flag) {
46 if (val & def->flag) {
47 if (s.length()) s += ", ";
48 s += def->str;
49 val &= ~def->flag;
50 }
51 def++;
52 }
53 if (val) {
54 if (s.length()) s += ", ";
55 s += num2s(val);
56 }
57 return s;
58 }
59
cap2s(unsigned cap)60 static std::string cap2s(unsigned cap)
61 {
62 std::string s;
63
64 if (cap & V4L2_CAP_VIDEO_CAPTURE)
65 s += "\t\tVideo Capture\n";
66 if (cap & V4L2_CAP_VIDEO_CAPTURE_MPLANE)
67 s += "\t\tVideo Capture Multiplanar\n";
68 if (cap & V4L2_CAP_VIDEO_OUTPUT)
69 s += "\t\tVideo Output\n";
70 if (cap & V4L2_CAP_VIDEO_OUTPUT_MPLANE)
71 s += "\t\tVideo Output Multiplanar\n";
72 if (cap & V4L2_CAP_VIDEO_M2M)
73 s += "\t\tVideo Memory-to-Memory\n";
74 if (cap & V4L2_CAP_VIDEO_M2M_MPLANE)
75 s += "\t\tVideo Memory-to-Memory Multiplanar\n";
76 if (cap & V4L2_CAP_VIDEO_OVERLAY)
77 s += "\t\tVideo Overlay\n";
78 if (cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY)
79 s += "\t\tVideo Output Overlay\n";
80 if (cap & V4L2_CAP_VBI_CAPTURE)
81 s += "\t\tVBI Capture\n";
82 if (cap & V4L2_CAP_VBI_OUTPUT)
83 s += "\t\tVBI Output\n";
84 if (cap & V4L2_CAP_SLICED_VBI_CAPTURE)
85 s += "\t\tSliced VBI Capture\n";
86 if (cap & V4L2_CAP_SLICED_VBI_OUTPUT)
87 s += "\t\tSliced VBI Output\n";
88 if (cap & V4L2_CAP_RDS_CAPTURE)
89 s += "\t\tRDS Capture\n";
90 if (cap & V4L2_CAP_RDS_OUTPUT)
91 s += "\t\tRDS Output\n";
92 if (cap & V4L2_CAP_SDR_CAPTURE)
93 s += "\t\tSDR Capture\n";
94 if (cap & V4L2_CAP_SDR_OUTPUT)
95 s += "\t\tSDR Output\n";
96 if (cap & V4L2_CAP_META_CAPTURE)
97 s += "\t\tMetadata Capture\n";
98 if (cap & V4L2_CAP_META_OUTPUT)
99 s += "\t\tMetadata Output\n";
100 if (cap & V4L2_CAP_TUNER)
101 s += "\t\tTuner\n";
102 if (cap & V4L2_CAP_TOUCH)
103 s += "\t\tTouch Device\n";
104 if (cap & V4L2_CAP_HW_FREQ_SEEK)
105 s += "\t\tHW Frequency Seek\n";
106 if (cap & V4L2_CAP_MODULATOR)
107 s += "\t\tModulator\n";
108 if (cap & V4L2_CAP_AUDIO)
109 s += "\t\tAudio\n";
110 if (cap & V4L2_CAP_RADIO)
111 s += "\t\tRadio\n";
112 if (cap & V4L2_CAP_READWRITE)
113 s += "\t\tRead/Write\n";
114 if (cap & V4L2_CAP_ASYNCIO)
115 s += "\t\tAsync I/O\n";
116 if (cap & V4L2_CAP_STREAMING)
117 s += "\t\tStreaming\n";
118 if (cap & V4L2_CAP_EXT_PIX_FORMAT)
119 s += "\t\tExtended Pix Format\n";
120 if (cap & V4L2_CAP_DEVICE_CAPS)
121 s += "\t\tDevice Capabilities\n";
122 return s;
123 }
124
v4l2_info_capability(const v4l2_capability & vcap)125 void v4l2_info_capability(const v4l2_capability &vcap)
126 {
127 printf("\tDriver name : %s\n", vcap.driver);
128 printf("\tCard type : %s\n", vcap.card);
129 printf("\tBus info : %s\n", vcap.bus_info);
130 printf("\tDriver version : %d.%d.%d\n",
131 vcap.version >> 16,
132 (vcap.version >> 8) & 0xff,
133 vcap.version & 0xff);
134 printf("\tCapabilities : 0x%08x\n", vcap.capabilities);
135 printf("%s", cap2s(vcap.capabilities).c_str());
136 if (vcap.capabilities & V4L2_CAP_DEVICE_CAPS) {
137 printf("\tDevice Caps : 0x%08x\n", vcap.device_caps);
138 printf("%s", cap2s(vcap.device_caps).c_str());
139 }
140 }
141
fcc2s(uint32_t val)142 std::string fcc2s(uint32_t val)
143 {
144 std::string s;
145
146 s += val & 0x7f;
147 s += (val >> 8) & 0x7f;
148 s += (val >> 16) & 0x7f;
149 s += (val >> 24) & 0x7f;
150 if (val & (1U << 31))
151 s += "-BE";
152 return s;
153 }
154
pixfmt2s(uint32_t format)155 std::string pixfmt2s(uint32_t format)
156 {
157 switch (format) {
158 #include "v4l2-pix-formats.h"
159 default:
160 return std::string("Unknown (") + num2s(format) + ")";
161 }
162 }
163
buftype2s(int type)164 std::string buftype2s(int type)
165 {
166 switch (type) {
167 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
168 return "Video Capture";
169 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
170 return "Video Capture Multiplanar";
171 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
172 return "Video Output";
173 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
174 return "Video Output Multiplanar";
175 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
176 return "Video Overlay";
177 case V4L2_BUF_TYPE_VBI_CAPTURE:
178 return "VBI Capture";
179 case V4L2_BUF_TYPE_VBI_OUTPUT:
180 return "VBI Output";
181 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
182 return "Sliced VBI Capture";
183 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
184 return "Sliced VBI Output";
185 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
186 return "Video Output Overlay";
187 case V4L2_BUF_TYPE_SDR_CAPTURE:
188 return "SDR Capture";
189 case V4L2_BUF_TYPE_SDR_OUTPUT:
190 return "SDR Output";
191 case V4L2_BUF_TYPE_META_CAPTURE:
192 return "Metadata Capture";
193 case V4L2_BUF_TYPE_META_OUTPUT:
194 return "Metadata Output";
195 case V4L2_BUF_TYPE_PRIVATE:
196 return "Private";
197 default:
198 return std::string("Unknown (") + num2s(type) + ")";
199 }
200 }
201
202 static const flag_def bufcap_def[] = {
203 { V4L2_BUF_CAP_SUPPORTS_MMAP, "mmap" },
204 { V4L2_BUF_CAP_SUPPORTS_USERPTR, "userptr" },
205 { V4L2_BUF_CAP_SUPPORTS_DMABUF, "dmabuf" },
206 { V4L2_BUF_CAP_SUPPORTS_REQUESTS, "requests" },
207 { V4L2_BUF_CAP_SUPPORTS_ORPHANED_BUFS, "orphaned-bufs" },
208 { V4L2_BUF_CAP_SUPPORTS_M2M_HOLD_CAPTURE_BUF, "m2m-hold-capture-buf" },
209 { 0, NULL }
210 };
211
bufcap2s(uint32_t caps)212 std::string bufcap2s(uint32_t caps)
213 {
214 return flags2s(caps, bufcap_def);
215 }
216
field2s(int val)217 std::string field2s(int val)
218 {
219 switch (val) {
220 case V4L2_FIELD_ANY:
221 return "Any";
222 case V4L2_FIELD_NONE:
223 return "None";
224 case V4L2_FIELD_TOP:
225 return "Top";
226 case V4L2_FIELD_BOTTOM:
227 return "Bottom";
228 case V4L2_FIELD_INTERLACED:
229 return "Interlaced";
230 case V4L2_FIELD_SEQ_TB:
231 return "Sequential Top-Bottom";
232 case V4L2_FIELD_SEQ_BT:
233 return "Sequential Bottom-Top";
234 case V4L2_FIELD_ALTERNATE:
235 return "Alternating";
236 case V4L2_FIELD_INTERLACED_TB:
237 return "Interlaced Top-Bottom";
238 case V4L2_FIELD_INTERLACED_BT:
239 return "Interlaced Bottom-Top";
240 default:
241 return "Unknown (" + num2s(val) + ")";
242 }
243 }
244
colorspace2s(int val)245 std::string colorspace2s(int val)
246 {
247 switch (val) {
248 case V4L2_COLORSPACE_DEFAULT:
249 return "Default";
250 case V4L2_COLORSPACE_SMPTE170M:
251 return "SMPTE 170M";
252 case V4L2_COLORSPACE_SMPTE240M:
253 return "SMPTE 240M";
254 case V4L2_COLORSPACE_REC709:
255 return "Rec. 709";
256 case V4L2_COLORSPACE_BT878:
257 return "Broken Bt878";
258 case V4L2_COLORSPACE_470_SYSTEM_M:
259 return "470 System M";
260 case V4L2_COLORSPACE_470_SYSTEM_BG:
261 return "470 System BG";
262 case V4L2_COLORSPACE_JPEG:
263 return "JPEG";
264 case V4L2_COLORSPACE_SRGB:
265 return "sRGB";
266 case V4L2_COLORSPACE_OPRGB:
267 return "opRGB";
268 case V4L2_COLORSPACE_DCI_P3:
269 return "DCI-P3";
270 case V4L2_COLORSPACE_BT2020:
271 return "BT.2020";
272 case V4L2_COLORSPACE_RAW:
273 return "Raw";
274 default:
275 return "Unknown (" + num2s(val) + ")";
276 }
277 }
278
xfer_func2s(int val)279 std::string xfer_func2s(int val)
280 {
281 switch (val) {
282 case V4L2_XFER_FUNC_DEFAULT:
283 return "Default";
284 case V4L2_XFER_FUNC_709:
285 return "Rec. 709";
286 case V4L2_XFER_FUNC_SRGB:
287 return "sRGB";
288 case V4L2_XFER_FUNC_OPRGB:
289 return "opRGB";
290 case V4L2_XFER_FUNC_DCI_P3:
291 return "DCI-P3";
292 case V4L2_XFER_FUNC_SMPTE2084:
293 return "SMPTE 2084";
294 case V4L2_XFER_FUNC_SMPTE240M:
295 return "SMPTE 240M";
296 case V4L2_XFER_FUNC_NONE:
297 return "None";
298 default:
299 return "Unknown (" + num2s(val) + ")";
300 }
301 }
302
ycbcr_enc2s(int val)303 std::string ycbcr_enc2s(int val)
304 {
305 switch (val) {
306 case V4L2_YCBCR_ENC_DEFAULT:
307 return "Default";
308 case V4L2_YCBCR_ENC_601:
309 return "ITU-R 601";
310 case V4L2_YCBCR_ENC_709:
311 return "Rec. 709";
312 case V4L2_YCBCR_ENC_XV601:
313 return "xvYCC 601";
314 case V4L2_YCBCR_ENC_XV709:
315 return "xvYCC 709";
316 case V4L2_YCBCR_ENC_BT2020:
317 return "BT.2020";
318 case V4L2_YCBCR_ENC_BT2020_CONST_LUM:
319 return "BT.2020 Constant Luminance";
320 case V4L2_YCBCR_ENC_SMPTE240M:
321 return "SMPTE 240M";
322 case V4L2_HSV_ENC_180:
323 return "HSV with Hue 0-179";
324 case V4L2_HSV_ENC_256:
325 return "HSV with Hue 0-255";
326 default:
327 return "Unknown (" + num2s(val) + ")";
328 }
329 }
330
quantization2s(int val)331 std::string quantization2s(int val)
332 {
333 switch (val) {
334 case V4L2_QUANTIZATION_DEFAULT:
335 return "Default";
336 case V4L2_QUANTIZATION_FULL_RANGE:
337 return "Full Range";
338 case V4L2_QUANTIZATION_LIM_RANGE:
339 return "Limited Range";
340 default:
341 return "Unknown (" + num2s(val) + ")";
342 }
343 }
344
345 static const flag_def pixflags_def[] = {
346 { V4L2_PIX_FMT_FLAG_PREMUL_ALPHA, "premultiplied-alpha" },
347 { 0, NULL }
348 };
349
pixflags2s(unsigned flags)350 std::string pixflags2s(unsigned flags)
351 {
352 return flags2s(flags, pixflags_def);
353 }
354
355 static const flag_def service_def[] = {
356 { V4L2_SLICED_TELETEXT_B, "teletext" },
357 { V4L2_SLICED_VPS, "vps" },
358 { V4L2_SLICED_CAPTION_525, "cc" },
359 { V4L2_SLICED_WSS_625, "wss" },
360 { 0, NULL }
361 };
362
service2s(unsigned service)363 std::string service2s(unsigned service)
364 {
365 return flags2s(service, service_def);
366 }
367
368 static const flag_def fmtdesc_def[] = {
369 { V4L2_FMT_FLAG_COMPRESSED, "compressed" },
370 { V4L2_FMT_FLAG_EMULATED, "emulated" },
371 { V4L2_FMT_FLAG_CONTINUOUS_BYTESTREAM, "continuous-bytestream" },
372 { V4L2_FMT_FLAG_DYN_RESOLUTION, "dyn-resolution" },
373 { 0, NULL }
374 };
375
fmtdesc2s(unsigned flags)376 std::string fmtdesc2s(unsigned flags)
377 {
378 return flags2s(flags, fmtdesc_def);
379 }
380
381 static const flag_def selection_targets_def[] = {
382 { V4L2_SEL_TGT_CROP_ACTIVE, "crop" },
383 { V4L2_SEL_TGT_CROP_DEFAULT, "crop_default" },
384 { V4L2_SEL_TGT_CROP_BOUNDS, "crop_bounds" },
385 { V4L2_SEL_TGT_COMPOSE_ACTIVE, "compose" },
386 { V4L2_SEL_TGT_COMPOSE_DEFAULT, "compose_default" },
387 { V4L2_SEL_TGT_COMPOSE_BOUNDS, "compose_bounds" },
388 { V4L2_SEL_TGT_COMPOSE_PADDED, "compose_padded" },
389 { V4L2_SEL_TGT_NATIVE_SIZE, "native_size" },
390 { 0, NULL }
391 };
392
valid_seltarget_at_idx(unsigned i)393 bool valid_seltarget_at_idx(unsigned i)
394 {
395 return i < sizeof(selection_targets_def) / sizeof(selection_targets_def[0]) - 1;
396 }
397
seltarget_at_idx(unsigned i)398 unsigned seltarget_at_idx(unsigned i)
399 {
400 if (valid_seltarget_at_idx(i))
401 return selection_targets_def[i].flag;
402 return 0;
403 }
404
seltarget2s(uint32_t target)405 std::string seltarget2s(uint32_t target)
406 {
407 int i = 0;
408
409 while (selection_targets_def[i].str != NULL) {
410 if (selection_targets_def[i].flag == target)
411 return selection_targets_def[i].str;
412 i++;
413 }
414 return std::string("Unknown (") + num2s(target) + ")";
415 }
416
417 const flag_def selection_flags_def[] = {
418 { V4L2_SEL_FLAG_GE, "ge" },
419 { V4L2_SEL_FLAG_LE, "le" },
420 { V4L2_SEL_FLAG_KEEP_CONFIG, "keep-config" },
421 { 0, NULL }
422 };
423
selflags2s(uint32_t flags)424 std::string selflags2s(uint32_t flags)
425 {
426 return flags2s(flags, selection_flags_def);
427 }
428
429 static const char *std_pal[] = {
430 "B", "B1", "G", "H", "I", "D", "D1", "K",
431 "M", "N", "Nc", "60",
432 NULL
433 };
434 static const char *std_ntsc[] = {
435 "M", "M-JP", "443", "M-KR",
436 NULL
437 };
438 static const char *std_secam[] = {
439 "B", "D", "G", "H", "K", "K1", "L", "Lc",
440 NULL
441 };
442 static const char *std_atsc[] = {
443 "8-VSB", "16-VSB",
444 NULL
445 };
446
partstd2s(const char * prefix,const char * stds[],unsigned long long std)447 static std::string partstd2s(const char *prefix, const char *stds[], unsigned long long std)
448 {
449 std::string s = std::string(prefix) + "-";
450 int first = 1;
451
452 while (*stds) {
453 if (std & 1) {
454 if (!first)
455 s += "/";
456 first = 0;
457 s += *stds;
458 }
459 stds++;
460 std >>= 1;
461 }
462 return s;
463 }
464
std2s(v4l2_std_id std,const char * sep)465 std::string std2s(v4l2_std_id std, const char *sep)
466 {
467 std::string s;
468
469 if (std & 0xfff) {
470 s += partstd2s("PAL", std_pal, std);
471 }
472 if (std & 0xf000) {
473 if (s.length()) s += sep;
474 s += partstd2s("NTSC", std_ntsc, std >> 12);
475 }
476 if (std & 0xff0000) {
477 if (s.length()) s += sep;
478 s += partstd2s("SECAM", std_secam, std >> 16);
479 }
480 if (std & 0xf000000) {
481 if (s.length()) s += sep;
482 s += partstd2s("ATSC", std_atsc, std >> 24);
483 }
484 return s;
485 }
486
ctrlflags2s(uint32_t flags)487 std::string ctrlflags2s(uint32_t flags)
488 {
489 static const flag_def def[] = {
490 { V4L2_CTRL_FLAG_GRABBED, "grabbed" },
491 { V4L2_CTRL_FLAG_DISABLED, "disabled" },
492 { V4L2_CTRL_FLAG_READ_ONLY, "read-only" },
493 { V4L2_CTRL_FLAG_UPDATE, "update" },
494 { V4L2_CTRL_FLAG_INACTIVE, "inactive" },
495 { V4L2_CTRL_FLAG_SLIDER, "slider" },
496 { V4L2_CTRL_FLAG_WRITE_ONLY, "write-only" },
497 { V4L2_CTRL_FLAG_VOLATILE, "volatile" },
498 { V4L2_CTRL_FLAG_HAS_PAYLOAD,"has-payload" },
499 { V4L2_CTRL_FLAG_EXECUTE_ON_WRITE, "execute-on-write" },
500 { V4L2_CTRL_FLAG_MODIFY_LAYOUT, "modify-layout" },
501 { 0, NULL }
502 };
503 return flags2s(flags, def);
504 }
505
506 static const flag_def in_status_def[] = {
507 { V4L2_IN_ST_NO_POWER, "no power" },
508 { V4L2_IN_ST_NO_SIGNAL, "no signal" },
509 { V4L2_IN_ST_NO_COLOR, "no color" },
510 { V4L2_IN_ST_HFLIP, "hflip" },
511 { V4L2_IN_ST_VFLIP, "vflip" },
512 { V4L2_IN_ST_NO_H_LOCK, "no hsync lock" },
513 { V4L2_IN_ST_NO_V_LOCK, "no vsync lock" },
514 { V4L2_IN_ST_NO_STD_LOCK, "no standard format lock" },
515 { V4L2_IN_ST_COLOR_KILL, "color kill" },
516 { V4L2_IN_ST_NO_SYNC, "no sync lock" },
517 { V4L2_IN_ST_NO_EQU, "no equalizer lock" },
518 { V4L2_IN_ST_NO_CARRIER, "no carrier" },
519 { V4L2_IN_ST_MACROVISION, "macrovision" },
520 { V4L2_IN_ST_NO_ACCESS, "no conditional access" },
521 { V4L2_IN_ST_VTR, "VTR time constant" },
522 { 0, NULL }
523 };
524
in_status2s(uint32_t status)525 std::string in_status2s(uint32_t status)
526 {
527 return status ? flags2s(status, in_status_def) : "ok";
528 }
529
530 static const flag_def input_cap_def[] = {
531 { V4L2_IN_CAP_DV_TIMINGS, "DV timings" },
532 { V4L2_IN_CAP_STD, "SDTV standards" },
533 { V4L2_IN_CAP_NATIVE_SIZE, "Native Size" },
534 { 0, NULL }
535 };
536
input_cap2s(uint32_t capabilities)537 std::string input_cap2s(uint32_t capabilities)
538 {
539 return capabilities ? flags2s(capabilities, input_cap_def) : "not defined";
540 }
541
542 static const flag_def output_cap_def[] = {
543 { V4L2_OUT_CAP_DV_TIMINGS, "DV timings" },
544 { V4L2_OUT_CAP_STD, "SDTV standards" },
545 { V4L2_OUT_CAP_NATIVE_SIZE, "Native Size" },
546 { 0, NULL }
547 };
548
output_cap2s(uint32_t capabilities)549 std::string output_cap2s(uint32_t capabilities)
550 {
551 return capabilities ? flags2s(capabilities, output_cap_def) : "not defined";
552 }
553
fbufcap2s(unsigned cap)554 std::string fbufcap2s(unsigned cap)
555 {
556 std::string s;
557
558 if (cap & V4L2_FBUF_CAP_EXTERNOVERLAY)
559 s += "\t\t\tExtern Overlay\n";
560 if (cap & V4L2_FBUF_CAP_CHROMAKEY)
561 s += "\t\t\tChromakey\n";
562 if (cap & V4L2_FBUF_CAP_SRC_CHROMAKEY)
563 s += "\t\t\tSource Chromakey\n";
564 if (cap & V4L2_FBUF_CAP_GLOBAL_ALPHA)
565 s += "\t\t\tGlobal Alpha\n";
566 if (cap & V4L2_FBUF_CAP_LOCAL_ALPHA)
567 s += "\t\t\tLocal Alpha\n";
568 if (cap & V4L2_FBUF_CAP_LOCAL_INV_ALPHA)
569 s += "\t\t\tLocal Inverted Alpha\n";
570 if (cap & V4L2_FBUF_CAP_LIST_CLIPPING)
571 s += "\t\t\tClipping List\n";
572 if (cap & V4L2_FBUF_CAP_BITMAP_CLIPPING)
573 s += "\t\t\tClipping Bitmap\n";
574 if (s.empty()) s += "\t\t\t\n";
575 return s;
576 }
577
fbufflags2s(unsigned fl)578 std::string fbufflags2s(unsigned fl)
579 {
580 std::string s;
581
582 if (fl & V4L2_FBUF_FLAG_PRIMARY)
583 s += "\t\t\tPrimary Graphics Surface\n";
584 if (fl & V4L2_FBUF_FLAG_OVERLAY)
585 s += "\t\t\tOverlay Matches Capture/Output Size\n";
586 if (fl & V4L2_FBUF_FLAG_CHROMAKEY)
587 s += "\t\t\tChromakey\n";
588 if (fl & V4L2_FBUF_FLAG_SRC_CHROMAKEY)
589 s += "\t\t\tSource Chromakey\n";
590 if (fl & V4L2_FBUF_FLAG_GLOBAL_ALPHA)
591 s += "\t\t\tGlobal Alpha\n";
592 if (fl & V4L2_FBUF_FLAG_LOCAL_ALPHA)
593 s += "\t\t\tLocal Alpha\n";
594 if (fl & V4L2_FBUF_FLAG_LOCAL_INV_ALPHA)
595 s += "\t\t\tLocal Inverted Alpha\n";
596 if (s.empty()) s += "\t\t\t\n";
597 return s;
598 }
599
600 static const flag_def dv_standards_def[] = {
601 { V4L2_DV_BT_STD_CEA861, "CTA-861" },
602 { V4L2_DV_BT_STD_DMT, "DMT" },
603 { V4L2_DV_BT_STD_CVT, "CVT" },
604 { V4L2_DV_BT_STD_GTF, "GTF" },
605 { V4L2_DV_BT_STD_SDI, "SDI" },
606 { 0, NULL }
607 };
608
dv_standards2s(uint32_t flags)609 std::string dv_standards2s(uint32_t flags)
610 {
611 return flags2s(flags, dv_standards_def);
612 }
613
dvflags2s(unsigned vsync,int val)614 std::string dvflags2s(unsigned vsync, int val)
615 {
616 std::string s;
617
618 if (val & V4L2_DV_FL_REDUCED_BLANKING)
619 s += vsync == 8 ?
620 "reduced blanking v2, " :
621 "reduced blanking, ";
622 if (val & V4L2_DV_FL_CAN_REDUCE_FPS)
623 s += "framerate can be reduced by 1/1.001, ";
624 if (val & V4L2_DV_FL_REDUCED_FPS)
625 s += "framerate is reduced by 1/1.001, ";
626 if (val & V4L2_DV_FL_CAN_DETECT_REDUCED_FPS)
627 s += "can detect reduced framerates, ";
628 if (val & V4L2_DV_FL_HALF_LINE)
629 s += "half-line, ";
630 if (val & V4L2_DV_FL_IS_CE_VIDEO)
631 s += "CE-video, ";
632 if (val & V4L2_DV_FL_FIRST_FIELD_EXTRA_LINE)
633 s += "first field has extra line, ";
634 if (val & V4L2_DV_FL_HAS_PICTURE_ASPECT)
635 s += "has picture aspect, ";
636 if (val & V4L2_DV_FL_HAS_CEA861_VIC)
637 s += "has CTA-861 VIC, ";
638 if (val & V4L2_DV_FL_HAS_HDMI_VIC)
639 s += "has HDMI VIC, ";
640 if (s.length())
641 return s.erase(s.length() - 2, 2);
642 return s;
643 }
644
645 static const flag_def dv_caps_def[] = {
646 { V4L2_DV_BT_CAP_INTERLACED, "Interlaced" },
647 { V4L2_DV_BT_CAP_PROGRESSIVE, "Progressive" },
648 { V4L2_DV_BT_CAP_REDUCED_BLANKING, "Reduced Blanking" },
649 { V4L2_DV_BT_CAP_CUSTOM, "Custom Formats" },
650 { 0, NULL }
651 };
652
dv_caps2s(uint32_t flags)653 std::string dv_caps2s(uint32_t flags)
654 {
655 return flags2s(flags, dv_caps_def);
656 }
657
658 static const flag_def tc_flags_def[] = {
659 { V4L2_TC_FLAG_DROPFRAME, "dropframe" },
660 { V4L2_TC_FLAG_COLORFRAME, "colorframe" },
661 { V4L2_TC_USERBITS_field, "userbits-field" },
662 { V4L2_TC_USERBITS_USERDEFINED, "userbits-userdefined" },
663 { V4L2_TC_USERBITS_8BITCHARS, "userbits-8bitchars" },
664 { 0, NULL }
665 };
666
tc_flags2s(uint32_t flags)667 std::string tc_flags2s(uint32_t flags)
668 {
669 return flags2s(flags, tc_flags_def);
670 }
671
672 static const flag_def buffer_flags_def[] = {
673 { V4L2_BUF_FLAG_MAPPED, "mapped" },
674 { V4L2_BUF_FLAG_QUEUED, "queued" },
675 { V4L2_BUF_FLAG_DONE, "done" },
676 { V4L2_BUF_FLAG_KEYFRAME, "keyframe" },
677 { V4L2_BUF_FLAG_PFRAME, "P-frame" },
678 { V4L2_BUF_FLAG_BFRAME, "B-frame" },
679 { V4L2_BUF_FLAG_ERROR, "error" },
680 { V4L2_BUF_FLAG_TIMECODE, "timecode" },
681 { V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF, "m2m-hold-capture-buf" },
682 { V4L2_BUF_FLAG_PREPARED, "prepared" },
683 { V4L2_BUF_FLAG_NO_CACHE_INVALIDATE, "no-cache-invalidate" },
684 { V4L2_BUF_FLAG_NO_CACHE_CLEAN, "no-cache-clean" },
685 { V4L2_BUF_FLAG_LAST, "last" },
686 { V4L2_BUF_FLAG_REQUEST_FD, "request-fd" },
687 { V4L2_BUF_FLAG_IN_REQUEST, "in-request" },
688 { 0, NULL }
689 };
690
bufferflags2s(uint32_t flags)691 std::string bufferflags2s(uint32_t flags)
692 {
693 const unsigned ts_mask = V4L2_BUF_FLAG_TIMESTAMP_MASK | V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
694 std::string s = flags2s(flags & ~ts_mask, buffer_flags_def);
695
696 if (s.length())
697 s += ", ";
698
699 switch (flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) {
700 case V4L2_BUF_FLAG_TIMESTAMP_UNKNOWN:
701 s += "ts-unknown";
702 break;
703 case V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC:
704 s += "ts-monotonic";
705 break;
706 case V4L2_BUF_FLAG_TIMESTAMP_COPY:
707 s += "ts-copy";
708 break;
709 default:
710 s += "ts-invalid";
711 break;
712 }
713 switch (flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK) {
714 case V4L2_BUF_FLAG_TSTAMP_SRC_EOF:
715 s += ", ts-src-eof";
716 break;
717 case V4L2_BUF_FLAG_TSTAMP_SRC_SOE:
718 s += ", ts-src-soe";
719 break;
720 default:
721 s += ", ts-src-invalid";
722 break;
723 }
724 return s;
725 }
726
727 static const flag_def vbi_def[] = {
728 { V4L2_VBI_UNSYNC, "unsynchronized" },
729 { V4L2_VBI_INTERLACED, "interlaced" },
730 { 0, NULL }
731 };
732
vbiflags2s(uint32_t flags)733 std::string vbiflags2s(uint32_t flags)
734 {
735 return flags2s(flags, vbi_def);
736 }
737