| // SPDX-License-Identifier: LGPL-2.1-only |
| /* |
| * Copyright 2018 Cisco Systems, Inc. and/or its affiliates. All rights reserved. |
| */ |
| |
| #include <v4l2-info.h> |
| |
| static std::string num2s(unsigned num, bool is_hex = true) |
| { |
| char buf[16]; |
| |
| if (is_hex) |
| sprintf(buf, "0x%08x", num); |
| else |
| sprintf(buf, "%u", num); |
| return buf; |
| } |
| |
| struct flag_def { |
| unsigned flag; |
| const char *str; |
| }; |
| |
| static std::string flags2s(unsigned val, const flag_def *def) |
| { |
| std::string s; |
| |
| while (def->flag) { |
| if (val & def->flag) { |
| if (s.length()) s += ", "; |
| s += def->str; |
| val &= ~def->flag; |
| } |
| def++; |
| } |
| if (val) { |
| if (s.length()) s += ", "; |
| s += num2s(val); |
| } |
| return s; |
| } |
| |
| static std::string cap2s(unsigned cap) |
| { |
| std::string s; |
| |
| if (cap & V4L2_CAP_VIDEO_CAPTURE) |
| s += "\t\tVideo Capture\n"; |
| if (cap & V4L2_CAP_VIDEO_CAPTURE_MPLANE) |
| s += "\t\tVideo Capture Multiplanar\n"; |
| if (cap & V4L2_CAP_VIDEO_OUTPUT) |
| s += "\t\tVideo Output\n"; |
| if (cap & V4L2_CAP_VIDEO_OUTPUT_MPLANE) |
| s += "\t\tVideo Output Multiplanar\n"; |
| if (cap & V4L2_CAP_VIDEO_M2M) |
| s += "\t\tVideo Memory-to-Memory\n"; |
| if (cap & V4L2_CAP_VIDEO_M2M_MPLANE) |
| s += "\t\tVideo Memory-to-Memory Multiplanar\n"; |
| if (cap & V4L2_CAP_VIDEO_OVERLAY) |
| s += "\t\tVideo Overlay\n"; |
| if (cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY) |
| s += "\t\tVideo Output Overlay\n"; |
| if (cap & V4L2_CAP_VBI_CAPTURE) |
| s += "\t\tVBI Capture\n"; |
| if (cap & V4L2_CAP_VBI_OUTPUT) |
| s += "\t\tVBI Output\n"; |
| if (cap & V4L2_CAP_SLICED_VBI_CAPTURE) |
| s += "\t\tSliced VBI Capture\n"; |
| if (cap & V4L2_CAP_SLICED_VBI_OUTPUT) |
| s += "\t\tSliced VBI Output\n"; |
| if (cap & V4L2_CAP_RDS_CAPTURE) |
| s += "\t\tRDS Capture\n"; |
| if (cap & V4L2_CAP_RDS_OUTPUT) |
| s += "\t\tRDS Output\n"; |
| if (cap & V4L2_CAP_SDR_CAPTURE) |
| s += "\t\tSDR Capture\n"; |
| if (cap & V4L2_CAP_SDR_OUTPUT) |
| s += "\t\tSDR Output\n"; |
| if (cap & V4L2_CAP_META_CAPTURE) |
| s += "\t\tMetadata Capture\n"; |
| if (cap & V4L2_CAP_META_OUTPUT) |
| s += "\t\tMetadata Output\n"; |
| if (cap & V4L2_CAP_TUNER) |
| s += "\t\tTuner\n"; |
| if (cap & V4L2_CAP_TOUCH) |
| s += "\t\tTouch Device\n"; |
| if (cap & V4L2_CAP_HW_FREQ_SEEK) |
| s += "\t\tHW Frequency Seek\n"; |
| if (cap & V4L2_CAP_MODULATOR) |
| s += "\t\tModulator\n"; |
| if (cap & V4L2_CAP_AUDIO) |
| s += "\t\tAudio\n"; |
| if (cap & V4L2_CAP_RADIO) |
| s += "\t\tRadio\n"; |
| if (cap & V4L2_CAP_READWRITE) |
| s += "\t\tRead/Write\n"; |
| if (cap & V4L2_CAP_ASYNCIO) |
| s += "\t\tAsync I/O\n"; |
| if (cap & V4L2_CAP_STREAMING) |
| s += "\t\tStreaming\n"; |
| if (cap & V4L2_CAP_EXT_PIX_FORMAT) |
| s += "\t\tExtended Pix Format\n"; |
| if (cap & V4L2_CAP_DEVICE_CAPS) |
| s += "\t\tDevice Capabilities\n"; |
| return s; |
| } |
| |
| static std::string subdevcap2s(unsigned cap) |
| { |
| std::string s; |
| |
| if (cap & V4L2_SUBDEV_CAP_RO_SUBDEV) |
| s += "\t\tRead-Only Sub-Device\n"; |
| return s; |
| } |
| |
| void v4l2_info_capability(const v4l2_capability &vcap) |
| { |
| printf("\tDriver name : %s\n", vcap.driver); |
| printf("\tCard type : %s\n", vcap.card); |
| printf("\tBus info : %s\n", vcap.bus_info); |
| printf("\tDriver version : %d.%d.%d\n", |
| vcap.version >> 16, |
| (vcap.version >> 8) & 0xff, |
| vcap.version & 0xff); |
| printf("\tCapabilities : 0x%08x\n", vcap.capabilities); |
| printf("%s", cap2s(vcap.capabilities).c_str()); |
| if (vcap.capabilities & V4L2_CAP_DEVICE_CAPS) { |
| printf("\tDevice Caps : 0x%08x\n", vcap.device_caps); |
| printf("%s", cap2s(vcap.device_caps).c_str()); |
| } |
| } |
| |
| void v4l2_info_subdev_capability(const v4l2_subdev_capability &subdevcap) |
| { |
| printf("\tDriver version : %d.%d.%d\n", |
| subdevcap.version >> 16, |
| (subdevcap.version >> 8) & 0xff, |
| subdevcap.version & 0xff); |
| printf("\tCapabilities : 0x%08x\n", subdevcap.capabilities); |
| printf("%s", subdevcap2s(subdevcap.capabilities).c_str()); |
| } |
| |
| std::string fcc2s(__u32 val) |
| { |
| std::string s; |
| |
| s += val & 0x7f; |
| s += (val >> 8) & 0x7f; |
| s += (val >> 16) & 0x7f; |
| s += (val >> 24) & 0x7f; |
| if (val & (1U << 31)) |
| s += "-BE"; |
| return s; |
| } |
| |
| std::string pixfmt2s(__u32 format) |
| { |
| switch (format) { |
| #include "v4l2-pix-formats.h" |
| default: |
| return std::string("Unknown (") + num2s(format) + ")"; |
| } |
| } |
| |
| std::string buftype2s(int type) |
| { |
| switch (type) { |
| case V4L2_BUF_TYPE_VIDEO_CAPTURE: |
| return "Video Capture"; |
| case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: |
| return "Video Capture Multiplanar"; |
| case V4L2_BUF_TYPE_VIDEO_OUTPUT: |
| return "Video Output"; |
| case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: |
| return "Video Output Multiplanar"; |
| case V4L2_BUF_TYPE_VIDEO_OVERLAY: |
| return "Video Overlay"; |
| case V4L2_BUF_TYPE_VBI_CAPTURE: |
| return "VBI Capture"; |
| case V4L2_BUF_TYPE_VBI_OUTPUT: |
| return "VBI Output"; |
| case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: |
| return "Sliced VBI Capture"; |
| case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: |
| return "Sliced VBI Output"; |
| case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: |
| return "Video Output Overlay"; |
| case V4L2_BUF_TYPE_SDR_CAPTURE: |
| return "SDR Capture"; |
| case V4L2_BUF_TYPE_SDR_OUTPUT: |
| return "SDR Output"; |
| case V4L2_BUF_TYPE_META_CAPTURE: |
| return "Metadata Capture"; |
| case V4L2_BUF_TYPE_META_OUTPUT: |
| return "Metadata Output"; |
| case V4L2_BUF_TYPE_PRIVATE: |
| return "Private"; |
| default: |
| return std::string("Unknown (") + num2s(type) + ")"; |
| } |
| } |
| |
| static constexpr flag_def bufcap_def[] = { |
| { V4L2_BUF_CAP_SUPPORTS_MMAP, "mmap" }, |
| { V4L2_BUF_CAP_SUPPORTS_USERPTR, "userptr" }, |
| { V4L2_BUF_CAP_SUPPORTS_DMABUF, "dmabuf" }, |
| { V4L2_BUF_CAP_SUPPORTS_REQUESTS, "requests" }, |
| { V4L2_BUF_CAP_SUPPORTS_ORPHANED_BUFS, "orphaned-bufs" }, |
| { V4L2_BUF_CAP_SUPPORTS_M2M_HOLD_CAPTURE_BUF, "m2m-hold-capture-buf" }, |
| { V4L2_BUF_CAP_SUPPORTS_MMAP_CACHE_HINTS, "mmap-cache-hints" }, |
| { 0, nullptr } |
| }; |
| |
| std::string bufcap2s(__u32 caps) |
| { |
| return flags2s(caps, bufcap_def); |
| } |
| |
| std::string field2s(int val) |
| { |
| switch (val) { |
| case V4L2_FIELD_ANY: |
| return "Any"; |
| case V4L2_FIELD_NONE: |
| return "None"; |
| case V4L2_FIELD_TOP: |
| return "Top"; |
| case V4L2_FIELD_BOTTOM: |
| return "Bottom"; |
| case V4L2_FIELD_INTERLACED: |
| return "Interlaced"; |
| case V4L2_FIELD_SEQ_TB: |
| return "Sequential Top-Bottom"; |
| case V4L2_FIELD_SEQ_BT: |
| return "Sequential Bottom-Top"; |
| case V4L2_FIELD_ALTERNATE: |
| return "Alternating"; |
| case V4L2_FIELD_INTERLACED_TB: |
| return "Interlaced Top-Bottom"; |
| case V4L2_FIELD_INTERLACED_BT: |
| return "Interlaced Bottom-Top"; |
| default: |
| return "Unknown (" + num2s(val) + ")"; |
| } |
| } |
| |
| std::string colorspace2s(int val) |
| { |
| switch (val) { |
| case V4L2_COLORSPACE_DEFAULT: |
| return "Default"; |
| case V4L2_COLORSPACE_SMPTE170M: |
| return "SMPTE 170M"; |
| case V4L2_COLORSPACE_SMPTE240M: |
| return "SMPTE 240M"; |
| case V4L2_COLORSPACE_REC709: |
| return "Rec. 709"; |
| case V4L2_COLORSPACE_BT878: |
| return "Broken Bt878"; |
| case V4L2_COLORSPACE_470_SYSTEM_M: |
| return "470 System M"; |
| case V4L2_COLORSPACE_470_SYSTEM_BG: |
| return "470 System BG"; |
| case V4L2_COLORSPACE_JPEG: |
| return "JPEG"; |
| case V4L2_COLORSPACE_SRGB: |
| return "sRGB"; |
| case V4L2_COLORSPACE_OPRGB: |
| return "opRGB"; |
| case V4L2_COLORSPACE_DCI_P3: |
| return "DCI-P3"; |
| case V4L2_COLORSPACE_BT2020: |
| return "BT.2020"; |
| case V4L2_COLORSPACE_RAW: |
| return "Raw"; |
| default: |
| return "Unknown (" + num2s(val) + ")"; |
| } |
| } |
| |
| std::string xfer_func2s(int val) |
| { |
| switch (val) { |
| case V4L2_XFER_FUNC_DEFAULT: |
| return "Default"; |
| case V4L2_XFER_FUNC_709: |
| return "Rec. 709"; |
| case V4L2_XFER_FUNC_SRGB: |
| return "sRGB"; |
| case V4L2_XFER_FUNC_OPRGB: |
| return "opRGB"; |
| case V4L2_XFER_FUNC_DCI_P3: |
| return "DCI-P3"; |
| case V4L2_XFER_FUNC_SMPTE2084: |
| return "SMPTE 2084"; |
| case V4L2_XFER_FUNC_SMPTE240M: |
| return "SMPTE 240M"; |
| case V4L2_XFER_FUNC_NONE: |
| return "None"; |
| default: |
| return "Unknown (" + num2s(val) + ")"; |
| } |
| } |
| |
| std::string ycbcr_enc2s(int val) |
| { |
| switch (val) { |
| case V4L2_YCBCR_ENC_DEFAULT: |
| return "Default"; |
| case V4L2_YCBCR_ENC_601: |
| return "ITU-R 601"; |
| case V4L2_YCBCR_ENC_709: |
| return "Rec. 709"; |
| case V4L2_YCBCR_ENC_XV601: |
| return "xvYCC 601"; |
| case V4L2_YCBCR_ENC_XV709: |
| return "xvYCC 709"; |
| case V4L2_YCBCR_ENC_BT2020: |
| return "BT.2020"; |
| case V4L2_YCBCR_ENC_BT2020_CONST_LUM: |
| return "BT.2020 Constant Luminance"; |
| case V4L2_YCBCR_ENC_SMPTE240M: |
| return "SMPTE 240M"; |
| case V4L2_HSV_ENC_180: |
| return "HSV with Hue 0-179"; |
| case V4L2_HSV_ENC_256: |
| return "HSV with Hue 0-255"; |
| default: |
| return "Unknown (" + num2s(val) + ")"; |
| } |
| } |
| |
| std::string quantization2s(int val) |
| { |
| switch (val) { |
| case V4L2_QUANTIZATION_DEFAULT: |
| return "Default"; |
| case V4L2_QUANTIZATION_FULL_RANGE: |
| return "Full Range"; |
| case V4L2_QUANTIZATION_LIM_RANGE: |
| return "Limited Range"; |
| default: |
| return "Unknown (" + num2s(val) + ")"; |
| } |
| } |
| |
| static constexpr flag_def pixflags_def[] = { |
| { V4L2_PIX_FMT_FLAG_PREMUL_ALPHA, "premultiplied-alpha" }, |
| { 0, nullptr } |
| }; |
| |
| std::string pixflags2s(unsigned flags) |
| { |
| return flags2s(flags, pixflags_def); |
| } |
| |
| static constexpr flag_def service_def[] = { |
| { V4L2_SLICED_TELETEXT_B, "teletext" }, |
| { V4L2_SLICED_VPS, "vps" }, |
| { V4L2_SLICED_CAPTION_525, "cc" }, |
| { V4L2_SLICED_WSS_625, "wss" }, |
| { 0, nullptr } |
| }; |
| |
| std::string service2s(unsigned service) |
| { |
| return flags2s(service, service_def); |
| } |
| |
| #define FMTDESC_DEF(enc_type) \ |
| static constexpr flag_def fmtdesc_ ## enc_type ## _def[] = { \ |
| { V4L2_FMT_FLAG_COMPRESSED, "compressed" }, \ |
| { V4L2_FMT_FLAG_EMULATED, "emulated" }, \ |
| { V4L2_FMT_FLAG_CONTINUOUS_BYTESTREAM, "continuous-bytestream" }, \ |
| { V4L2_FMT_FLAG_DYN_RESOLUTION, "dyn-resolution" }, \ |
| { V4L2_FMT_FLAG_ENC_CAP_FRAME_INTERVAL, "enc-cap-frame-interval" }, \ |
| { V4L2_FMT_FLAG_CSC_COLORSPACE, "csc-colorspace" }, \ |
| { V4L2_FMT_FLAG_CSC_YCBCR_ENC, "csc-"#enc_type }, \ |
| { V4L2_FMT_FLAG_CSC_QUANTIZATION, "csc-quantization" }, \ |
| { V4L2_FMT_FLAG_CSC_XFER_FUNC, "csc-xfer-func" }, \ |
| { 0, NULL } \ |
| }; |
| |
| FMTDESC_DEF(ycbcr) |
| FMTDESC_DEF(hsv) |
| |
| std::string fmtdesc2s(unsigned flags, bool is_hsv) |
| { |
| if (is_hsv) |
| return flags2s(flags, fmtdesc_hsv_def); |
| return flags2s(flags, fmtdesc_ycbcr_def); |
| } |
| |
| #define MBUS_DEF(enc_type) \ |
| static constexpr flag_def mbus_ ## enc_type ## _def[] = { \ |
| { V4L2_SUBDEV_MBUS_CODE_CSC_COLORSPACE, "csc-colorspace" }, \ |
| { V4L2_SUBDEV_MBUS_CODE_CSC_YCBCR_ENC, "csc-"#enc_type }, \ |
| { V4L2_SUBDEV_MBUS_CODE_CSC_QUANTIZATION, "csc-quantization" }, \ |
| { V4L2_SUBDEV_MBUS_CODE_CSC_XFER_FUNC, "csc-xfer-func" }, \ |
| { 0, NULL } \ |
| }; |
| |
| MBUS_DEF(ycbcr) |
| MBUS_DEF(hsv) |
| |
| std::string mbus2s(unsigned flags, bool is_hsv) |
| { |
| if (is_hsv) |
| return flags2s(flags, mbus_hsv_def); |
| return flags2s(flags, mbus_ycbcr_def); |
| } |
| |
| static constexpr flag_def selection_targets_def[] = { |
| { V4L2_SEL_TGT_CROP_ACTIVE, "crop" }, |
| { V4L2_SEL_TGT_CROP_DEFAULT, "crop_default" }, |
| { V4L2_SEL_TGT_CROP_BOUNDS, "crop_bounds" }, |
| { V4L2_SEL_TGT_COMPOSE_ACTIVE, "compose" }, |
| { V4L2_SEL_TGT_COMPOSE_DEFAULT, "compose_default" }, |
| { V4L2_SEL_TGT_COMPOSE_BOUNDS, "compose_bounds" }, |
| { V4L2_SEL_TGT_COMPOSE_PADDED, "compose_padded" }, |
| { V4L2_SEL_TGT_NATIVE_SIZE, "native_size" }, |
| { 0, nullptr } |
| }; |
| |
| bool valid_seltarget_at_idx(unsigned i) |
| { |
| return i < sizeof(selection_targets_def) / sizeof(selection_targets_def[0]) - 1; |
| } |
| |
| unsigned seltarget_at_idx(unsigned i) |
| { |
| if (valid_seltarget_at_idx(i)) |
| return selection_targets_def[i].flag; |
| return 0; |
| } |
| |
| std::string seltarget2s(__u32 target) |
| { |
| int i = 0; |
| |
| while (selection_targets_def[i].str != nullptr) { |
| if (selection_targets_def[i].flag == target) |
| return selection_targets_def[i].str; |
| i++; |
| } |
| return std::string("Unknown (") + num2s(target) + ")"; |
| } |
| |
| const flag_def selection_flags_def[] = { |
| { V4L2_SEL_FLAG_GE, "ge" }, |
| { V4L2_SEL_FLAG_LE, "le" }, |
| { V4L2_SEL_FLAG_KEEP_CONFIG, "keep-config" }, |
| { 0, nullptr } |
| }; |
| |
| std::string selflags2s(__u32 flags) |
| { |
| return flags2s(flags, selection_flags_def); |
| } |
| |
| static const char *std_pal[] = { |
| "B", "B1", "G", "H", "I", "D", "D1", "K", |
| "M", "N", "Nc", "60", |
| nullptr |
| }; |
| static const char *std_ntsc[] = { |
| "M", "M-JP", "443", "M-KR", |
| nullptr |
| }; |
| static const char *std_secam[] = { |
| "B", "D", "G", "H", "K", "K1", "L", "Lc", |
| nullptr |
| }; |
| static const char *std_atsc[] = { |
| "8-VSB", "16-VSB", |
| nullptr |
| }; |
| |
| static std::string partstd2s(const char *prefix, const char *stds[], unsigned long long std) |
| { |
| std::string s = std::string(prefix) + "-"; |
| int first = 1; |
| |
| while (*stds) { |
| if (std & 1) { |
| if (!first) |
| s += "/"; |
| first = 0; |
| s += *stds; |
| } |
| stds++; |
| std >>= 1; |
| } |
| return s; |
| } |
| |
| std::string std2s(v4l2_std_id std, const char *sep) |
| { |
| std::string s; |
| |
| if (std & 0xfff) { |
| s += partstd2s("PAL", std_pal, std); |
| } |
| if (std & 0xf000) { |
| if (s.length()) s += sep; |
| s += partstd2s("NTSC", std_ntsc, std >> 12); |
| } |
| if (std & 0xff0000) { |
| if (s.length()) s += sep; |
| s += partstd2s("SECAM", std_secam, std >> 16); |
| } |
| if (std & 0xf000000) { |
| if (s.length()) s += sep; |
| s += partstd2s("ATSC", std_atsc, std >> 24); |
| } |
| return s; |
| } |
| |
| std::string ctrlflags2s(__u32 flags) |
| { |
| static constexpr flag_def def[] = { |
| { V4L2_CTRL_FLAG_GRABBED, "grabbed" }, |
| { V4L2_CTRL_FLAG_DISABLED, "disabled" }, |
| { V4L2_CTRL_FLAG_READ_ONLY, "read-only" }, |
| { V4L2_CTRL_FLAG_UPDATE, "update" }, |
| { V4L2_CTRL_FLAG_INACTIVE, "inactive" }, |
| { V4L2_CTRL_FLAG_SLIDER, "slider" }, |
| { V4L2_CTRL_FLAG_WRITE_ONLY, "write-only" }, |
| { V4L2_CTRL_FLAG_VOLATILE, "volatile" }, |
| { V4L2_CTRL_FLAG_HAS_PAYLOAD,"has-payload" }, |
| { V4L2_CTRL_FLAG_EXECUTE_ON_WRITE, "execute-on-write" }, |
| { V4L2_CTRL_FLAG_MODIFY_LAYOUT, "modify-layout" }, |
| { 0, nullptr } |
| }; |
| return flags2s(flags, def); |
| } |
| |
| static constexpr flag_def in_status_def[] = { |
| { V4L2_IN_ST_NO_POWER, "no power" }, |
| { V4L2_IN_ST_NO_SIGNAL, "no signal" }, |
| { V4L2_IN_ST_NO_COLOR, "no color" }, |
| { V4L2_IN_ST_HFLIP, "hflip" }, |
| { V4L2_IN_ST_VFLIP, "vflip" }, |
| { V4L2_IN_ST_NO_H_LOCK, "no hsync lock" }, |
| { V4L2_IN_ST_NO_V_LOCK, "no vsync lock" }, |
| { V4L2_IN_ST_NO_STD_LOCK, "no standard format lock" }, |
| { V4L2_IN_ST_COLOR_KILL, "color kill" }, |
| { V4L2_IN_ST_NO_SYNC, "no sync lock" }, |
| { V4L2_IN_ST_NO_EQU, "no equalizer lock" }, |
| { V4L2_IN_ST_NO_CARRIER, "no carrier" }, |
| { V4L2_IN_ST_MACROVISION, "macrovision" }, |
| { V4L2_IN_ST_NO_ACCESS, "no conditional access" }, |
| { V4L2_IN_ST_VTR, "VTR time constant" }, |
| { 0, nullptr } |
| }; |
| |
| std::string in_status2s(__u32 status) |
| { |
| return status ? flags2s(status, in_status_def) : "ok"; |
| } |
| |
| static constexpr flag_def input_cap_def[] = { |
| { V4L2_IN_CAP_DV_TIMINGS, "DV timings" }, |
| { V4L2_IN_CAP_STD, "SDTV standards" }, |
| { V4L2_IN_CAP_NATIVE_SIZE, "Native Size" }, |
| { 0, nullptr } |
| }; |
| |
| std::string input_cap2s(__u32 capabilities) |
| { |
| return capabilities ? flags2s(capabilities, input_cap_def) : "not defined"; |
| } |
| |
| static constexpr flag_def output_cap_def[] = { |
| { V4L2_OUT_CAP_DV_TIMINGS, "DV timings" }, |
| { V4L2_OUT_CAP_STD, "SDTV standards" }, |
| { V4L2_OUT_CAP_NATIVE_SIZE, "Native Size" }, |
| { 0, nullptr } |
| }; |
| |
| std::string output_cap2s(__u32 capabilities) |
| { |
| return capabilities ? flags2s(capabilities, output_cap_def) : "not defined"; |
| } |
| |
| std::string fbufcap2s(unsigned cap) |
| { |
| std::string s; |
| |
| if (cap & V4L2_FBUF_CAP_EXTERNOVERLAY) |
| s += "\t\t\tExtern Overlay\n"; |
| if (cap & V4L2_FBUF_CAP_CHROMAKEY) |
| s += "\t\t\tChromakey\n"; |
| if (cap & V4L2_FBUF_CAP_SRC_CHROMAKEY) |
| s += "\t\t\tSource Chromakey\n"; |
| if (cap & V4L2_FBUF_CAP_GLOBAL_ALPHA) |
| s += "\t\t\tGlobal Alpha\n"; |
| if (cap & V4L2_FBUF_CAP_LOCAL_ALPHA) |
| s += "\t\t\tLocal Alpha\n"; |
| if (cap & V4L2_FBUF_CAP_LOCAL_INV_ALPHA) |
| s += "\t\t\tLocal Inverted Alpha\n"; |
| if (cap & V4L2_FBUF_CAP_LIST_CLIPPING) |
| s += "\t\t\tClipping List\n"; |
| if (cap & V4L2_FBUF_CAP_BITMAP_CLIPPING) |
| s += "\t\t\tClipping Bitmap\n"; |
| if (s.empty()) s += "\t\t\t\n"; |
| return s; |
| } |
| |
| std::string fbufflags2s(unsigned fl) |
| { |
| std::string s; |
| |
| if (fl & V4L2_FBUF_FLAG_PRIMARY) |
| s += "\t\t\tPrimary Graphics Surface\n"; |
| if (fl & V4L2_FBUF_FLAG_OVERLAY) |
| s += "\t\t\tOverlay Matches Capture/Output Size\n"; |
| if (fl & V4L2_FBUF_FLAG_CHROMAKEY) |
| s += "\t\t\tChromakey\n"; |
| if (fl & V4L2_FBUF_FLAG_SRC_CHROMAKEY) |
| s += "\t\t\tSource Chromakey\n"; |
| if (fl & V4L2_FBUF_FLAG_GLOBAL_ALPHA) |
| s += "\t\t\tGlobal Alpha\n"; |
| if (fl & V4L2_FBUF_FLAG_LOCAL_ALPHA) |
| s += "\t\t\tLocal Alpha\n"; |
| if (fl & V4L2_FBUF_FLAG_LOCAL_INV_ALPHA) |
| s += "\t\t\tLocal Inverted Alpha\n"; |
| if (s.empty()) s += "\t\t\t\n"; |
| return s; |
| } |
| |
| static constexpr flag_def dv_standards_def[] = { |
| { V4L2_DV_BT_STD_CEA861, "CTA-861" }, |
| { V4L2_DV_BT_STD_DMT, "DMT" }, |
| { V4L2_DV_BT_STD_CVT, "CVT" }, |
| { V4L2_DV_BT_STD_GTF, "GTF" }, |
| { V4L2_DV_BT_STD_SDI, "SDI" }, |
| { 0, nullptr } |
| }; |
| |
| std::string dv_standards2s(__u32 flags) |
| { |
| return flags2s(flags, dv_standards_def); |
| } |
| |
| std::string dvflags2s(unsigned vsync, int val) |
| { |
| std::string s; |
| |
| if (val & V4L2_DV_FL_REDUCED_BLANKING) |
| s += vsync == 8 ? |
| "reduced blanking v2, " : |
| "reduced blanking, "; |
| if (val & V4L2_DV_FL_CAN_REDUCE_FPS) |
| s += "framerate can be reduced by 1/1.001, "; |
| if (val & V4L2_DV_FL_REDUCED_FPS) |
| s += "framerate is reduced by 1/1.001, "; |
| if (val & V4L2_DV_FL_CAN_DETECT_REDUCED_FPS) |
| s += "can detect reduced framerates, "; |
| if (val & V4L2_DV_FL_HALF_LINE) |
| s += "half-line, "; |
| if (val & V4L2_DV_FL_IS_CE_VIDEO) |
| s += "CE-video, "; |
| if (val & V4L2_DV_FL_FIRST_FIELD_EXTRA_LINE) |
| s += "first field has extra line, "; |
| if (val & V4L2_DV_FL_HAS_PICTURE_ASPECT) |
| s += "has picture aspect, "; |
| if (val & V4L2_DV_FL_HAS_CEA861_VIC) |
| s += "has CTA-861 VIC, "; |
| if (val & V4L2_DV_FL_HAS_HDMI_VIC) |
| s += "has HDMI VIC, "; |
| if (s.length()) |
| return s.erase(s.length() - 2, 2); |
| return s; |
| } |
| |
| static constexpr flag_def dv_caps_def[] = { |
| { V4L2_DV_BT_CAP_INTERLACED, "Interlaced" }, |
| { V4L2_DV_BT_CAP_PROGRESSIVE, "Progressive" }, |
| { V4L2_DV_BT_CAP_REDUCED_BLANKING, "Reduced Blanking" }, |
| { V4L2_DV_BT_CAP_CUSTOM, "Custom Formats" }, |
| { 0, nullptr } |
| }; |
| |
| std::string dv_caps2s(__u32 flags) |
| { |
| return flags2s(flags, dv_caps_def); |
| } |
| |
| static constexpr flag_def tc_flags_def[] = { |
| { V4L2_TC_FLAG_DROPFRAME, "dropframe" }, |
| { V4L2_TC_FLAG_COLORFRAME, "colorframe" }, |
| { V4L2_TC_USERBITS_field, "userbits-field" }, |
| { V4L2_TC_USERBITS_USERDEFINED, "userbits-userdefined" }, |
| { V4L2_TC_USERBITS_8BITCHARS, "userbits-8bitchars" }, |
| { 0, nullptr } |
| }; |
| |
| std::string tc_flags2s(__u32 flags) |
| { |
| return flags2s(flags, tc_flags_def); |
| } |
| |
| static constexpr flag_def buffer_flags_def[] = { |
| { V4L2_BUF_FLAG_MAPPED, "mapped" }, |
| { V4L2_BUF_FLAG_QUEUED, "queued" }, |
| { V4L2_BUF_FLAG_DONE, "done" }, |
| { V4L2_BUF_FLAG_KEYFRAME, "keyframe" }, |
| { V4L2_BUF_FLAG_PFRAME, "P-frame" }, |
| { V4L2_BUF_FLAG_BFRAME, "B-frame" }, |
| { V4L2_BUF_FLAG_ERROR, "error" }, |
| { V4L2_BUF_FLAG_TIMECODE, "timecode" }, |
| { V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF, "m2m-hold-capture-buf" }, |
| { V4L2_BUF_FLAG_PREPARED, "prepared" }, |
| { V4L2_BUF_FLAG_NO_CACHE_INVALIDATE, "no-cache-invalidate" }, |
| { V4L2_BUF_FLAG_NO_CACHE_CLEAN, "no-cache-clean" }, |
| { V4L2_BUF_FLAG_LAST, "last" }, |
| { V4L2_BUF_FLAG_REQUEST_FD, "request-fd" }, |
| { V4L2_BUF_FLAG_IN_REQUEST, "in-request" }, |
| { 0, nullptr } |
| }; |
| |
| std::string bufferflags2s(__u32 flags) |
| { |
| const unsigned ts_mask = V4L2_BUF_FLAG_TIMESTAMP_MASK | V4L2_BUF_FLAG_TSTAMP_SRC_MASK; |
| std::string s = flags2s(flags & ~ts_mask, buffer_flags_def); |
| |
| if (s.length()) |
| s += ", "; |
| |
| switch (flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) { |
| case V4L2_BUF_FLAG_TIMESTAMP_UNKNOWN: |
| s += "ts-unknown"; |
| break; |
| case V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC: |
| s += "ts-monotonic"; |
| break; |
| case V4L2_BUF_FLAG_TIMESTAMP_COPY: |
| s += "ts-copy"; |
| break; |
| default: |
| s += "ts-invalid"; |
| break; |
| } |
| switch (flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK) { |
| case V4L2_BUF_FLAG_TSTAMP_SRC_EOF: |
| s += ", ts-src-eof"; |
| break; |
| case V4L2_BUF_FLAG_TSTAMP_SRC_SOE: |
| s += ", ts-src-soe"; |
| break; |
| default: |
| s += ", ts-src-invalid"; |
| break; |
| } |
| return s; |
| } |
| |
| static const flag_def vbi_def[] = { |
| { V4L2_VBI_UNSYNC, "unsynchronized" }, |
| { V4L2_VBI_INTERLACED, "interlaced" }, |
| { 0, nullptr } |
| }; |
| |
| std::string vbiflags2s(__u32 flags) |
| { |
| return flags2s(flags, vbi_def); |
| } |