blob: 1e4117cbb52aa6e11790823f76961aea9c993079 [file] [log] [blame]
#include <endian.h>
#include "v4l2-ctl.h"
static struct v4l2_format vfmt; /* set_format/get_format */
static unsigned mbus_code;
static unsigned mbus_code_out;
void meta_usage()
{
printf("\nMetadata Formats options:\n"
" --list-formats-meta [<mbus_code>] display supported metadata capture formats.\n"
" <mbus_code> is an optional media bus code, if the device has\n"
" capability V4L2_CAP_IO_MC then only formats that support this\n"
" media bus code are listed [VIDIOC_ENUM_FMT]\n"
" --get-fmt-meta query the metadata capture format [VIDIOC_G_FMT]\n"
" --set-fmt-meta <f> set the metadata capture format [VIDIOC_S_FMT]\n"
" parameter is either the format index as reported by\n"
" --list-formats-meta, or the fourcc value as a string\n"
" --try-fmt-meta <f> try the metadata capture format [VIDIOC_TRY_FMT]\n"
" parameter is either the format index as reported by\n"
" --list-formats-meta, or the fourcc value as a string\n"
" --list-formats-meta-out [<mbus_code>] display supported metadata output formats.\n"
" <mbus_code> is an optional media bus code, if the device has\n"
" capability V4L2_CAP_IO_MC then only formats that support this\n"
" media bus code are listed [VIDIOC_ENUM_FMT]\n"
" --get-fmt-meta-out query the metadata output format [VIDIOC_G_FMT]\n"
" --set-fmt-meta-out <f> set the metadata output format [VIDIOC_S_FMT]\n"
" parameter is either the format index as reported by\n"
" --list-formats-meta-out, or the fourcc value as a string\n"
" --try-fmt-meta-out <f> try the metadata output format [VIDIOC_TRY_FMT]\n"
" parameter is either the format index as reported by\n"
" --list-formats-meta-out, or the fourcc value as a string\n"
);
}
void meta_cmd(int ch, char *optarg)
{
switch (ch) {
case OptSetMetaFormat:
case OptTryMetaFormat:
case OptSetMetaOutFormat:
case OptTryMetaOutFormat:
if (strlen(optarg) == 0) {
meta_usage();
std::exit(EXIT_FAILURE);
} else if (strlen(optarg) == 4) {
vfmt.fmt.meta.dataformat = v4l2_fourcc(optarg[0],
optarg[1], optarg[2], optarg[3]);
} else {
vfmt.fmt.meta.dataformat = strtol(optarg, nullptr, 0);
}
break;
case OptListMetaFormats:
if (optarg)
mbus_code = strtoul(optarg, nullptr, 0);
break;
case OptListMetaOutFormats:
if (optarg)
mbus_code_out = strtoul(optarg, nullptr, 0);
break;
}
}
static void __meta_set(cv4l_fd &_fd, bool set, bool _try, __u32 type)
{
struct v4l2_format in_vfmt;
int fd = _fd.g_fd();
int ret;
if (!set && !_try)
return;
in_vfmt.type = type;
in_vfmt.fmt.meta.dataformat = vfmt.fmt.meta.dataformat;
if (in_vfmt.fmt.meta.dataformat < 256) {
struct v4l2_fmtdesc fmt = {};
fmt.index = in_vfmt.fmt.meta.dataformat;
fmt.type = in_vfmt.type;
if (doioctl(fd, VIDIOC_ENUM_FMT, &fmt))
fmt.pixelformat = 0;
in_vfmt.fmt.meta.dataformat = fmt.pixelformat;
}
if (set)
ret = doioctl(fd, VIDIOC_S_FMT, &in_vfmt);
else
ret = doioctl(fd, VIDIOC_TRY_FMT, &in_vfmt);
if (ret == 0 && (verbose || _try))
printfmt(fd, in_vfmt);
}
void meta_set(cv4l_fd &_fd)
{
__meta_set(_fd, options[OptSetMetaFormat], options[OptTryMetaFormat],
V4L2_BUF_TYPE_META_CAPTURE);
__meta_set(_fd, options[OptSetMetaOutFormat],
options[OptTryMetaOutFormat], V4L2_BUF_TYPE_META_OUTPUT);
}
static void __meta_get(cv4l_fd &fd, __u32 type)
{
vfmt.type = type;
if (doioctl(fd.g_fd(), VIDIOC_G_FMT, &vfmt) == 0)
printfmt(fd.g_fd(), vfmt);
}
void meta_get(cv4l_fd &fd)
{
if (options[OptGetMetaFormat])
__meta_get(fd, V4L2_BUF_TYPE_META_CAPTURE);
if (options[OptGetMetaOutFormat])
__meta_get(fd, V4L2_BUF_TYPE_META_OUTPUT);
}
void meta_list(cv4l_fd &fd)
{
if (options[OptListMetaFormats]) {
printf("ioctl: VIDIOC_ENUM_FMT\n");
print_video_formats(fd, V4L2_BUF_TYPE_META_CAPTURE, mbus_code);
}
if (options[OptListMetaOutFormats]) {
printf("ioctl: VIDIOC_ENUM_FMT\n");
print_video_formats(fd, V4L2_BUF_TYPE_META_OUTPUT, mbus_code_out);
}
}
struct uvc_meta_buf {
__u64 ns;
__u16 sof;
__u8 length;
__u8 flags;
__u8 buf[10];
};
#define UVC_STREAM_SCR (1 << 3)
#define UVC_STREAM_PTS (1 << 2)
struct vivid_meta_out_buf {
__u16 brightness;
__u16 contrast;
__u16 saturation;
__s16 hue;
};
void print_meta_buffer(FILE *f, cv4l_buffer &buf, cv4l_fmt &fmt, cv4l_queue &q)
{
struct uvc_meta_buf *vbuf;
int buf_off = 0;
struct vivid_meta_out_buf *vbuf_out;
switch (fmt.g_pixelformat()) {
case V4L2_META_FMT_UVC:
fprintf(f, "UVC: ");
vbuf = static_cast<uvc_meta_buf *>(q.g_dataptr(buf.g_index(), 0));
fprintf(f, "%.6fs sof: %4d len: %u flags: 0x%02x",
static_cast<double>(vbuf->ns) / 1000000000.0,
vbuf->sof,
vbuf->length,
vbuf->flags);
if (vbuf->flags & UVC_STREAM_PTS) {
fprintf(f, " PTS: %u", le32toh(*(__u32*)(vbuf->buf)));
buf_off = 4;
}
if (vbuf->flags & UVC_STREAM_SCR)
fprintf(f, " STC: %u SOF counter: %u",
le32toh(*(__u32*)(vbuf->buf + buf_off)),
le16toh(*(__u16*)(vbuf->buf + buf_off + 4)));
fprintf(f, "\n");
break;
case V4L2_META_FMT_VIVID:
fprintf(f, "VIVID:");
vbuf_out = static_cast<vivid_meta_out_buf *>(q.g_dataptr(buf.g_index(), 0));
fprintf(f, " brightness: %u contrast: %u saturation: %u hue: %d\n",
vbuf_out->brightness, vbuf_out->contrast,
vbuf_out->saturation, vbuf_out->hue);
break;
}
}
void meta_fillbuffer(cv4l_buffer &buf, cv4l_fmt &fmt, cv4l_queue &q)
{
struct vivid_meta_out_buf *vbuf;
switch (fmt.g_pixelformat()) {
case V4L2_META_FMT_VIVID:
vbuf = static_cast<vivid_meta_out_buf *>(q.g_dataptr(buf.g_index(), 0));
vbuf->brightness = buf.g_sequence() % 192 + 64;
vbuf->contrast = (buf.g_sequence() + 10) % 192 + 64;
vbuf->saturation = (buf.g_sequence() + 20) % 256;
vbuf->hue = buf.g_sequence() % 257 - 128;
break;
}
}