1 #include <endian.h>
2
3 #include "v4l2-ctl.h"
4
5 static struct v4l2_format vfmt; /* set_format/get_format */
6 static unsigned mbus_code;
7 static unsigned mbus_code_out;
8
meta_usage()9 void meta_usage()
10 {
11 printf("\nMetadata Formats options:\n"
12 " --list-formats-meta [<mbus_code>] display supported metadata capture formats.\n"
13 " <mbus_code> is an optional media bus code, if the device has\n"
14 " capability V4L2_CAP_IO_MC then only formats that support this\n"
15 " media bus code are listed [VIDIOC_ENUM_FMT]\n"
16 " --get-fmt-meta query the metadata capture format [VIDIOC_G_FMT]\n"
17 " --set-fmt-meta <f> set the metadata capture format [VIDIOC_S_FMT]\n"
18 " parameter is either the format index as reported by\n"
19 " --list-formats-meta, or the fourcc value as a string\n"
20 " --try-fmt-meta <f> try the metadata capture format [VIDIOC_TRY_FMT]\n"
21 " parameter is either the format index as reported by\n"
22 " --list-formats-meta, or the fourcc value as a string\n"
23 " --list-formats-meta-out [<mbus_code>] display supported metadata output formats.\n"
24 " <mbus_code> is an optional media bus code, if the device has\n"
25 " capability V4L2_CAP_IO_MC then only formats that support this\n"
26 " media bus code are listed [VIDIOC_ENUM_FMT]\n"
27 " --get-fmt-meta-out query the metadata output format [VIDIOC_G_FMT]\n"
28 " --set-fmt-meta-out <f> set the metadata output format [VIDIOC_S_FMT]\n"
29 " parameter is either the format index as reported by\n"
30 " --list-formats-meta-out, or the fourcc value as a string\n"
31 " --try-fmt-meta-out <f> try the metadata output format [VIDIOC_TRY_FMT]\n"
32 " parameter is either the format index as reported by\n"
33 " --list-formats-meta-out, or the fourcc value as a string\n"
34 );
35 }
36
meta_cmd(int ch,char * optarg)37 void meta_cmd(int ch, char *optarg)
38 {
39 switch (ch) {
40 case OptSetMetaFormat:
41 case OptTryMetaFormat:
42 case OptSetMetaOutFormat:
43 case OptTryMetaOutFormat:
44 if (strlen(optarg) == 0) {
45 meta_usage();
46 std::exit(EXIT_FAILURE);
47 } else if (strlen(optarg) == 4) {
48 vfmt.fmt.meta.dataformat = v4l2_fourcc(optarg[0],
49 optarg[1], optarg[2], optarg[3]);
50 } else {
51 vfmt.fmt.meta.dataformat = strtol(optarg, nullptr, 0);
52 }
53 break;
54 case OptListMetaFormats:
55 if (optarg)
56 mbus_code = strtoul(optarg, nullptr, 0);
57 break;
58 case OptListMetaOutFormats:
59 if (optarg)
60 mbus_code_out = strtoul(optarg, nullptr, 0);
61 break;
62 }
63 }
64
__meta_set(cv4l_fd & _fd,bool set,bool _try,__u32 type)65 static void __meta_set(cv4l_fd &_fd, bool set, bool _try, __u32 type)
66 {
67 struct v4l2_format in_vfmt;
68 int fd = _fd.g_fd();
69 int ret;
70
71 if (!set && !_try)
72 return;
73
74 in_vfmt.type = type;
75 in_vfmt.fmt.meta.dataformat = vfmt.fmt.meta.dataformat;
76
77 if (in_vfmt.fmt.meta.dataformat < 256) {
78 struct v4l2_fmtdesc fmt = {};
79
80 fmt.index = in_vfmt.fmt.meta.dataformat;
81 fmt.type = in_vfmt.type;
82
83 if (doioctl(fd, VIDIOC_ENUM_FMT, &fmt))
84 fmt.pixelformat = 0;
85
86 in_vfmt.fmt.meta.dataformat = fmt.pixelformat;
87 }
88
89 if (set)
90 ret = doioctl(fd, VIDIOC_S_FMT, &in_vfmt);
91 else
92 ret = doioctl(fd, VIDIOC_TRY_FMT, &in_vfmt);
93 if (ret == 0 && (verbose || _try))
94 printfmt(fd, in_vfmt);
95 }
96
meta_set(cv4l_fd & _fd)97 void meta_set(cv4l_fd &_fd)
98 {
99 __meta_set(_fd, options[OptSetMetaFormat], options[OptTryMetaFormat],
100 V4L2_BUF_TYPE_META_CAPTURE);
101 __meta_set(_fd, options[OptSetMetaOutFormat],
102 options[OptTryMetaOutFormat], V4L2_BUF_TYPE_META_OUTPUT);
103 }
104
__meta_get(cv4l_fd & fd,__u32 type)105 static void __meta_get(cv4l_fd &fd, __u32 type)
106 {
107 vfmt.type = type;
108 if (doioctl(fd.g_fd(), VIDIOC_G_FMT, &vfmt) == 0)
109 printfmt(fd.g_fd(), vfmt);
110 }
111
meta_get(cv4l_fd & fd)112 void meta_get(cv4l_fd &fd)
113 {
114 if (options[OptGetMetaFormat])
115 __meta_get(fd, V4L2_BUF_TYPE_META_CAPTURE);
116 if (options[OptGetMetaOutFormat])
117 __meta_get(fd, V4L2_BUF_TYPE_META_OUTPUT);
118 }
119
meta_list(cv4l_fd & fd)120 void meta_list(cv4l_fd &fd)
121 {
122 if (options[OptListMetaFormats]) {
123 printf("ioctl: VIDIOC_ENUM_FMT\n");
124 print_video_formats(fd, V4L2_BUF_TYPE_META_CAPTURE, mbus_code);
125 }
126
127 if (options[OptListMetaOutFormats]) {
128 printf("ioctl: VIDIOC_ENUM_FMT\n");
129 print_video_formats(fd, V4L2_BUF_TYPE_META_OUTPUT, mbus_code_out);
130 }
131 }
132
133 struct uvc_meta_buf {
134 __u64 ns;
135 __u16 sof;
136 __u8 length;
137 __u8 flags;
138 __u8 buf[10];
139 };
140
141 #define UVC_STREAM_SCR (1 << 3)
142 #define UVC_STREAM_PTS (1 << 2)
143
144 struct vivid_meta_out_buf {
145 __u16 brightness;
146 __u16 contrast;
147 __u16 saturation;
148 __s16 hue;
149 };
150
print_meta_buffer(FILE * f,cv4l_buffer & buf,cv4l_fmt & fmt,cv4l_queue & q)151 void print_meta_buffer(FILE *f, cv4l_buffer &buf, cv4l_fmt &fmt, cv4l_queue &q)
152 {
153 struct uvc_meta_buf *vbuf;
154 int buf_off = 0;
155 struct vivid_meta_out_buf *vbuf_out;
156
157 switch (fmt.g_pixelformat()) {
158 case V4L2_META_FMT_UVC:
159 fprintf(f, "UVC: ");
160 vbuf = static_cast<uvc_meta_buf *>(q.g_dataptr(buf.g_index(), 0));
161
162 fprintf(f, "%.6fs sof: %4d len: %u flags: 0x%02x",
163 static_cast<double>(vbuf->ns) / 1000000000.0,
164 vbuf->sof,
165 vbuf->length,
166 vbuf->flags);
167 if (vbuf->flags & UVC_STREAM_PTS) {
168 fprintf(f, " PTS: %u", le32toh(*(__u32*)(vbuf->buf)));
169 buf_off = 4;
170 }
171 if (vbuf->flags & UVC_STREAM_SCR)
172 fprintf(f, " STC: %u SOF counter: %u",
173 le32toh(*(__u32*)(vbuf->buf + buf_off)),
174 le16toh(*(__u16*)(vbuf->buf + buf_off + 4)));
175 fprintf(f, "\n");
176 break;
177 case V4L2_META_FMT_VIVID:
178 fprintf(f, "VIVID:");
179 vbuf_out = static_cast<vivid_meta_out_buf *>(q.g_dataptr(buf.g_index(), 0));
180
181 fprintf(f, " brightness: %u contrast: %u saturation: %u hue: %d\n",
182 vbuf_out->brightness, vbuf_out->contrast,
183 vbuf_out->saturation, vbuf_out->hue);
184 break;
185 }
186 }
187
meta_fillbuffer(cv4l_buffer & buf,cv4l_fmt & fmt,cv4l_queue & q)188 void meta_fillbuffer(cv4l_buffer &buf, cv4l_fmt &fmt, cv4l_queue &q)
189 {
190 struct vivid_meta_out_buf *vbuf;
191
192 switch (fmt.g_pixelformat()) {
193 case V4L2_META_FMT_VIVID:
194 vbuf = static_cast<vivid_meta_out_buf *>(q.g_dataptr(buf.g_index(), 0));
195 vbuf->brightness = buf.g_sequence() % 192 + 64;
196 vbuf->contrast = (buf.g_sequence() + 10) % 192 + 64;
197 vbuf->saturation = (buf.g_sequence() + 20) % 256;
198 vbuf->hue = buf.g_sequence() % 257 - 128;
199 break;
200 }
201 }
202