This is an automatic generated email to let you know that the following patch 
were queued at the 
http://git.linuxtv.org/v4l-utils.git tree:

Subject: qv4l2: add raw VBI support.
Author:  Hans Verkuil <[email protected]>
Date:    Fri Jul 20 12:47:56 2012 +0200

Note: the slicing code was copied from zvbi. Eventually I intend to move the
slicing code to a library. It effectively transforms raw VBI into sliced VBI,
so that should make it very easy for applications to handle both raw and
sliced VBI.

Signed-off-by: Hans Verkuil <[email protected]>
(cherry picked from commit c7b253738d45d8f7bebeace186fc733bc700879d)

Signed-off-by: Gregor Jasny <[email protected]>

 utils/qv4l2/.gitignore     |    1 +
 utils/qv4l2/general-tab.h  |    1 -
 utils/qv4l2/qv4l2.cpp      |   20 ++
 utils/qv4l2/qv4l2.h        |    4 +
 utils/qv4l2/qv4l2.pro      |    4 +-
 utils/qv4l2/raw2sliced.cpp |  474 ++++++++++++++++++++++++++++++++++++++++++++
 utils/qv4l2/raw2sliced.h   |   75 +++++++
 utils/qv4l2/vbi-tab.cpp    |  367 ++++++++++++++++++++++++++++++++++
 utils/qv4l2/vbi-tab.h      |   54 +++++
 9 files changed, 997 insertions(+), 3 deletions(-)

---

http://git.linuxtv.org/v4l-utils.git?a=commitdiff;h=4ca8436f31b03370bcd150f3c55db445b2f5ceb1

diff --git a/utils/qv4l2/.gitignore b/utils/qv4l2/.gitignore
index 502d6fe..e7c7867 100644
--- a/utils/qv4l2/.gitignore
+++ b/utils/qv4l2/.gitignore
@@ -2,6 +2,7 @@ Makefile
 moc_capture-win.cpp
 moc_general-tab.cpp
 moc_qv4l2.cpp
+moc_vbi-tab.cpp
 qrc_qv4l2.cpp
 qv4l2
 
diff --git a/utils/qv4l2/general-tab.h b/utils/qv4l2/general-tab.h
index 8e4af75..e2681f4 100644
--- a/utils/qv4l2/general-tab.h
+++ b/utils/qv4l2/general-tab.h
@@ -166,7 +166,6 @@ private:
        QComboBox *m_frameInterval;
        QComboBox *m_vidOutFormats;
        QComboBox *m_capMethods;
-       QGridLayout *m_layout;
 };
 
 #endif
diff --git a/utils/qv4l2/qv4l2.cpp b/utils/qv4l2/qv4l2.cpp
index 749e421..087f782 100644
--- a/utils/qv4l2/qv4l2.cpp
+++ b/utils/qv4l2/qv4l2.cpp
@@ -19,6 +19,7 @@
 
 #include "qv4l2.h"
 #include "general-tab.h"
+#include "vbi-tab.h"
 #include "capture-win.h"
 
 #include <QToolBar>
@@ -146,6 +147,11 @@ void ApplicationWindow::setDevice(const QString &device, 
bool rawOpen)
        m_genTab = new GeneralTab(device, *this, 4, w);
        m_tabs->addTab(w, "General");
        addTabs();
+       if (caps() & (V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_CAPTURE)) {
+               w = new QWidget(m_tabs);
+               m_vbiTab = new VbiTab(w);
+               m_tabs->addTab(w, "VBI");
+       }
        if (QWidget *current = m_tabs->currentWidget()) {
                current->show();
        }
@@ -239,9 +245,16 @@ void ApplicationWindow::capVbiFrame()
                }
        }
 
+       struct v4l2_sliced_vbi_format sfmt;
+       struct v4l2_sliced_vbi_data sdata[m_vbiHandle.count[0] + 
m_vbiHandle.count[1]];
+
+       vbi_parse(&m_vbiHandle, data, &sfmt, sdata);
+
        if (m_capMethod != methodRead)
                qbuf(buf);
 
+       m_vbiTab->slicedData(sdata);
+
        QString status, curStatus;
        struct timeval tv, res;
 
@@ -572,12 +585,19 @@ void ApplicationWindow::capStart(bool start)
 
        if (m_genTab->isVbi()) {
                v4l2_format fmt;
+               v4l2_std_id std;
 
                g_fmt_vbi(fmt);
                if (fmt.fmt.vbi.sample_format != V4L2_PIX_FMT_GREY) {
                        error("non-grey pixelformat not supported for VBI\n");
                        return;
                }
+               g_std(std);
+               if (!vbi_prepare(&m_vbiHandle, &fmt.fmt.vbi, std)) {
+                       error("no services possible\n");
+                       return;
+               }
+               m_vbiTab->rawFormat(fmt.fmt.vbi);
                m_vbiWidth = fmt.fmt.vbi.samples_per_line;
                if (fmt.fmt.vbi.flags & V4L2_VBI_INTERLACED)
                        m_vbiHeight = fmt.fmt.vbi.count[0];
diff --git a/utils/qv4l2/qv4l2.h b/utils/qv4l2/qv4l2.h
index 6ec251a..758e6f4 100644
--- a/utils/qv4l2/qv4l2.h
+++ b/utils/qv4l2/qv4l2.h
@@ -31,10 +31,12 @@
 #include <vector>
 
 #include "v4l2-api.h"
+#include "raw2sliced.h"
 
 class QComboBox;
 class QSpinBox;
 class GeneralTab;
+class VbiTab;
 class QCloseEvent;
 class CaptureWin;
 
@@ -147,6 +149,7 @@ private:
        void updateFreqChannel();
 
        GeneralTab *m_genTab;
+       VbiTab *m_vbiTab;
        QAction *m_capStartAct;
        QAction *m_showFramesAct;
        QString m_filename;
@@ -163,6 +166,7 @@ private:
        int m_vbiSize;
        unsigned m_vbiWidth;
        unsigned m_vbiHeight;
+       struct vbi_handle m_vbiHandle;
        unsigned m_frame;
        unsigned m_lastFrame;
        unsigned m_fps;
diff --git a/utils/qv4l2/qv4l2.pro b/utils/qv4l2/qv4l2.pro
index 87cf097..144d875 100644
--- a/utils/qv4l2/qv4l2.pro
+++ b/utils/qv4l2/qv4l2.pro
@@ -7,8 +7,8 @@ INCLUDEPATH += . ../libv4l2util ../../lib/include ../../include
 CONFIG += debug
 
 # Input
-HEADERS += qv4l2.h general-tab.h v4l2-api.h capture-win.h
-SOURCES += qv4l2.cpp general-tab.cpp ctrl-tab.cpp v4l2-api.cpp capture-win.cpp
+HEADERS += qv4l2.h general-tab.h v4l2-api.h capture-win.h vbi-tab.h 
raw2sliced.h
+SOURCES += qv4l2.cpp general-tab.cpp ctrl-tab.cpp v4l2-api.cpp capture-win.cpp 
vbi-tab.cpp raw2sliced.cpp
 LIBS += -L../../lib/libv4l2 -lv4l2 -L../../lib/libv4lconvert -lv4lconvert -lrt 
-L../libv4l2util -lv4l2util
 
 RESOURCES += qv4l2.qrc
diff --git a/utils/qv4l2/raw2sliced.cpp b/utils/qv4l2/raw2sliced.cpp
new file mode 100644
index 0000000..6edbc04
--- /dev/null
+++ b/utils/qv4l2/raw2sliced.cpp
@@ -0,0 +1,474 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#include <assert.h>
+#include <unistd.h>
+#include <sys/fcntl.h>
+
+#include "raw2sliced.h"
+
+/*
+ * The slicing code was copied from libzvbi. The original copyright notice is:
+ *
+ * Copyright (C) 2000-2004 Michael H. Schimek
+ *
+ * The vbi_prepare/vbi_parse functions are:
+ *
+ * Copyright (C) 2012 Hans Verkuil <[email protected]>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the 
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02110-1301  USA.
+ */
+
+// Modulation used for VBI data transmission.
+enum vbi_modulation {
+       /*
+        * The data is 'non-return to zero' coded, logical '1' bits
+        * are described by high sample values, logical '0' bits by
+        * low values. The data is last significant bit first transmitted.
+        */
+       VBI_MODULATION_NRZ_LSB,
+       /*
+        * The data is 'bi-phase' coded. Each data bit is described
+        * by two complementary signalling elements, a logical '1'
+        * by a sequence of '10' elements, a logical '0' by a '01'
+        * sequence. The data is last significant bit first transmitted.
+        */
+       VBI_MODULATION_BIPHASE_LSB,
+       /*
+        * 'Bi-phase' coded, most significant bit first transmitted.
+        */
+       VBI_MODULATION_BIPHASE_MSB
+};
+
+// Service definition struct
+struct service {
+       __u16 service;
+       v4l2_std_id std;
+       /*
+        * Most scan lines used by the data service, first and last
+        * line of first and second field. ITU-R numbering scheme.
+        * Zero if no data from this field, requires field sync.
+        */
+       int             first[2];
+        int            last[2];
+
+       /*
+        * Leading edge hsync to leading edge first CRI one bit,
+        * half amplitude points, in nanoseconds.
+        */
+       unsigned int            offset;
+
+       unsigned int            cri_rate;       /* Hz */
+       unsigned int            bit_rate;       /* Hz */
+
+       /* Clock Run In and FRaming Code, LSB last txed bit of FRC. */
+       unsigned int            cri_frc;
+
+       /* CRI and FRC bits significant for identification. */
+       unsigned int            cri_frc_mask;
+
+       /*
+        * Number of significat cri_bits (at cri_rate),
+        * frc_bits (at bit_rate).
+        */
+       unsigned int            cri_bits;
+       unsigned int            frc_bits;
+
+       unsigned int            payload;        /* bits */
+       enum vbi_modulation     modulation;
+};
+
+// Supported services
+static const struct service services[] = {
+       {
+               V4L2_SLICED_TELETEXT_B,
+               V4L2_STD_625_50,
+               { 6, 318 },
+               { 22, 335 },
+               10300, 6937500, 6937500, /* 444 x FH */
+               0x00AAAAE4, 0xFFFF, 18, 6, 42 * 8,
+               VBI_MODULATION_NRZ_LSB,
+       }, {
+               V4L2_SLICED_VPS,
+               V4L2_STD_PAL_BG,
+               { 16, 0 },
+               { 16, 0 },
+               12500, 5000000, 2500000, /* 160 x FH */
+               0xAAAA8A99, 0xFFFFFF, 32, 0, 13 * 8,
+               VBI_MODULATION_BIPHASE_MSB,
+       }, {
+               V4L2_SLICED_WSS_625,
+               V4L2_STD_625_50,
+               { 23, 0 },
+               { 23, 0 },
+               11000, 5000000, 833333, /* 160/3 x FH */
+               /* ...1000 111 / 0 0011 1100 0111 1000 0011 111x */
+               /* ...0010 010 / 0 1001 1001 0011 0011 1001 110x */     
+               0x8E3C783E, 0x2499339C, 32, 0, 14 * 1,
+               VBI_MODULATION_BIPHASE_LSB,
+       }, {
+               V4L2_SLICED_CAPTION_525,
+               V4L2_STD_525_60,
+               { 21, 284 },
+               { 21, 284 },
+               10500, 1006976, 503488, /* 32 x FH */
+               /* Test of CRI bits has been removed to handle the
+                  incorrect signal observed by Rich Kandel (see
+                  _VBI_RAW_SHIFT_CC_CRI). */
+               0x03, 0x0F, 4, 0, 2 * 8,
+               VBI_MODULATION_NRZ_LSB,
+       }
+};
+
+static const unsigned int DEF_THR_FRAC = 9;
+static const unsigned int LP_AVG = 4;
+
+static inline unsigned int vbi_sample(const uint8_t *raw, unsigned i)
+{
+       unsigned ii = i >> 8;
+       unsigned int raw0 = raw[ii];
+       unsigned int raw1 = raw[ii + 1];
+
+       return (int)(raw1 - raw0) * (i & 255) + (raw0 << 8);
+}
+
+// Slice the raw data
+static bool low_pass_bit_slicer_Y8(struct vbi_bit_slicer *bs, uint8_t *buffer, 
const uint8_t *raw)
+{
+       unsigned int i, j;
+       unsigned int cl;        /* clock */
+       unsigned int thresh0;   /* old 0/1 threshold */
+       unsigned int tr;        /* current threshold */
+       unsigned int c;         /* current byte */
+       unsigned int t;         /* t = raw[0] * j + raw[1] * (1 - j) */
+       unsigned int raw0;      /* oversampling temporary */
+       unsigned int raw1;
+       unsigned char b1;       /* previous bit */
+       unsigned int oversampling = 4;
+
+       raw += bs->skip;
+
+       thresh0 = bs->thresh;
+
+       c = 0;
+       cl = 0;
+       b1 = 0;
+
+       for (i = bs->cri_samples; i > 0; --i) {
+               int r;
+               tr = bs->thresh >> bs->thresh_frac;
+               raw0 = raw[0];
+               raw1 = raw[1];
+               raw1 -= raw0;
+               r = raw1;
+               bs->thresh += (int)(raw0 - tr) * (r < 0 ? -r : r);
+               t = raw0 * oversampling;
+
+               for (j = oversampling; j > 0; --j) {
+                       unsigned int tavg;
+                       unsigned char b; /* current bit */
+
+                       tavg = (t + (oversampling / 2)) / oversampling;
+                       b = (tavg >= tr);
+
+                       if ((b ^ b1)) {
+                               cl = bs->oversampling_rate >> 1;
+                       } else {
+                               cl += bs->cri_rate;
+
+                               if (cl >= bs->oversampling_rate) {
+                                       cl -= bs->oversampling_rate;
+                                       c = c * 2 + b;
+                                       if ((c & bs->cri_mask) == bs->cri)
+                                               break;
+                               }
+                       }
+
+                       b1 = b;
+
+                       if (oversampling > 1)
+                               t += raw1;
+               }
+               if (j)
+                       break;
+
+               raw++;
+       }
+       if (i == 0) {
+               bs->thresh = thresh0;
+               return false;
+       }
+
+       i = bs->phase_shift; /* current bit position << 8 */
+       tr *= 256;
+       c = 0;
+
+       for (j = bs->frc_bits; j > 0; --j) {
+               raw0 = vbi_sample(raw, i);
+               c = c * 2 + (raw0 >= tr);
+               i += bs->step; /* next bit */
+       }
+
+       if (c != bs->frc) {
+               bs->thresh = thresh0;
+               return false;
+       }
+
+       c = 0;
+
+       if (bs->endian) {
+               /* bitwise, lsb first */
+               for (j = 0; j < bs->payload; ++j) {
+                       raw0 = vbi_sample(raw, i);
+                       c = (c >> 1) + ((raw0 >= tr) << 7);
+                       i += bs->step;
+                       if ((j & 7) == 7)
+                               *buffer++ = c;
+               }
+               *buffer = c >> ((8 - bs->payload) & 7);
+       } else {
+               /* bitwise, msb first */
+               for (j = 0; j < bs->payload; ++j) {
+                       raw0 = vbi_sample(raw, i);
+                       c = c * 2 + (raw0 >= tr);
+                       i += bs->step;
+                       if ((j & 7) == 7)
+                               *buffer++ = c;
+               }
+               *buffer = c & ((1 << (bs->payload & 7)) - 1);
+       }
+
+       return true;
+}
+
+// Prepare the vbi_bit_slicer struct
+static bool vbi_bit_slicer_prepare(struct vbi_bit_slicer *bs,
+               const struct service *s,
+               const struct v4l2_vbi_format *fmt)
+{
+       unsigned int sample_offset = 0;
+       unsigned int c_mask;
+       unsigned int f_mask;
+       unsigned int min_samples_per_bit;
+       unsigned int oversampling;
+       unsigned int data_bits;
+       unsigned int data_samples;
+       unsigned int cri, cri_mask, frc;
+       unsigned int cri_end;
+       unsigned int cri_samples;
+       unsigned int skip;
+
+       assert (s->cri_bits <= 32);
+       assert (s->frc_bits <= 32);
+       assert (s->payload <= 32767);
+       assert (fmt->samples_per_line <= 32767);
+
+       cri = s->cri_frc >> s->frc_bits;
+       cri_mask = s->cri_frc_mask >> s->frc_bits;
+       frc = (s->cri_frc & ((1U << s->frc_bits) - 1));
+       if (s->cri_rate > fmt->sampling_rate) {
+               fprintf(stderr, "cri_rate %u > sampling_rate %u.\n",
+                        s->cri_rate, fmt->sampling_rate);
+               return false;
+       }
+
+       if (s->bit_rate > fmt->sampling_rate) {
+               fprintf(stderr, "bit_rate %u > sampling_rate %u.\n",
+                        s->bit_rate, fmt->sampling_rate);
+               return false;
+       }
+
+       min_samples_per_bit = fmt->sampling_rate / ((s->cri_rate > s->bit_rate) 
? s->cri_rate : s->bit_rate);
+
+       c_mask = (s->cri_bits == 32) ? ~0U : (1U << s->cri_bits) - 1;
+       f_mask = (s->frc_bits == 32) ? ~0U : (1U << s->frc_bits) - 1;
+
+       oversampling = 4;
+       skip = 0;
+
+       /* 0-1 threshold, start value. */
+       bs->thresh = 105 << DEF_THR_FRAC;
+       bs->thresh_frac = DEF_THR_FRAC;
+
+       if (min_samples_per_bit > (3U << (LP_AVG - 1))) {
+               oversampling = 1;
+               bs->thresh <<= LP_AVG - 2;
+               bs->thresh_frac += LP_AVG - 2;
+       }
+
+       bs->skip = sample_offset + skip;
+
+       bs->cri_mask = cri_mask & c_mask;
+       bs->cri = cri & bs->cri_mask;
+
+       /* We stop searching for CRI when CRI, FRC and payload
+          cannot possibly fit anymore. Additionally this eliminates
+          a data end check in the payload loop. */
+       cri_samples = (fmt->sampling_rate * (int64_t) s->cri_bits) / 
s->cri_rate;
+
+       data_bits = s->payload + s->frc_bits;
+       data_samples = (fmt->sampling_rate * (int64_t) data_bits) / s->bit_rate;
+
+       if ((fmt->offset > fmt->samples_per_line)
+           || ((cri_samples + data_samples)
+               > (fmt->samples_per_line - fmt->offset))) {
+               /*fprintf(stderr,
+                        "%u samples_per_line too small for "
+                        "sample_offset %u + %u cri_bits (%u samples) "
+                        "+ %u frc_bits and %u payload "
+                        "(%u samples).\n",
+                        fmt->samples_per_line, fmt->offset,
+                        s->cri_bits, cri_samples,
+                        s->frc_bits, s->payload, data_samples);*/
+       }
+       if ((sample_offset > fmt->samples_per_line)
+           || ((cri_samples + data_samples)
+               > (fmt->samples_per_line - sample_offset))) {
+               /*
+               fprintf(stderr,
+                        "%u samples_per_line too small for "
+                        "sample_offset %u + %u cri_bits (%u samples) "
+                        "+ %u frc_bits and %u payload "
+                        "(%u samples).\n",
+                        fmt->samples_per_line, sample_offset,
+                        s->cri_bits, cri_samples,
+                        s->frc_bits, s->payload, data_samples);*/
+               return false;
+       }
+
+       cri_end = fmt->samples_per_line - data_samples;
+
+       bs->cri_samples = cri_end - sample_offset;
+       bs->cri_rate = s->cri_rate;
+
+       bs->oversampling_rate = fmt->sampling_rate * oversampling;
+
+       bs->frc = frc & f_mask;
+       bs->frc_bits = s->frc_bits;
+
+       /* Payload bit distance in 1/256 raw samples. */
+       bs->step = (fmt->sampling_rate * (int64_t) 256) / s->bit_rate;
+
+       bs->payload = s->payload;
+       bs->endian = 1;
+
+       switch (s->modulation) {
+       case VBI_MODULATION_NRZ_LSB:
+               bs->phase_shift = (int)
+                       (fmt->sampling_rate * 256.0 / s->cri_rate * .5
+                        + bs->step * .5 + 128);
+               break;
+
+       case VBI_MODULATION_BIPHASE_MSB:
+               bs->endian = 0;
+               /* fall through */
+       case VBI_MODULATION_BIPHASE_LSB:
+               /* Phase shift between the NRZ modulated CRI and the
+                  biphase modulated rest. */
+               bs->phase_shift = (int)
+                       (fmt->sampling_rate * 256.0 / s->cri_rate * .5
+                        + bs->step * .25 + 128);
+               break;
+       }
+       return true;
+}
+
+bool vbi_prepare(struct vbi_handle *vh, const struct v4l2_vbi_format *fmt, 
v4l2_std_id std)
+{
+       unsigned i;
+
+       memset(vh, 0, sizeof(*vh));
+       // Sanity check
+       if ((std & V4L2_STD_525_60) && (std & V4L2_STD_625_50))
+               return false;
+       vh->start_of_field_2 = (std & V4L2_STD_525_60) ? 263 : 313;
+       vh->stride = fmt->samples_per_line;
+       vh->interlaced = fmt->flags & V4L2_VBI_INTERLACED;
+       vh->start[0] = fmt->start[0];
+       vh->start[1] = fmt->start[1];
+       vh->count[0] = fmt->count[0];
+       vh->count[1] = fmt->count[1];
+       for (i = 0; i < sizeof(services) / sizeof(services[0]); i++) {
+               const struct service *s = services + i;
+               struct vbi_bit_slicer *slicer = vh->slicers + vh->services;
+
+               if (!(std & s->std))
+                       continue;
+               if (s->last[0] < vh->start[0] &&
+                   s->last[1] < vh->start[1])
+                       continue;
+               if (s->first[0] >= vh->start[0] + vh->count[0] &&
+                   s->first[1] >= vh->start[1] + vh->count[1])
+                       continue;
+               slicer->service = i;
+               vbi_bit_slicer_prepare(slicer, s, fmt);
+               vh->services++;
+       }
+       return vh->services;
+}
+
+void vbi_parse(struct vbi_handle *vh, const unsigned char *buf,
+               struct v4l2_sliced_vbi_format *vbi,
+               struct v4l2_sliced_vbi_data *data)
+{
+       const unsigned char *p;
+       unsigned i;
+       int y;
+
+       memset(vbi, 0, sizeof(*vbi));
+       vbi->io_size = sizeof(*data) * (vh->count[0] + vh->count[1]);
+       for (i = 0; i < vh->services; i++) {
+               const struct service *s = services + vh->slicers[i].service;
+
+               for (y = s->first[0] - vh->start[0]; y <= s->last[0] - 
vh->start[0]; y++) {
+                       if (y < 0 || y >= vh->count[0])
+                               continue;
+                       if (vh->interlaced)
+                               p = buf + vh->stride * y * 2;
+                       else
+                               p = buf + vh->stride * y;
+                       data[y].id = data[y].reserved = 0;
+                       if (low_pass_bit_slicer_Y8(vh->slicers + i, 
data[y].data, p)) {
+                               vbi->service_set |= s->service;
+                               vbi->service_lines[0][y + vh->start[0]] = 
s->service;
+                               data[y].id = s->service;
+                               data[y].field = 0;
+                               data[y].line = y + vh->start[0];
+                       }
+               }
+
+               for (y = s->first[1] - vh->start[1]; y <= s->last[1] - 
vh->start[1]; y++) {
+                       unsigned yy = y + vh->count[0];
+
+                       if (y < 0 || y >= vh->count[1])
+                               continue;
+                       if (vh->interlaced)
+                               p = buf + vh->stride * y * 2 + 1;
+                       else
+                               p = buf + vh->stride * yy;
+                       data[yy].id = data[yy].reserved = 0;
+                       if (low_pass_bit_slicer_Y8(vh->slicers + i, 
data[yy].data, p)) {
+                               vbi->service_set |= s->service;
+                               vbi->service_lines[1][y + vh->start[1] - 
vh->start_of_field_2] = s->service;
+                               data[yy].id = s->service;
+                               data[yy].field = 1;
+                               data[yy].line = y + vh->start[1] - 
vh->start_of_field_2;
+                       }
+               }
+       }
+}
diff --git a/utils/qv4l2/raw2sliced.h b/utils/qv4l2/raw2sliced.h
new file mode 100644
index 0000000..bcc134c
--- /dev/null
+++ b/utils/qv4l2/raw2sliced.h
@@ -0,0 +1,75 @@
+/*
+ * Raw VBI to sliced VBI parser.
+ *
+ * The slicing code was copied from libzvbi. The original copyright notice is:
+ *
+ * Copyright (C) 2000-2004 Michael H. Schimek
+ *
+ * The vbi_prepare/vbi_parse functions are:
+ *
+ * Copyright (C) 2012 Hans Verkuil <[email protected]>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the 
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02110-1301  USA.
+ */
+
+#ifndef _RAW2SLICED_H
+#define _RAW2SLICED_H
+
+#include <linux/videodev2.h>
+
+#define VBI_MAX_SERVICES (3)
+
+// Bit slicer internal struct
+struct vbi_bit_slicer {
+       unsigned int            service;
+       unsigned int            cri;
+       unsigned int            cri_mask;
+       unsigned int            thresh;
+       unsigned int            thresh_frac;
+       unsigned int            cri_samples;
+       unsigned int            cri_rate;
+       unsigned int            oversampling_rate;
+       unsigned int            phase_shift;
+       unsigned int            step;
+       unsigned int            frc;
+       unsigned int            frc_bits;
+       unsigned int            payload;
+       unsigned int            endian;
+       unsigned int            skip;
+};
+
+struct vbi_handle {
+       unsigned services;
+       unsigned start_of_field_2;
+       unsigned stride;
+       bool interlaced;
+       int start[2];
+       int count[2];
+       struct vbi_bit_slicer slicers[VBI_MAX_SERVICES];
+};
+
+// Fills in vbi_handle based on the standard and VBI format
+// Returns true if one or more services are valid for the fmt/std combination.
+bool vbi_prepare(struct vbi_handle *vh,
+               const struct v4l2_vbi_format *fmt, v4l2_std_id std);
+
+// Parses the raw buffer and fills in sliced_vbi_format and _data.
+// data must be an array of count[0] + count[1] v4l2_sliced_vbi_data structs.
+void vbi_parse(struct vbi_handle *vh, const unsigned char *buf,
+               struct v4l2_sliced_vbi_format *vbi,
+               struct v4l2_sliced_vbi_data *data);
+
+#endif
diff --git a/utils/qv4l2/vbi-tab.cpp b/utils/qv4l2/vbi-tab.cpp
new file mode 100644
index 0000000..92d0703
--- /dev/null
+++ b/utils/qv4l2/vbi-tab.cpp
@@ -0,0 +1,367 @@
+/* qv4l2: a control panel controlling v4l2 devices.
+ *
+ * Copyright (C) 2012 Hans Verkuil <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Vbi Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Vbi Public License for more details.
+ *
+ * You should have received a copy of the GNU Vbi Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
USA.
+ */
+
+
+#include <stdint.h>
+#include "vbi-tab.h"
+#include <QTableWidget>
+
+#include <stdio.h>
+#include <errno.h>
+
+VbiTab::VbiTab(QWidget *parent) :
+       QGridLayout(parent)
+{
+       QStringList q;
+
+       m_tableF1 = new QTableWidget(1, 1, parent);
+       m_tableF2 = new QTableWidget(1, 1, parent);
+       q.append("Field 1");
+       m_tableF1->setHorizontalHeaderLabels(q);
+       q.clear();
+       q.append("Field 2");
+       m_tableF2->setHorizontalHeaderLabels(q);
+       q.clear();
+       q.append("Line");
+       m_tableF1->setVerticalHeaderLabels(q);
+       m_tableF2->setVerticalHeaderLabels(q);
+       addWidget(m_tableF1, 0, 0);
+       addWidget(m_tableF2, 0, 1);
+}
+
+void VbiTab::rawFormat(const v4l2_vbi_format &fmt)
+{
+       QTableWidgetItem *item;
+       QStringList q;
+       unsigned i;
+
+       m_tableF1->setRowCount(fmt.count[0]);
+       m_tableF2->setRowCount(fmt.count[1]);
+       for (i = 0; i < fmt.count[0]; i++) {
+               item = new QTableWidgetItem();
+               item->setFlags(Qt::ItemIsEnabled);
+               m_tableF1->setItem(i, 0, item);
+               q.append("Line " + QString::number(i + fmt.start[0]));
+       }
+       m_tableF1->setVerticalHeaderLabels(q);
+       q.clear();
+       for (i = 0; i < fmt.count[1]; i++) {
+               item = new QTableWidgetItem();
+               item->setFlags(Qt::ItemIsEnabled);
+               m_tableF2->setItem(i, 0, item);
+               q.append("Line " + QString::number(i + fmt.start[1]));
+       }
+       m_tableF2->setVerticalHeaderLabels(q);
+}
+
+static const char *formats[] = {
+       "Full format 4:3, 576 lines",
+       "Letterbox 14:9 centre, 504 lines",
+       "Letterbox 14:9 top, 504 lines",
+       "Letterbox 16:9 centre, 430 lines",
+       "Letterbox 16:9 top, 430 lines",
+       "Letterbox > 16:9 centre",
+       "Full format 14:9 centre, 576 lines",
+       "Anamorphic 16:9, 576 lines"
+};
+
+static const char *subtitles[] = {
+       "none",
+       "in active image area",
+       "out of active image area",
+       "?"
+};
+
+static void decode_wss(QTableWidgetItem *item, const struct 
v4l2_sliced_vbi_data *s)
+{
+       unsigned char parity;
+       int wss;
+
+       wss = s->data[0] | (s->data[1] << 8);
+
+       parity = wss & 15;
+       parity ^= parity >> 2;
+       parity ^= parity >> 1;
+
+       if (!(parity & 1)) {
+               item->setStatusTip("");
+               return;
+       }
+
+       item->setToolTip(QString(formats[wss & 7]) + "\n" + 
+                       ((wss & 0x10) ? "Film" : "Camera") + " mode\n" +
+                       ((wss & 0x20) ? "Motion Adaptive ColorPlus" : 
"Standard") + " color coding\n" +
+                       "Helper signals " + ((wss & 0x40) ? "" : "not ") + 
"present\n" +
+                       ((wss & 0x0100) ? "Teletext subtitles\n" : "") +
+                       "Open subtitles: " + subtitles[(wss >> 9) & 3] + "\n" +
+                       ((wss & 0x0800) ? "Surround sound\n" : "") +
+                       "Copyright " + ((wss & 0x1000) ? "asserted\n" : 
"unknown\n") +
+                       "Copying " + ((wss & 0x2000) ? "restricted" : "not 
restricted"));
+}
+
+const uint8_t vbi_bit_reverse[256] = {
+       0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
+       0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
+       0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
+       0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
+       0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
+       0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
+       0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
+       0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
+       0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
+       0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
+       0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
+       0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
+       0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
+       0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
+       0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
+       0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
+       0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
+       0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
+       0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
+       0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
+       0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
+       0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
+       0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
+       0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
+       0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
+       0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
+       0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
+       0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
+       0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
+       0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
+       0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
+       0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
+};
+
+#define printable(c) ((((c) & 0x7F) < 0x20 || ((c) & 0x7F) > 0x7E) ? '.' : 
((c) & 0x7F))
+
+#define PIL(day, mon, hour, min) \
+       (((day) << 15) + ((mon) << 11) + ((hour) << 6) + ((min) << 0))
+
+static QString dump_pil(int pil)
+{
+       int day, mon, hour, min;
+       char buf[50];
+
+       day = pil >> 15;
+       mon = (pil >> 11) & 0xF;
+       hour = (pil >> 6) & 0x1F;
+       min = pil & 0x3F;
+
+       if (pil == PIL(0, 15, 31, 63))
+               return QString("PDC: Timer-control (no PDC)");
+       if (pil == PIL(0, 15, 30, 63))
+               return QString("PDC: Recording inhibit/terminate");
+       if (pil == PIL(0, 15, 29, 63))
+               return QString("PDC: Interruption");
+       if (pil == PIL(0, 15, 28, 63))
+               return QString("PDC: Continue");
+       if (pil == PIL(31, 15, 31, 63))
+               return QString("PDC: No time");
+       sprintf(buf, "PDC: 20XX-%02d-%02d %02d:%02d",
+                      mon, day, hour, min);
+       return buf;
+}
+
+static const char *pcs_text[] = {
+       "unknown",
+       "mono",
+       "stereo",
+       "dual sound",
+};
+
+static const char *pty_text[] = {
+       /* 0x00 - 0x0f */
+       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+       
+       /* 0x10 - 0x1f */
+       "movie (general)",
+       "detective/thriller",
+       "adventure/western/war",
+       "science fiction/fantasy/horror",
+       "comedy",
+       "soap/melodrama/folklore",
+       "romance",
+       "serious/classical/religious/historical drama",
+       "adult movie",
+       NULL, NULL, NULL, NULL, NULL, NULL,
+       "user defined",
+
+       /* 0x20 - 0x2f */
+       "news/current affairs (general)",
+       "news/weather report",
+       "news magazine",
+       "documentary",
+       "discussion/interview/debate",
+       "social/political issues/economics (general)",
+       "magazines/reports/documentary",
+       "economics/social advisory",
+       "remarkable people",
+       NULL, NULL, NULL, NULL, NULL, NULL,
+       "user defined",
+
+       /* 0x30 - 0x3f */
+       "show/game show (general)",
+       "game show/quiz/contest",
+       "variety show",
+       "talk show",
+       "leisure hobbies (general)",
+       "tourism/travel",
+       "handicraft",
+       "motoring",
+       "fitness and health",
+       "cooking",
+       "advertisement/shopping",
+       NULL, NULL, NULL, NULL,
+       "alarm/emergency identification",
+
+       /* 0x40 - 0x4f */
+       "sports (general)",
+       "special events (Olympic Games, World Cup etc.)",
+       "sports magazines",
+       "football/soccer",
+       "tennis/squash",
+       "team sports (excluding football)",
+       "athletics",
+       "motor sport",
+       "water sport",
+       "winter sports",
+       "equestrian",
+       "martial sports",
+       "local sports",
+       NULL, NULL,
+       "user defined",
+
+       /* 0x50 - 0x5f */
+       "children's/youth programmes (general)",
+       "pre-school children's programmes",
+       "entertainment programmes for 6 to 14",
+       "entertainment programmes for 10 to 16",
+       "informational/educational/school programmes",
+       "cartoons/puppets",
+       "education/science/factual topics (general)",
+       "nature/animals/environment",
+       "technology/natural sciences",
+       "medicine/physiology/psychology",
+       "foreign countries/expeditions",
+       "social/spiritual sciences",
+       "further education",
+       "languages",
+       NULL,
+       "user defined",
+
+       /* 0x60 - 0x6f */
+       "music/ballet/dance (general)",
+       "rock/pop",
+       "serious music/classical music",
+       "folk/traditional music",
+       "jazz",
+       "musical/opera",
+       "ballet",
+       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+       "user defined",
+
+       /* 0x70 - 0x7f */
+       "arts/culture (without music, general)",
+       "performing arts",
+       "fine arts",
+       "religion",
+       "popular culture/traditional arts",
+       "literature",
+       "film/cinema",
+       "experimental film/video",
+       "broadcasting/press",
+       "new media",
+       "arts/culture magazines",
+       "fashion",
+       NULL, NULL, NULL,
+       "user defined",
+};
+
+static void decode_vps(QTableWidgetItem *item, const struct 
v4l2_sliced_vbi_data *s)
+{
+       QString q;
+       int cni, pcs, pty, pil;
+       const char *pty_txt;
+       const unsigned char *buf = s->data;
+
+       pcs = buf[2] >> 6;
+
+       cni = +((buf[10] & 3) << 10)
+           + ((buf[11] & 0xC0) << 2)
+           + ((buf[8] & 0xC0) << 0)
+           + (buf[11] & 0x3F);
+
+       pil = ((buf[8] & 0x3F) << 14) + (buf[9] << 6) + (buf[10] >> 2);
+
+       pty = buf[12];
+       if (pty > 0x7f)
+               pty_txt = "service specific";
+       else if (pty < 0x10)
+               pty_txt = "undefined content";
+       else
+               pty_txt = pty_text[pty];
+       if (pty_txt == NULL)
+               pty_txt = "reserved for future use";
+
+       q = "CNI: 0x";
+       q += QString::number(cni, 16) + " PCS: " + pcs_text[pcs] + " PTY: " + 
pty_txt + "\n";
+       item->setToolTip(q + dump_pil(pil));
+}
+
+static void setItem(QTableWidgetItem *item, const v4l2_sliced_vbi_data *data)
+{
+       switch (data->id) {
+       case V4L2_SLICED_TELETEXT_B:
+               item->setText("TXT");
+               break;
+       case V4L2_SLICED_VPS:
+               item->setText("VPS");
+               decode_vps(item, data);
+               break;
+       case V4L2_SLICED_CAPTION_525:
+               item->setText("CC");
+               break;
+       case V4L2_SLICED_WSS_625:
+               item->setText("WSS");
+               decode_wss(item, data);
+               break;
+       default:
+               item->setText("");
+               break;
+       }
+}
+
+void VbiTab::slicedData(const v4l2_sliced_vbi_data *data)
+{
+       int i;
+
+       for (i = 0; i < m_tableF1->rowCount(); i++) {
+               QTableWidgetItem *item = m_tableF1->item(i, 0);
+
+               setItem(item, data + i);
+       }
+       for (i = 0; i < m_tableF2->rowCount(); i++) {
+               QTableWidgetItem *item = m_tableF2->item(i, 0);
+
+               setItem(item, data + i + m_tableF1->rowCount());
+       }
+}
diff --git a/utils/qv4l2/vbi-tab.h b/utils/qv4l2/vbi-tab.h
new file mode 100644
index 0000000..7950e0d
--- /dev/null
+++ b/utils/qv4l2/vbi-tab.h
@@ -0,0 +1,54 @@
+/* qv4l2: a control panel controlling v4l2 devices.
+ *
+ * Copyright (C) 2012 Hans Verkuil <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Vbi Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Vbi Public License for more details.
+ *
+ * You should have received a copy of the GNU Vbi Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
USA.
+ */
+
+
+#ifndef VBI_TAB_H
+#define VBI_TAB_H
+
+#include "qv4l2.h"
+#include "v4l2-api.h"
+
+class QTableWidget;
+
+class VbiTab: public QGridLayout
+{
+       Q_OBJECT
+
+public:
+       VbiTab(QWidget *parent = 0);
+       virtual ~VbiTab() {}
+
+       void rawFormat(const v4l2_vbi_format &fmt);
+       void slicedData(const v4l2_sliced_vbi_data *data);
+
+private:
+       void info(const QString &info)
+       {
+               g_mw->info(info);
+       }
+       virtual void error(const QString &error)
+       {
+               g_mw->error(error);
+       }
+
+       QTableWidget *m_tableF1;
+       QTableWidget *m_tableF2;
+};
+
+#endif

_______________________________________________
linuxtv-commits mailing list
[email protected]
http://www.linuxtv.org/cgi-bin/mailman/listinfo/linuxtv-commits

Reply via email to