README for the IVTV VBI Support

Hans Verkuil (hverkuil@xs4all.nl)


Introduction
============

This document provides information on the ivtv VBI support and the vbi utility.
Many thanks must go to Chris Kennedy for helping out on the NTSC support for VBI.

The TV signal uses the Vertical Blank Interval (i.e. the time between finishing
one picture and moving the electron beam up to start another) for special data
services like teletext, closed caption and the widescreen signal. The saa7115
chip supports these standards. It can provide the data in either raw format
(720 luminosity samples per line) or in a sliced format (here the chip decodes
the luminosity samples to the actual bytes). It also has read-back registers
where the data of several small-payload VBI standards is stored. 

There are some cards that use the saa7114 chip. While this chip does support VBI,
it is currently not working, so for these cards VBI is disabled. 

Patches
=======

Not all programs use the v4l2 API properly, so a few patches are provided:

- zvbi.diff fixes the libzvbi library (http://sourceforge.net/projects/zapping,
  versions 2.7.0 & 2.8.0). The patch is needed because the library expects
  streaming ioctls which are not (yet) available at the moment.

- alevt.diff fixes incorrect v4l2 defines (probably derived from older v4l2 API
  revisions). The patch is for version 1.6.1 and this teletext decoder/browser
  can be found here: http://www.goron.de/~froese (although this site seems
  to be down a lot).

Those who are using nxtvepg (Electronic Program Guide, http://nxtvepg.sourceforge.net)
must upgrade to version 2.7.1 and higher. Older versions had some bugs in the
use of the V4L2 API.


Raw VBI output
==============

Current linux VBI decoding applications only accept raw VBI data. While a
proposal for a sliced VBI v4l2 API is available, it is not yet implemented.
The ivtv driver adds its own API for sliced VBI data which is modelled on the
proposal.

For the testing of raw VBI output I have used the libzvbi library with the patch
mentioned in the previous section applied.

The VBI output appears at device /dev/vbi0. By running 'osc -d /dev/vbi0' from
the zvbi test directory you should see the raw VBI lines. Use the up/down arrow
keys to see all VBI lines. Use the capture tool to actually extract the data. See
the README file in the zvbi test directory for more information.


VBI mode ioctls
===============

Even though /dev/vbi0 can be set to sliced VBI mode, as soon as the VIDIOC_G_FMT
or VIDIOC_S_FMT ioctls are used it is switched to raw VBI mode. All currently
available linux utilities use these ioctls and expect to see raw VBI mode.

The vbi.c example utility shows how to use the sliced VBI mode. It is my hope
that this utility will be expanded to support all the main VBI standards and
can be used as a reference for other programs. Currently only the PAL WSS
signal and PAL VPS signal are fully decoded. Closed captioning for NTSC is
partially decoded.

Two new ioctls are added: IVTV_IOC_S_VBI_MODE and IVTV_IOC_G_VBI_MODE. These
should be used to set and get the VBI mode. You must provide a pointer to the
following structure:

struct ivtv_sliced_vbi_format {
        unsigned long service_set;      /* one or more of the IVTV_SLICED_ defines */
        unsigned long packet_size;      /* the size in bytes of the ivtv_sliced_data packet */
        unsigned long io_size;          /* maximum number of bytes passed by one read() call */
        unsigned long reserved;
};

The IVTV_IOC_G_VBI_MODE ioctl will fill in this structure with the current
settings. The packet_size and io_size fields are discussed in the Sliced VBI
Output Format section below.
For the IVTV_IOC_S_VBI_MODE ioctl you only have to fill in the 
service_set. The service_set member has the following values:

        #define IVTV_SLICED_TELETEXT_B  (1 << 0)
        #define IVTV_SLICED_CAPTION_625 (1 << 1)
        #define IVTV_SLICED_CAPTION_525 (1 << 2)
        #define IVTV_SLICED_WSS_625     (1 << 3)
        #define IVTV_SLICED_VPS         (1 << 4)

If service_set is set to 0, then the VBI format is reset to raw VBI. The
IVTV_IOC_S_VBI_MODE will update the values of the other ivtv_sliced_vbi_format
fields on return.


Sliced VBI output format
========================

You must call the IVTV_IOC_G_VBI_MODE ioctl to obtain the packet_size and io_size
values. These values are based on the proposed v4l2 sliced VBI API. The packet_size
is the size in bytes of the ivtv_sliced_data structure, which contains the sliced
data of one VBI line. The io_size is the maximum size in bytes that is passed in
one read() call (this is the number of VBI lines in a single frame * packet_size).
So you should allocate a buffer of this size.

The ivtv_sliced_data structure has the following format:

        /* This structure is the same as the proposed v4l2_sliced_data structure */
        /* id is one of the VBI_SLICED_ flags. */
        struct ivtv_sliced_data {
                unsigned long id;
                unsigned long line;
                unsigned char data[];
        };

The ID field determines the VBI format of the line. It is one of the VBI_SLICED
types or 0 if there is no VBI data in this line. The line field is the line number and
data is the actual VBI data. The length of the data array is determined by
packet_size - sizeof(struct ivtv_sliced_data). After the payload of the VBI line
the data array is padded with 0xA0 bytes. If no data was found in the VBI line that
corresponded to the chosen VBI format, then the whole data array is filled with
0xA0 bytes.


General Remarks
===============

You should set the VBI mode before starting capturing. Once a capture is in
progress the VBI_MODE ioctls will return EBUSY.

A /dev/vbi4 device is also created. If VBI data is captured in the MPEG stream
and is played back on the PVR-350 you can read back the captured VBI stream using
this device. Since the VBI data in the MPEG stream is always in sliced format, you
should use the same procedure as described in the 'Sliced VBI output format' section.

Originally I used DMA for the VBI transfer. It turned out that that interfered
with the MPEG DMA, and also that sometimes the VBI DMA transfer did not actually
transfer the data. So instead the VBI data is transferred by just copying the memory.


Passing captured VBI data to TV-out
===================================

When you capture VBI data in the MPEG stream, then the driver is able to
pass certain signals on to TV-out. This only works for the Widescreen signal,
Close Caption data and VPS data. You use the -b option of ivtvctl to instruct
the driver which signals should be captured, and -x that the VBI data should
be embedded in the MPEG stream. E.g. use

        ivtvctl -b wss,cc -x 1

to add WSS and close caption data to the stream (currently works only for
the Program Stream).

Use the -w option to select which signals are passed on to the TV-out (if
supported by your card):

        ivtvctl -w wss,cc

This will automatically copy the wss and cc signals to TV-out.

Note that at the moment the CC output is not in sync with the video output.
This is still under investigation.


Format of embedded VBI data
===========================

This section documents the format of the VBI data embedded in an MPEG stream.
The stream ID of the VBI data is 0xBD. The maximum size of the embedded data is
4 + 43 * 36, which is 4 bytes for a header and 2 * 18 VBI lines with a 1 byte
header and a 42 bytes payload each. Anything beyond this limit is cut off by
the firmware. Besides the data for the VBI lines we also need 36 bits for a bitmask
determining which lines are captured and 4 bytes for a magic cookie, signifying
that this data package contains ivtv VBI data. If all lines are used, then there
is no longer room for the bitmask. To solve this two different magic numbers
were introduced:

'itv0': After this magic number two unsigned longs follow. Bits 0-17 of the first
unsigned long denote which lines of the first field are captured. Bits 18-31 of
the first unsigned long and bits 0-3 of the second unsigned long are used for the
second field.

'ITV0': This magic number assumes all VBI lines are capture, i.e. it implicitly
implies that the bitmasks are 0xffffffff and 0xf.

After these magic cookies (and the 8 byte bitmask in case of cookie 'itv0') the
captured VBI lines start:

For each line the least significant 4 bits of the first byte contain the data type.
Possible values are shown in the table below. The payload is in the following 42
bytes.

See the function passthrough_vbi_data() in ivtv-vbi.c how to decode the
embedded VBI data.

Here is the list of possible data types:

#define VBI_TYPE_TELETEXT       0x1     // Teletext (uses lines 6-22 for PAL, 10-21 for NTSC)
#define VBI_TYPE_CC             0x4     // Closed Captions (line 21 NTSC, line 22 PAL)
#define VBI_TYPE_WSS            0x5     // Wide Screen Signal (line 20 NTSC, line 23 PAL)
#define VBI_TYPE_VPS            0x7     // Video Programming System (PAL) (line 16)

Note that currently only Program Streams are supported!


Writing VBI data to TV-out
==========================

Just as embedded VBI data can be passed to TV-out, so it is also possible to
write VBI data to TV-out using a device: /dev/vbi8. You must first select the
signals that should be serviced using the IVTV_IOC_S_VBI_MODE ioctl. Only
sliced VBI data is accepted, and only VPS, WSS and CC data can be serviced.
Next call the IVTV_IOC_G_VBI_MODE ioctl to obtain the packet size and io_size.
Now you can start writing struct ivtv_sliced_data packets to the device.
There is currently no way to synchronize with the video. Someone who can actually
test closed captioning should implement this.

Two example utilities are added to illustrate how to use it. The wss utility
can be used to set/unset the WSS signal: 'wss 0 /dev/vbi8' select 4x3 format,
'wss 1 /dev/vbi8' selects 16x9 format. The vbi_passthrough utility can be
used to pass the input from /dev/vbi0 directly on to /dev/vbi8. You can test
this by turning on passthrough mode (ivtvctl -K 1) and then running
vbi_passthrough /dev/vbi0 /dev/vbi8. All WSS, CC and VPS data should be copied
to TV-out.


TODO
====

1) Add support for handling teletext-supplied subtitling. It would be nice if
   only the teletext lines that actually are used for subtitling are inserted
   into the MPEG stream, to reduce overhead.
2) Add example code that reads the teletext data and shows it using the OSD.
   Especially useful for subtitling.
3) Extend vbi.c with more VBI format decoders.
4) NTSC and PAL use different ways of programming the saa7115 VBI registers.
   PAL should use the NTSC method as that is actually a more logical way of
   doing it.
5) Support the VBI data insertion for more stream types than just Program Stream.

