README for the IVTV VBI Support Hans Verkuil (hverkuil@xs4all.nl) [NOTE: parts of this document are outdated. Sliced VBI is now setup using a standard V4L2 API. See test/vbi.c or test/vbi-detect.c for an example of the new API. The format of the sliced VBI data embedded in the MPEG stream is still valid though.] 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/vbi8 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/vbi16. 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/vbi16' select 4x3 format, 'wss 1 /dev/vbi16' selects 16x9 format. The vbi_passthrough utility can be used to pass the input from /dev/vbi0 directly on to /dev/vbi16. You can test this by turning on passthrough mode (ivtvctl -K 1) and then running vbi_passthrough /dev/vbi0 /dev/vbi16. 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.