qv4l2: add basic raw VBI support.
authorHans Verkuil <hans.verkuil@cisco.com>
Sun, 10 Jun 2012 13:25:28 +0000 (15:25 +0200)
committerHans Verkuil <hans.verkuil@cisco.com>
Sun, 10 Jun 2012 13:25:28 +0000 (15:25 +0200)
Just show the VBI data as a greyscale picture.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
utils/qv4l2/general-tab.cpp
utils/qv4l2/general-tab.h
utils/qv4l2/qv4l2.cpp
utils/qv4l2/v4l2-api.cpp
utils/qv4l2/v4l2-api.h

index d0a8c17..edbe19b 100644 (file)
@@ -38,6 +38,7 @@ GeneralTab::GeneralTab(const QString &device, v4l2 &fd, int n, QWidget *parent)
        m_col(0),
        m_cols(n),
        m_isRadio(false),
+       m_isVbi(false),
        m_audioInput(NULL),
        m_tvStandard(NULL),
        m_qryStandard(NULL),
@@ -80,6 +81,8 @@ GeneralTab::GeneralTab(const QString &device, v4l2 &fd, int n, QWidget *parent)
                m_isRadio = true;
        if (m_modulator.capability && m_modulator.capability & V4L2_TUNER_CAP_LOW)
                m_isRadio = true;
+       if (m_querycap.capabilities & V4L2_CAP_DEVICE_CAPS)
+               m_isVbi = caps() & V4L2_CAP_VBI_CAPTURE;
 
        if (!isRadio() && enum_input(vin, true)) {
                addLabel("Input");
@@ -277,6 +280,9 @@ GeneralTab::GeneralTab(const QString &device, v4l2 &fd, int n, QWidget *parent)
        if (isRadio())
                goto done;
 
+       if (isVbi())
+               goto capture_method;
+
        v4l2_fmtdesc fmt;
        addLabel("Capture Image Formats");
        m_vidCapFormats = new QComboBox(parent);
@@ -331,8 +337,11 @@ GeneralTab::GeneralTab(const QString &device, v4l2 &fd, int n, QWidget *parent)
                connect(m_vidOutFormats, SIGNAL(activated(int)), SLOT(vidOutFormatChanged(int)));
        }
 
+capture_method:
        addLabel("Capture Method");
        m_capMethods = new QComboBox(parent);
+       m_buftype = isVbi() ? V4L2_BUF_TYPE_VBI_CAPTURE :
+               V4L2_BUF_TYPE_VIDEO_CAPTURE;
        if (caps() & V4L2_CAP_STREAMING) {
                v4l2_requestbuffers reqbuf;
 
@@ -345,13 +354,13 @@ GeneralTab::GeneralTab(const QString &device, v4l2 &fd, int n, QWidget *parent)
                // unexpected. So the only way at the moment to do this that works
                // everywhere is to call REQBUFS with a count of 1, and then again with
                // a count of 0.
-               if (reqbufs_user_cap(reqbuf, 1)) {
+               if (reqbufs_user(reqbuf, 1)) {
                        m_capMethods->addItem("User pointer I/O", QVariant(methodUser));
-                       reqbufs_user_cap(reqbuf, 0);
+                       reqbufs_user(reqbuf, 0);
                }
-               if (reqbufs_mmap_cap(reqbuf, 1)) {
+               if (reqbufs_mmap(reqbuf, 1)) {
                        m_capMethods->addItem("Memory mapped I/O", QVariant(methodMmap));
-                       reqbufs_mmap_cap(reqbuf, 0);
+                       reqbufs_mmap(reqbuf, 0);
                }
        }
        if (caps() & V4L2_CAP_READWRITE) {
index 2d5ffa6..8e4af75 100644 (file)
@@ -45,6 +45,28 @@ public:
        int width() const { return m_width; }
        int height() const { return m_height; }
        bool isRadio() const { return m_isRadio; }
+       bool isVbi() const { return m_isVbi; }
+       __u32 bufType() const { return m_buftype; }
+       inline bool reqbufs_mmap(v4l2_requestbuffers &reqbuf, int count = 0) {
+               return v4l2::reqbufs_mmap(reqbuf, m_buftype, count);
+       }
+       inline bool reqbufs_user(v4l2_requestbuffers &reqbuf, int count = 0) {
+               return v4l2::reqbufs_user(reqbuf, m_buftype, count);
+       }
+       inline bool dqbuf_mmap(v4l2_buffer &buf, bool &again) {
+               return v4l2::dqbuf_mmap(buf, m_buftype, again);
+       }
+       inline bool dqbuf_user(v4l2_buffer &buf, bool &again) {
+               return v4l2::dqbuf_user(buf, m_buftype, again);
+       }
+       inline bool qbuf_mmap(int index) {
+               return v4l2::qbuf_mmap(index, m_buftype);
+       }
+       inline bool qbuf_user(int index, void *ptr, int length) {
+               return v4l2::qbuf_user(index, m_buftype, ptr, length);
+       }
+       inline bool streamon() { return v4l2::streamon(m_buftype); }
+       inline bool streamoff() { return v4l2::streamoff(m_buftype); }
 
 private slots:
        void inputChanged(int);
@@ -107,6 +129,8 @@ private:
        int m_col;
        int m_cols;
        bool m_isRadio;
+       bool m_isVbi;
+       __u32 m_buftype;
        __u32 m_audioModes[5];
        struct v4l2_tuner m_tuner;
        struct v4l2_modulator m_modulator;
index 341d812..04a55a8 100644 (file)
@@ -180,6 +180,7 @@ void ApplicationWindow::openrawdev()
 
 void ApplicationWindow::capFrame()
 {
+       __u32 buftype = m_genTab->bufType();
        v4l2_buffer buf;
        int s = 0;
        int err = 0;
@@ -206,7 +207,7 @@ void ApplicationWindow::capFrame()
                break;
 
        case methodMmap:
-               if (!dqbuf_mmap_cap(buf, again)) {
+               if (!dqbuf_mmap(buf, buftype, again)) {
                        error("dqbuf");
                        m_capStartAct->setChecked(false);
                        return;
@@ -230,7 +231,7 @@ void ApplicationWindow::capFrame()
                break;
 
        case methodUser:
-               if (!dqbuf_user_cap(buf, again)) {
+               if (!dqbuf_user(buf, buftype, again)) {
                        error("dqbuf");
                        m_capStartAct->setChecked(false);
                        return;
@@ -280,8 +281,9 @@ void ApplicationWindow::capFrame()
 
 bool ApplicationWindow::startCapture(unsigned buffer_size)
 {
-       unsigned int i;
+       __u32 buftype = m_genTab->bufType();
        v4l2_requestbuffers req;
+       unsigned int i;
 
        memset(&req, 0, sizeof(req));
 
@@ -291,14 +293,14 @@ bool ApplicationWindow::startCapture(unsigned buffer_size)
                return true;
 
        case methodMmap:
-               if (!reqbufs_mmap_cap(req, 3)) {
+               if (!reqbufs_mmap(req, buftype, 3)) {
                        error("Cannot capture");
                        break;
                }
 
                if (req.count < 2) {
                        error("Too few buffers");
-                       reqbufs_mmap_cap(req);
+                       reqbufs_mmap(req, buftype);
                        break;
                }
 
@@ -306,7 +308,7 @@ bool ApplicationWindow::startCapture(unsigned buffer_size)
 
                if (!m_buffers) {
                        error("Out of memory");
-                       reqbufs_mmap_cap(req);
+                       reqbufs_mmap(req, buftype);
                        break;
                }
 
@@ -315,7 +317,7 @@ bool ApplicationWindow::startCapture(unsigned buffer_size)
 
                        memset(&buf, 0, sizeof(buf));
 
-                       buf.type        = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+                       buf.type        = buftype;
                        buf.memory      = V4L2_MEMORY_MMAP;
                        buf.index       = m_nbuffers;
 
@@ -333,26 +335,26 @@ bool ApplicationWindow::startCapture(unsigned buffer_size)
                        }
                }
                for (i = 0; i < m_nbuffers; ++i) {
-                       if (!qbuf_mmap_cap(i)) {
+                       if (!qbuf_mmap(i, buftype)) {
                                perror("VIDIOC_QBUF");
                                goto error;
                        }
                }
-               if (!streamon_cap()) {
+               if (!streamon(buftype)) {
                        perror("VIDIOC_STREAMON");
                        goto error;
                }
                return true;
 
        case methodUser:
-               if (!reqbufs_user_cap(req, 3)) {
+               if (!reqbufs_user(req, buftype, 3)) {
                        error("Cannot capture");
                        break;
                }
 
                if (req.count < 2) {
                        error("Too few buffers");
-                       reqbufs_user_cap(req);
+                       reqbufs_user(req, buftype);
                        break;
                }
 
@@ -373,11 +375,11 @@ bool ApplicationWindow::startCapture(unsigned buffer_size)
                        }
                }
                for (i = 0; i < m_nbuffers; ++i)
-                       if (!qbuf_user_cap(i, m_buffers[i].start, m_buffers[i].length)) {
+                       if (!qbuf_user(i, buftype, m_buffers[i].start, m_buffers[i].length)) {
                                perror("VIDIOC_QBUF");
                                goto error;
                        }
-               if (!streamon_cap()) {
+               if (!streamon(buftype)) {
                        perror("VIDIOC_STREAMON");
                        goto error;
                }
@@ -391,6 +393,7 @@ error:
 
 void ApplicationWindow::stopCapture()
 {
+       __u32 buftype = m_genTab->bufType();
        v4l2_requestbuffers reqbufs;
        v4l2_encoder_cmd cmd;
        unsigned i;
@@ -405,22 +408,22 @@ void ApplicationWindow::stopCapture()
        case methodMmap:
                if (m_buffers == NULL)
                        break;
-               if (!streamoff_cap())
+               if (!streamoff(buftype))
                        perror("VIDIOC_STREAMOFF");
                for (i = 0; i < m_nbuffers; ++i)
                        if (-1 == munmap(m_buffers[i].start, m_buffers[i].length))
                                perror("munmap");
                // Free all buffers.
-               reqbufs_mmap_cap(reqbufs, 1);  // videobuf workaround
-               reqbufs_mmap_cap(reqbufs, 0);
+               reqbufs_mmap(reqbufs, buftype, 1);  // videobuf workaround
+               reqbufs_mmap(reqbufs, buftype, 0);
                break;
 
        case methodUser:
-               if (!streamoff_cap())
+               if (!streamoff(buftype))
                        perror("VIDIOC_STREAMOFF");
                // Free all buffers.
-               reqbufs_user_cap(reqbufs, 1);  // videobuf workaround
-               reqbufs_user_cap(reqbufs, 0);
+               reqbufs_user(reqbufs, buftype, 1);  // videobuf workaround
+               reqbufs_user(reqbufs, buftype, 0);
                for (i = 0; i < m_nbuffers; ++i)
                        free(m_buffers[i].start);
                break;
@@ -465,6 +468,8 @@ void ApplicationWindow::capStart(bool start)
        };
        QImage::Format dstFmt = QImage::Format_RGB888;
        struct v4l2_fract interval;
+       v4l2_pix_format &srcPix = m_capSrcFormat.fmt.pix;
+       v4l2_pix_format &dstPix = m_capDestFormat.fmt.pix;
 
        if (!start) {
                stopCapture();
@@ -477,41 +482,66 @@ void ApplicationWindow::capStart(bool start)
        m_showFrames = m_showFramesAct->isChecked();
        m_frame = m_lastFrame = m_fps = 0;
        m_capMethod = m_genTab->capMethod();
-       g_fmt_cap(m_capSrcFormat);
-       s_fmt(m_capSrcFormat);
-       if (m_genTab->get_interval(interval))
-               set_interval(interval);
+
+       if (m_genTab->isVbi()) {
+               v4l2_format fmt;
+
+               g_fmt_vbi(fmt);
+               srcPix.pixelformat = fmt.fmt.vbi.sample_format;
+               srcPix.width = srcPix.bytesperline =
+                                       fmt.fmt.vbi.samples_per_line;
+               if (fmt.fmt.vbi.flags & V4L2_VBI_INTERLACED) {
+                       srcPix.height = fmt.fmt.vbi.count[0];
+                       srcPix.field = V4L2_FIELD_INTERLACED;
+               } else {
+                       srcPix.height = fmt.fmt.vbi.count[0] + fmt.fmt.vbi.count[1];
+                       srcPix.field = V4L2_FIELD_NONE;
+               }
+               srcPix.sizeimage = srcPix.bytesperline * srcPix.height;
+       } else {
+               g_fmt_cap(m_capSrcFormat);
+               s_fmt(m_capSrcFormat);
+               if (m_genTab->get_interval(interval))
+                       set_interval(interval);
+       }
 
        m_mustConvert = m_showFrames;
        if (m_showFrames) {
-               m_frameData = new unsigned char[m_capSrcFormat.fmt.pix.sizeimage];
+               m_frameData = new unsigned char[srcPix.sizeimage];
                m_capDestFormat = m_capSrcFormat;
-               m_capDestFormat.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB24;
+               dstPix.pixelformat = V4L2_PIX_FMT_RGB24;
 
                for (int i = 0; supported_fmts[i].v4l2_pixfmt; i++) {
-                       if (supported_fmts[i].v4l2_pixfmt == m_capSrcFormat.fmt.pix.pixelformat) {
-                               m_capDestFormat.fmt.pix.pixelformat = supported_fmts[i].v4l2_pixfmt;
+                       if (supported_fmts[i].v4l2_pixfmt == srcPix.pixelformat) {
+                               dstPix.pixelformat = supported_fmts[i].v4l2_pixfmt;
                                dstFmt = supported_fmts[i].qt_pixfmt;
                                m_mustConvert = false;
                                break;
                        }
                }
                if (m_mustConvert) {
+                       v4l2_format copy = m_capSrcFormat;
+
                        v4lconvert_try_format(m_convertData, &m_capDestFormat, &m_capSrcFormat);
                        // v4lconvert_try_format sometimes modifies the source format if it thinks
                        // that there is a better format available. Restore our selected source
                        // format since we do not want that happening.
-                       g_fmt_cap(m_capSrcFormat);
+                       m_capSrcFormat = copy;
                }
 
-               m_capture->setMinimumSize(m_capDestFormat.fmt.pix.width, m_capDestFormat.fmt.pix.height);
-               m_capImage = new QImage(m_capDestFormat.fmt.pix.width, m_capDestFormat.fmt.pix.height, dstFmt);
+               if (m_genTab->isVbi()) {
+                       dstPix.bytesperline = (dstPix.bytesperline + 3) & ~3;
+                       dstPix.sizeimage = dstPix.bytesperline * dstPix.height * 3;
+               }
+               m_capture->setMinimumSize(dstPix.width, dstPix.height);
+               m_capImage = new QImage(dstPix.width, dstPix.height, dstFmt);
                m_capImage->fill(0);
                m_capture->setImage(*m_capImage, "No frame");
                m_capture->show();
        }
+
        statusBar()->showMessage("No frame");
-       if (startCapture(m_capSrcFormat.fmt.pix.sizeimage)) {
+       if (startCapture(srcPix.sizeimage)) {
                m_capNotifier = new QSocketNotifier(fd(), QSocketNotifier::Read, m_tabs);
                connect(m_capNotifier, SIGNAL(activated(int)), this, SLOT(capFrame()));
        }
index cf88eb5..fbdd9e4 100644 (file)
@@ -303,6 +303,13 @@ bool v4l2::g_fmt_out(v4l2_format &fmt)
        return ioctl(VIDIOC_G_FMT, &fmt) >= 0;
 }
 
+bool v4l2::g_fmt_vbi(v4l2_format &fmt)
+{
+       memset(&fmt, 0, sizeof(fmt));
+       fmt.type = V4L2_BUF_TYPE_VBI_CAPTURE;
+       return ioctl(VIDIOC_G_FMT, &fmt) >= 0;
+}
+
 bool v4l2::try_fmt(v4l2_format &fmt)
 {
        fmt.fmt.pix.field = V4L2_FIELD_ANY;
@@ -439,44 +446,44 @@ bool v4l2::enum_frameintervals(v4l2_frmivalenum &frm, __u32 init_pixfmt, __u32 w
        return ioctl(VIDIOC_ENUM_FRAMEINTERVALS, &frm) >= 0;
 }
 
-bool v4l2::reqbufs_user_cap(v4l2_requestbuffers &reqbuf, int count)
+bool v4l2::reqbufs_user(v4l2_requestbuffers &reqbuf, __u32 buftype, int count)
 {
        memset(&reqbuf, 0, sizeof (reqbuf));
-       reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       reqbuf.type = buftype;
        reqbuf.memory = V4L2_MEMORY_USERPTR;
        reqbuf.count = count;
 
        return ioctl(VIDIOC_REQBUFS, &reqbuf) >= 0;
 }
 
-bool v4l2::reqbufs_mmap_cap(v4l2_requestbuffers &reqbuf, int count)
+bool v4l2::reqbufs_mmap(v4l2_requestbuffers &reqbuf, __u32 buftype, int count)
 {
        memset(&reqbuf, 0, sizeof (reqbuf));
-       reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       reqbuf.type = buftype;
        reqbuf.memory = V4L2_MEMORY_MMAP;
        reqbuf.count = count;
 
        return ioctl(VIDIOC_REQBUFS, &reqbuf) >= 0;
 }
 
-bool v4l2::dqbuf_mmap_cap(v4l2_buffer &buf, bool &again)
+bool v4l2::dqbuf_mmap(v4l2_buffer &buf, __u32 buftype, bool &again)
 {
        int res;
 
        memset(&buf, 0, sizeof(buf));
-       buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       buf.type = buftype;
        buf.memory = V4L2_MEMORY_MMAP;
        res = ioctl(VIDIOC_DQBUF, &buf);
        again = res < 0 && errno == EAGAIN;
        return res >= 0 || again;
 }
 
-bool v4l2::dqbuf_user_cap(v4l2_buffer &buf, bool &again)
+bool v4l2::dqbuf_user(v4l2_buffer &buf, __u32 buftype, bool &again)
 {
        int res;
 
        memset(&buf, 0, sizeof(buf));
-       buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       buf.type = buftype;
        buf.memory = V4L2_MEMORY_USERPTR;
        res = ioctl(VIDIOC_DQBUF, &buf);
        again = res < 0 && errno == EAGAIN;
@@ -488,23 +495,23 @@ bool v4l2::qbuf(v4l2_buffer &buf)
        return ioctl(VIDIOC_QBUF, &buf) >= 0;
 }
 
-bool v4l2::qbuf_mmap_cap(int index)
+bool v4l2::qbuf_mmap(int index, __u32 buftype)
 {
        v4l2_buffer buf;
 
        memset(&buf, 0, sizeof(buf));
-       buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       buf.type = buftype;
        buf.memory = V4L2_MEMORY_MMAP;
        buf.index = index;
        return qbuf(buf);
 }
 
-bool v4l2::qbuf_user_cap(int index, void *ptr, int length)
+bool v4l2::qbuf_user(int index, __u32 buftype, void *ptr, int length)
 {
        v4l2_buffer buf;
 
        memset(&buf, 0, sizeof(buf));
-       buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       buf.type = buftype;
        buf.memory = V4L2_MEMORY_USERPTR;
        buf.m.userptr = (unsigned long)ptr;
        buf.length = length;
@@ -512,18 +519,14 @@ bool v4l2::qbuf_user_cap(int index, void *ptr, int length)
        return qbuf(buf);
 }
 
-bool v4l2::streamon_cap()
+bool v4l2::streamon(__u32 buftype)
 {
-       enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
-       return ioctl("Start Capture", VIDIOC_STREAMON, &type);
+       return ioctl("Start Streaming", VIDIOC_STREAMON, &buftype);
 }
 
-bool v4l2::streamoff_cap()
+bool v4l2::streamoff(__u32 buftype)
 {
-       enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
-       return ioctl("Stop Capture", VIDIOC_STREAMOFF, &type);
+       return ioctl("Stop Streaming", VIDIOC_STREAMOFF, &buftype);
 }
 
 bool v4l2::reqbufs_user_out(v4l2_requestbuffers &reqbuf)
index a451268..8067354 100644 (file)
@@ -84,6 +84,7 @@ public:
        bool s_frequency(int freq, bool low = false);
        bool g_fmt_cap(v4l2_format &fmt);
        bool g_fmt_out(v4l2_format &fmt);
+       bool g_fmt_vbi(v4l2_format &fmt);
        bool try_fmt(v4l2_format &fmt);
        bool s_fmt(v4l2_format &fmt);
        bool enum_input(v4l2_input &in, bool init = false, int index = 0);
@@ -98,15 +99,57 @@ public:
        bool enum_framesizes(v4l2_frmsizeenum &frm, __u32 init_pixfmt = 0, int index = 0);
        bool enum_frameintervals(v4l2_frmivalenum &frm, __u32 init_pixfmt = 0, __u32 w = 0, __u32 h = 0, int index = 0);
 
-       bool reqbufs_mmap_cap(v4l2_requestbuffers &reqbuf, int count = 0);
-       bool reqbufs_user_cap(v4l2_requestbuffers &reqbuf, int count = 0);
-       bool dqbuf_mmap_cap(v4l2_buffer &buf, bool &again);
-       bool dqbuf_user_cap(v4l2_buffer &buf, bool &again);
+       bool reqbufs_mmap(v4l2_requestbuffers &reqbuf, __u32 buftype, int count = 0);
+       bool reqbufs_user(v4l2_requestbuffers &reqbuf, __u32 buftype, int count = 0);
+       bool dqbuf_mmap(v4l2_buffer &buf, __u32 buftype, bool &again);
+       bool dqbuf_user(v4l2_buffer &buf, __u32 buftype, bool &again);
        bool qbuf(v4l2_buffer &buf);
-       bool qbuf_mmap_cap(int index);
-       bool qbuf_user_cap(int index, void *ptr, int length);
-       bool streamon_cap();
-       bool streamoff_cap();
+       bool qbuf_mmap(int index, __u32 buftype);
+       bool qbuf_user(int index, __u32 buftype, void *ptr, int length);
+       bool streamon(__u32 buftype);
+       bool streamoff(__u32 buftype);
+
+       inline bool reqbufs_mmap_cap(v4l2_requestbuffers &reqbuf, int count = 0) {
+               return reqbufs_mmap(reqbuf, V4L2_BUF_TYPE_VIDEO_CAPTURE, count);
+       }
+       inline bool reqbufs_user_cap(v4l2_requestbuffers &reqbuf, int count = 0) {
+               return reqbufs_user(reqbuf, V4L2_BUF_TYPE_VIDEO_CAPTURE, count);
+       }
+       inline bool dqbuf_mmap_cap(v4l2_buffer &buf, bool &again) {
+               return dqbuf_mmap(buf, V4L2_BUF_TYPE_VIDEO_CAPTURE, again);
+       }
+       inline bool dqbuf_user_cap(v4l2_buffer &buf, bool &again) {
+               return dqbuf_user(buf, V4L2_BUF_TYPE_VIDEO_CAPTURE, again);
+       }
+       inline bool qbuf_mmap_cap(int index) {
+               return qbuf_mmap(index, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+       }
+       inline bool qbuf_user_cap(int index, void *ptr, int length) {
+               return qbuf_user(index, V4L2_BUF_TYPE_VIDEO_CAPTURE, ptr, length);
+       }
+       inline bool streamon_cap() { return streamon(V4L2_BUF_TYPE_VIDEO_CAPTURE); }
+       inline bool streamoff_cap() { return streamoff(V4L2_BUF_TYPE_VIDEO_CAPTURE); }
+
+       inline bool reqbufs_mmap_vbi(v4l2_requestbuffers &reqbuf, int count = 0) {
+               return reqbufs_mmap(reqbuf, V4L2_BUF_TYPE_VBI_CAPTURE, count);
+       }
+       inline bool reqbufs_user_vbi(v4l2_requestbuffers &reqbuf, int count = 0) {
+               return reqbufs_user(reqbuf, V4L2_BUF_TYPE_VBI_CAPTURE, count);
+       }
+       inline bool dqbuf_mmap_vbi(v4l2_buffer &buf, bool &again) {
+               return dqbuf_mmap(buf, V4L2_BUF_TYPE_VBI_CAPTURE, again);
+       }
+       inline bool dqbuf_user_vbi(v4l2_buffer &buf, bool &again) {
+               return dqbuf_user(buf, V4L2_BUF_TYPE_VBI_CAPTURE, again);
+       }
+       inline bool qbuf_mmap_vbi(int index) {
+               return qbuf_mmap(index, V4L2_BUF_TYPE_VBI_CAPTURE);
+       }
+       inline bool qbuf_user_vbi(int index, void *ptr, int length) {
+               return qbuf_user(index, V4L2_BUF_TYPE_VBI_CAPTURE, ptr, length);
+       }
+       inline bool streamon_vbi() { return streamon(V4L2_BUF_TYPE_VBI_CAPTURE); }
+       inline bool streamoff_vbi() { return streamoff(V4L2_BUF_TYPE_VBI_CAPTURE); }
 
        bool reqbufs_mmap_out(v4l2_requestbuffers &reqbuf, int count = 0);
        bool reqbufs_user_out(v4l2_requestbuffers &reqbuf);