#include "v4l2-ctl.h"
-static struct v4l2_format vfmt_cap; /* set_format/get_format for video */
static struct v4l2_frmsizeenum frmsize; /* list frame sizes */
static struct v4l2_frmivalenum frmival; /* list frame intervals */
static unsigned set_fmts;
+static __u32 width, height, pixfmt, field;
+static __u32 bytesperline[VIDEO_MAX_PLANES];
void vidcap_usage(void)
{
" -V, --get-fmt-video\n"
" query the video capture format [VIDIOC_G_FMT]\n"
" -v, --set-fmt-video\n"
- " --try-fmt-video=width=<w>,height=<h>,pixelformat=<pf>,field=<f>\n"
+ " --try-fmt-video=width=<w>,height=<h>,pixelformat=<pf>,field=<f>,bytesperline=<bpl>\n"
" set/try the video capture format [VIDIOC_S/TRY_FMT]\n"
" pixelformat is either the format index as reported by\n"
" --list-formats, or the fourcc value as a string.\n"
+ " The bytesperline option can be used multiple times, once for each plane.\n"
" <f> can be one of:\n"
" any, none, top, bottom, interlaced, seq_tb, seq_bt,\n"
" alternate, interlaced_tb, interlaced_bt\n"
void vidcap_cmd(int ch, char *optarg)
{
- __u32 width, height, pixfmt, field, colorspace;
+ __u32 colorspace;
char *value, *subs;
switch (ch) {
case OptSetVideoFormat:
case OptTryVideoFormat:
- set_fmts = parse_fmt(optarg, width, height, pixfmt, field, colorspace);
+ set_fmts = parse_fmt(optarg, width, height, pixfmt, field, colorspace, bytesperline);
if (!set_fmts || (set_fmts & FmtColorspace)) {
vidcap_usage();
exit(1);
}
- if (is_multiplanar) {
- vfmt_cap.fmt.pix_mp.width = width;
- vfmt_cap.fmt.pix_mp.height = height;
- vfmt_cap.fmt.pix_mp.pixelformat = pixfmt;
- vfmt_cap.fmt.pix_mp.field = field;
- vfmt_cap.fmt.pix_mp.colorspace = colorspace;
- } else {
- vfmt_cap.fmt.pix.width = width;
- vfmt_cap.fmt.pix.height = height;
- vfmt_cap.fmt.pix.pixelformat = pixfmt;
- vfmt_cap.fmt.pix.field = field;
- vfmt_cap.fmt.pix.colorspace = colorspace;
- }
break;
case OptListFrameSizes:
if (strlen(optarg) == 4)
struct v4l2_format vfmt;
vfmt.type = vidcap_buftype;
+
if (doioctl(fd, VIDIOC_G_FMT, &vfmt) == 0) {
if (is_multiplanar) {
if (set_fmts & FmtWidth)
- vfmt.fmt.pix_mp.width = vfmt_cap.fmt.pix_mp.width;
+ vfmt.fmt.pix_mp.width = width;
if (set_fmts & FmtHeight)
- vfmt.fmt.pix_mp.height = vfmt_cap.fmt.pix_mp.height;
+ vfmt.fmt.pix_mp.height = height;
if (set_fmts & FmtPixelFormat) {
- vfmt.fmt.pix_mp.pixelformat = vfmt_cap.fmt.pix_mp.pixelformat;
+ vfmt.fmt.pix_mp.pixelformat = pixfmt;
if (vfmt.fmt.pix_mp.pixelformat < 256) {
vfmt.fmt.pix_mp.pixelformat =
find_pixel_format(fd, vfmt.fmt.pix_mp.pixelformat,
}
}
if (set_fmts & FmtField)
- vfmt.fmt.pix_mp.field = vfmt_cap.fmt.pix_mp.field;
- /* 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;
+ vfmt.fmt.pix_mp.field = field;
+ if (set_fmts & 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;
+ }
} else {
if (set_fmts & FmtWidth)
- vfmt.fmt.pix.width = vfmt_cap.fmt.pix.width;
+ vfmt.fmt.pix.width = width;
if (set_fmts & FmtHeight)
- vfmt.fmt.pix.height = vfmt_cap.fmt.pix.height;
+ vfmt.fmt.pix.height = height;
if (set_fmts & FmtPixelFormat) {
- vfmt.fmt.pix.pixelformat = vfmt_cap.fmt.pix.pixelformat;
+ vfmt.fmt.pix.pixelformat = pixfmt;
if (vfmt.fmt.pix.pixelformat < 256) {
vfmt.fmt.pix.pixelformat =
find_pixel_format(fd, vfmt.fmt.pix.pixelformat,
}
}
if (set_fmts & FmtField)
- vfmt.fmt.pix.field = vfmt_cap.fmt.pix.field;
- /* 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;
+ vfmt.fmt.pix.field = field;
+ if (set_fmts & 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 (options[OptSetVideoFormat])
void vidcap_get(int fd)
{
if (options[OptGetVideoFormat]) {
- vfmt_cap.type = vidcap_buftype;
- if (doioctl(fd, VIDIOC_G_FMT, &vfmt_cap) == 0)
- printfmt(vfmt_cap);
+ struct v4l2_format vfmt;
+
+ vfmt.type = vidcap_buftype;
+ if (doioctl(fd, VIDIOC_G_FMT, &vfmt) == 0)
+ printfmt(vfmt);
}
}
#include "v4l2-ctl.h"
-static struct v4l2_format vfmt_out; /* set_format/get_format for video */
static unsigned set_fmts_out;
+static __u32 width, height, pixfmt, field, colorspace;
+static __u32 bytesperline[VIDEO_MAX_PLANES];
void vidout_usage(void)
{
" --get-fmt-video-out\n"
" query the video output format [VIDIOC_G_FMT]\n"
" --set-fmt-video-out\n"
- " --try-fmt-video-out=width=<w>,height=<h>,pixelformat=<pf>,field=<f>,colorspace=<c>\n"
+ " --try-fmt-video-out=width=<w>,height=<h>,pixelformat=<pf>,field=<f>,colorspace=<c>,bytesperline=<bpl>\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"
+ " The bytesperline option can be used multiple times, once for each plane.\n"
" <f> can be one of:\n"
" any, none, top, bottom, interlaced, seq_tb, seq_bt,\n"
" alternate, interlaced_tb, interlaced_bt\n"
void vidout_cmd(int ch, char *optarg)
{
- __u32 width, height, pixfmt, field, colorspace;
-
switch (ch) {
case OptSetVideoOutFormat:
case OptTryVideoOutFormat:
- set_fmts_out = parse_fmt(optarg, width, height, pixfmt, field, colorspace);
+ set_fmts_out = parse_fmt(optarg, width, height, pixfmt, field, colorspace, bytesperline);
if (!set_fmts_out) {
vidcap_usage();
exit(1);
}
- if (is_multiplanar) {
- vfmt_out.fmt.pix_mp.width = width;
- vfmt_out.fmt.pix_mp.height = height;
- vfmt_out.fmt.pix_mp.pixelformat = pixfmt;
- vfmt_out.fmt.pix_mp.field = field;
- vfmt_out.fmt.pix_mp.colorspace = colorspace;
- } else {
- vfmt_out.fmt.pix.width = width;
- vfmt_out.fmt.pix.height = height;
- vfmt_out.fmt.pix.pixelformat = pixfmt;
- vfmt_out.fmt.pix.field = field;
- vfmt_out.fmt.pix.colorspace = colorspace;
- }
break;
}
}
if (doioctl(fd, VIDIOC_G_FMT, &vfmt) == 0) {
if (is_multiplanar) {
if (set_fmts_out & FmtWidth)
- vfmt.fmt.pix_mp.width = vfmt_out.fmt.pix_mp.width;
+ vfmt.fmt.pix_mp.width = width;
if (set_fmts_out & FmtHeight)
- vfmt.fmt.pix_mp.height = vfmt_out.fmt.pix_mp.height;
+ vfmt.fmt.pix_mp.height = height;
if (set_fmts_out & FmtPixelFormat) {
- vfmt.fmt.pix_mp.pixelformat = vfmt_out.fmt.pix_mp.pixelformat;
+ vfmt.fmt.pix_mp.pixelformat = pixfmt;
if (vfmt.fmt.pix_mp.pixelformat < 256) {
vfmt.fmt.pix_mp.pixelformat =
find_pixel_format(fd, vfmt.fmt.pix_mp.pixelformat,
}
}
if (set_fmts_out & FmtField)
- vfmt.fmt.pix_mp.field = vfmt_out.fmt.pix_mp.field;
+ vfmt.fmt.pix_mp.field = field;
if (set_fmts_out & FmtColorspace)
- vfmt.fmt.pix_mp.colorspace = vfmt_out.fmt.pix_mp.colorspace;
- /* 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;
+ vfmt.fmt.pix_mp.colorspace = colorspace;
+ 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;
+ }
} else {
if (set_fmts_out & FmtWidth)
- vfmt.fmt.pix.width = vfmt_out.fmt.pix.width;
+ vfmt.fmt.pix.width = width;
if (set_fmts_out & FmtHeight)
- vfmt.fmt.pix.height = vfmt_out.fmt.pix.height;
+ vfmt.fmt.pix.height = height;
if (set_fmts_out & FmtPixelFormat) {
- vfmt.fmt.pix.pixelformat = vfmt_out.fmt.pix.pixelformat;
+ vfmt.fmt.pix.pixelformat = pixfmt;
if (vfmt.fmt.pix.pixelformat < 256) {
vfmt.fmt.pix.pixelformat =
find_pixel_format(fd, vfmt.fmt.pix.pixelformat,
}
}
if (set_fmts_out & FmtField)
- vfmt.fmt.pix.field = vfmt_out.fmt.pix.field;
+ vfmt.fmt.pix.field = field;
if (set_fmts_out & FmtColorspace)
- vfmt.fmt.pix.colorspace = vfmt_out.fmt.pix.colorspace;
- /* 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;
+ vfmt.fmt.pix.colorspace = colorspace;
+ 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 (options[OptSetVideoOutFormat])
void vidout_get(int fd)
{
if (options[OptGetVideoOutFormat]) {
- vfmt_out.type = vidout_buftype;
- if (doioctl(fd, VIDIOC_G_FMT, &vfmt_out) == 0)
- printfmt(vfmt_out);
+ struct v4l2_format vfmt;
+
+ vfmt.type = vidout_buftype;
+ if (doioctl(fd, VIDIOC_G_FMT, &vfmt) == 0)
+ printfmt(vfmt);
}
}
}
int parse_fmt(char *optarg, __u32 &width, __u32 &height, __u32 &pixelformat,
- __u32 &field, __u32 &colorspace)
+ __u32 &field, __u32 &colorspace, __u32 *bytesperline)
{
char *value, *subs;
int fmts = 0;
+ unsigned bpl_index = 0;
field = V4L2_FIELD_ANY;
subs = optarg;
"pixelformat",
"field",
"colorspace",
+ "bytesperline",
NULL
};
switch (parse_subopt(&subs, subopts, &value)) {
case 0:
- width = strtol(value, 0L, 0);
+ width = strtoul(value, 0L, 0);
fmts |= FmtWidth;
break;
case 1:
- height = strtol(value, 0L, 0);
+ height = strtoul(value, 0L, 0);
fmts |= FmtHeight;
break;
case 2:
else
fprintf(stderr, "unknown colorspace %s\n", value);
break;
+ case 5:
+ bytesperline[bpl_index] = strtoul(value, 0L, 0);
+ if (bytesperline[bpl_index] > 0xffff) {
+ fprintf(stderr, "bytesperline can't be more than 65535\n");
+ bytesperline[bpl_index] = 0;
+ }
+ bpl_index++;
+ fmts |= FmtBytesPerLine;
+ break;
default:
return 0;
}
#define FmtTop (1L<<6)
#define FmtField (1L<<7)
#define FmtColorspace (1L<<8)
+#define FmtBytesPerLine (1L<<9)
// v4l2-ctl.cpp
int doioctl_name(int fd, unsigned long int request, void *parm, const char *name);
void print_v4lstd(v4l2_std_id std);
__u32 parse_field(const char *s);
int parse_fmt(char *optarg, __u32 &width, __u32 &height, __u32 &pixelformat,
- __u32 &field, __u32 &colorspace);
+ __u32 &field, __u32 &colorspace, __u32 *bytesperline);
__u32 find_pixel_format(int fd, unsigned index, bool output, bool mplane);
void printfmt(const struct v4l2_format &vfmt);
void print_video_formats(int fd, __u32 type);