blob: 15bedc442249c7f90462f97c8d0edf72b0b146e6 [file] [log] [blame]
#include "v4l2-ctl.h"
static unsigned set_fmts_out;
static __u32 width, height, pixfmt, field, colorspace, xfer_func, ycbcr, quantization, flags;
static __u32 bytesperline[VIDEO_MAX_PLANES];
static __u32 sizeimage[VIDEO_MAX_PLANES];
static unsigned mbus_code_out;
void vidout_usage()
{
printf("\nVideo Output Formats options:\n"
" --list-formats-out [<mbus_code>] display supported video 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"
" --list-formats-out-ext [<mbus_code>] display supported video output formats including\n"
" frame sizes and intervals. <mbus_code> is an optional media bus code,\n"
" if the device has capability V4L2_CAP_IO_MC then only formats that\n"
" support this media bus code are listed [VIDIOC_ENUM_FMT]\n"
" --list-fields-out list supported fields for the current output format\n"
" -X, --get-fmt-video-out\n"
" query the video output format [VIDIOC_G_FMT]\n"
" -x, --set-fmt-video-out\n"
" --try-fmt-video-out width=<w>,height=<h>,pixelformat=<pf>,field=<f>,colorspace=<c>,\n"
" xfer=<xf>,ycbcr=<y>,hsv=<hsv>,quantization=<q>,\n"
" premul-alpha,bytesperline=<bpl>,sizeimage=<sz>\n"
" set/try the video output format [VIDIOC_S/TRY_FMT]\n"
" pixelformat is either the format index as reported by\n"
" --list-formats-out, or the fourcc value as a string.\n"
" premul-alpha sets V4L2_PIX_FMT_FLAG_PREMUL_ALPHA.\n"
" The bytesperline and sizeimage options can be used multiple times,\n"
" once for each plane.\n"
" <f> can be one of the following field layouts:\n"
" any, none, top, bottom, interlaced, seq_tb, seq_bt,\n"
" alternate, interlaced_tb, interlaced_bt\n"
" <c> can be one of the following colorspaces:\n"
" smpte170m, smpte240m, rec709, 470m, 470bg, jpeg, srgb,\n"
" oprgb, bt2020, dcip3\n"
" <xf> can be one of the following transfer functions:\n"
" default, 709, srgb, oprgb, smpte240m, smpte2084, dcip3, none\n"
" <y> can be one of the following Y'CbCr encodings:\n"
" default, 601, 709, xv601, xv709, bt2020, bt2020c, smpte240m\n"
" <hsv> can be one of the following HSV encodings:\n"
" default, 180, 256\n"
" <q> can be one of the following quantization methods:\n"
" default, full-range, lim-range\n"
);
}
static void print_video_out_fields(int fd)
{
struct v4l2_format fmt;
struct v4l2_format tmp;
memset(&fmt, 0, sizeof(fmt));
fmt.fmt.pix.priv = priv_magic;
fmt.type = vidout_buftype;
if (test_ioctl(fd, VIDIOC_G_FMT, &fmt) < 0)
return;
printf("Supported Video Output Fields:\n");
for (__u32 f = V4L2_FIELD_NONE; f <= V4L2_FIELD_INTERLACED_BT; f++) {
bool ok;
tmp = fmt;
if (is_multiplanar)
tmp.fmt.pix_mp.field = f;
else
tmp.fmt.pix.field = f;
if (test_ioctl(fd, VIDIOC_TRY_FMT, &tmp) < 0)
continue;
if (is_multiplanar)
ok = tmp.fmt.pix_mp.field == f;
else
ok = tmp.fmt.pix.field == f;
if (ok)
printf("\t%s\n", field2s(f).c_str());
}
}
void vidout_cmd(int ch, char *optarg)
{
switch (ch) {
case OptSetVideoOutFormat:
case OptTryVideoOutFormat:
set_fmts_out = parse_fmt(optarg, width, height, pixfmt, field,
colorspace, xfer_func, ycbcr, quantization, flags, bytesperline,
sizeimage);
if (!set_fmts_out) {
vidcap_usage();
std::exit(EXIT_FAILURE);
}
break;
case OptListOutFormats:
case OptListOutFormatsExt:
if (optarg)
mbus_code_out = strtoul(optarg, nullptr, 0);
break;
}
}
void vidout_set(cv4l_fd &_fd)
{
int fd = _fd.g_fd();
int ret;
if (options[OptSetVideoOutFormat] || options[OptTryVideoOutFormat]) {
struct v4l2_format vfmt;
memset(&vfmt, 0, sizeof(vfmt));
vfmt.fmt.pix.priv = priv_magic;
vfmt.type = vidout_buftype;
if (doioctl(fd, VIDIOC_G_FMT, &vfmt) == 0) {
if (is_multiplanar) {
if (set_fmts_out & FmtWidth)
vfmt.fmt.pix_mp.width = width;
if (set_fmts_out & FmtHeight)
vfmt.fmt.pix_mp.height = height;
if (set_fmts_out & FmtPixelFormat) {
vfmt.fmt.pix_mp.pixelformat = pixfmt;
if (vfmt.fmt.pix_mp.pixelformat < 256) {
vfmt.fmt.pix_mp.pixelformat = pixfmt =
find_pixel_format(fd, vfmt.fmt.pix_mp.pixelformat,
true, true);
}
}
if (set_fmts_out & FmtField)
vfmt.fmt.pix_mp.field = field;
if (set_fmts_out & FmtColorspace)
vfmt.fmt.pix_mp.colorspace = colorspace;
if (set_fmts_out & FmtXferFunc)
vfmt.fmt.pix_mp.xfer_func = xfer_func;
if (set_fmts_out & FmtYCbCr)
vfmt.fmt.pix_mp.ycbcr_enc = ycbcr;
if (set_fmts_out & FmtQuantization)
vfmt.fmt.pix_mp.quantization = quantization;
if (set_fmts_out & FmtFlags)
vfmt.fmt.pix_mp.flags = flags;
if (set_fmts_out & FmtBytesPerLine) {
for (unsigned i = 0; i < VIDEO_MAX_PLANES; i++)
vfmt.fmt.pix_mp.plane_fmt[i].bytesperline =
bytesperline[i];
} else {
/* G_FMT might return bytesperline values > width,
* reset them to 0 to force the driver to update them
* to the closest value for the new width. */
for (unsigned i = 0; i < vfmt.fmt.pix_mp.num_planes; i++)
vfmt.fmt.pix_mp.plane_fmt[i].bytesperline = 0;
}
if (set_fmts_out & FmtSizeImage) {
for (unsigned i = 0; i < VIDEO_MAX_PLANES; i++)
vfmt.fmt.pix_mp.plane_fmt[i].sizeimage =
sizeimage[i];
}
} else {
if (set_fmts_out & FmtWidth)
vfmt.fmt.pix.width = width;
if (set_fmts_out & FmtHeight)
vfmt.fmt.pix.height = height;
if (set_fmts_out & FmtPixelFormat) {
vfmt.fmt.pix.pixelformat = pixfmt;
if (vfmt.fmt.pix.pixelformat < 256) {
vfmt.fmt.pix.pixelformat = pixfmt =
find_pixel_format(fd, vfmt.fmt.pix.pixelformat,
true, false);
}
}
if (set_fmts_out & FmtField)
vfmt.fmt.pix.field = field;
if (set_fmts_out & FmtColorspace)
vfmt.fmt.pix.colorspace = colorspace;
if (set_fmts_out & FmtXferFunc)
vfmt.fmt.pix.xfer_func = xfer_func;
if (set_fmts_out & FmtYCbCr)
vfmt.fmt.pix.ycbcr_enc = ycbcr;
if (set_fmts_out & FmtQuantization)
vfmt.fmt.pix.quantization = quantization;
if (set_fmts_out & FmtFlags)
vfmt.fmt.pix.flags = flags;
if (set_fmts_out & FmtBytesPerLine) {
vfmt.fmt.pix.bytesperline = bytesperline[0];
} else {
/* G_FMT might return a bytesperline value > width,
* reset this to 0 to force the driver to update it
* to the closest value for the new width. */
vfmt.fmt.pix.bytesperline = 0;
}
if (set_fmts_out & FmtSizeImage)
vfmt.fmt.pix.sizeimage = sizeimage[0];
}
if ((set_fmts_out & FmtPixelFormat) &&
!valid_pixel_format(fd, pixfmt, true, is_multiplanar)) {
if (pixfmt)
fprintf(stderr, "The pixelformat '%s' is invalid\n",
fcc2s(pixfmt).c_str());
else
fprintf(stderr, "The pixelformat index was invalid\n");
std::exit(EXIT_FAILURE);
}
if (options[OptSetVideoOutFormat])
ret = doioctl(fd, VIDIOC_S_FMT, &vfmt);
else
ret = doioctl(fd, VIDIOC_TRY_FMT, &vfmt);
if (ret == 0 && (verbose || options[OptTryVideoOutFormat]))
printfmt(fd, vfmt);
}
}
}
void vidout_get(cv4l_fd &fd)
{
if (options[OptGetVideoOutFormat]) {
struct v4l2_format vfmt;
memset(&vfmt, 0, sizeof(vfmt));
vfmt.fmt.pix.priv = priv_magic;
vfmt.type = vidout_buftype;
if (doioctl(fd.g_fd(), VIDIOC_G_FMT, &vfmt) == 0)
printfmt(fd.g_fd(), vfmt);
}
}
void vidout_list(cv4l_fd &fd)
{
if (options[OptListOutFormats]) {
printf("ioctl: VIDIOC_ENUM_FMT\n");
print_video_formats(fd, vidout_buftype, mbus_code_out);
}
if (options[OptListOutFormatsExt]) {
printf("ioctl: VIDIOC_ENUM_FMT\n");
print_video_formats_ext(fd, vidout_buftype, mbus_code_out);
}
if (options[OptListOutFields]) {
print_video_out_fields(fd.g_fd());
}
}