v4l2-compliance: reworked the (c)v4l-helpers.h headers
authorHans Verkuil <hans.verkuil@cisco.com>
Sun, 20 Jul 2014 12:20:09 +0000 (14:20 +0200)
committerHans Verkuil <hans.verkuil@cisco.com>
Sun, 20 Jul 2014 12:20:09 +0000 (14:20 +0200)
These headers were designed to easy coding for the V4L2 API, in particular
hiding the complexity relating to single and multiplanar formats.

These reworked headers resolve a number of design issues and they are now ready
to be used elsewhere.

As an example, the C++ code below works for single and multiplanar video capture and
output, vbi capture and output and sdr capture. By replacing V4L2_MEMORY_MMAP with
_USERPTR it will work with userptr streaming as well. But note that the code is
missing error handling, so a real application will need to do a bit more.

int main(int argc, char **argv)
{
cv4l_fd fd;
unsigned cnt = 0;

fd.open(argc >= 2 ? argv[1] : "/dev/video0");

cv4l_queue q(fd.g_type(), V4L2_MEMORY_MMAP);

q.reqbufs(&fd, 4);
q.obtain_bufs(&fd);
q.queue_all(&fd);
fd.streamon();

cv4l_buffer buf(q);

while (fd.dqbuf(buf) == 0) {
printf("seqnr: %u bytesused[0]: %u bytesused[1]: %u\n", buf.g_sequence(),
buf.g_bytesused(0), buf.g_bytesused(1));
fd.qbuf(buf);
if (cnt++ >= 60)
break;
}
q.free(&fd);
fd.close();
}

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
utils/v4l2-compliance/cv4l-helpers.h
utils/v4l2-compliance/v4l-helpers.h
utils/v4l2-compliance/v4l2-compliance.cpp
utils/v4l2-compliance/v4l2-compliance.h
utils/v4l2-compliance/v4l2-test-buffers.cpp
utils/v4l2-compliance/v4l2-test-controls.cpp
utils/v4l2-compliance/v4l2-test-formats.cpp
utils/v4l2-compliance/v4l2-test-input-output.cpp
utils/v4l2-compliance/v4l2-test-io-config.cpp

index 9fb9370..0702766 100644 (file)
 #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;
@@ -141,99 +514,86 @@ 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 {
@@ -251,20 +611,22 @@ public:
                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); }
@@ -274,6 +636,20 @@ public:
        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); }
@@ -285,90 +661,19 @@ public:
        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
index 5567528..8362144 100644 (file)
 #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)
@@ -63,162 +225,145 @@ static inline __u32 v4l_capability_g_caps(const 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 :
@@ -240,83 +385,38 @@ static inline __u32 v4l_g_buf_type(struct v4l_fd *f)
        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)
@@ -539,17 +639,24 @@ v4l_format_g_num_planes(const struct v4l2_format *fmt)
 }
 
 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;
        }
 }
 
@@ -559,22 +666,27 @@ v4l_format_g_bytesperline(const struct v4l2_format *fmt, unsigned plane)
        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:
@@ -589,15 +701,39 @@ v4l_format_g_sizeimage(const struct v4l2_format *fmt, unsigned plane)
        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;
@@ -616,44 +752,65 @@ static inline void v4l_buffer_init(struct v4l_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;
 }
@@ -765,74 +922,82 @@ static inline void v4l_buffer_s_timestamp_src(struct v4l_buffer *buf, __u32 src)
 
 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)
@@ -882,60 +1047,10 @@ static inline void v4l_queue_init(struct v4l_queue *q,
                        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)
 {
@@ -954,6 +1069,8 @@ static inline void v4l_queue_s_mmapping(struct v4l_queue *q, unsigned index, uns
 
 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];
 }
 
@@ -964,6 +1081,8 @@ static inline void v4l_queue_s_userptr(struct v4l_queue *q, unsigned index, unsi
 
 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];
 }
 
@@ -977,6 +1096,13 @@ static inline int v4l_queue_g_fd(const struct v4l_queue *q, unsigned index, unsi
        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;
@@ -1056,16 +1182,6 @@ static inline int v4l_queue_create_bufs(struct v4l_fd *f,
        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)
 {
@@ -1146,13 +1262,28 @@ static inline int v4l_queue_free_bufs(struct v4l_queue *q)
                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)
 {
@@ -1205,9 +1336,8 @@ static inline void v4l_queue_close_exported_fds(struct v4l_queue *q)
 
 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);
 }
@@ -1217,14 +1347,16 @@ static inline void v4l_queue_buffer_init(const struct v4l_queue *q, struct v4l_b
        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++)
@@ -1235,4 +1367,8 @@ static inline void v4l_queue_buffer_init(const struct v4l_queue *q, struct v4l_b
        }
 }
 
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
 #endif
index b8f828b..0f859a6 100644 (file)
@@ -26,7 +26,6 @@
 #include <getopt.h>
 #include <sys/types.h>
 #include <sys/stat.h>
-#include <fcntl.h>
 #include <ctype.h>
 #include <errno.h>
 #include <sys/ioctl.h>
@@ -69,7 +68,6 @@ static int tests_total, tests_ok;
 // Globals
 bool show_info;
 bool show_warnings = true;
-bool wrapper;
 int kernel_version;
 unsigned warnings;
 
@@ -129,38 +127,6 @@ static void usage(void)
        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;
@@ -352,7 +318,7 @@ static int testCap(struct node *node)
        // 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
@@ -446,7 +412,7 @@ static void streamingSetup(struct node *node)
                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);
@@ -499,16 +465,16 @@ static void streamingSetup(struct node *node)
 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;
@@ -632,7 +598,7 @@ int main(int argc, char **argv)
                usage();
                return 1;
        }
-       wrapper = options[OptUseWrapper];
+       bool direct = !options[OptUseWrapper];
 
        struct utsname uts;
        int v1, v2, v3;
@@ -647,105 +613,99 @@ int main(int argc, char **argv)
                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 */
 
@@ -768,7 +728,7 @@ int main(int argc, char **argv)
        }
 
        printf("\nCompliance test for device %s (%susing libv4l2):\n\n",
-                       device, wrapper ? "" : "not ");
+                       device, direct ? "not " : "");
 
        /* Required ioctls */
 
@@ -782,8 +742,8 @@ int main(int argc, char **argv)
        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)));
@@ -793,8 +753,8 @@ int main(int argc, char **argv)
        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)));
@@ -804,8 +764,8 @@ int main(int argc, char **argv)
        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)));
@@ -815,8 +775,8 @@ int main(int argc, char **argv)
        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)));
@@ -940,17 +900,17 @@ int main(int argc, char **argv)
                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");
 
@@ -962,11 +922,11 @@ int main(int argc, char **argv)
 
        /* 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);
index ade9d4b..be3f127 100644 (file)
 
 #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>
@@ -48,7 +40,6 @@
 
 extern bool show_info;
 extern bool show_warnings;
-extern bool wrapper;
 extern int kernel_version;
 extern unsigned warnings;
 
@@ -59,10 +50,9 @@ struct test_queryctrl: v4l2_queryctrl {
 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;
@@ -72,7 +62,6 @@ struct node {
        bool can_capture;
        bool can_output;
        const char *device;
-       unsigned caps;
        struct node *node2;     /* second open filehandle */
        bool has_outputs;
        bool has_inputs;
@@ -85,14 +74,19 @@ struct node {
        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)                                  \
@@ -118,59 +112,6 @@ struct node {
                        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)
@@ -183,9 +124,7 @@ static inline double fract2f(const struct v4l2_fract *f)
        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);
index 1ccd66d..32923da 100644 (file)
@@ -106,20 +106,8 @@ static std::string field2s(unsigned val)
        }
 }
 
-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) :
@@ -128,39 +116,28 @@ public:
 
        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);
 
@@ -168,7 +145,7 @@ public:
                        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);
 
@@ -176,7 +153,7 @@ public:
                        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);
 
@@ -196,7 +173,7 @@ public:
 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;
@@ -229,7 +206,7 @@ private:
        }
 };
 
-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++) {
@@ -261,7 +238,7 @@ int buffer::check(unsigned type, unsigned memory, unsigned index,
                     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++;
@@ -282,7 +259,7 @@ int buffer::check(unsigned type, unsigned memory, unsigned index,
                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;
@@ -292,7 +269,7 @@ int buffer::check(unsigned type, unsigned memory, unsigned index,
                }
        }
 
-       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");
 
@@ -304,7 +281,7 @@ int buffer::check(unsigned type, unsigned memory, unsigned index,
                }
                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) {
@@ -327,12 +304,12 @@ int buffer::check(unsigned type, unsigned memory, unsigned index,
                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 |
@@ -355,7 +332,7 @@ static int testQueryBuf(struct node *node, unsigned type, unsigned count)
 
        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));
        }
@@ -366,34 +343,35 @@ static int testQueryBuf(struct node *node, unsigned type, unsigned count)
 
 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;
@@ -401,7 +379,7 @@ int testReqBufs(struct node *node)
        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;
@@ -414,19 +392,19 @@ int testReqBufs(struct node *node)
                        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);
@@ -436,33 +414,33 @@ int testReqBufs(struct node *node)
 
                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;
                }
@@ -471,30 +449,30 @@ int testReqBufs(struct node *node)
                        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;
@@ -503,12 +481,12 @@ int testReqBufs(struct node *node)
                        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;
 }
@@ -519,53 +497,53 @@ int testExpBuf(struct node *node)
        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
@@ -577,22 +555,22 @@ int testReadWrite(struct node *node)
        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;
@@ -604,7 +582,7 @@ static int captureBufs(struct node *node, const queue &q,
        }
 
        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);
 
@@ -613,18 +591,18 @@ static int captureBufs(struct node *node, const queue &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)
@@ -636,11 +614,11 @@ static int captureBufs(struct node *node, const queue &q,
                                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);
@@ -650,7 +628,7 @@ static int captureBufs(struct node *node, const queue &q,
                                        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;
                }
@@ -658,7 +636,7 @@ static int captureBufs(struct node *node, const queue &q,
                        continue;
 
                buf.init(m2m_q);
-               ret = buf.dqbuf(m2m_q);
+               ret = buf.dqbuf(node);
                if (ret == EAGAIN)
                        continue;
                if (show_info)
@@ -667,7 +645,7 @@ static int captureBufs(struct node *node, const queue &q,
                                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);
@@ -677,10 +655,10 @@ static int captureBufs(struct node *node, const queue &q,
                                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);
@@ -690,33 +668,33 @@ static int captureBufs(struct node *node, const queue &q,
 
 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;
 }
 
@@ -735,7 +713,7 @@ static int bufferOutputErrorTest(struct node *node, const buffer &orig_buf)
        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);
@@ -766,56 +744,56 @@ static int bufferOutputErrorTest(struct node *node, const buffer &orig_buf)
        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;
@@ -827,55 +805,55 @@ int testMmap(struct node *node, unsigned frame_count)
        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;
@@ -886,47 +864,48 @@ int testMmap(struct node *node, unsigned frame_count)
                                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;
@@ -934,39 +913,39 @@ static int setupUserPtr(struct node *node, queue &q)
                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;
@@ -974,7 +953,7 @@ static int setupUserPtr(struct node *node, queue &q)
 
 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;
 
@@ -985,16 +964,16 @@ int testUserPtr(struct node *node, unsigned frame_count)
        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;
@@ -1002,76 +981,75 @@ int testUserPtr(struct node *node, unsigned frame_count)
                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;
 
@@ -1082,52 +1060,52 @@ int testDmaBuf(struct node *expbuf_node, struct node *node, unsigned frame_count
        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;
 }
index 70bf97e..c45181a 100644 (file)
@@ -721,8 +721,8 @@ int testControlEvents(struct node *node)
                        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);
index dc7f665..6746c0d 100644 (file)
@@ -165,7 +165,7 @@ static int testEnumFrameSizes(struct node *node, __u32 pixfmt)
                                        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:
@@ -243,7 +243,7 @@ static int testEnumFormatsType(struct node *node, unsigned type)
                        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);
@@ -282,10 +282,10 @@ int testEnumFormats(struct node *node)
                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;
@@ -330,15 +330,15 @@ int testFBuf(struct node *node)
        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));
@@ -551,10 +551,10 @@ int testGetFormats(struct node *node)
                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;
@@ -773,7 +773,7 @@ static int testGlobalFormat(struct node *node, int type)
        // 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) {
@@ -993,13 +993,13 @@ static int testSlicedVBICapType(struct node *node, unsigned type)
        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++)
@@ -1035,9 +1035,9 @@ static int testParmStruct(struct node *node, struct v4l2_streamparm &parm)
                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);
@@ -1053,9 +1053,9 @@ static int testParmStruct(struct node *node, struct v4l2_streamparm &parm)
                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);
@@ -1117,7 +1117,7 @@ int testParm(struct node *node)
                            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());
                }
index dcece7b..0d61289 100644 (file)
@@ -110,8 +110,8 @@ static int checkTuner(struct node *node, const struct v4l2_tuner &tuner,
        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");
@@ -136,10 +136,10 @@ static int checkTuner(struct node *node, const struct v4l2_tuner &tuner,
                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");
@@ -208,13 +208,13 @@ int testTuner(struct node *node)
        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;
 }
@@ -244,10 +244,10 @@ int testTunerFreq(struct node *node)
                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");
@@ -292,7 +292,7 @@ int testTunerFreq(struct node *node)
        }
 
        /* 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;
@@ -327,11 +327,11 @@ int testTunerHwSeek(struct node *node)
                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);
@@ -490,7 +490,7 @@ int testEnumInputAudio(struct node *node)
                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;
 }
@@ -592,10 +592,10 @@ static int checkModulator(struct node *node, const struct v4l2_modulator &mod, u
        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);
@@ -632,13 +632,13 @@ int testModulator(struct node *node)
        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;
 }
@@ -699,7 +699,7 @@ int testModulatorFreq(struct node *node)
        }
 
        /* 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;
@@ -833,7 +833,7 @@ int testEnumOutputAudio(struct node *node)
                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;
 }
@@ -893,7 +893,7 @@ int testOutputAudio(struct node *node)
                        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;
 }
index 150477c..c75ea55 100644 (file)
@@ -155,7 +155,7 @@ static int checkTimings(struct node *node, bool has_timings, bool is_input)
        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;