#ifndef _CV4L_HELPERS_H_
#define _CV4L_HELPERS_H_
+#include <limits.h>
#include <v4l-helpers.h>
-class cv4l_fmt : public v4l2_format {
+#define cv4l_ioctl(cmd, arg) v4l_named_ioctl(g_v4l_fd(), #cmd, cmd, arg)
+
+class cv4l_fd : v4l_fd {
public:
- cv4l_fmt()
+ cv4l_fd()
+ {
+ v4l_fd_init(this);
+ }
+ cv4l_fd(cv4l_fd *fd)
+ {
+ *this = *fd;
+ }
+
+ __u32 g_type() const { return type; }
+ void s_type(__u32 type) { v4l_s_type(this, type); }
+ __u32 g_selection_type() const { return v4l_g_selection_type(this); }
+ __u32 g_caps() const { return caps; }
+ int g_fd() const { return fd; }
+ v4l_fd *g_v4l_fd() { return this; }
+ bool g_direct() const { return v4l_fd_g_direct(this); }
+ void s_direct(bool direct) { v4l_fd_s_direct(this, direct); }
+ bool g_trace() const { return v4l_fd_g_trace(this); }
+ void s_trace(bool trace) { v4l_fd_s_trace(this, trace); }
+
+ int open(const char *devname, bool non_blocking = false) { return v4l_open(this, devname, non_blocking); }
+ int close() { return v4l_close(this); }
+ int reopen(bool non_blocking = false) { return v4l_reopen(this, non_blocking); }
+ ssize_t read(void *buffer, size_t n) { return v4l_read(this, buffer, n); }
+ ssize_t write(const void *buffer, size_t n) { return v4l_write(this, buffer, n); }
+ void *mmap(size_t length, off_t offset) { return v4l_mmap(this, length, offset); }
+ int munmap(void *start, size_t length) { return v4l_munmap(this, start, length); }
+
+ bool has_vid_cap() const { return v4l_has_vid_cap(this); }
+ bool has_vid_out() const { return v4l_has_vid_out(this); }
+ bool has_vid_m2m() const { return v4l_has_vid_m2m(this); }
+ bool has_vid_mplane() const { return v4l_has_vid_mplane(this); }
+ bool has_overlay_cap() const { return v4l_has_overlay_cap(this); }
+ bool has_overlay_out() const { return v4l_has_overlay_out(this); }
+ bool has_raw_vbi_cap() const { return v4l_has_raw_vbi_cap(this); }
+ bool has_sliced_vbi_cap() const { return v4l_has_sliced_vbi_cap(this); }
+ bool has_vbi_cap() const { return v4l_has_vbi_cap(this); }
+ bool has_raw_vbi_out() const { return v4l_has_raw_vbi_out(this); }
+ bool has_sliced_vbi_out() const { return v4l_has_sliced_vbi_out(this); }
+ bool has_vbi_out() const { return v4l_has_vbi_out(this); }
+ bool has_vbi() const { return v4l_has_vbi(this); }
+ bool has_radio_rx() const { return v4l_has_radio_rx(this); }
+ bool has_radio_tx() const { return v4l_has_radio_tx(this); }
+ bool has_rds_cap() const { return v4l_has_rds_cap(this); }
+ bool has_rds_out() const { return v4l_has_rds_out(this); }
+ bool has_sdr_cap() const { return v4l_has_sdr_cap(this); }
+ bool has_hwseek() const { return v4l_has_hwseek(this); }
+ bool has_rw() const { return v4l_has_rw(this); }
+ bool has_streaming() const { return v4l_has_streaming(this); }
+ bool has_ext_pix_format() const { return v4l_has_ext_pix_format(this); }
+
+ int queryctrl(v4l2_queryctrl &qc)
+ {
+ return cv4l_ioctl(VIDIOC_QUERYCTRL, &qc);
+ }
+
+ int querymenu(v4l2_querymenu &qm)
+ {
+ return cv4l_ioctl(VIDIOC_QUERYMENU, &qm);
+ }
+
+ int g_fmt(v4l2_format &fmt, unsigned type = 0)
{
- fd = NULL;
- type = 0;
- memset(&fmt, 0, sizeof(fmt));
+ return v4l_g_fmt(this, &fmt, type);
}
- cv4l_fmt(v4l_fd *_fd, unsigned _type = 0)
+
+ int try_fmt(v4l2_format &fmt)
{
- fd = _fd;
- memset(&fmt, 0, sizeof(fmt));
- if (_type == 0)
- type = v4l_buf_type_g_vid_cap(fd);
- else
- type = _type;
+ return v4l_try_fmt(this, &fmt);
}
- cv4l_fmt(v4l_fd *_fd, const v4l2_format &_fmt)
+
+ int s_fmt(v4l2_format &fmt)
{
- fd = _fd;
- type = _fmt.type;
- fmt = _fmt.fmt;
+ return v4l_s_fmt(this, &fmt);
}
- cv4l_fmt(const cv4l_fmt &_fmt)
+
+ int g_tuner(v4l2_tuner &tuner, unsigned index = 0)
{
- fd = _fmt.fd;
- type = _fmt.type;
- fmt = _fmt.fmt;
+ memset(&tuner, 0, sizeof(tuner));
+ tuner.index = index;
+ int ret = cv4l_ioctl(VIDIOC_G_TUNER, &tuner);
+ if (ret == 0 && tuner.rangehigh > INT_MAX)
+ tuner.rangehigh = INT_MAX;
+ return ret;
}
- void init(v4l_fd *_fd, unsigned _type = 0)
+
+ int s_tuner(v4l2_tuner &tuner)
{
- fd = _fd;
- memset(&fmt, 0, sizeof(fmt));
- if (_type == 0)
- type = v4l_buf_type_g_vid_cap(fd);
- else
- type = _type;
+ return cv4l_ioctl(VIDIOC_S_TUNER, &tuner);
}
- void init(v4l_fd *_fd, const v4l2_format &_fmt)
+
+ int g_modulator(v4l2_modulator &modulator)
{
- fd = _fd;
- type = _fmt.type;
- fmt = _fmt.fmt;
+ memset(&modulator, 0, sizeof(modulator));
+ return cv4l_ioctl(VIDIOC_G_MODULATOR, &modulator);
}
- int g_fmt(unsigned _type = 0)
+
+ int s_modulator(v4l2_modulator &modulator)
{
- return v4l_g_fmt(fd, this, _type ? _type : type);
+ return cv4l_ioctl(VIDIOC_S_MODULATOR, &modulator);
}
- int try_fmt()
+
+ int enum_input(v4l2_input &in, bool init = false, int index = 0)
{
- return v4l_try_fmt(fd, this);
+ if (init) {
+ memset(&in, 0, sizeof(in));
+ in.index = index;
+ } else {
+ in.index++;
+ }
+ return cv4l_ioctl(VIDIOC_ENUMINPUT, &in);
+ }
+
+ int enum_output(v4l2_output &out, bool init = false, int index = 0)
+ {
+ if (init) {
+ memset(&out, 0, sizeof(out));
+ out.index = index;
+ } else {
+ out.index++;
+ }
+ return cv4l_ioctl(VIDIOC_ENUMOUTPUT, &out);
+ }
+
+ int enum_audio(v4l2_audio &audio, bool init = false, int index = 0)
+ {
+ if (init) {
+ memset(&audio, 0, sizeof(audio));
+ audio.index = index;
+ } else {
+ audio.index++;
+ }
+ return cv4l_ioctl(VIDIOC_ENUMAUDIO, &audio);
+ }
+
+ int enum_audout(v4l2_audioout &audout, bool init = false, int index = 0)
+ {
+ if (init) {
+ memset(&audout, 0, sizeof(audout));
+ audout.index = index;
+ } else {
+ audout.index++;
+ }
+ return cv4l_ioctl(VIDIOC_ENUMAUDOUT, &audout);
+ }
+
+ bool ioctl_exists(int ret)
+ {
+ return ret == 0 || errno != ENOTTY;
+ }
+
+ bool has_crop()
+ {
+ v4l2_crop crop;
+ v4l2_cropcap cropcap;
+
+ crop.type = g_selection_type();
+ cropcap.type = crop.type;
+ return ioctl_exists(cv4l_ioctl(VIDIOC_G_CROP, &crop)) &&
+ ioctl_exists(cv4l_ioctl(VIDIOC_S_CROP, &crop)) &&
+ ioctl_exists(cv4l_ioctl(VIDIOC_CROPCAP, &cropcap));
+ }
+
+ bool has_compose()
+ {
+ v4l2_selection sel;
+
+ memset(&sel, 0, sizeof(sel));
+ sel.type = g_selection_type();
+ sel.target = V4L2_SEL_TGT_COMPOSE;
+ return ioctl_exists(cv4l_ioctl(VIDIOC_G_SELECTION, &sel)) &&
+ ioctl_exists(cv4l_ioctl(VIDIOC_S_SELECTION, &sel));
+ }
+
+ bool input_has_crop()
+ {
+ v4l2_crop crop;
+ v4l2_cropcap cropcap;
+
+ crop.type = g_selection_type();
+ cropcap.type = crop.type;
+ return cv4l_ioctl(VIDIOC_G_CROP, &crop) == 0 &&
+ cv4l_ioctl(VIDIOC_S_CROP, &crop) == 0 &&
+ cv4l_ioctl(VIDIOC_CROPCAP, &cropcap) == 0 &&
+ cropcap.bounds.width && cropcap.bounds.height;
}
- int s_fmt()
+
+ bool input_has_compose()
+ {
+ v4l2_selection sel;
+
+ memset(&sel, 0, sizeof(sel));
+ sel.type = g_selection_type();
+ sel.target = V4L2_SEL_TGT_COMPOSE;
+ return cv4l_ioctl(VIDIOC_G_SELECTION, &sel) == 0 &&
+ cv4l_ioctl(VIDIOC_S_SELECTION, &sel) == 0;
+ }
+
+ int subscribe_event(v4l2_event_subscription &sub)
+ {
+ return cv4l_ioctl(VIDIOC_SUBSCRIBE_EVENT, &sub);
+ }
+
+ int dqevent(v4l2_event &ev)
+ {
+ return cv4l_ioctl(VIDIOC_DQEVENT, &ev);
+ }
+
+ int g_input(int &input)
+ {
+ return cv4l_ioctl(VIDIOC_G_INPUT, &input);
+ }
+
+ int s_input(int input)
+ {
+ return cv4l_ioctl(VIDIOC_S_INPUT, &input);
+ }
+
+ int g_output(int &output)
+ {
+ return cv4l_ioctl(VIDIOC_G_OUTPUT, &output);
+ }
+
+ int s_output(int output)
+ {
+ return cv4l_ioctl(VIDIOC_S_OUTPUT, &output);
+ }
+
+ int g_audio(v4l2_audio &audio)
+ {
+ memset(&audio, 0, sizeof(audio));
+ return cv4l_ioctl(VIDIOC_G_AUDIO, &audio);
+ }
+
+ int s_audio(int input)
+ {
+ v4l2_audio audio;
+
+ memset(&audio, 0, sizeof(audio));
+ audio.index = input;
+ return cv4l_ioctl(VIDIOC_S_AUDIO, &audio);
+ }
+
+ int g_audout(v4l2_audioout &audout)
+ {
+ memset(&audout, 0, sizeof(audout));
+ return cv4l_ioctl(VIDIOC_G_AUDOUT, &audout);
+ }
+
+ int s_audout(int output)
+ {
+ v4l2_audioout audout;
+
+ memset(&audout, 0, sizeof(audout));
+ audout.index = output;
+ return cv4l_ioctl(VIDIOC_S_AUDOUT, &audout);
+ }
+
+ int g_std(v4l2_std_id &std)
+ {
+ return cv4l_ioctl(VIDIOC_G_STD, &std);
+ }
+
+ int s_std(v4l2_std_id std)
+ {
+ return cv4l_ioctl(VIDIOC_S_STD, &std);
+ }
+
+ int query_std(v4l2_std_id &std)
+ {
+ return cv4l_ioctl(VIDIOC_QUERYSTD, &std);
+ }
+
+ int g_dv_timings(v4l2_dv_timings &timings)
{
- return v4l_s_fmt(fd, this);
+ return cv4l_ioctl(VIDIOC_G_DV_TIMINGS, &timings);
}
- void s_width(__u32 width)
+
+ int s_dv_timings(v4l2_dv_timings &timings)
{
- v4l_format_s_width(this, width);
+ return cv4l_ioctl(VIDIOC_S_DV_TIMINGS, &timings);
}
- __u32 g_width()
+
+ int query_dv_timings(v4l2_dv_timings &timings)
{
- return v4l_format_g_width(this);
+ return cv4l_ioctl(VIDIOC_QUERY_DV_TIMINGS, &timings);
}
- void s_height(__u32 height)
+
+ int g_frequency(v4l2_frequency &freq, unsigned index = 0)
{
- v4l_format_s_height(this, height);
+ memset(&freq, 0, sizeof(freq));
+ freq.tuner = index;
+ freq.type = V4L2_TUNER_ANALOG_TV;
+ return cv4l_ioctl(VIDIOC_G_FREQUENCY, &freq);
}
- __u32 g_height()
+
+ int s_frequency(v4l2_frequency &freq)
{
- return v4l_format_g_height(this);
+ return cv4l_ioctl(VIDIOC_S_FREQUENCY, &freq);
}
- void s_pixelformat(__u32 pixelformat)
+
+ int streamon(__u32 type = 0)
{
- v4l_format_s_pixelformat(this, pixelformat);
+ if (type == 0)
+ type = g_type();
+ return cv4l_ioctl(VIDIOC_STREAMON, &type);
}
- __u32 g_pixelformat()
+
+ int streamoff(__u32 type = 0)
{
- return v4l_format_g_pixelformat(this);
+ if (type == 0)
+ type = g_type();
+ return cv4l_ioctl(VIDIOC_STREAMOFF, &type);
}
- void s_field(unsigned field)
+
+ int querybuf(v4l_buffer &buf, unsigned index)
{
- v4l_format_s_field(this, field);
+ return v4l_buffer_querybuf(this, &buf, index);
}
- unsigned g_field()
+
+ int dqbuf(v4l_buffer &buf)
{
- return v4l_format_g_field(this);
+ return v4l_buffer_dqbuf(this, &buf);
}
- unsigned g_first_field(v4l2_std_id std)
+
+ int qbuf(v4l_buffer &buf)
{
- return v4l_format_g_first_field(this, std);
+ return v4l_buffer_qbuf(this, &buf);
}
- unsigned g_flds_per_frm()
+
+ int prepare_buf(v4l_buffer &buf)
{
- return v4l_format_g_flds_per_frm(this);
+ return v4l_buffer_prepare_buf(this, &buf);
}
- void s_colorspace(unsigned colorspace)
+
+ int enum_std(v4l2_standard &std, bool init = false, int index = 0)
{
- v4l_format_s_colorspace(this, colorspace);
+ if (init) {
+ memset(&std, 0, sizeof(std));
+ std.index = index;
+ } else {
+ std.index++;
+ }
+ return cv4l_ioctl(VIDIOC_ENUMSTD, &std);
}
- unsigned g_colorspace()
+
+ int enum_dv_timings(v4l2_enum_dv_timings &timings, bool init = false, int index = 0)
{
- return v4l_format_g_colorspace(this);
+ if (init) {
+ memset(&timings, 0, sizeof(timings));
+ timings.index = index;
+ } else {
+ timings.index++;
+ }
+ return cv4l_ioctl(VIDIOC_ENUM_DV_TIMINGS, &timings);
}
- void s_num_planes(__u8 num_planes)
+
+ int enum_fmt(v4l2_fmtdesc &fmt, bool init = false, int index = 0, unsigned type = 0)
{
- v4l_format_s_num_planes(this, num_planes);
+ if (init) {
+ memset(&fmt, 0, sizeof(fmt));
+ fmt.index = index;
+ } else {
+ fmt.index++;
+ }
+ fmt.type = type ? type : g_type();
+ return cv4l_ioctl(VIDIOC_ENUM_FMT, &fmt);
}
- __u8 g_num_planes()
+
+ int enum_framesizes(v4l2_frmsizeenum &frm, __u32 init_pixfmt = 0, int index = 0)
{
- return v4l_format_g_num_planes(this);
+ if (init_pixfmt) {
+ memset(&frm, 0, sizeof(frm));
+ frm.pixel_format = init_pixfmt;
+ frm.index = index;
+ } else {
+ frm.index++;
+ }
+ return cv4l_ioctl(VIDIOC_ENUM_FRAMESIZES, &frm);
+ }
+
+ int enum_frameintervals(v4l2_frmivalenum &frm, __u32 init_pixfmt = 0, __u32 w = 0, __u32 h = 0, int index = 0)
+ {
+ if (init_pixfmt) {
+ memset(&frm, 0, sizeof(frm));
+ frm.pixel_format = init_pixfmt;
+ frm.width = w;
+ frm.height = h;
+ frm.index = index;
+ } else {
+ frm.index++;
+ }
+ return cv4l_ioctl(VIDIOC_ENUM_FRAMEINTERVALS, &frm);
}
- void s_bytesperline(unsigned plane, __u32 bytesperline)
+
+ int set_interval(v4l2_fract interval, unsigned type = 0)
{
- v4l_format_s_bytesperline(this, plane, bytesperline);
+ v4l2_streamparm parm;
+
+ parm.type = type ? type : g_type();
+ if (cv4l_ioctl(VIDIOC_G_PARM, &parm) ||
+ !(parm.parm.capture.capability & V4L2_CAP_TIMEPERFRAME))
+ return -1;
+
+ parm.parm.capture.timeperframe = interval;
+
+ return cv4l_ioctl(VIDIOC_S_PARM, &parm);
}
- __u32 g_bytesperline(unsigned plane)
+
+ int get_interval(v4l2_fract &interval, unsigned type = 0)
{
- return v4l_format_g_bytesperline(this, plane);
+ v4l2_streamparm parm;
+
+ parm.type = type ? type : g_type();
+ if (cv4l_ioctl(VIDIOC_G_PARM, &parm) == 0 &&
+ (parm.parm.capture.capability & V4L2_CAP_TIMEPERFRAME)) {
+ interval = parm.parm.capture.timeperframe;
+ return 0;
+ }
+
+ return -1;
}
- void s_sizeimage(unsigned plane, __u32 sizeimage)
+
+ v4l2_fract g_pixel_aspect(unsigned &width, unsigned &height, unsigned type = 0)
+ {
+ v4l2_cropcap ratio;
+ v4l2_dv_timings timings;
+ v4l2_std_id std;
+ static const v4l2_fract square = { 1, 1 };
+ static const v4l2_fract hz50 = { 11, 12 };
+ static const v4l2_fract hz60 = { 11, 10 };
+
+ ratio.type = type ? type : g_selection_type();
+ if (cv4l_ioctl(VIDIOC_CROPCAP, &ratio) == 0) {
+ width = ratio.defrect.width;
+ height = ratio.defrect.height;
+ if (ratio.pixelaspect.numerator && ratio.pixelaspect.denominator)
+ return ratio.pixelaspect;
+ }
+
+ width = 720;
+ height = 480;
+ if (!g_std(std)) {
+ if (std & V4L2_STD_525_60)
+ return hz60;
+ if (std & V4L2_STD_625_50) {
+ height = 576;
+ return hz50;
+ }
+ }
+
+ if (!g_dv_timings(timings)) {
+ width = timings.bt.width;
+ height = timings.bt.height;
+ if (width == 720 && height == 480)
+ return hz60;
+ if (width == 720 && height == 576) {
+ height = 576;
+ return hz50;
+ }
+ return square;
+ }
+ width = 0;
+ height = 0;
+ return square;
+ }
+};
+
+class cv4l_fmt : public v4l2_format {
+public:
+ cv4l_fmt(unsigned _type = 0)
{
- v4l_format_s_sizeimage(this, plane, sizeimage);
+ v4l_format_init(this, _type);
}
- __u32 g_sizeimage(unsigned plane)
+ cv4l_fmt(const v4l2_format &_fmt)
{
- return v4l_format_g_sizeimage(this, plane);
+ *this = _fmt;
}
-protected:
- v4l_fd *fd;
+ __u32 g_type() { return type; }
+ void s_type(unsigned type) { v4l_format_init(this, type); }
+ __u32 g_width() { return v4l_format_g_width(this); }
+ void s_width(__u32 width) { v4l_format_s_width(this, width); }
+ __u32 g_height() { return v4l_format_g_height(this); }
+ void s_height(__u32 height) { v4l_format_s_height(this, height); }
+ __u32 g_pixelformat() { return v4l_format_g_pixelformat(this); }
+ void s_pixelformat(__u32 pixelformat) { v4l_format_s_pixelformat(this, pixelformat); }
+ unsigned g_colorspace() { return v4l_format_g_colorspace(this); }
+ void s_colorspace(unsigned colorspace) { v4l_format_s_colorspace(this, colorspace); }
+ __u8 g_num_planes() { return v4l_format_g_num_planes(this); }
+ void s_num_planes(__u8 num_planes) { v4l_format_s_num_planes(this, num_planes); }
+ __u32 g_bytesperline(unsigned plane = 0) { return v4l_format_g_bytesperline(this, plane); }
+ void s_bytesperline(__u32 bytesperline, unsigned plane = 0) { v4l_format_s_bytesperline(this, bytesperline, plane); }
+ __u32 g_sizeimage(unsigned plane = 0) { return v4l_format_g_sizeimage(this, plane); }
+ void s_sizeimage(__u32 sizeimage, unsigned plane = 0) { v4l_format_s_sizeimage(this, sizeimage, plane); }
+ unsigned g_field() { return v4l_format_g_field(this); }
+ void s_field(unsigned field) { v4l_format_s_field(this, field); }
+ unsigned g_first_field(v4l2_std_id std) { return v4l_format_g_first_field(this, std); }
+ unsigned g_flds_per_frm() { return v4l_format_g_flds_per_frm(this); }
};
class cv4l_buffer;
class cv4l_queue : v4l_queue {
friend class cv4l_buffer;
public:
- cv4l_queue(v4l_fd *_fd, unsigned type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
- unsigned memory = V4L2_MEMORY_MMAP)
+ cv4l_queue(unsigned type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ unsigned memory = V4L2_MEMORY_MMAP)
{
- fd = _fd;
v4l_queue_init(this, type, memory);
}
- virtual ~cv4l_queue()
- {
- if (fd->fd != -1)
- v4l_queue_free(fd, this);
- }
-
void init(unsigned type, unsigned memory)
{
- if (fd->fd != -1)
- v4l_queue_free(fd, this);
v4l_queue_init(this, type, memory);
}
unsigned g_type() const { return v4l_queue_g_type(this); }
unsigned g_memory() const { return v4l_queue_g_memory(this); }
- bool is_planar() const { return v4l_queue_is_planar(this); }
- bool is_output() const { return v4l_queue_is_output(this); }
- bool is_capture() const { return v4l_queue_is_capture(this); }
- bool is_video() const { return v4l_queue_is_video(this); }
- bool is_vbi() const { return v4l_queue_is_vbi(this); }
- bool is_sliced_vbi() const { return v4l_queue_is_sliced_vbi(this); }
- bool is_sdr() const { return v4l_queue_is_sdr(this); }
unsigned g_buffers() const { return v4l_queue_g_buffers(this); }
unsigned g_num_planes() const { return v4l_queue_g_num_planes(this); }
unsigned g_length(unsigned plane) const { return v4l_queue_g_length(this, plane); }
unsigned g_mem_offset(unsigned index, unsigned plane) const { return v4l_queue_g_mem_offset(this, index, plane); }
- void s_mmapping(unsigned index, unsigned plane, void *m) { v4l_queue_s_mmapping(this, index, plane, m); }
void *g_mmapping(unsigned index, unsigned plane) const { return v4l_queue_g_mmapping(this, index, plane); }
- void s_userptr(unsigned index, unsigned plane, void *m) { v4l_queue_s_userptr(this, index, plane, m); }
+ void s_mmapping(unsigned index, unsigned plane, void *m) { v4l_queue_s_mmapping(this, index, plane, m); }
void *g_userptr(unsigned index, unsigned plane) const { return v4l_queue_g_userptr(this, index, plane); }
- void s_fd(unsigned index, unsigned plane, int fd) { v4l_queue_s_fd(this, index, plane, fd); }
+ void s_userptr(unsigned index, unsigned plane, void *m) { v4l_queue_s_userptr(this, index, plane, m); }
+ void *g_dataptr(unsigned index, unsigned plane) const { return v4l_queue_g_dataptr(this, index, plane); }
int g_fd(unsigned index, unsigned plane) const { return v4l_queue_g_fd(this, index, plane); }
+ void s_fd(unsigned index, unsigned plane, int fd) { v4l_queue_s_fd(this, index, plane, fd); }
- int reqbufs(unsigned count = 0)
+ int reqbufs(cv4l_fd *fd, unsigned count = 0)
{
- return v4l_queue_reqbufs(fd, this, count);
+ return v4l_queue_reqbufs(fd->g_v4l_fd(), this, count);
}
- bool has_create_bufs() const
+ bool has_create_bufs(cv4l_fd *fd) const
{
- return v4l_queue_has_create_bufs(fd, this);
+ return v4l_queue_has_create_bufs(fd->g_v4l_fd(), this);
}
- int create_bufs(unsigned count, const v4l2_format *fmt = NULL)
+ int create_bufs(cv4l_fd *fd, unsigned count, const v4l2_format *fmt = NULL)
{
- return v4l_queue_create_bufs(fd, this, count, fmt);
+ return v4l_queue_create_bufs(fd->g_v4l_fd(), this, count, fmt);
}
- int streamon()
+ int mmap_bufs(cv4l_fd *fd, unsigned from = 0)
{
- return v4l_queue_streamon(fd, this);
+ return v4l_queue_mmap_bufs(fd->g_v4l_fd(), this, from);
}
- int streamoff()
+ int munmap_bufs(cv4l_fd *fd)
{
- return v4l_queue_streamoff(fd, this);
+ return v4l_queue_munmap_bufs(fd->g_v4l_fd(), this);
}
- int mmap_bufs(unsigned from = 0)
+ int alloc_bufs(cv4l_fd *fd, unsigned from = 0)
{
- return v4l_queue_mmap_bufs(fd, this, from);
+ return v4l_queue_alloc_bufs(fd->g_v4l_fd(), this, from);
}
- int munmap_bufs()
+ int free_bufs()
{
- return v4l_queue_munmap_bufs(fd, this);
+ return v4l_queue_free_bufs(this);
}
- int alloc_bufs(unsigned from = 0)
+ int obtain_bufs(cv4l_fd *fd, unsigned from = 0)
{
- return v4l_queue_alloc_bufs(fd, this, from);
+ return v4l_queue_obtain_bufs(fd->g_v4l_fd(), this, from);
}
- int free_bufs()
+ int release_bufs(cv4l_fd *fd)
{
- return v4l_queue_free_bufs(this);
+ return v4l_queue_release_bufs(fd->g_v4l_fd(), this);
}
- bool has_expbuf()
+ bool has_expbuf(cv4l_fd *fd)
{
- return v4l_queue_has_expbuf(fd);
+ return v4l_queue_has_expbuf(fd->g_v4l_fd());
}
- int export_bufs()
+ int export_bufs(cv4l_fd *fd)
{
- return v4l_queue_export_bufs(fd, this);
+ return v4l_queue_export_bufs(fd->g_v4l_fd(), this);
}
void close_exported_fds()
{
v4l_queue_close_exported_fds(this);
}
- void buffer_init(struct v4l_buffer *buf, unsigned index) const
+ void free(cv4l_fd *fd)
{
- v4l_queue_buffer_init(this, buf, index);
+ v4l_queue_free(fd->g_v4l_fd(), this);
}
-
-protected:
- v4l_fd *fd;
+ void buffer_init(v4l_buffer &buf, unsigned index) const
+ {
+ v4l_queue_buffer_init(this, &buf, index);
+ }
+ int queue_all(cv4l_fd *fd);
};
class cv4l_buffer : public v4l_buffer {
init(b);
}
virtual ~cv4l_buffer() {}
+
void init(unsigned type = 0, unsigned memory = 0, unsigned index = 0)
{
v4l_buffer_init(this, type, memory, index);
}
void init(const cv4l_queue &q, unsigned index = 0)
{
- q.buffer_init(this, index);
+ q.buffer_init(*this, index);
}
void init(const cv4l_buffer &b)
{
*this = b;
- if (is_planar())
+ if (v4l_type_is_planar(g_type()))
buf.m.planes = planes;
}
+
__u32 g_index() const { return v4l_buffer_g_index(this); }
void s_index(unsigned index) { v4l_buffer_s_index(this, index); }
unsigned g_type() const { return v4l_buffer_g_type(this); }
void or_flags(__u32 flags) { v4l_buffer_or_flags(this, flags); }
unsigned g_field() const { return v4l_buffer_g_field(this); }
void s_field(unsigned field) { v4l_buffer_s_field(this, field); }
+
+ unsigned g_num_planes() const { return v4l_buffer_g_num_planes(this); }
+ __u32 g_mem_offset(unsigned plane = 0) const { return v4l_buffer_g_mem_offset(this, plane); }
+ void *g_userptr(unsigned plane = 0) const { return v4l_buffer_g_userptr(this, plane); }
+ void s_userptr(void *userptr, unsigned plane = 0) { v4l_buffer_s_userptr(this, plane, userptr); }
+ int g_fd(unsigned plane = 0) const { return v4l_buffer_g_fd(this, plane); }
+ void s_fd(int fd, unsigned plane = 0) { v4l_buffer_s_fd(this, plane, fd); }
+ __u32 g_bytesused(unsigned plane = 0) const { return v4l_buffer_g_bytesused(this, plane); }
+ void s_bytesused(__u32 bytesused, unsigned plane = 0) { v4l_buffer_s_bytesused(this, plane, bytesused); }
+ __u32 g_data_offset(unsigned plane = 0) const { return v4l_buffer_g_data_offset(this, plane); }
+ void s_data_offset(__u32 data_offset, unsigned plane = 0) { v4l_buffer_s_data_offset(this, plane, data_offset); }
+ __u32 g_length(unsigned plane = 0) const { return v4l_buffer_g_length(this, plane); }
+ void s_length(unsigned length, unsigned plane = 0) { return v4l_buffer_s_length(this, plane, length); }
+
__u32 g_sequence() const { return v4l_buffer_g_sequence(this); }
__u32 g_timestamp_type() const { return v4l_buffer_g_timestamp_type(this); }
__u32 g_timestamp_src() const { return v4l_buffer_g_timestamp_src(this); }
void s_timestamp_clock() { v4l_buffer_s_timestamp_clock(this); }
const v4l2_timecode &g_timecode() const { return *v4l_buffer_g_timecode(this); }
void s_timecode(const v4l2_timecode &tc) { v4l_buffer_s_timecode(this, &tc); }
- __u32 g_mem_offset(unsigned plane = 0) const
- {
- return v4l_buffer_g_mem_offset(this, plane);
- }
- void *g_userptr(unsigned plane = 0) const
- {
- return v4l_buffer_g_userptr(this, plane);
- }
- int g_fd(unsigned plane = 0) const
- {
- return v4l_buffer_g_fd(this, plane);
- }
- __u32 g_bytesused(unsigned plane = 0) const
- {
- return v4l_buffer_g_bytesused(this, plane);
- }
- __u32 g_length(unsigned plane = 0) const
- {
- return v4l_buffer_g_length(this, plane);
- }
- __u32 g_data_offset(unsigned plane = 0) const
- {
- return v4l_buffer_g_data_offset(this, plane);
- }
- void s_userptr(void *userptr, unsigned plane = 0)
- {
- v4l_buffer_s_userptr(this, plane, userptr);
- }
- void s_fd(int fd, unsigned plane = 0)
- {
- v4l_buffer_s_fd(this, plane, fd);
- }
- void s_bytesused(__u32 bytesused, unsigned plane = 0)
- {
- v4l_buffer_s_bytesused(this, plane, bytesused);
- }
- void s_data_offset(__u32 data_offset, unsigned plane = 0)
- {
- v4l_buffer_s_data_offset(this, plane, data_offset);
- }
- bool is_planar() const { return v4l_buffer_is_planar(this); }
- bool is_output() const { return v4l_buffer_is_output(this); }
- bool is_capture() const { return v4l_buffer_is_capture(this); }
- bool is_video() const { return v4l_buffer_is_video(this); }
- bool is_vbi() const { return v4l_buffer_is_vbi(this); }
- bool is_sliced_vbi() const { return v4l_buffer_is_sliced_vbi(this); }
- bool is_sdr() const { return v4l_buffer_is_sdr(this); }
- unsigned g_num_planes() const
- {
- return v4l_buffer_g_num_planes(this);
- }
-
- int querybuf(v4l_fd *fd, unsigned index)
- {
- return v4l_buffer_querybuf(fd, this, index);
- }
- int querybuf(const cv4l_queue &q, unsigned index)
- {
- return querybuf(q.fd, index);
- }
- int dqbuf(v4l_fd *fd)
- {
- return v4l_buffer_dqbuf(fd, this);
- }
- int dqbuf(const cv4l_queue &q)
- {
- return dqbuf(q.fd);
- }
- int qbuf(v4l_fd *fd)
- {
- return v4l_buffer_qbuf(fd, this);
- }
- int qbuf(const cv4l_queue &q)
- {
- return qbuf(q.fd);
- }
- int prepare_buf(v4l_fd *fd)
- {
- return v4l_buffer_prepare_buf(fd, this);
- }
- int prepare_buf(const cv4l_queue &q)
- {
- return prepare_buf(q.fd);
- }
};
+inline int cv4l_queue::queue_all(cv4l_fd *fd)
+{
+ cv4l_buffer buf;
+
+ for (unsigned i = 0; i < g_buffers(); i++) {
+ buf.init(*this, i);
+ int ret = fd->qbuf(buf);
+ if (ret)
+ return ret;
+ }
+ return 0;
+}
+
#endif
#define _V4L_HELPERS_H_
#include <linux/videodev2.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <time.h>
+#include <unistd.h>
#include <sys/ioctl.h>
+#include <sys/fcntl.h>
#include <sys/mman.h>
#include <errno.h>
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
struct v4l_fd {
int fd;
+ struct v4l2_capability cap;
+ char devname[128];
+ __u32 type;
__u32 caps;
bool trace;
- int (*ioctl)(int fd, unsigned long cmd, ...);
+ bool direct;
+
+ int (*open)(struct v4l_fd *f, const char *file, int oflag, ...);
+ int (*close)(struct v4l_fd *f);
+ int (*ioctl)(struct v4l_fd *f, unsigned long cmd, ...);
+ ssize_t (*read)(struct v4l_fd *f, void *buffer, size_t n);
+ ssize_t (*write)(struct v4l_fd *f, const void *buffer, size_t n);
void *(*mmap)(void *addr, size_t length, int prot, int flags,
- int fd, int64_t offset);
- int (*munmap)(void *addr, size_t length);
+ struct v4l_fd *f, off_t offset);
+ int (*munmap)(struct v4l_fd *f, void *addr, size_t length);
};
-static inline int v4l_named_ioctl(struct v4l_fd *f, const char *cmd_name,
- unsigned long cmd, void *arg)
+#ifdef __LIBV4L2_H
+
+static inline int v4l_wrap_open(struct v4l_fd *f, const char *file, int oflag, ...)
+{
+ return f->direct ? open(file, oflag) : v4l2_open(file, oflag);
+}
+
+static inline int v4l_wrap_close(struct v4l_fd *f)
+{
+ return f->direct ? close(f->fd) : v4l2_close(f->fd);
+}
+
+static inline ssize_t v4l_wrap_read(struct v4l_fd *f, void *buffer, size_t n)
+{
+ return f->direct ? read(f->fd, buffer, n) : v4l2_read(f->fd, buffer, n);
+}
+
+static inline ssize_t v4l_wrap_write(struct v4l_fd *f, const void *buffer, size_t n)
+{
+ return f->direct ? write(f->fd, buffer, n) : v4l2_write(f->fd, buffer, n);
+}
+
+static inline int v4l_wrap_ioctl(struct v4l_fd *f, unsigned long cmd, ...)
+{
+ void *arg;
+ va_list ap;
+
+ va_start(ap, cmd);
+ arg = va_arg(ap, void *);
+ va_end(ap);
+ return f->direct ? ioctl(f->fd, cmd, arg) : v4l2_ioctl(f->fd, cmd, arg);
+}
+
+static inline void *v4l_wrap_mmap(void *start, size_t length, int prot, int flags,
+ struct v4l_fd *f, off_t offset)
+{
+ return f->direct ? mmap(start, length, prot, flags, f->fd, offset) :
+ v4l2_mmap(start, length, prot, flags, f->fd, offset);
+}
+
+static inline int v4l_wrap_munmap(struct v4l_fd *f, void *start, size_t length)
+{
+ return f->direct ? munmap(start, length) : v4l2_munmap(start, length);
+}
+
+static inline bool v4l_fd_g_direct(const struct v4l_fd *f)
+{
+ return f->direct;
+}
+
+static inline void v4l_fd_s_direct(struct v4l_fd *f, bool direct)
+{
+ f->direct = direct;
+}
+
+#else
+
+static inline int v4l_wrap_open(struct v4l_fd *f, const char *file, int oflag, ...)
+{
+ return open(file, oflag);
+}
+
+static inline int v4l_wrap_close(struct v4l_fd *f)
+{
+ return close(f->fd);
+}
+
+static inline ssize_t v4l_wrap_read(struct v4l_fd *f, void *buffer, size_t n)
+{
+ return read(f->fd, buffer, n);
+}
+
+static inline ssize_t v4l_wrap_write(struct v4l_fd *f, const void *buffer, size_t n)
+{
+ return write(f->fd, buffer, n);
+}
+
+static inline int v4l_wrap_ioctl(struct v4l_fd *f, unsigned long cmd, ...)
+{
+ void *arg;
+ va_list ap;
+
+ va_start(ap, cmd);
+ arg = va_arg(ap, void *);
+ va_end(ap);
+ return ioctl(f->fd, cmd, arg);
+}
+
+static inline void *v4l_wrap_mmap(void *start, size_t length, int prot, int flags,
+ struct v4l_fd *f, off_t offset)
+{
+ return mmap(start, length, prot, flags, f->fd, offset);
+}
+
+static inline int v4l_wrap_munmap(struct v4l_fd *f, void *start, size_t length)
+{
+ return munmap(start, length);
+}
+
+static inline bool v4l_fd_g_direct(const struct v4l_fd *f)
+{
+ return true;
+}
+
+static inline void v4l_fd_s_direct(struct v4l_fd *f, bool direct)
+{
+}
+
+#endif
+
+static inline void v4l_fd_init(struct v4l_fd *f)
+{
+ memset(f, 0, sizeof(*f));
+ f->fd = -1;
+ f->open = v4l_wrap_open;
+ f->close = v4l_wrap_close;
+ f->ioctl = v4l_wrap_ioctl;
+ f->read = v4l_wrap_read;
+ f->write = v4l_wrap_write;
+ f->mmap = v4l_wrap_mmap;
+ f->munmap = v4l_wrap_munmap;
+}
+
+static inline bool v4l_fd_g_trace(const struct v4l_fd *f)
+{
+ return f->trace;
+}
+
+static inline void v4l_fd_s_trace(struct v4l_fd *f, bool trace)
+{
+ f->trace = trace;
+}
+
+static inline int v4l_named_ioctl(struct v4l_fd *f,
+ const char *cmd_name, unsigned long cmd, void *arg)
{
int retval;
int e;
- errno = 0;
- retval = f->ioctl(f->fd, cmd, arg);
- e = errno;
+ retval = f->ioctl(f, cmd, arg);
+ e = retval == 0 ? 0 : errno;
if (f->trace)
- fprintf(stderr, "\t\t%s returned %d (%s)\n", cmd_name, retval, strerror(e));
- return retval ? e : 0;
+ fprintf(stderr, "\t\t%s returned %d (%s)\n",
+ cmd_name, retval, strerror(e));
+ return retval == -1 ? e : (retval ? -1 : 0);
}
#define v4l_ioctl(f, cmd, arg) v4l_named_ioctl(f, #cmd, cmd, arg)
-/*
- * mmap has a different prototype compared to v4l2_mmap. Because of
- * this we have to make a wrapper for it.
- */
-static inline void *v4l_fd_mmap(void *addr, size_t length, int prot, int flags,
- int fd, int64_t offset)
+static inline void *v4l_mmap(struct v4l_fd *f, size_t length, off_t offset)
{
- return mmap(addr, length, prot, flags, fd, offset);
+ return f->mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, f, offset);
}
-static inline void *v4l_mmap(struct v4l_fd *f, size_t length, off_t offset)
+static inline int v4l_munmap(struct v4l_fd *f, void *start, size_t length)
{
- return f->mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, f->fd, offset);
+ return f->munmap(f, start, length);
}
-static inline int v4l_munmap(struct v4l_fd *f, void *start, size_t length)
+static inline ssize_t v4l_read(struct v4l_fd *f, void *buffer, size_t n)
+{
+ return f->read(f, buffer, n);
+}
+
+static inline ssize_t v4l_write(struct v4l_fd *f, const void *buffer, size_t n)
{
- return f->munmap(start, length) ? errno : 0;
+ return f->write(f, buffer, n);
+}
+
+static inline int v4l_close(struct v4l_fd *f)
+{
+ int res = f->close(f);
+
+ f->caps = f->type = 0;
+ f->fd = -1;
+ return res;
}
static inline int v4l_querycap(struct v4l_fd *f, struct v4l2_capability *cap)
cap->device_caps : cap->capabilities;
}
-static inline __u32 v4l_g_caps(struct v4l_fd *f)
+static inline __u32 v4l_g_type(const struct v4l_fd *f)
+{
+ return f->type;
+}
+
+static inline void v4l_s_type(struct v4l_fd *f, __u32 type)
+{
+ f->type = type;
+}
+
+static inline __u32 v4l_g_selection_type(const struct v4l_fd *f)
+{
+ if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+ return V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+ return V4L2_BUF_TYPE_VIDEO_OUTPUT;
+ return f->type;
+}
+
+static inline __u32 v4l_g_caps(const struct v4l_fd *f)
{
return f->caps;
}
-static inline bool v4l_has_vid_cap(struct v4l_fd *f)
+static inline bool v4l_has_vid_cap(const struct v4l_fd *f)
{
return v4l_g_caps(f) & (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_CAPTURE_MPLANE);
}
-static inline bool v4l_has_vid_out(struct v4l_fd *f)
+static inline bool v4l_has_vid_out(const struct v4l_fd *f)
{
return v4l_g_caps(f) & (V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_VIDEO_OUTPUT_MPLANE);
}
-static inline bool v4l_has_vid_m2m(struct v4l_fd *f)
+static inline bool v4l_has_vid_m2m(const struct v4l_fd *f)
{
return v4l_g_caps(f) & (V4L2_CAP_VIDEO_M2M | V4L2_CAP_VIDEO_M2M_MPLANE);
}
-static inline bool v4l_has_vid_mplane(struct v4l_fd *f)
+static inline bool v4l_has_vid_mplane(const struct v4l_fd *f)
{
return v4l_g_caps(f) & (V4L2_CAP_VIDEO_CAPTURE_MPLANE |
V4L2_CAP_VIDEO_OUTPUT_MPLANE |
V4L2_CAP_VIDEO_M2M_MPLANE);
}
-static inline bool v4l_has_overlay_cap(struct v4l_fd *f)
+static inline bool v4l_has_overlay_cap(const struct v4l_fd *f)
{
return v4l_g_caps(f) & V4L2_CAP_VIDEO_OVERLAY;
}
-static inline bool v4l_has_overlay_out(struct v4l_fd *f)
+static inline bool v4l_has_overlay_out(const struct v4l_fd *f)
{
return v4l_g_caps(f) & V4L2_CAP_VIDEO_OUTPUT_OVERLAY;
}
-static inline bool v4l_has_raw_vbi_cap(struct v4l_fd *f)
+static inline bool v4l_has_raw_vbi_cap(const struct v4l_fd *f)
{
return v4l_g_caps(f) & V4L2_CAP_VBI_CAPTURE;
}
-static inline bool v4l_has_sliced_vbi_cap(struct v4l_fd *f)
+static inline bool v4l_has_sliced_vbi_cap(const struct v4l_fd *f)
{
return v4l_g_caps(f) & V4L2_CAP_SLICED_VBI_CAPTURE;
}
-static inline bool v4l_has_vbi_cap(struct v4l_fd *f)
+static inline bool v4l_has_vbi_cap(const struct v4l_fd *f)
{
return v4l_has_raw_vbi_cap(f) || v4l_has_sliced_vbi_cap(f);
}
-static inline bool v4l_has_raw_vbi_out(struct v4l_fd *f)
+static inline bool v4l_has_raw_vbi_out(const struct v4l_fd *f)
{
return v4l_g_caps(f) & V4L2_CAP_VBI_OUTPUT;
}
-static inline bool v4l_has_sliced_vbi_out(struct v4l_fd *f)
+static inline bool v4l_has_sliced_vbi_out(const struct v4l_fd *f)
{
return v4l_g_caps(f) & V4L2_CAP_SLICED_VBI_OUTPUT;
}
-static inline bool v4l_has_vbi_out(struct v4l_fd *f)
+static inline bool v4l_has_vbi_out(const struct v4l_fd *f)
{
return v4l_has_raw_vbi_out(f) || v4l_has_sliced_vbi_out(f);
}
-static inline bool v4l_has_vbi(struct v4l_fd *f)
+static inline bool v4l_has_vbi(const struct v4l_fd *f)
{
return v4l_has_vbi_cap(f) || v4l_has_vbi_out(f);
}
-static inline bool v4l_has_radio_rx(struct v4l_fd *f)
+static inline bool v4l_has_radio_rx(const struct v4l_fd *f)
{
return (v4l_g_caps(f) & V4L2_CAP_RADIO) &&
(v4l_g_caps(f) & V4L2_CAP_TUNER);
}
-static inline bool v4l_has_radio_tx(struct v4l_fd *f)
+static inline bool v4l_has_radio_tx(const struct v4l_fd *f)
{
return (v4l_g_caps(f) & V4L2_CAP_RADIO) &&
(v4l_g_caps(f) & V4L2_CAP_MODULATOR);
}
-static inline bool v4l_has_rds_cap(struct v4l_fd *f)
+static inline bool v4l_has_rds_cap(const struct v4l_fd *f)
{
return v4l_g_caps(f) & V4L2_CAP_RDS_CAPTURE;
}
-static inline bool v4l_has_rds_out(struct v4l_fd *f)
+static inline bool v4l_has_rds_out(const struct v4l_fd *f)
{
return v4l_g_caps(f) & V4L2_CAP_RDS_OUTPUT;
}
-static inline bool v4l_has_sdr_cap(struct v4l_fd *f)
+static inline bool v4l_has_sdr_cap(const struct v4l_fd *f)
{
return v4l_g_caps(f) & V4L2_CAP_SDR_CAPTURE;
}
-static inline bool v4l_has_hwseek(struct v4l_fd *f)
+static inline bool v4l_has_hwseek(const struct v4l_fd *f)
{
return v4l_g_caps(f) & V4L2_CAP_HW_FREQ_SEEK;
}
-static inline bool v4l_has_rw(struct v4l_fd *f)
+static inline bool v4l_has_rw(const struct v4l_fd *f)
{
return v4l_g_caps(f) & V4L2_CAP_READWRITE;
}
-static inline bool v4l_has_streaming(struct v4l_fd *f)
+static inline bool v4l_has_streaming(const struct v4l_fd *f)
{
return v4l_g_caps(f) & V4L2_CAP_STREAMING;
}
-static inline void v4l_fd_init(struct v4l_fd *f, int fd)
+static inline bool v4l_has_ext_pix_format(const struct v4l_fd *f)
{
- struct v4l2_capability cap;
-
- f->fd = fd;
- f->ioctl = ioctl;
- f->mmap = v4l_fd_mmap;
- f->munmap = munmap;
- f->caps = v4l_querycap(f, &cap) ? 0 : v4l_capability_g_caps(&cap);
+ return v4l_g_caps(f) & V4L2_CAP_EXT_PIX_FORMAT;
}
-#define v4l_fd_libv4l2_init(f, fd) \
- do { \
- struct v4l2_capability cap; \
- \
- (f)->fd = fd; \
- (f)->ioctl = v4l2_ioctl; \
- (f)->mmap = v4l2_mmap; \
- (f)->munmap = v4l2_munmap; \
- (f)->caps = v4l_querycap(f, &cap) ? 0 : \
- v4l_capability_g_caps(&cap); \
- } while (0)
-
-static inline __u32 v4l_buf_type_g_vid_cap(struct v4l_fd *f)
-{
- if (v4l_g_caps(f) & (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_M2M))
- return V4L2_BUF_TYPE_VIDEO_CAPTURE;
- if (v4l_g_caps(f) & (V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_VIDEO_M2M_MPLANE))
- return V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
- return 0;
-}
-
-static inline __u32 v4l_buf_type_g_vid_out(struct v4l_fd *f)
-{
- if (f->caps & (V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_VIDEO_M2M))
- return V4L2_BUF_TYPE_VIDEO_OUTPUT;
- if (f->caps & (V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_VIDEO_M2M_MPLANE))
- return V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
- return 0;
-}
-
-static inline __u32 v4l_g_buf_type(struct v4l_fd *f)
+static inline __u32 v4l_determine_type(const struct v4l_fd *f)
{
if (v4l_has_vid_mplane(f))
return v4l_has_vid_cap(f) ? V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE :
return 0;
}
-
-static inline bool v4l_buf_type_is_planar(unsigned type)
-{
- return V4L2_TYPE_IS_MULTIPLANAR(type);
-}
-
-static inline bool v4l_buf_type_is_output(unsigned type)
+static inline int v4l_open(struct v4l_fd *f, const char *devname, bool non_blocking)
{
- return V4L2_TYPE_IS_OUTPUT(type);
-}
-
-static inline bool v4l_buf_type_is_capture(unsigned type)
-{
- return !v4l_buf_type_is_output(type);
-}
+ f->fd = f->open(f, devname, O_RDWR | (non_blocking ? O_NONBLOCK : 0));
-static inline bool v4l_buf_type_is_video(unsigned type)
-{
- switch (type) {
- case V4L2_BUF_TYPE_VIDEO_CAPTURE:
- case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
- case V4L2_BUF_TYPE_VIDEO_OUTPUT:
- case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
- return true;
- default:
- return false;
+ if (f->fd < 0)
+ return f->fd;
+ if (f->devname != devname) {
+ strncpy(f->devname, devname, sizeof(f->devname));
+ f->devname[sizeof(f->devname) - 1] = '\0';
}
+ if (v4l_querycap(f, &f->cap)) {
+ v4l_close(f);
+ return -1;
+ }
+ f->caps = v4l_capability_g_caps(&f->cap);
+ f->type = v4l_determine_type(f);
+ return f->fd;
}
-static inline bool v4l_buf_type_is_raw_vbi(unsigned type)
-{
- return type == V4L2_BUF_TYPE_VBI_CAPTURE ||
- type == V4L2_BUF_TYPE_VBI_OUTPUT;
-}
-
-static inline bool v4l_buf_type_is_sliced_vbi(unsigned type)
-{
- return type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE ||
- type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT;
-}
-
-static inline bool v4l_buf_type_is_vbi(unsigned type)
-{
- return v4l_buf_type_is_raw_vbi(type) || v4l_buf_type_is_sliced_vbi(type);
-}
-
-static inline bool v4l_buf_type_is_overlay(unsigned type)
-{
- return type == V4L2_BUF_TYPE_VIDEO_OVERLAY ||
- type == V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY;
-}
-
-static inline bool v4l_buf_type_is_sdr(unsigned type)
-{
- return type == V4L2_BUF_TYPE_SDR_CAPTURE;
-}
-
-static inline int v4l_g_fmt(struct v4l_fd *f, struct v4l2_format *fmt, unsigned type)
-{
- fmt->type = type;
- return v4l_ioctl(f, VIDIOC_G_FMT, fmt);
-}
-
-static inline int v4l_try_fmt(struct v4l_fd *f, struct v4l2_format *fmt)
+static inline int v4l_reopen(struct v4l_fd *f, bool non_blocking)
{
- return v4l_ioctl(f, VIDIOC_TRY_FMT, fmt);
-}
-
-static inline int v4l_s_fmt(struct v4l_fd *f, struct v4l2_format *fmt)
-{
- return v4l_ioctl(f, VIDIOC_S_FMT, fmt);
+ f->close(f);
+ return v4l_open(f, f->devname, non_blocking);
}
static inline void v4l_format_init(struct v4l2_format *fmt, unsigned type)
{
memset(fmt, 0, sizeof(*fmt));
fmt->type = type;
+ if (fmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+ fmt->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
+ fmt->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC;
}
static inline void v4l_format_s_width(struct v4l2_format *fmt, __u32 width)
}
static inline void v4l_format_s_bytesperline(struct v4l2_format *fmt,
- unsigned plane, __u32 bytesperline)
+ __u32 bytesperline, unsigned plane)
{
switch (fmt->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
- fmt->fmt.pix.bytesperline = bytesperline;
+ if (plane == 0)
+ fmt->fmt.pix.bytesperline = bytesperline;
break;
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
fmt->fmt.pix_mp.plane_fmt[plane].bytesperline = bytesperline;
break;
+ case V4L2_BUF_TYPE_VBI_CAPTURE:
+ case V4L2_BUF_TYPE_VBI_OUTPUT:
+ /* This assumes V4L2_PIX_FMT_GREY which is always the case */
+ if (plane == 0)
+ fmt->fmt.vbi.samples_per_line = bytesperline;
+ break;
}
}
switch (fmt->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
- return fmt->fmt.pix.bytesperline;
+ return plane ? 0 : fmt->fmt.pix.bytesperline;
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
return fmt->fmt.pix_mp.plane_fmt[plane].bytesperline;
+ case V4L2_BUF_TYPE_VBI_CAPTURE:
+ case V4L2_BUF_TYPE_VBI_OUTPUT:
+ /* This assumes V4L2_PIX_FMT_GREY which is always the case */
+ return plane ? 0 : fmt->fmt.vbi.samples_per_line;
default:
return 0;
}
}
static inline void v4l_format_s_sizeimage(struct v4l2_format *fmt,
- unsigned plane, __u32 sizeimage)
+ __u32 sizeimage, unsigned plane)
{
switch (fmt->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
- fmt->fmt.pix.sizeimage = sizeimage;
+ if (plane == 0)
+ fmt->fmt.pix.sizeimage = sizeimage;
break;
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
switch (fmt->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
- return fmt->fmt.pix.sizeimage;
+ return plane ? 0 : fmt->fmt.pix.sizeimage;
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
return fmt->fmt.pix_mp.plane_fmt[plane].sizeimage;
+ case V4L2_BUF_TYPE_VBI_CAPTURE:
+ case V4L2_BUF_TYPE_VBI_OUTPUT:
+ /* This assumes V4L2_PIX_FMT_GREY which is always the case */
+ return plane ? 0 : fmt->fmt.vbi.samples_per_line *
+ (fmt->fmt.vbi.count[0] + fmt->fmt.vbi.count[1]);
+ case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+ case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
+ return plane ? 0 : fmt->fmt.sliced.io_size;
default:
return 0;
}
}
+static inline int v4l_g_fmt(struct v4l_fd *f, struct v4l2_format *fmt, unsigned type)
+{
+ v4l_format_init(fmt, type ? type : f->type);
+ return v4l_ioctl(f, VIDIOC_G_FMT, fmt);
+}
+
+static inline int v4l_try_fmt(struct v4l_fd *f, struct v4l2_format *fmt)
+{
+ return v4l_ioctl(f, VIDIOC_TRY_FMT, fmt);
+}
+
+static inline int v4l_s_fmt(struct v4l_fd *f, struct v4l2_format *fmt)
+{
+ return v4l_ioctl(f, VIDIOC_S_FMT, fmt);
+}
+
struct v4l_buffer {
struct v4l2_plane planes[VIDEO_MAX_PLANES];
struct v4l2_buffer buf;
}
}
-static inline bool v4l_buffer_is_planar(const struct v4l_buffer *buf)
+static inline bool v4l_type_is_planar(unsigned type)
{
- return v4l_buf_type_is_planar(buf->buf.type);
+ return V4L2_TYPE_IS_MULTIPLANAR(type);
}
-static inline bool v4l_buffer_is_output(const struct v4l_buffer *buf)
+static inline bool v4l_type_is_output(unsigned type)
{
- return v4l_buf_type_is_output(buf->buf.type);
+ return V4L2_TYPE_IS_OUTPUT(type);
}
-static inline bool v4l_buffer_is_capture(const struct v4l_buffer *buf)
+static inline bool v4l_type_is_capture(unsigned type)
{
- return v4l_buf_type_is_capture(buf->buf.type);
+ return !v4l_type_is_output(type);
}
-static inline bool v4l_buffer_is_video(const struct v4l_buffer *buf)
+static inline bool v4l_type_is_video(unsigned type)
{
- return v4l_buf_type_is_video(buf->buf.type);
+ switch (type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+ return true;
+ default:
+ return false;
+ }
}
-static inline bool v4l_buffer_is_vbi(const struct v4l_buffer *buf)
+static inline bool v4l_type_is_raw_vbi(unsigned type)
{
- return v4l_buf_type_is_vbi(buf->buf.type);
+ return type == V4L2_BUF_TYPE_VBI_CAPTURE ||
+ type == V4L2_BUF_TYPE_VBI_OUTPUT;
}
-static inline bool v4l_buffer_is_sliced_vbi(const struct v4l_buffer *buf)
+static inline bool v4l_type_is_sliced_vbi(unsigned type)
{
- return v4l_buf_type_is_sliced_vbi(buf->buf.type);
+ return type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE ||
+ type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT;
}
-static inline bool v4l_buffer_is_sdr(const struct v4l_buffer *buf)
+static inline bool v4l_type_is_vbi(unsigned type)
{
- return v4l_buf_type_is_sdr(buf->buf.type);
+ return v4l_type_is_raw_vbi(type) || v4l_type_is_sliced_vbi(type);
+}
+
+static inline bool v4l_type_is_overlay(unsigned type)
+{
+ return type == V4L2_BUF_TYPE_VIDEO_OVERLAY ||
+ type == V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY;
+}
+
+static inline bool v4l_type_is_sdr(unsigned type)
+{
+ return type == V4L2_BUF_TYPE_SDR_CAPTURE;
}
static inline unsigned v4l_buffer_g_num_planes(const struct v4l_buffer *buf)
{
- if (v4l_buffer_is_planar(buf))
+ if (v4l_type_is_planar(buf->buf.type))
return buf->buf.length;
return 1;
}
static inline unsigned v4l_buffer_g_length(const struct v4l_buffer *buf, unsigned plane)
{
- if (v4l_buffer_is_planar(buf))
+ if (v4l_type_is_planar(buf->buf.type))
return buf->planes[plane].length;
- return buf->buf.length;
+ return plane ? 0 : buf->buf.length;
+}
+
+static inline void v4l_buffer_s_length(struct v4l_buffer *buf, unsigned plane, unsigned length)
+{
+ if (v4l_type_is_planar(buf->buf.type))
+ buf->planes[plane].length = length;
+ else if (plane == 0)
+ buf->buf.length = length;
}
static inline unsigned v4l_buffer_g_bytesused(const struct v4l_buffer *buf, unsigned plane)
{
- if (v4l_buffer_is_planar(buf))
+ if (v4l_type_is_planar(buf->buf.type))
return buf->planes[plane].bytesused;
- return buf->buf.bytesused;
+ return plane ? 0 : buf->buf.bytesused;
}
static inline void v4l_buffer_s_bytesused(struct v4l_buffer *buf, unsigned plane, __u32 bytesused)
{
- if (v4l_buffer_is_planar(buf))
+ if (v4l_type_is_planar(buf->buf.type))
buf->planes[plane].bytesused = bytesused;
- else
+ else if (plane == 0)
buf->buf.bytesused = bytesused;
}
static inline unsigned v4l_buffer_g_data_offset(const struct v4l_buffer *buf, unsigned plane)
{
- if (v4l_buffer_is_planar(buf))
+ if (v4l_type_is_planar(buf->buf.type))
return buf->planes[plane].data_offset;
return 0;
}
static inline void v4l_buffer_s_data_offset(struct v4l_buffer *buf, unsigned plane, __u32 data_offset)
{
- if (v4l_buffer_is_planar(buf))
+ if (v4l_type_is_planar(buf->buf.type))
buf->planes[plane].data_offset = data_offset;
}
static inline __u32 v4l_buffer_g_mem_offset(const struct v4l_buffer *buf, unsigned plane)
{
- if (v4l_buffer_is_planar(buf))
+ if (v4l_type_is_planar(buf->buf.type))
return buf->planes[plane].m.mem_offset;
- return buf->buf.m.offset;
+ return plane ? 0 : buf->buf.m.offset;
}
static inline void v4l_buffer_s_userptr(struct v4l_buffer *buf, unsigned plane, void *userptr)
{
- if (v4l_buffer_is_planar(buf))
+ if (v4l_type_is_planar(buf->buf.type))
buf->planes[plane].m.userptr = (unsigned long)userptr;
- else
+ else if (plane == 0)
buf->buf.m.userptr = (unsigned long)userptr;
}
static inline void *v4l_buffer_g_userptr(const struct v4l_buffer *buf, unsigned plane)
{
- if (v4l_buffer_is_planar(buf))
+ if (v4l_type_is_planar(buf->buf.type))
return (void *)buf->planes[plane].m.userptr;
- return (void *)buf->buf.m.userptr;
+ return plane ? NULL : (void *)buf->buf.m.userptr;
}
static inline void v4l_buffer_s_fd(struct v4l_buffer *buf, unsigned plane, int fd)
{
- if (v4l_buffer_is_planar(buf))
+ if (v4l_type_is_planar(buf->buf.type))
buf->planes[plane].m.fd = fd;
- else
+ else if (plane == 0)
buf->buf.m.fd = fd;
}
static inline int v4l_buffer_g_fd(const struct v4l_buffer *buf, unsigned plane)
{
- if (v4l_buffer_is_planar(buf))
+ if (v4l_type_is_planar(buf->buf.type))
return buf->planes[plane].m.fd;
- return buf->buf.m.fd;
+ return plane ? -1 : buf->buf.m.fd;
}
static inline int v4l_buffer_prepare_buf(struct v4l_fd *f, struct v4l_buffer *buf)
q->fds[i][p] = -1;
}
-static inline unsigned v4l_queue_g_type(const struct v4l_queue *q)
-{
- return q->type;
-}
-
-static inline unsigned v4l_queue_g_memory(const struct v4l_queue *q)
-{
- return q->memory;
-}
-
-static inline bool v4l_queue_is_planar(const struct v4l_queue *q)
-{
- return v4l_buf_type_is_planar(q->type);
-}
-
-static inline bool v4l_queue_is_output(const struct v4l_queue *q)
-{
- return v4l_buf_type_is_output(q->type);
-}
-
-static inline bool v4l_queue_is_capture(const struct v4l_queue *q)
-{
- return v4l_buf_type_is_capture(q->type);
-}
-
-static inline bool v4l_queue_is_video(const struct v4l_queue *q)
-{
- return v4l_buf_type_is_video(q->type);
-}
-
-static inline bool v4l_queue_is_vbi(const struct v4l_queue *q)
-{
- return v4l_buf_type_is_vbi(q->type);
-}
-
-static inline bool v4l_queue_is_sliced_vbi(const struct v4l_queue *q)
-{
- return v4l_buf_type_is_sliced_vbi(q->type);
-}
-
-static inline bool v4l_queue_is_sdr(const struct v4l_queue *q)
-{
- return v4l_buf_type_is_sdr(q->type);
-}
-
-static inline unsigned v4l_queue_g_buffers(const struct v4l_queue *q)
-{
- return q->buffers;
-}
-
-static inline unsigned v4l_queue_g_num_planes(const struct v4l_queue *q)
-{
- return q->num_planes;
-}
+static inline unsigned v4l_queue_g_type(const struct v4l_queue *q) { return q->type; }
+static inline unsigned v4l_queue_g_memory(const struct v4l_queue *q) { return q->memory; }
+static inline unsigned v4l_queue_g_buffers(const struct v4l_queue *q) { return q->buffers; }
+static inline unsigned v4l_queue_g_num_planes(const struct v4l_queue *q) { return q->num_planes; }
static inline __u32 v4l_queue_g_length(const struct v4l_queue *q, unsigned plane)
{
static inline void *v4l_queue_g_mmapping(const struct v4l_queue *q, unsigned index, unsigned plane)
{
+ if (index >= v4l_queue_g_buffers(q) || plane >= v4l_queue_g_num_planes(q))
+ return NULL;
return q->mmappings[index][plane];
}
static inline void *v4l_queue_g_userptr(const struct v4l_queue *q, unsigned index, unsigned plane)
{
+ if (index >= v4l_queue_g_buffers(q) || plane >= v4l_queue_g_num_planes(q))
+ return NULL;
return (void *)q->userptrs[index][plane];
}
return q->fds[index][plane];
}
+static inline void *v4l_queue_g_dataptr(const struct v4l_queue *q, unsigned index, unsigned plane)
+{
+ if (q->memory == V4L2_MEMORY_USERPTR)
+ return v4l_queue_g_userptr(q, index, plane);
+ return v4l_queue_g_mmapping(q, index, plane);
+}
+
static inline int v4l_queue_querybufs(struct v4l_fd *f, struct v4l_queue *q, unsigned from)
{
unsigned b, p;
return v4l_queue_querybufs(f, q, q->buffers - createbufs.count);
}
-static inline int v4l_queue_streamon(struct v4l_fd *f, struct v4l_queue *q)
-{
- return v4l_ioctl(f, VIDIOC_STREAMON, &q->type);
-}
-
-static inline int v4l_queue_streamoff(struct v4l_fd *f, struct v4l_queue *q)
-{
- return v4l_ioctl(f, VIDIOC_STREAMOFF, &q->type);
-}
-
static inline int v4l_queue_mmap_bufs(struct v4l_fd *f,
struct v4l_queue *q, unsigned from)
{
return 0;
for (b = 0; b < v4l_queue_g_buffers(q); b++) {
for (p = 0; p < v4l_queue_g_num_planes(q); p++) {
- free(v4l_queue_g_mmapping(q, b, p));
- v4l_queue_s_mmapping(q, b, p, NULL);
+ free(v4l_queue_g_userptr(q, b, p));
+ v4l_queue_s_userptr(q, b, p, NULL);
}
}
return 0;
}
+static inline int v4l_queue_obtain_bufs(struct v4l_fd *f,
+ struct v4l_queue *q, unsigned from)
+{
+ if (q->memory == V4L2_MEMORY_USERPTR)
+ return v4l_queue_alloc_bufs(f, q, from);
+ return v4l_queue_mmap_bufs(f, q, from);
+}
+
+static inline int v4l_queue_release_bufs(struct v4l_fd *f, struct v4l_queue *q)
+{
+ if (q->memory == V4L2_MEMORY_USERPTR)
+ return v4l_queue_free_bufs(q);
+ return v4l_queue_munmap_bufs(f, q);
+}
+
static inline bool v4l_queue_has_expbuf(struct v4l_fd *f)
{
static inline void v4l_queue_free(struct v4l_fd *f, struct v4l_queue *q)
{
- v4l_queue_streamoff(f, q);
- v4l_queue_free_bufs(q);
- v4l_queue_munmap_bufs(f, q);
+ v4l_ioctl(f, VIDIOC_STREAMOFF, &q->type);
+ v4l_queue_release_bufs(f, q);
v4l_queue_close_exported_fds(q);
v4l_queue_reqbufs(f, q, 0);
}
unsigned p;
v4l_buffer_init(buf, v4l_queue_g_type(q), v4l_queue_g_memory(q), index);
- if (v4l_queue_is_planar(q)) {
+ if (v4l_type_is_planar(q->type)) {
buf->buf.length = v4l_queue_g_num_planes(q);
buf->buf.m.planes = buf->planes;
}
switch (q->memory) {
case V4L2_MEMORY_USERPTR:
- for (p = 0; p < v4l_queue_g_num_planes(q); p++)
+ for (p = 0; p < v4l_queue_g_num_planes(q); p++) {
v4l_buffer_s_userptr(buf, p, v4l_queue_g_userptr(q, index, p));
+ v4l_buffer_s_length(buf, p, v4l_queue_g_length(q, p));
+ }
break;
case V4L2_MEMORY_DMABUF:
for (p = 0; p < v4l_queue_g_num_planes(q); p++)
}
}
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
#endif
#include <getopt.h>
#include <sys/types.h>
#include <sys/stat.h>
-#include <fcntl.h>
#include <ctype.h>
#include <errno.h>
#include <sys/ioctl.h>
// Globals
bool show_info;
bool show_warnings = true;
-bool wrapper;
int kernel_version;
unsigned warnings;
exit(0);
}
-static void v4l_fd_test_init(struct v4l_fd *f, int fd)
-{
- struct v4l2_capability cap;
-
- f->fd = fd;
- f->ioctl = test_ioctl;
- f->mmap = test_mmap;
- f->munmap = test_munmap;
- f->trace = options[OptTrace];
- f->caps = v4l_querycap(f, &cap) ? 0 : v4l_capability_g_caps(&cap);
-}
-
-int doioctl_name(struct node *node, unsigned long int request, void *parm,
- const char *name)
-{
- int retval;
- int e;
-
- errno = 0;
- retval = test_ioctl(node->vfd.fd, request, parm);
- e = errno;
- if (options[OptTrace])
- printf("\t\t%s returned %d (%s)\n", name, retval, strerror(e));
- if (retval == 0)
- return 0;
- if (retval != -1) {
- fail("%s returned %d instead of 0 or -1\n", name, retval);
- return -1;
- }
- return e;
-}
-
std::string cap2s(unsigned cap)
{
std::string s;
// set by the core, so this really should always be there
// for a modern driver for both caps and dcaps
fail_on_test(!(caps & V4L2_CAP_EXT_PIX_FORMAT));
- fail_on_test(!(dcaps & V4L2_CAP_EXT_PIX_FORMAT));
+ //fail_on_test(!(dcaps & V4L2_CAP_EXT_PIX_FORMAT));
fail_on_test(node->is_video && !(dcaps & video_caps));
fail_on_test(node->is_radio && !(dcaps & radio_caps));
// V4L2_CAP_AUDIO is invalid for radio and sdr
struct v4l2_frequency f = { 0 };
unsigned freq_caps;
- if (node->caps & V4L2_CAP_MODULATOR) {
+ if (node->g_caps() & V4L2_CAP_MODULATOR) {
struct v4l2_modulator m = { 0 };
doioctl(node, VIDIOC_G_MODULATOR, &m);
int main(int argc, char **argv)
{
int i;
- struct node node = { -1 };
- struct node video_node = { -1 };
- struct node video_node2 = { -1 };
- struct node vbi_node = { -1 };
- struct node vbi_node2 = { -1 };
- struct node radio_node = { -1 };
- struct node radio_node2 = { -1 };
- struct node sdr_node = { -1 };
- struct node sdr_node2 = { -1 };
- struct node expbuf_node = { -1 };
+ struct node node;
+ struct node video_node;
+ struct node video_node2;
+ struct node vbi_node;
+ struct node vbi_node2;
+ struct node radio_node;
+ struct node radio_node2;
+ struct node sdr_node;
+ struct node sdr_node2;
+ struct node expbuf_node;
/* command args */
int ch;
usage();
return 1;
}
- wrapper = options[OptUseWrapper];
+ bool direct = !options[OptUseWrapper];
struct utsname uts;
int v1, v2, v3;
video_device = "/dev/video0";
if (video_device) {
- fd = test_open(video_device, O_RDWR);
+ video_node.s_trace(options[OptTrace]);
+ video_node.s_direct(direct);
+ fd = video_node.open(video_device, false);
if (fd < 0) {
fprintf(stderr, "Failed to open %s: %s\n", video_device,
strerror(errno));
exit(1);
}
- v4l_fd_test_init(&video_node.vfd, fd);
}
if (vbi_device) {
- fd = test_open(vbi_device, O_RDWR);
+ vbi_node.s_trace(options[OptTrace]);
+ vbi_node.s_direct(direct);
+ fd = vbi_node.open(vbi_device, false);
if (fd < 0) {
fprintf(stderr, "Failed to open %s: %s\n", vbi_device,
strerror(errno));
exit(1);
}
- v4l_fd_test_init(&vbi_node.vfd, fd);
}
if (radio_device) {
- fd = test_open(radio_device, O_RDWR);
+ radio_node.s_trace(options[OptTrace]);
+ radio_node.s_direct(direct);
+ fd = radio_node.open(radio_device, false);
if (fd < 0) {
fprintf(stderr, "Failed to open %s: %s\n", radio_device,
strerror(errno));
exit(1);
}
- v4l_fd_test_init(&radio_node.vfd, fd);
}
if (sdr_device) {
- fd = test_open(sdr_device, O_RDWR);
+ sdr_node.s_trace(options[OptTrace]);
+ sdr_node.s_direct(direct);
+ fd = sdr_node.open(sdr_device, false);
if (fd < 0) {
fprintf(stderr, "Failed to open %s: %s\n", sdr_device,
strerror(errno));
exit(1);
}
- v4l_fd_test_init(&sdr_node.vfd, fd);
}
if (expbuf_device) {
- fd = open(expbuf_device, O_RDWR);
+ expbuf_node.s_trace(options[OptTrace]);
+ expbuf_node.s_direct(true);
+ fd = expbuf_node.open(expbuf_device, false);
if (fd < 0) {
fprintf(stderr, "Failed to open %s: %s\n", expbuf_device,
strerror(errno));
exit(1);
}
- v4l_fd_init(&expbuf_node.vfd, fd);
}
- if (video_node.vfd.fd >= 0) {
- node.vfd = video_node.vfd;
+ if (video_node.g_fd() >= 0) {
+ node = video_node;
device = video_device;
node.is_video = true;
- } else if (vbi_node.vfd.fd >= 0) {
- node.vfd = vbi_node.vfd;
+ } else if (vbi_node.g_fd() >= 0) {
+ node = vbi_node;
device = vbi_device;
node.is_vbi = true;
- } else if (radio_node.vfd.fd >= 0) {
- node.vfd = radio_node.vfd;
+ } else if (radio_node.g_fd() >= 0) {
+ node = radio_node;
device = radio_device;
node.is_radio = true;
- } else if (sdr_node.vfd.fd >= 0) {
- node.vfd = sdr_node.vfd;
+ } else if (sdr_node.g_fd() >= 0) {
+ node = sdr_node;
device = sdr_device;
node.is_sdr = true;
}
node.device = device;
doioctl(&node, VIDIOC_QUERYCAP, &vcap);
- if (vcap.capabilities & V4L2_CAP_DEVICE_CAPS)
- node.caps = vcap.device_caps;
- else
- node.caps = vcap.capabilities;
- if (node.caps & (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VBI_CAPTURE |
+ if (node.g_caps() & (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VBI_CAPTURE |
V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_SLICED_VBI_CAPTURE))
node.has_inputs = true;
- if (node.caps & (V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_VBI_OUTPUT |
+ if (node.g_caps() & (V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_VBI_OUTPUT |
V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_SLICED_VBI_OUTPUT))
node.has_outputs = true;
- if (node.caps & (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VBI_CAPTURE |
+ if (node.g_caps() & (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VBI_CAPTURE |
V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_VIDEO_M2M_MPLANE |
V4L2_CAP_VIDEO_M2M | V4L2_CAP_SLICED_VBI_CAPTURE |
V4L2_CAP_RDS_CAPTURE | V4L2_CAP_SDR_CAPTURE))
node.can_capture = true;
- if (node.caps & (V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_VBI_OUTPUT |
+ if (node.g_caps() & (V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_VBI_OUTPUT |
V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_VIDEO_M2M_MPLANE |
V4L2_CAP_VIDEO_M2M | V4L2_CAP_SLICED_VBI_OUTPUT |
V4L2_CAP_RDS_OUTPUT))
node.can_output = true;
- if (node.caps & (V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_VIDEO_OUTPUT_MPLANE |
+ if (node.g_caps() & (V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_VIDEO_OUTPUT_MPLANE |
V4L2_CAP_VIDEO_M2M_MPLANE))
node.is_planar = true;
- if (expbuf_device) {
- doioctl(&expbuf_node, VIDIOC_QUERYCAP, &vcap);
- if (vcap.capabilities & V4L2_CAP_DEVICE_CAPS)
- expbuf_node.caps = vcap.device_caps;
- else
- expbuf_node.caps = vcap.capabilities;
- }
/* Information Opts */
}
printf("\nCompliance test for device %s (%susing libv4l2):\n\n",
- device, wrapper ? "" : "not ");
+ device, direct ? "not " : "");
/* Required ioctls */
if (video_device) {
video_node2 = node;
printf("\ttest second video open: %s\n",
- ok((video_node2.vfd.fd = test_open(video_device, O_RDWR)) < 0));
- if (video_node2.vfd.fd >= 0) {
+ ok(video_node2.open(video_device, false) >= 0 ? 0 : errno));
+ if (video_node2.g_fd() >= 0) {
printf("\ttest VIDIOC_QUERYCAP: %s\n", ok(testCap(&video_node2)));
printf("\ttest VIDIOC_G/S_PRIORITY: %s\n",
ok(testPrio(&node, &video_node2)));
if (vbi_device) {
vbi_node2 = node;
printf("\ttest second vbi open: %s\n",
- ok((vbi_node2.vfd.fd = test_open(vbi_device, O_RDWR)) < 0));
- if (vbi_node2.vfd.fd >= 0) {
+ ok(vbi_node2.open(vbi_device, false) >= 0 ? 0 : errno));
+ if (vbi_node2.g_fd() >= 0) {
printf("\ttest VIDIOC_QUERYCAP: %s\n", ok(testCap(&vbi_node2)));
printf("\ttest VIDIOC_G/S_PRIORITY: %s\n",
ok(testPrio(&node, &vbi_node2)));
if (radio_device) {
radio_node2 = node;
printf("\ttest second radio open: %s\n",
- ok((radio_node2.vfd.fd = test_open(radio_device, O_RDWR)) < 0));
- if (radio_node2.vfd.fd >= 0) {
+ ok(radio_node2.open(radio_device, false) >= 0 ? 0 : errno));
+ if (radio_node2.g_fd() >= 0) {
printf("\ttest VIDIOC_QUERYCAP: %s\n", ok(testCap(&radio_node2)));
printf("\ttest VIDIOC_G/S_PRIORITY: %s\n",
ok(testPrio(&node, &radio_node2)));
if (sdr_device) {
sdr_node2 = node;
printf("\ttest second sdr open: %s\n",
- ok((sdr_node2.vfd.fd = test_open(sdr_device, O_RDWR)) < 0));
- if (sdr_node2.vfd.fd >= 0) {
+ ok(sdr_node2.open(sdr_device, false) >= 0 ? 0 : errno));
+ if (sdr_node2.g_fd() >= 0) {
printf("\ttest VIDIOC_QUERYCAP: %s\n", ok(testCap(&sdr_node2)));
printf("\ttest VIDIOC_G/S_PRIORITY: %s\n",
ok(testPrio(&node, &sdr_node2)));
printf("\ttest read/write: %s\n", ok(testReadWrite(&node)));
// Reopen after each streaming test to reset the streaming state
// in case of any errors in the preceeding test.
- reopen(&node);
+ node.reopen();
printf("\ttest MMAP: %s\n", ok(testMmap(&node, frame_count)));
- reopen(&node);
+ node.reopen();
printf("\ttest USERPTR: %s\n", ok(testUserPtr(&node, frame_count)));
- reopen(&node);
+ node.reopen();
if (options[OptSetExpBufDevice] ||
!(node.valid_memorytype & (1 << V4L2_MEMORY_DMABUF)))
printf("\ttest DMABUF: %s\n", ok(testDmaBuf(&expbuf_node, &node, frame_count)));
else if (!options[OptSetExpBufDevice])
printf("\ttest DMABUF: Cannot test, specify --expbuf-device\n");
- reopen(&node);
+ node.reopen();
}
printf("\n");
/* Final test report */
- test_close(node.vfd.fd);
+ node.close();
if (node.node2)
- test_close(node.node2->vfd.fd);
+ node.node2->close();
if (expbuf_device)
- close(expbuf_node.vfd.fd);
+ expbuf_node.close();
printf("Total: %d, Succeeded: %d, Failed: %d, Warnings: %d\n",
tests_total, tests_ok, tests_total - tests_ok, warnings);
exit(app_result);
#ifndef NO_LIBV4L2
#include <libv4l2.h>
-#else
-#define v4l2_open(file, oflag, ...) (-1)
-#define v4l2_close(fd) (-1)
-#define v4l2_read(fd, buffer, n) (-1)
-#define v4l2_write(fd, buffer, n) (-1)
-#define v4l2_ioctl(fd, request, ...) (-1)
-#define v4l2_mmap(start, length, prot, flags, fd, offset) (MAP_FAILED)
-#define v4l2_munmap(_start, length) (-1)
#endif
#include <cv4l-helpers.h>
extern bool show_info;
extern bool show_warnings;
-extern bool wrapper;
extern int kernel_version;
extern unsigned warnings;
typedef std::list<test_queryctrl> qctrl_list;
typedef std::set<__u32> pixfmt_set;
-struct node;
+struct base_node;
-struct node {
- struct v4l_fd vfd;
+struct base_node {
bool is_video;
bool is_radio;
bool is_vbi;
bool can_capture;
bool can_output;
const char *device;
- unsigned caps;
struct node *node2; /* second open filehandle */
bool has_outputs;
bool has_inputs;
unsigned cur_io_caps;
unsigned std_controls;
unsigned priv_controls;
- qctrl_list controls;
__u32 fbuf_caps;
- pixfmt_set buftype_pixfmts[V4L2_BUF_TYPE_SDR_CAPTURE + 1];
__u32 valid_buftypes;
__u32 valid_buftype;
__u32 valid_memorytype;
};
+struct node : public base_node, public cv4l_fd {
+ node() : base_node() {}
+
+ qctrl_list controls;
+ pixfmt_set buftype_pixfmts[V4L2_BUF_TYPE_SDR_CAPTURE + 1];
+};
+
#define info(fmt, args...) \
do { \
if (show_info) \
return fail("%s\n", #test); \
} while (0)
-static inline int test_open(const char *file, int oflag)
-{
- return wrapper ? v4l2_open(file, oflag) : open(file, oflag);
-}
-
-static inline int test_close(int fd)
-{
- return wrapper ? v4l2_close(fd) : close(fd);
-}
-
-static inline void reopen(struct node *node)
-{
- test_close(node->vfd.fd);
- if ((node->vfd.fd = test_open(node->device, O_RDWR)) < 0) {
- fprintf(stderr, "Failed to open %s: %s\n", node->device,
- strerror(errno));
- exit(1);
- }
-}
-
-static inline ssize_t test_read(int fd, void *buffer, size_t n)
-{
- return wrapper ? v4l2_read(fd, buffer, n) : read(fd, buffer, n);
-}
-
-static inline ssize_t test_write(int fd, const void *buffer, size_t n)
-{
- return wrapper ? v4l2_write(fd, buffer, n) : write(fd, buffer, n);
-}
-
-static inline int test_ioctl(int fd, unsigned long cmd, ...)
-{
- void *arg;
- va_list ap;
-
- va_start(ap, cmd);
- arg = va_arg(ap, void *);
- va_end(ap);
- return wrapper ? v4l2_ioctl(fd, cmd, arg) : ioctl(fd, cmd, arg);
-}
-
-static inline void *test_mmap(void *start, size_t length, int prot, int flags,
- int fd, int64_t offset)
-{
- return wrapper ? v4l2_mmap(start, length, prot, flags, fd, offset) :
- mmap(start, length, prot, flags, fd, offset);
-}
-
-static inline int test_munmap(void *start, size_t length)
-{
- return wrapper ? v4l2_munmap(start, length) : munmap(start, length);
-}
-
static inline int check_fract(const struct v4l2_fract *f)
{
if (f->numerator && f->denominator)
return (double)f->numerator / (double)f->denominator;
}
-int doioctl_name(struct node *node, unsigned long int request, void *parm,
- const char *name);
-#define doioctl(n, r, p) doioctl_name(n, r, p, #r)
+#define doioctl(n, r, p) v4l_named_ioctl((n)->g_v4l_fd(), #r, r, p)
std::string cap2s(unsigned cap);
std::string buftype2s(int type);
}
}
-class queue : public cv4l_queue {
-public:
- queue(node *node, unsigned type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
- unsigned memory = V4L2_MEMORY_MMAP) :
- cv4l_queue(&node->vfd, type, memory) {}
-};
-
class buffer : public cv4l_buffer {
public:
- using cv4l_buffer::querybuf;
- using cv4l_buffer::prepare_buf;
- using cv4l_buffer::qbuf;
- using cv4l_buffer::dqbuf;
-
buffer(unsigned type = 0, unsigned memory = 0, unsigned index = 0) :
cv4l_buffer(type, memory, index) {}
buffer(const cv4l_queue &q, unsigned index = 0) :
int querybuf(node *node, unsigned index)
{
- return querybuf(&node->vfd, index);
+ return node->querybuf(*this, index);
}
int prepare_buf(node *node)
{
- return prepare_buf(&node->vfd);
+ return node->prepare_buf(*this);
}
int dqbuf(node *node)
{
- return dqbuf(&node->vfd);
+ return node->dqbuf(*this);
}
int qbuf(node *node, bool fill_bytesused = true)
{
int err;
- if (is_output())
- fill_output_buf(fill_bytesused);
- err = qbuf(&node->vfd);
- if (err == 0 && is_output())
- buffer_info[g_timestamp()] = buf;
- return err;
- }
- int qbuf(const queue &q, bool fill_bytesused = true)
- {
- int err;
-
- if (is_output())
+ if (v4l_type_is_output(g_type()))
fill_output_buf(fill_bytesused);
- err = cv4l_buffer::qbuf(q);
- if (err == 0 && is_output())
+ err = node->qbuf(*this);
+ if (err == 0 && v4l_type_is_output(g_type()))
buffer_info[g_timestamp()] = buf;
return err;
}
- int check(const queue &q, enum QueryBufMode mode)
+ int check(const cv4l_queue &q, enum QueryBufMode mode)
{
int ret = check(q.g_type(), q.g_memory(), g_index(), mode, last_seq);
ret = check_planes(q, mode);
return ret;
}
- int check(const queue &q, enum QueryBufMode mode, __u32 index)
+ int check(const cv4l_queue &q, enum QueryBufMode mode, __u32 index)
{
int ret = check(q.g_type(), q.g_memory(), index, mode, last_seq);
ret = check_planes(q, mode);
return ret;
}
- int check(const queue &q, buf_seq &seq)
+ int check(const cv4l_queue &q, buf_seq &seq)
{
int ret = check(q.g_type(), q.g_memory(), g_index(), Dequeued, seq);
private:
int check(unsigned type, unsigned memory, unsigned index,
enum QueryBufMode mode, struct buf_seq &seq);
- int check_planes(const queue &q, enum QueryBufMode mode);
+ int check_planes(const cv4l_queue &q, enum QueryBufMode mode);
void fill_output_buf(bool fill_bytesused = true)
{
timespec ts;
}
};
-int buffer::check_planes(const queue &q, enum QueryBufMode mode)
+int buffer::check_planes(const cv4l_queue &q, enum QueryBufMode mode)
{
if (mode == Dequeued || mode == Prepared) {
for (unsigned p = 0; p < g_num_planes(); p++) {
timestamp != V4L2_BUF_FLAG_TIMESTAMP_COPY);
fail_on_test(timestamp_src != V4L2_BUF_FLAG_TSTAMP_SRC_SOE &&
timestamp_src != V4L2_BUF_FLAG_TSTAMP_SRC_EOF);
- fail_on_test(!ts_copy && is_output() &&
+ fail_on_test(!ts_copy && v4l_type_is_output(g_type()) &&
timestamp_src == V4L2_BUF_FLAG_TSTAMP_SRC_SOE);
if (g_flags() & V4L2_BUF_FLAG_KEYFRAME)
frame_types++;
buf_states++;
fail_on_test(buf_states > 1);
fail_on_test(buf.length == 0);
- if (is_planar()) {
+ if (v4l_type_is_planar(g_type())) {
fail_on_test(buf.length > VIDEO_MAX_PLANES);
for (unsigned p = 0; p < buf.length; p++) {
struct v4l2_plane *vp = buf.m.planes + p;
}
}
- if (is_capture() && !ts_copy &&
+ if (v4l_type_is_capture(g_type()) && !ts_copy &&
(g_flags() & V4L2_BUF_FLAG_TIMECODE))
warn("V4L2_BUF_FLAG_TIMECODE was used!\n");
}
fail_on_test(!g_timestamp().tv_sec && !g_timestamp().tv_usec);
fail_on_test(!(g_flags() & (V4L2_BUF_FLAG_DONE | V4L2_BUF_FLAG_ERROR)));
- if (is_video()) {
+ if (v4l_type_is_video(g_type())) {
fail_on_test(g_field() == V4L2_FIELD_ALTERNATE);
fail_on_test(g_field() == V4L2_FIELD_ANY);
if (cur_fmt.g_field() == V4L2_FIELD_ALTERNATE) {
seq.last_field = g_field();
} else {
fail_on_test(g_sequence());
- if (mode == Queued && ts_copy && is_output()) {
+ if (mode == Queued && ts_copy && v4l_type_is_output(g_type())) {
fail_on_test(!g_timestamp().tv_sec && !g_timestamp().tv_usec);
} else {
fail_on_test(g_timestamp().tv_sec || g_timestamp().tv_usec);
}
- if (!is_output() || mode == Unqueued)
+ if (!v4l_type_is_output(g_type()) || mode == Unqueued)
fail_on_test(frame_types);
if (mode == Unqueued)
fail_on_test(g_flags() & (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_PREPARED |
for (i = 0; i < count; i++) {
fail_on_test(buf.querybuf(node, i));
- if (buf.is_planar())
+ if (v4l_type_is_planar(buf.g_type()))
fail_on_test(buf.buf.m.planes != buf.planes);
fail_on_test(buf.check(Unqueued, i));
}
static int testSetupVbi(struct node *node, int type)
{
- if (!v4l_buf_type_is_vbi(type))
+ if (!v4l_type_is_vbi(type))
return 0;
if (!(node->cur_io_caps & V4L2_IN_CAP_STD))
return -1;
- cv4l_fmt vbi_fmt(&node->vfd, type);
+ node->s_type(type);
+ cv4l_fmt vbi_fmt;
- if (!vbi_fmt.g_fmt())
- vbi_fmt.s_fmt();
+ if (!node->g_fmt(vbi_fmt))
+ node->s_fmt(vbi_fmt);
return 0;
}
int testReqBufs(struct node *node)
{
- bool can_stream = node->caps & V4L2_CAP_STREAMING;
- bool can_rw = node->caps & V4L2_CAP_READWRITE;
+ bool can_stream = node->g_caps() & V4L2_CAP_STREAMING;
+ bool can_rw = node->g_caps() & V4L2_CAP_READWRITE;
bool mmap_valid;
bool userptr_valid;
bool dmabuf_valid;
int ret;
unsigned i, m;
- reopen(node);
+ node->reopen();
- queue q(node, 0, 0);
+ cv4l_queue q(0, 0);
- ret = q.reqbufs(0);
+ ret = q.reqbufs(node, 0);
if (ret == ENOTTY) {
fail_on_test(can_stream);
return ret;
fail_on_test(ret != EINVAL);
fail_on_test(node->node2 == NULL);
for (i = 1; i <= V4L2_BUF_TYPE_SDR_CAPTURE; i++) {
- bool is_overlay = v4l_buf_type_is_overlay(i);
+ bool is_overlay = v4l_type_is_overlay(i);
if (!(node->valid_buftypes & (1 << i)))
continue;
node->valid_buftype = i;
q.init(0, 0);
- fail_on_test(q.reqbufs(i) != EINVAL);
+ fail_on_test(q.reqbufs(node, i) != EINVAL);
q.init(i, V4L2_MEMORY_MMAP);
- ret = q.reqbufs(0);
+ ret = q.reqbufs(node, 0);
fail_on_test(ret && ret != EINVAL);
mmap_valid = !ret;
q.init(i, V4L2_MEMORY_USERPTR);
- ret = q.reqbufs(0);
+ ret = q.reqbufs(node, 0);
fail_on_test(ret && ret != EINVAL);
userptr_valid = !ret;
q.init(i, V4L2_MEMORY_DMABUF);
- ret = q.reqbufs(0);
+ ret = q.reqbufs(node, 0);
fail_on_test(ret && ret != EINVAL);
dmabuf_valid = !ret;
fail_on_test((can_stream && !is_overlay) && !mmap_valid && !userptr_valid && !dmabuf_valid);
if (mmap_valid) {
q.init(i, V4L2_MEMORY_MMAP);
- fail_on_test(q.reqbufs(1));
+ fail_on_test(q.reqbufs(node, 1));
fail_on_test(q.g_buffers() == 0);
fail_on_test(q.g_memory() != V4L2_MEMORY_MMAP);
fail_on_test(q.g_type() != i);
- fail_on_test(q.reqbufs(1));
+ fail_on_test(q.reqbufs(node, 1));
fail_on_test(testQueryBuf(node, i, q.g_buffers()));
node->valid_memorytype |= 1 << V4L2_MEMORY_MMAP;
}
if (userptr_valid) {
q.init(i, V4L2_MEMORY_USERPTR);
- fail_on_test(q.reqbufs(1));
+ fail_on_test(q.reqbufs(node, 1));
fail_on_test(q.g_buffers() == 0);
fail_on_test(q.g_memory() != V4L2_MEMORY_USERPTR);
fail_on_test(q.g_type() != i);
- fail_on_test(q.reqbufs(1));
+ fail_on_test(q.reqbufs(node, 1));
fail_on_test(testQueryBuf(node, i, q.g_buffers()));
node->valid_memorytype |= 1 << V4L2_MEMORY_USERPTR;
}
if (dmabuf_valid) {
q.init(i, V4L2_MEMORY_DMABUF);
- fail_on_test(q.reqbufs(1));
+ fail_on_test(q.reqbufs(node, 1));
fail_on_test(q.g_buffers() == 0);
fail_on_test(q.g_memory() != V4L2_MEMORY_DMABUF);
fail_on_test(q.g_type() != i);
- fail_on_test(q.reqbufs(1));
+ fail_on_test(q.reqbufs(node, 1));
fail_on_test(testQueryBuf(node, i, q.g_buffers()));
node->valid_memorytype |= 1 << V4L2_MEMORY_DMABUF;
}
char buf = 0;
if (node->can_capture)
- ret = test_read(node->vfd.fd, &buf, 1);
+ ret = node->read(&buf, 1);
else
- ret = test_write(node->vfd.fd, &buf, 1);
+ ret = node->write(&buf, 1);
if (ret != -1)
return fail("Expected -1, got %d\n", ret);
if (errno != EBUSY)
return fail("Expected EBUSY, got %d\n", errno);
}
- fail_on_test(q.reqbufs(0));
+ fail_on_test(q.reqbufs(node, 0));
for (m = V4L2_MEMORY_MMAP; m <= V4L2_MEMORY_DMABUF; m++) {
if (!(node->valid_memorytype & (1 << m)))
continue;
- queue q2(node->node2, i, m);
- fail_on_test(q.reqbufs(1));
+ cv4l_queue q2(i, m);
+ fail_on_test(q.reqbufs(node, 1));
if (!node->is_m2m) {
- fail_on_test(q2.reqbufs(1) != EBUSY);
- fail_on_test(q2.reqbufs() != EBUSY);
- fail_on_test(q.reqbufs());
- fail_on_test(q2.reqbufs(1));
- fail_on_test(q2.reqbufs());
+ fail_on_test(q2.reqbufs(node->node2, 1) != EBUSY);
+ fail_on_test(q2.reqbufs(node->node2) != EBUSY);
+ fail_on_test(q.reqbufs(node));
+ fail_on_test(q2.reqbufs(node->node2, 1));
+ fail_on_test(q2.reqbufs(node->node2));
}
- fail_on_test(q.reqbufs());
- ret = q.create_bufs(1);
+ fail_on_test(q.reqbufs(node));
+ ret = q.create_bufs(node, 1);
if (ret == ENOTTY) {
warn("VIDIOC_CREATE_BUFS not supported\n");
break;
fail_on_test(q.g_buffers() == 0);
fail_on_test(q.g_type() != i);
fail_on_test(testQueryBuf(node, i, q.g_buffers()));
- fail_on_test(q.create_bufs(1));
+ fail_on_test(q.create_bufs(node, 1));
fail_on_test(testQueryBuf(node, i, q.g_buffers()));
if (!node->is_m2m)
- fail_on_test(q2.create_bufs(1) != EBUSY);
+ fail_on_test(q2.create_bufs(node->node2, 1) != EBUSY);
}
- fail_on_test(q.reqbufs());
+ fail_on_test(q.reqbufs(node));
}
return 0;
}
int type;
if (!(node->valid_memorytype & (1 << V4L2_MEMORY_MMAP))) {
- queue q(node);
+ cv4l_queue q;
- fail_on_test(q.has_expbuf());
+ fail_on_test(q.has_expbuf(node));
return ENOTTY;
}
for (type = 0; type <= V4L2_BUF_TYPE_SDR_CAPTURE; type++) {
if (!(node->valid_buftypes & (1 << type)))
continue;
- if (v4l_buf_type_is_overlay(type))
+ if (v4l_type_is_overlay(type))
continue;
if (testSetupVbi(node, type))
continue;
- queue q(node, type, V4L2_MEMORY_MMAP);
+ cv4l_queue q(type, V4L2_MEMORY_MMAP);
- fail_on_test(q.reqbufs(1));
- if (q.has_expbuf()) {
- fail_on_test(q.export_bufs());
+ fail_on_test(q.reqbufs(node, 1));
+ if (q.has_expbuf(node)) {
+ fail_on_test(q.export_bufs(node));
have_expbuf = true;
} else {
- fail_on_test(!q.export_bufs());
+ fail_on_test(!q.export_bufs(node));
}
q.close_exported_fds();
- fail_on_test(q.reqbufs());
+ fail_on_test(q.reqbufs(node));
}
return have_expbuf ? 0 : ENOTTY;
}
int testReadWrite(struct node *node)
{
- bool can_rw = node->caps & V4L2_CAP_READWRITE;
- int fd_flags = fcntl(node->vfd.fd, F_GETFL);
+ bool can_rw = node->g_caps() & V4L2_CAP_READWRITE;
+ int fd_flags = fcntl(node->g_fd(), F_GETFL);
char buf = 0;
int ret;
- if (v4l_has_vbi(&node->vfd) &&
+ if (v4l_has_vbi(node->g_v4l_fd()) &&
!(node->cur_io_caps & V4L2_IN_CAP_STD)) {
return 0;
}
- fcntl(node->vfd.fd, F_SETFL, fd_flags | O_NONBLOCK);
+ fcntl(node->g_fd(), F_SETFL, fd_flags | O_NONBLOCK);
if (node->can_capture)
- ret = read(node->vfd.fd, &buf, 1);
+ ret = node->read(&buf, 1);
else
- ret = write(node->vfd.fd, &buf, 1);
+ ret = node->write(&buf, 1);
// Note: RDS can only return multiples of 3, so we accept
// both 0 and 1 as return code.
// EBUSY can be returned when attempting to read/write to a
if (!can_rw)
return ENOTTY;
- reopen(node);
- fcntl(node->vfd.fd, F_SETFL, fd_flags | O_NONBLOCK);
+ node->reopen();
+ fcntl(node->g_fd(), F_SETFL, fd_flags | O_NONBLOCK);
/* check that the close cleared the busy flag */
if (node->can_capture)
- ret = read(node->vfd.fd, &buf, 1);
+ ret = node->read(&buf, 1);
else
- ret = write(node->vfd.fd, &buf, 1);
+ ret = node->write(&buf, 1);
fail_on_test((ret < 0 && errno != EAGAIN && errno != EBUSY) || ret > 1);
return 0;
}
-static int captureBufs(struct node *node, const queue &q,
- const queue &m2m_q, unsigned frame_count, bool use_poll)
+static int captureBufs(struct node *node, const cv4l_queue &q,
+ const cv4l_queue &m2m_q, unsigned frame_count, bool use_poll)
{
- int fd_flags = fcntl(node->vfd.fd, F_GETFL);
+ int fd_flags = fcntl(node->g_fd(), F_GETFL);
buffer buf(q);
unsigned count = frame_count;
int ret;
}
if (use_poll)
- fcntl(node->vfd.fd, F_SETFL, fd_flags | O_NONBLOCK);
+ fcntl(node->g_fd(), F_SETFL, fd_flags | O_NONBLOCK);
for (;;) {
buf.init(q);
fd_set fds;
FD_ZERO(&fds);
- FD_SET(node->vfd.fd, &fds);
+ FD_SET(node->g_fd(), &fds);
if (node->is_m2m)
- ret = select(node->vfd.fd + 1, &fds, &fds, NULL, &tv);
- else if (q.is_output())
- ret = select(node->vfd.fd + 1, NULL, &fds, NULL, &tv);
+ ret = select(node->g_fd() + 1, &fds, &fds, NULL, &tv);
+ else if (v4l_type_is_output(q.g_type()))
+ ret = select(node->g_fd() + 1, NULL, &fds, NULL, &tv);
else
- ret = select(node->vfd.fd + 1, &fds, NULL, NULL, &tv);
+ ret = select(node->g_fd() + 1, &fds, NULL, NULL, &tv);
fail_on_test(ret <= 0);
- fail_on_test(!FD_ISSET(node->vfd.fd, &fds));
+ fail_on_test(!FD_ISSET(node->g_fd(), &fds));
}
- ret = buf.dqbuf(q);
+ ret = buf.dqbuf(node);
if (ret != EAGAIN) {
fail_on_test(ret);
if (show_info)
printf("\r\t%s: Frame #%03d%s",
buftype2s(q.g_type()).c_str(),
frame_count - count, use_poll ? " (polling)" : "");
- if (node->vfd.trace)
+ if (node->g_trace())
printf("\n");
fflush(stdout);
}
- if (buf.is_capture() && node->is_m2m && buf.ts_is_copy()) {
+ if (v4l_type_is_capture(buf.g_type()) && node->is_m2m && buf.ts_is_copy()) {
fail_on_test(buffer_info.find(buf.g_timestamp()) == buffer_info.end());
struct v4l2_buffer &orig_buf = buffer_info[buf.g_timestamp()];
fail_on_test(buf.g_field() != orig_buf.field);
fail_on_test(memcmp(&buf.g_timecode(), &orig_buf.timecode,
sizeof(orig_buf.timecode)));
}
- fail_on_test(buf.qbuf(q));
+ fail_on_test(buf.qbuf(node));
if (--count == 0)
break;
}
continue;
buf.init(m2m_q);
- ret = buf.dqbuf(m2m_q);
+ ret = buf.dqbuf(node);
if (ret == EAGAIN)
continue;
if (show_info)
buf.g_timestamp().tv_sec, buf.g_timestamp().tv_usec);
fail_on_test(ret);
fail_on_test(buf.check(m2m_q, last_m2m_seq));
- if (buf.is_capture() && buf.ts_is_copy()) {
+ if (v4l_type_is_capture(buf.g_type()) && buf.ts_is_copy()) {
fail_on_test(buffer_info.find(buf.g_timestamp()) == buffer_info.end());
struct v4l2_buffer &orig_buf = buffer_info[buf.g_timestamp()];
fail_on_test(buf.g_field() != orig_buf.field);
fail_on_test(memcmp(&buf.g_timecode(), &orig_buf.timecode,
sizeof(orig_buf.timecode)));
}
- fail_on_test(buf.qbuf(m2m_q));
+ fail_on_test(buf.qbuf(node));
}
if (use_poll)
- fcntl(node->vfd.fd, F_SETFL, fd_flags);
+ fcntl(node->g_fd(), F_SETFL, fd_flags);
if (!show_info) {
printf("\r\t \r");
fflush(stdout);
static unsigned invert_buf_type(unsigned type)
{
- if (v4l_buf_type_is_planar(type))
- return v4l_buf_type_is_output(type) ?
+ if (v4l_type_is_planar(type))
+ return v4l_type_is_output(type) ?
V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE :
V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
- return v4l_buf_type_is_output(type) ?
+ return v4l_type_is_output(type) ?
V4L2_BUF_TYPE_VIDEO_CAPTURE :
V4L2_BUF_TYPE_VIDEO_OUTPUT;
}
-static int setupM2M(struct node *node, queue &q)
+static int setupM2M(struct node *node, cv4l_queue &q)
{
last_m2m_seq.init();
- fail_on_test(q.reqbufs(1));
+ fail_on_test(q.reqbufs(node, 1));
for (unsigned i = 0; i < q.g_buffers(); i++) {
buffer buf(q);
- fail_on_test(buf.querybuf(q, i));
- fail_on_test(buf.qbuf(q));
+ fail_on_test(buf.querybuf(node, i));
+ fail_on_test(buf.qbuf(node));
}
- if (q.is_video()) {
- cv4l_fmt fmt(&node->vfd, q.g_type());
+ if (v4l_type_is_video(q.g_type())) {
+ cv4l_fmt fmt(q.g_type());
- fmt.g_fmt();
+ node->g_fmt(fmt);
last_m2m_seq.last_field = fmt.g_field();
}
- fail_on_test(q.streamon());
+ fail_on_test(node->streamon(q.g_type()));
return 0;
}
have_prepare = ret != ENOTTY;
fail_on_test(buf.qbuf(node, false) != EINVAL);
- if (buf.is_planar()) {
+ if (v4l_type_is_planar(buf.g_type())) {
for (unsigned p = 0; p < buf.g_num_planes(); p++) {
buf.s_bytesused(buf.g_length(p) / 2, p);
buf.s_data_offset(buf.g_bytesused(p), p);
return 0;
}
-static int setupMmap(struct node *node, queue &q)
+static int setupMmap(struct node *node, cv4l_queue &q)
{
for (unsigned i = 0; i < q.g_buffers(); i++) {
buffer buf(q);
int ret;
- fail_on_test(buf.querybuf(q, i));
+ fail_on_test(buf.querybuf(node, i));
fail_on_test(buf.check(q, Unqueued, i));
for (unsigned p = 0; p < buf.g_num_planes(); p++) {
// Try a random offset
- fail_on_test(test_mmap(NULL, buf.g_length(p), PROT_READ | PROT_WRITE,
- MAP_SHARED, node->vfd.fd, buf.g_mem_offset(p) + 0xdeadbeef) != MAP_FAILED);
+ fail_on_test(node->mmap(buf.g_length(p),
+ buf.g_mem_offset(p) + 0xdeadbeef) != MAP_FAILED);
}
- fail_on_test(!buf.dqbuf(q));
- if (buf.is_output() && i == 0) {
+ fail_on_test(!buf.dqbuf(node));
+ if (v4l_type_is_output(buf.g_type()) && i == 0) {
fail_on_test(bufferOutputErrorTest(node, buf));
- fail_on_test(buf.querybuf(q, i));
+ fail_on_test(buf.querybuf(node, i));
fail_on_test(buf.check(q, Queued, i));
} else {
- ret = buf.prepare_buf(q);
+ ret = buf.prepare_buf(node);
fail_on_test(ret && ret != ENOTTY);
if (ret == 0) {
- fail_on_test(buf.querybuf(q, i));
+ fail_on_test(buf.querybuf(node, i));
fail_on_test(buf.check(q, Prepared, i));
- fail_on_test(!buf.prepare_buf(q));
+ fail_on_test(!buf.prepare_buf(node));
}
- fail_on_test(buf.qbuf(q));
- fail_on_test(!buf.qbuf(q));
- fail_on_test(!buf.prepare_buf(q));
+ fail_on_test(buf.qbuf(node));
+ fail_on_test(!buf.qbuf(node));
+ fail_on_test(!buf.prepare_buf(node));
// Test with invalid buffer index
buf.s_index(buf.g_index() + VIDEO_MAX_FRAME);
- fail_on_test(!buf.prepare_buf(q));
- fail_on_test(!buf.qbuf(q));
- fail_on_test(!buf.querybuf(q, buf.g_index()));
+ fail_on_test(!buf.prepare_buf(node));
+ fail_on_test(!buf.qbuf(node));
+ fail_on_test(!buf.querybuf(node, buf.g_index()));
buf.s_index(buf.g_index() - VIDEO_MAX_FRAME);
fail_on_test(buf.g_index() != i);
}
- fail_on_test(buf.querybuf(q, i));
+ fail_on_test(buf.querybuf(node, i));
fail_on_test(buf.check(q, Queued, i));
- fail_on_test(!buf.dqbuf(q));
+ fail_on_test(!buf.dqbuf(node));
}
- fail_on_test(q.mmap_bufs());
+ fail_on_test(q.mmap_bufs(node));
return 0;
}
int testMmap(struct node *node, unsigned frame_count)
{
- bool can_stream = node->caps & V4L2_CAP_STREAMING;
+ bool can_stream = node->g_caps() & V4L2_CAP_STREAMING;
bool have_createbufs = true;
int type;
int ret;
for (type = 0; type <= V4L2_BUF_TYPE_SDR_CAPTURE; type++) {
if (!(node->valid_buftypes & (1 << type)))
continue;
- if (v4l_buf_type_is_overlay(type))
+ if (v4l_type_is_overlay(type))
continue;
- queue q(node, type, V4L2_MEMORY_MMAP);
- queue m2m_q(node, invert_buf_type(type));
+ cv4l_queue q(type, V4L2_MEMORY_MMAP);
+ cv4l_queue m2m_q(invert_buf_type(type));
if (testSetupVbi(node, type))
continue;
- ret = q.reqbufs(0);
+ ret = q.reqbufs(node, 0);
if (ret) {
fail_on_test(can_stream);
return ret;
}
fail_on_test(!can_stream);
- fail_on_test(q.streamon() != EINVAL);
- fail_on_test(q.streamoff());
+ fail_on_test(node->streamon(q.g_type()) != EINVAL);
+ fail_on_test(node->streamoff(q.g_type()));
q.init(type, V4L2_MEMORY_MMAP);
- fail_on_test(q.reqbufs(1));
- fail_on_test(q.streamoff());
+ fail_on_test(q.reqbufs(node, 1));
+ fail_on_test(node->streamoff(q.g_type()));
last_seq.init();
// Test queuing buffers...
for (unsigned i = 0; i < q.g_buffers(); i++) {
buffer buf(q);
- fail_on_test(buf.querybuf(q, i));
- fail_on_test(buf.qbuf(q));
+ fail_on_test(buf.querybuf(node, i));
+ fail_on_test(buf.qbuf(node));
}
// calling STREAMOFF...
- fail_on_test(q.streamoff());
+ fail_on_test(node->streamoff(q.g_type()));
// and now we should be able to queue those buffers again since
// STREAMOFF should return them back to the dequeued state.
for (unsigned i = 0; i < q.g_buffers(); i++) {
buffer buf(q);
- fail_on_test(buf.querybuf(q, i));
- fail_on_test(buf.qbuf(q));
+ fail_on_test(buf.querybuf(node, i));
+ fail_on_test(buf.qbuf(node));
}
// Now request buffers again, freeing the old buffers.
// Good check for whether all the internal vb2 calls are in
// balance.
- fail_on_test(q.reqbufs(q.g_buffers()));
- cur_fmt.init(&node->vfd, q.g_type());
- cur_fmt.g_fmt();
+ fail_on_test(q.reqbufs(node, q.g_buffers()));
+ cur_fmt.s_type(q.g_type());
+ node->g_fmt(cur_fmt);
- ret = q.create_bufs(0);
+ ret = q.create_bufs(node, 0);
fail_on_test(ret != ENOTTY && ret != 0);
if (ret == ENOTTY)
have_createbufs = false;
last_seq.last_field = cur_fmt.g_field();
fmt.s_height(fmt.g_height() / 2);
for (unsigned p = 0; p < fmt.g_num_planes(); p++)
- fmt.s_sizeimage(p, fmt.g_sizeimage(p) / 2);
- ret = q.create_bufs(1, &fmt);
+ fmt.s_sizeimage(fmt.g_sizeimage(p) / 2, p);
+ ret = q.create_bufs(node, 1, &fmt);
fail_on_test(ret != EINVAL);
fail_on_test(testQueryBuf(node, cur_fmt.type, q.g_buffers()));
fmt = cur_fmt;
for (unsigned p = 0; p < fmt.g_num_planes(); p++)
- fmt.s_sizeimage(p, fmt.g_sizeimage(p) * 2);
+ fmt.s_sizeimage(fmt.g_sizeimage(p) * 2, p);
}
- fail_on_test(q.create_bufs(1, &fmt));
+ fail_on_test(q.create_bufs(node, 1, &fmt));
}
fail_on_test(setupMmap(node, q));
- fail_on_test(q.streamon());
- fail_on_test(q.streamon());
+ fail_on_test(node->streamon(q.g_type()));
+ fail_on_test(node->streamon(q.g_type()));
if (node->is_m2m)
fail_on_test(setupM2M(node, m2m_q));
else
fail_on_test(captureBufs(node, q, m2m_q, frame_count, false));
fail_on_test(captureBufs(node, q, m2m_q, frame_count, true));
- fail_on_test(q.streamoff());
- fail_on_test(q.streamoff());
+ fail_on_test(node->streamoff(q.g_type()));
+ fail_on_test(node->streamoff(q.g_type()));
+ q.munmap_bufs(node);
+ fail_on_test(q.reqbufs(node, 0));
}
return 0;
}
-static int setupUserPtr(struct node *node, queue &q)
+static int setupUserPtr(struct node *node, cv4l_queue &q)
{
- fail_on_test(q.alloc_bufs());
+ fail_on_test(q.alloc_bufs(node));
for (unsigned i = 0; i < q.g_buffers(); i++) {
buffer buf(q);
int ret;
- fail_on_test(buf.querybuf(q, i));
+ fail_on_test(buf.querybuf(node, i));
fail_on_test(buf.check(q, Unqueued, i));
for (unsigned p = 0; p < buf.g_num_planes(); p++) {
// This should not work!
- fail_on_test(test_mmap(NULL, buf.g_length(p), PROT_READ | PROT_WRITE,
- MAP_SHARED, node->vfd.fd, 0) != MAP_FAILED);
+ fail_on_test(node->mmap(buf.g_length(p), 0) != MAP_FAILED);
}
ret = ENOTTY;
if ((i & 1) == 0) {
for (unsigned p = 0; p < buf.g_num_planes(); p++)
buf.s_userptr(0UL, p);
- ret = buf.prepare_buf(q);
+ ret = buf.prepare_buf(node);
fail_on_test(!ret);
for (unsigned p = 0; p < buf.g_num_planes(); p++)
buf.s_userptr((char *)q.g_userptr(i, p) + 0xdeadbeef, p);
- ret = buf.prepare_buf(q);
+ ret = buf.prepare_buf(node);
fail_on_test(!ret);
for (unsigned p = 0; p < buf.g_num_planes(); p++)
buf.s_userptr(q.g_userptr(i, p), p);
- ret = buf.prepare_buf(q);
+ ret = buf.prepare_buf(node);
fail_on_test(ret && ret != ENOTTY);
if (ret == 0) {
- fail_on_test(buf.querybuf(q, i));
+ fail_on_test(buf.querybuf(node, i));
fail_on_test(buf.check(q, Prepared, i));
}
}
if (ret == ENOTTY) {
for (unsigned p = 0; p < buf.g_num_planes(); p++)
buf.s_userptr(0UL, p);
- ret = buf.qbuf(q);
+ ret = buf.qbuf(node);
fail_on_test(!ret);
for (unsigned p = 0; p < buf.g_num_planes(); p++)
buf.s_userptr((char *)q.g_userptr(i, p) + 0xdeadbeef, p);
- ret = buf.qbuf(q);
+ ret = buf.qbuf(node);
fail_on_test(!ret);
for (unsigned p = 0; p < buf.g_num_planes(); p++)
buf.s_userptr(q.g_userptr(i, p), p);
}
- fail_on_test(buf.qbuf(q));
- fail_on_test(buf.querybuf(q, i));
+ fail_on_test(buf.qbuf(node));
+ fail_on_test(buf.querybuf(node, i));
fail_on_test(buf.check(q, Queued, i));
}
return 0;
int testUserPtr(struct node *node, unsigned frame_count)
{
- bool can_stream = node->caps & V4L2_CAP_STREAMING;
+ bool can_stream = node->g_caps() & V4L2_CAP_STREAMING;
int type;
int ret;
for (type = 0; type <= V4L2_BUF_TYPE_SDR_CAPTURE; type++) {
if (!(node->valid_buftypes & (1 << type)))
continue;
- if (v4l_buf_type_is_overlay(type))
+ if (v4l_type_is_overlay(type))
continue;
- queue q(node, type, V4L2_MEMORY_USERPTR);
- queue m2m_q(node, invert_buf_type(type));
+ cv4l_queue q(type, V4L2_MEMORY_USERPTR);
+ cv4l_queue m2m_q(invert_buf_type(type));
if (testSetupVbi(node, type))
continue;
- ret = q.reqbufs(0);
+ ret = q.reqbufs(node, 0);
if (ret) {
fail_on_test(ret != EINVAL);
return ENOTTY;
fail_on_test(!can_stream);
q.init(type, V4L2_MEMORY_USERPTR);
- fail_on_test(q.reqbufs(1));
- fail_on_test(q.streamoff());
+ fail_on_test(q.reqbufs(node, 1));
+ fail_on_test(node->streamoff(q.g_type()));
last_seq.init();
if (node->is_video)
last_seq.last_field = cur_fmt.g_field();
fail_on_test(setupUserPtr(node, q));
- fail_on_test(q.streamon());
- fail_on_test(q.streamon());
+ fail_on_test(node->streamon(q.g_type()));
+ fail_on_test(node->streamon(q.g_type()));
if (node->is_m2m)
fail_on_test(setupM2M(node, m2m_q));
else
fail_on_test(captureBufs(node, q, m2m_q, frame_count, false));
fail_on_test(captureBufs(node, q, m2m_q, frame_count, true));
- fail_on_test(q.streamoff());
- fail_on_test(q.streamoff());
+ fail_on_test(node->streamoff(q.g_type()));
+ fail_on_test(node->streamoff(q.g_type()));
}
return 0;
}
static int setupDmaBuf(struct node *expbuf_node, struct node *node,
- queue &q, queue &exp_q)
+ cv4l_queue &q, cv4l_queue &exp_q)
{
- fail_on_test(exp_q.reqbufs(q.g_buffers()));
+ fail_on_test(exp_q.reqbufs(expbuf_node, q.g_buffers()));
fail_on_test(exp_q.g_buffers() < q.g_buffers());
- fail_on_test(exp_q.export_bufs());
+ fail_on_test(exp_q.export_bufs(expbuf_node));
for (unsigned i = 0; i < q.g_buffers(); i++) {
buffer buf(q);
int ret;
- fail_on_test(buf.querybuf(q, i));
+ fail_on_test(buf.querybuf(node, i));
fail_on_test(buf.check(q, Unqueued, i));
fail_on_test(exp_q.g_num_planes() < buf.g_num_planes());
for (unsigned p = 0; p < buf.g_num_planes(); p++) {
fail_on_test(exp_q.g_length(p) < buf.g_length(p));
// This should not work!
- fail_on_test(test_mmap(NULL, buf.g_length(p), PROT_READ | PROT_WRITE,
- MAP_SHARED, node->vfd.fd, 0) != MAP_FAILED);
+ fail_on_test(node->mmap(buf.g_length(p), 0) != MAP_FAILED);
q.s_fd(i, p, exp_q.g_fd(i, p));
}
for (unsigned p = 0; p < buf.g_num_planes(); p++)
buf.s_fd(0xdeadbeef + q.g_fd(i, p), p);
- ret = buf.prepare_buf(q);
+ ret = buf.prepare_buf(node);
fail_on_test(!ret);
if (ret != ENOTTY) {
buf.init(q, i);
- ret = buf.prepare_buf(q);
+ ret = buf.prepare_buf(node);
fail_on_test(ret);
- fail_on_test(buf.querybuf(q, i));
+ fail_on_test(buf.querybuf(node, i));
fail_on_test(buf.check(q, Prepared, i));
} else {
- fail_on_test(!buf.qbuf(q));
+ fail_on_test(!buf.qbuf(node));
buf.init(q, i);
}
- fail_on_test(buf.qbuf(q));
- fail_on_test(buf.querybuf(q, i));
+ fail_on_test(buf.qbuf(node));
+ fail_on_test(buf.querybuf(node, i));
fail_on_test(buf.check(q, Queued, i));
}
- fail_on_test(q.mmap_bufs());
+ fail_on_test(q.mmap_bufs(node));
return 0;
}
int testDmaBuf(struct node *expbuf_node, struct node *node, unsigned frame_count)
{
- bool can_stream = node->caps & V4L2_CAP_STREAMING;
+ bool can_stream = node->g_caps() & V4L2_CAP_STREAMING;
int expbuf_type, type;
int ret;
for (type = 0; type <= V4L2_BUF_TYPE_SDR_CAPTURE; type++) {
if (!(node->valid_buftypes & (1 << type)))
continue;
- if (v4l_buf_type_is_sdr(type))
+ if (v4l_type_is_sdr(type))
continue;
- if (v4l_buf_type_is_overlay(type))
+ if (v4l_type_is_overlay(type))
continue;
- if (expbuf_node->caps & V4L2_CAP_VIDEO_CAPTURE_MPLANE)
+ if (expbuf_node->g_caps() & V4L2_CAP_VIDEO_CAPTURE_MPLANE)
expbuf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
- else if (expbuf_node->caps & V4L2_CAP_VIDEO_CAPTURE)
+ else if (expbuf_node->g_caps() & V4L2_CAP_VIDEO_CAPTURE)
expbuf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- else if (expbuf_node->caps & V4L2_CAP_VIDEO_OUTPUT_MPLANE)
+ else if (expbuf_node->g_caps() & V4L2_CAP_VIDEO_OUTPUT_MPLANE)
expbuf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
else
expbuf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
- queue q(node, type, V4L2_MEMORY_DMABUF);
- queue m2m_q(node, invert_buf_type(type));
- queue exp_q(expbuf_node, expbuf_type, V4L2_MEMORY_MMAP);
+ cv4l_queue q(type, V4L2_MEMORY_DMABUF);
+ cv4l_queue m2m_q(invert_buf_type(type));
+ cv4l_queue exp_q(expbuf_type, V4L2_MEMORY_MMAP);
if (testSetupVbi(node, type))
continue;
- ret = q.reqbufs(0);
+ ret = q.reqbufs(node, 0);
if (ret) {
fail_on_test(ret != EINVAL);
return ENOTTY;
}
fail_on_test(!can_stream);
- fail_on_test(q.reqbufs(1));
- fail_on_test(q.streamoff());
+ fail_on_test(q.reqbufs(node, 1));
+ fail_on_test(node->streamoff(q.g_type()));
last_seq.init();
if (node->is_video)
last_seq.last_field = cur_fmt.g_field();
fail_on_test(setupDmaBuf(expbuf_node, node, q, exp_q));
- fail_on_test(q.streamon());
- fail_on_test(q.streamon());
+ fail_on_test(node->streamon(q.g_type()));
+ fail_on_test(node->streamon(q.g_type()));
if (node->is_m2m)
fail_on_test(setupM2M(node, m2m_q));
else
fail_on_test(captureBufs(node, q, m2m_q, frame_count, false));
fail_on_test(captureBufs(node, q, m2m_q, frame_count, true));
- fail_on_test(q.streamoff());
- fail_on_test(q.streamoff());
+ fail_on_test(node->streamoff(q.g_type()));
+ fail_on_test(node->streamoff(q.g_type()));
}
return 0;
}
return fail("subscribe event for control '%s' failed\n", iter->name);
//if (iter->type == V4L2_CTRL_TYPE_CTRL_CLASS)
FD_ZERO(&set);
- FD_SET(node->vfd.fd, &set);
- ret = select(node->vfd.fd + 1, NULL, NULL, &set, &timeout);
+ FD_SET(node->g_fd(), &set);
+ ret = select(node->g_fd() + 1, NULL, NULL, &set, &timeout);
if (ret == 0) {
if (iter->type != V4L2_CTRL_TYPE_CTRL_CLASS)
return fail("failed to find event for control '%s'\n", iter->name);
frmsize.discrete.width + 1, frmsize.discrete.height, 0);
if (ret && ret != ENOTTY)
return ret;
- if (ret == 0 && !(node->caps & (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_CAPTURE_MPLANE)))
+ if (ret == 0 && !(node->g_caps() & (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_CAPTURE_MPLANE)))
return fail("found discrete framesizes when no video capture is supported\n");
break;
case V4L2_FRMSIZE_TYPE_CONTINUOUS:
return fail("fmtdesc.description not set\n");
if (!fmtdesc.pixelformat)
return fail("fmtdesc.pixelformat not set\n");
- if (!wrapper && (fmtdesc.flags & V4L2_FMT_FLAG_EMULATED))
+ if (node->g_direct() && (fmtdesc.flags & V4L2_FMT_FLAG_EMULATED))
return fail("drivers must never set the emulated flag\n");
if (fmtdesc.flags & ~(V4L2_FMT_FLAG_COMPRESSED | V4L2_FMT_FLAG_EMULATED))
return fail("unknown flag %08x returned\n", fmtdesc.flags);
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
case V4L2_BUF_TYPE_SDR_CAPTURE:
- if (ret && (node->caps & buftype2cap[type]))
+ if (ret && (node->g_caps() & buftype2cap[type]))
return fail("%s cap set, but no %s formats defined\n",
buftype2s(type).c_str(), buftype2s(type).c_str());
- if (!ret && !(node->caps & buftype2cap[type]))
+ if (!ret && !(node->g_caps() & buftype2cap[type]))
return fail("%s cap not set, but %s formats defined\n",
buftype2s(type).c_str(), buftype2s(type).c_str());
break;
memset(&fbuf, 0xff, sizeof(fbuf));
fbuf.fmt.priv = 0;
ret = doioctl(node, VIDIOC_G_FBUF, &fbuf);
- fail_on_test(ret == 0 && !(node->caps & (V4L2_CAP_VIDEO_OVERLAY | V4L2_CAP_VIDEO_OUTPUT_OVERLAY)));
- fail_on_test(ret == ENOTTY && (node->caps & (V4L2_CAP_VIDEO_OVERLAY | V4L2_CAP_VIDEO_OUTPUT_OVERLAY)));
+ fail_on_test(ret == 0 && !(node->g_caps() & (V4L2_CAP_VIDEO_OVERLAY | V4L2_CAP_VIDEO_OUTPUT_OVERLAY)));
+ fail_on_test(ret == ENOTTY && (node->g_caps() & (V4L2_CAP_VIDEO_OVERLAY | V4L2_CAP_VIDEO_OUTPUT_OVERLAY)));
if (ret == ENOTTY)
return ret;
if (ret && ret != EINVAL)
return fail("expected EINVAL, but got %d when getting framebuffer format\n", ret);
node->fbuf_caps = caps = fbuf.capability;
flags = fbuf.flags;
- if (node->caps & V4L2_CAP_VIDEO_OUTPUT_OVERLAY)
+ if (node->g_caps() & V4L2_CAP_VIDEO_OUTPUT_OVERLAY)
fail_on_test(!fbuf.base);
if (flags & V4L2_FBUF_FLAG_CHROMAKEY)
fail_on_test(!(caps & V4L2_FBUF_CAP_CHROMAKEY));
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
case V4L2_BUF_TYPE_SDR_CAPTURE:
- if (ret && (node->caps & buftype2cap[type]))
+ if (ret && (node->g_caps() & buftype2cap[type]))
return fail("%s cap set, but no %s formats defined\n",
buftype2s(type).c_str(), buftype2s(type).c_str());
- if (!ret && !(node->caps & buftype2cap[type]))
+ if (!ret && !(node->g_caps() & buftype2cap[type]))
return fail("%s cap not set, but %s formats defined\n",
buftype2s(type).c_str(), buftype2s(type).c_str());
break;
// test is pointless.
// This test will also never succeed if we are using the libv4l2
// wrapper.
- if (wrapper || (pixfmt1 == pixfmt2 && w1 == w2 && h1 == h2))
+ if (!node->g_direct() || (pixfmt1 == pixfmt2 && w1 == w2 && h1 == h2))
return 0;
if (type == V4L2_BUF_TYPE_SDR_CAPTURE) {
ret = doioctl(node, VIDIOC_G_SLICED_VBI_CAP, &cap);
if (ret == ENOTTY || ret == EINVAL) {
if (node->cur_io_caps & V4L2_IN_CAP_STD)
- fail_on_test(sliced_type && (node->caps & buftype2cap[type]));
+ fail_on_test(sliced_type && (node->g_caps() & buftype2cap[type]));
return ret == ENOTTY ? ret : 0;
}
fail_on_test(ret);
fail_on_test(check_0(cap.reserved, sizeof(cap.reserved)));
fail_on_test(cap.type != type);
- fail_on_test(!sliced_type || !(node->caps & buftype2cap[type]));
+ fail_on_test(!sliced_type || !(node->g_caps() & buftype2cap[type]));
for (int f = 0; f < 2; f++)
for (int i = 0; i < 24; i++)
if (ret)
return fail("reserved not zeroed\n");
fail_on_test(cap->readbuffers > VIDEO_MAX_FRAME);
- if (!(node->caps & V4L2_CAP_READWRITE))
+ if (!(node->g_caps() & V4L2_CAP_READWRITE))
fail_on_test(cap->readbuffers);
- else if (node->caps & V4L2_CAP_STREAMING)
+ else if (node->g_caps() & V4L2_CAP_STREAMING)
fail_on_test(!cap->readbuffers);
fail_on_test(cap->capability & ~V4L2_CAP_TIMEPERFRAME);
fail_on_test(cap->capturemode & ~V4L2_MODE_HIGHQUALITY);
if (ret)
return fail("reserved not zeroed\n");
fail_on_test(out->writebuffers > VIDEO_MAX_FRAME);
- if (!(node->caps & V4L2_CAP_READWRITE))
+ if (!(node->g_caps() & V4L2_CAP_READWRITE))
fail_on_test(out->writebuffers);
- else if (node->caps & V4L2_CAP_STREAMING)
+ else if (node->g_caps() & V4L2_CAP_STREAMING)
fail_on_test(!out->writebuffers);
fail_on_test(out->capability & ~V4L2_CAP_TIMEPERFRAME);
fail_on_test(out->outputmode);
type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE &&
type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
return fail("G/S_PARM is only allowed for video capture/output\n");
- if (!(node->caps & buftype2cap[type]))
+ if (!(node->g_caps() & buftype2cap[type]))
return fail("%s cap not set, but G/S_PARM worked\n",
buftype2s(type).c_str());
}
if (node->is_sdr)
fail_on_test(!(V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_1HZ));
fail_on_test(!(tuner.capability & V4L2_TUNER_CAP_FREQ_BANDS));
- fail_on_test(!(node->caps & V4L2_CAP_HW_FREQ_SEEK) && hwseek_caps);
- fail_on_test((node->caps & V4L2_CAP_HW_FREQ_SEEK) &&
+ fail_on_test(!(node->g_caps() & V4L2_CAP_HW_FREQ_SEEK) && hwseek_caps);
+ fail_on_test((node->g_caps() & V4L2_CAP_HW_FREQ_SEEK) &&
!(tuner.capability & (V4L2_TUNER_CAP_HWSEEK_BOUNDED | V4L2_TUNER_CAP_HWSEEK_WRAP)));
if (tuner.rangelow > tuner.rangehigh)
return fail("rangelow > rangehigh\n");
return fail("V4L2_TUNER_CAP_RDS is set, but not V4L2_TUNER_CAP_RDS_* or vice versa\n");
fail_on_test(node->is_sdr && have_rds);
if ((tuner.capability & V4L2_TUNER_CAP_RDS_BLOCK_IO) &&
- !(node->caps & V4L2_CAP_READWRITE))
+ !(node->g_caps() & V4L2_CAP_READWRITE))
return fail("V4L2_TUNER_CAP_RDS_BLOCK_IO is set, but not V4L2_CAP_READWRITE\n");
if (node->is_radio && !(tuner.capability & V4L2_TUNER_CAP_RDS_BLOCK_IO) &&
- (node->caps & V4L2_CAP_READWRITE))
+ (node->g_caps() & V4L2_CAP_READWRITE))
return fail("V4L2_TUNER_CAP_RDS_BLOCK_IO is not set, but V4L2_CAP_READWRITE is\n");
if (std == V4L2_STD_NTSC_M && (tuner.rxsubchans & V4L2_TUNER_SUB_LANG1))
return fail("LANG1 subchan, but NTSC-M standard\n");
tuner.index = t;
if (doioctl(node, VIDIOC_S_TUNER, &tuner) != EINVAL)
return fail("could set invalid tuner %d\n", t);
- if (node->tuners && !(node->caps & V4L2_CAP_TUNER))
+ if (node->tuners && !(node->g_caps() & V4L2_CAP_TUNER))
return fail("tuners found, but no tuner capability set\n");
- if (!node->tuners && (node->caps & V4L2_CAP_TUNER))
+ if (!node->tuners && (node->g_caps() & V4L2_CAP_TUNER))
return fail("no tuners found, but tuner capability set\n");
- if (has_rds && !(node->caps & V4L2_CAP_RDS_CAPTURE))
+ if (has_rds && !(node->g_caps() & V4L2_CAP_RDS_CAPTURE))
return fail("RDS tuner capability, but no RDS capture capability?\n");
- if (!has_rds && (node->caps & V4L2_CAP_RDS_CAPTURE))
+ if (!has_rds && (node->g_caps() & V4L2_CAP_RDS_CAPTURE))
return fail("No RDS tuner capability, but RDS capture capability?\n");
return 0;
}
if (freq.type != V4L2_TUNER_RADIO && freq.type != V4L2_TUNER_ANALOG_TV &&
freq.type != V4L2_TUNER_ADC && freq.type != V4L2_TUNER_RF)
return fail("returned invalid tuner type %d\n", freq.type);
- if (freq.type == V4L2_TUNER_RADIO && !(node->caps & V4L2_CAP_RADIO))
+ if (freq.type == V4L2_TUNER_RADIO && !(node->g_caps() & V4L2_CAP_RADIO))
return fail("radio tuner found but no radio capability set\n");
if ((freq.type == V4L2_TUNER_ADC || freq.type == V4L2_TUNER_RF) &&
- !(node->caps & V4L2_CAP_SDR_CAPTURE))
+ !(node->g_caps() & V4L2_CAP_SDR_CAPTURE))
return fail("sdr tuner found but no sdr capture capability set\n");
if (freq.type != tuner.type)
return fail("frequency tuner type and tuner type mismatch\n");
}
/* If this is a modulator device, then skip the remaining tests */
- if (node->caps & V4L2_CAP_MODULATOR)
+ if (node->g_caps() & V4L2_CAP_MODULATOR)
return 0;
freq.tuner = t;
seek.tuner = t;
seek.type = V4L2_TUNER_RADIO;
ret = doioctl(node, VIDIOC_S_HW_FREQ_SEEK, &seek);
- if (!(node->caps & V4L2_CAP_HW_FREQ_SEEK) && ret != ENOTTY)
+ if (!(node->g_caps() & V4L2_CAP_HW_FREQ_SEEK) && ret != ENOTTY)
return fail("hw seek supported but capability not set\n");
if (!node->is_radio && ret != ENOTTY)
return fail("hw seek supported on a non-radio node?!\n");
- if (!node->is_radio || !(node->caps & V4L2_CAP_HW_FREQ_SEEK))
+ if (!node->is_radio || !(node->g_caps() & V4L2_CAP_HW_FREQ_SEEK))
return ENOTTY;
seek.type = V4L2_TUNER_ANALOG_TV;
ret = doioctl(node, VIDIOC_S_HW_FREQ_SEEK, &seek);
node->audio_inputs++;
i++;
}
- if (node->audio_inputs && !(node->caps & V4L2_CAP_AUDIO))
+ if (node->audio_inputs && !(node->g_caps() & V4L2_CAP_AUDIO))
return fail("audio inputs reported, but no CAP_AUDIO set\n");
return 0;
}
if (have_rds ^ have_rds_method)
return fail("V4L2_TUNER_CAP_RDS is set, but not V4L2_TUNER_CAP_RDS_* or vice versa\n");
if ((mod.capability & V4L2_TUNER_CAP_RDS_BLOCK_IO) &&
- !(node->caps & V4L2_CAP_READWRITE))
+ !(node->g_caps() & V4L2_CAP_READWRITE))
return fail("V4L2_TUNER_CAP_RDS_BLOCK_IO is set, but not V4L2_CAP_READWRITE\n");
if (!(mod.capability & V4L2_TUNER_CAP_RDS_BLOCK_IO) &&
- (node->caps & V4L2_CAP_READWRITE))
+ (node->g_caps() & V4L2_CAP_READWRITE))
return fail("V4L2_TUNER_CAP_RDS_BLOCK_IO is not set, but V4L2_CAP_READWRITE is\n");
return checkEnumFreqBands(node, mod.index, V4L2_TUNER_RADIO, mod.capability,
mod.rangelow, mod.rangehigh);
mod.index = m;
if (doioctl(node, VIDIOC_S_MODULATOR, &mod) != EINVAL)
return fail("could set invalid modulator %d\n", m);
- if (node->modulators && !(node->caps & V4L2_CAP_MODULATOR))
+ if (node->modulators && !(node->g_caps() & V4L2_CAP_MODULATOR))
return fail("modulators found, but no modulator capability set\n");
- if (!node->modulators && (node->caps & V4L2_CAP_MODULATOR))
+ if (!node->modulators && (node->g_caps() & V4L2_CAP_MODULATOR))
return fail("no modulators found, but modulator capability set\n");
- if (has_rds && !(node->caps & V4L2_CAP_RDS_OUTPUT))
+ if (has_rds && !(node->g_caps() & V4L2_CAP_RDS_OUTPUT))
return fail("RDS modulator capability, but no RDS output capability?\n");
- if (!has_rds && (node->caps & V4L2_CAP_RDS_OUTPUT))
+ if (!has_rds && (node->g_caps() & V4L2_CAP_RDS_OUTPUT))
return fail("No RDS modulator capability, but RDS output capability?\n");
return 0;
}
}
/* If this is a tuner device, then skip the remaining tests */
- if (node->caps & V4L2_CAP_TUNER)
+ if (node->g_caps() & V4L2_CAP_TUNER)
return 0;
freq.tuner = m;
o++;
}
- if (node->audio_outputs && !(node->caps & V4L2_CAP_AUDIO))
+ if (node->audio_outputs && !(node->g_caps() & V4L2_CAP_AUDIO))
return fail("audio outputs reported, but no CAP_AUDIO set\n");
return 0;
}
return fail("invalid audioset for output %d\n", o);
}
- if (node->audio_outputs == 0 && node->audio_inputs == 0 && (node->caps & V4L2_CAP_AUDIO))
+ if (node->audio_outputs == 0 && node->audio_inputs == 0 && (node->g_caps() & V4L2_CAP_AUDIO))
return fail("no audio inputs or outputs reported, but CAP_AUDIO set\n");
return node->audio_outputs ? 0 : ENOTTY;
}
struct v4l2_enum_dv_timings enumtimings;
struct v4l2_dv_timings timings;
struct v4l2_format fmt;
- bool is_mplane = node->caps & (V4L2_CAP_VIDEO_CAPTURE_MPLANE |
+ bool is_mplane = node->g_caps() & (V4L2_CAP_VIDEO_CAPTURE_MPLANE |
V4L2_CAP_VIDEO_OUTPUT_MPLANE |
V4L2_CAP_VIDEO_M2M_MPLANE);
unsigned type;