diff options
Diffstat (limited to 'test/sliced-vbi-test.c')
-rw-r--r-- | test/sliced-vbi-test.c | 469 |
1 files changed, 0 insertions, 469 deletions
diff --git a/test/sliced-vbi-test.c b/test/sliced-vbi-test.c deleted file mode 100644 index 3b4a7fc8f..000000000 --- a/test/sliced-vbi-test.c +++ /dev/null @@ -1,469 +0,0 @@ -/* - Sliced vbi demonstration utility - Copyright (C) 2004 Hans Verkuil <hverkuil@xs4all.nl> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* This test tool is used to test the sliced VBI implementation. It reads - from /dev/vbi0 by default (or the device name that is specified as the - first argument) and shows which packets arrive and what the contents - is. It also serves as example code on how to use the sliced VBI API. - */ - -#include <unistd.h> -#include <features.h> /* Uses _GNU_SOURCE to define getsubopt in stdlib.h */ -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <inttypes.h> -#include <getopt.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <errno.h> -#include <sys/ioctl.h> -#include <sys/time.h> -#include <math.h> - -#include <linux/videodev2.h> - -#define printable(c) ((((c) & 0x7F) < 0x20 || ((c) & 0x7F) > 0x7E) ? '.' : ((c) & 0x7F)) - -int valid_char(char c); - -int valid_char(char c) -{ - /* Invalid Character */ - if (((c) & 0x7F) < 0x20 || ((c) & 0x7F) > 0x7E) - return 0; - else /* Valid Character */ - return 1; -} - -int frames = 0; -int lines = 0; -int space_needed = 0; -int text_off = 0; - -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", - "?" -}; - -void decode_wss(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)) - return; - - printf("WSS: %s; %s mode; %s color coding;\n" - " %s helper; reserved b7=%d; %s\n" - " open subtitles: %s; %scopyright %s; copying %s\n", - formats[wss & 7], - (wss & 0x10) ? "film" : "camera", - (wss & 0x20) ? "MA/CP" : "standard", - (wss & 0x40) ? "modulated" : "no", - !!(wss & 0x80), - (wss & 0x0100) ? "have TTX subtitles; " : "", - subtitles[(wss >> 9) & 3], - (wss & 0x0800) ? "surround sound; " : "", - (wss & 0x1000) ? "asserted" : "unknown", - (wss & 0x2000) ? "restricted" : "not restricted"); -} - -static int odd_parity(uint8_t c) -{ - c ^= (c >> 4); - c ^= (c >> 2); - c ^= (c >> 1); - - return c & 1; -} - -static void decode_xds(struct v4l2_sliced_vbi_data *s) -{ - char c; - - //printf("XDS: %02x %02x: ", s->data[0], s->data[1]); - c = odd_parity(s->data[0]) ? s->data[0] & 0x7F : '?'; - c = printable(c); - //putchar(c); - c = odd_parity(s->data[1]) ? s->data[1] & 0x7F : '?'; - c = printable(c); - //putchar(c); - //putchar('\n'); -} - -#define CC_SIZE 64 - -static void decode_cc(struct v4l2_sliced_vbi_data *s) -{ - static int xds_transport = 0; - char c = s->data[0] & 0x7F; - static char cc[CC_SIZE + 1]; - static char cc_last[2 + 1] = { 0, 0 }; - char cc_disp[CC_SIZE + 1]; - static int cc_idx; - - if (s->field) { /* field 2 */ - /* 0x01xx..0x0Exx ASCII_or_NUL[0..32] 0x0Fchks */ - if (odd_parity(s->data[0]) && (c >= 0x01 && c <= 0x0F)) { - decode_xds(s); - xds_transport = (c != 0x0F); - } else if (xds_transport) { - decode_xds(s); - } - return; - } - - if (s->data[0] == 0x10 || - s->data[0] == 0x13 || - s->data[0] == 0x15 || - s->data[0] == 0x16 || - s->data[0] == 0x91 || - s->data[0] == 0x92 || - s->data[0] == 0x94 || s->data[0] == 0x97 || s->data[0] == 0x1c) { - if (text_off) { - if (s->data[0] == 0x94 && - (s->data[1] == 0xad || s->data[1] == 0x25)) { - text_off = 0; - } - } else { - if (s->data[0] == 0x1c && - (s->data[1] == 0x2a || s->data[1] == 0xab)) { - text_off = 1; - } - } - } - - if (text_off == 0) { - c = odd_parity(s->data[0]) ? s->data[0] & 0x7F : '?'; - - if (cc_idx >= CC_SIZE) { - cc_idx = CC_SIZE - 2; - memcpy(cc, cc + 2, cc_idx); - } - cc[cc_idx++] = c; - - c = odd_parity(s->data[1]) ? s->data[1] & 0x7F : '?'; - - cc[cc_idx++] = c; - - cc[cc_idx] = 0; - } - - if (cc_idx == CC_SIZE) { - int x = 0, y = 0; - int debug = 0; - - memset(cc_disp, 0, CC_SIZE); - - if (debug) - fprintf(stderr, "\n"); - for (y = 0, x = 0; y < cc_idx;) { - - /* Control Code or Valid Character */ - if (valid_char(cc[y]) == 0) { - if (debug) { - if (cc[y] == 0x00) - fprintf(stderr, "()"); - else - fprintf(stderr, "(0x%02x)", - cc[y]); - } - - /* skip over control code */ - if (cc[y] >= 0x11 && cc[y] <= 0x1f) { - if (debug) { - if (cc[y + 1] == 0x00) - fprintf(stderr, "()"); - else - fprintf(stderr, - "(0x%02x)", - cc[y + 1]); - } - - if (space_needed == 1) { - space_needed = 0; - cc_disp[x++] = ' '; - lines++; - } else if (cc[y] == 0x14 - && cc[y + 1] == 0x14) { - space_needed = 0; - cc_disp[x++] = ' '; - lines++; - } - - cc_last[0] = cc[y]; - cc_last[1] = cc[y + 1]; - y += 2; - } else { - cc_last[0] = cc_last[1]; - cc_last[1] = cc[y]; - y++; - } - } else { - if (debug) - fprintf(stderr, "(%c)", cc[y] & 0x7F); - - /* Record character */ - if ((cc[y] & 0x7F) == '\n') { - cc_disp[x] = ' '; - lines++; - } else if (cc_last[1] == 0x2B - && cc_last[0] == 0x14 - && (cc[y] & 0x7F) == '@') { - /* Do Nothing */ - cc_last[0] = cc_last[1]; - cc_last[1] = cc[y]; - y++; - continue; - } else if ((cc[y] & 0x7F) != '\n') { - cc_disp[x] = cc[y] & 0x7F; - lines++; - } else { - printf("\nOdd Character (%c)\n", - cc[y] & 0x7F); - } - - space_needed = 1; - x++; - cc_last[0] = cc_last[1]; - cc_last[1] = cc[y]; - y++; - } - - /* Insert CC_SIZE char Line Break */ - if (lines >= CC_SIZE && cc_disp[x - 1] == ' ') { - cc_disp[x++] = '\n'; - lines = 0; - space_needed = 0; - } - } - if (debug) - fprintf(stderr, "\n"); - printf("%s", cc_disp); - memset(cc_disp, 0, CC_SIZE); - //memset(cc, 0, CC_SIZE); - - cc_idx = 0; - } -} - -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 void dump_pil(int pil) -{ - int day, mon, hour, min; - - day = pil >> 15; - mon = (pil >> 11) & 0xF; - hour = (pil >> 6) & 0x1F; - min = pil & 0x3F; - - if (pil == PIL(0, 15, 31, 63)) - printf(" PDC: Timer-control (no PDC)\n"); - else if (pil == PIL(0, 15, 30, 63)) - printf(" PDC: Recording inhibit/terminate\n"); - else if (pil == PIL(0, 15, 29, 63)) - printf(" PDC: Interruption\n"); - else if (pil == PIL(0, 15, 28, 63)) - printf(" PDC: Continue\n"); - else if (pil == PIL(31, 15, 31, 63)) - printf(" PDC: No time\n"); - else - printf(" PDC: %05x, 200X-%02d-%02d %02d:%02d\n", - pil, mon, day, hour, min); -} - -void decode_vps(struct v4l2_sliced_vbi_data *s) -{ - static char pr_label[20]; - static char label[20]; - static int l = 0; - int cni, pcs, pty, pil; - int c; - unsigned char *buf = s->data; - - c = vbi_bit_reverse[buf[1]]; - - if ((int8_t) c < 0) { - label[l] = 0; - memcpy(pr_label, label, sizeof(pr_label)); - l = 0; - } - - c &= 0x7F; - - label[l] = printable(c); - - l = (l + 1) % 16; - - printf("VPS: 3-10: %02x %02x %02x %02x %02x %02x %02x %02x (\"%s\")\n", - buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], - pr_label); - - 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]; - - printf(" CNI: %04x PCS: %d PTY: %d ", cni, pcs, pty); - - dump_pil(pil); -} - -void process(struct v4l2_sliced_vbi_data *s) -{ - if (s->id == 0) - return; - - //printf("%04d: line %02u field %d type %x\n", frames, s->line, s->field, s->id); - switch (s->id) { - case V4L2_SLICED_TELETEXT_B: - printf("teletext\n"); - break; - case V4L2_SLICED_VPS: - if (s->line != 16 || s->field) - break; - decode_vps(s); - break; - case V4L2_SLICED_WSS_625: - if (s->line != 23 || s->field) - break; - decode_wss(s); - break; - case V4L2_SLICED_CAPTION_525: - if (s->line != 21) - break; - decode_cc(s); - break; - default: - printf("unknown\n"); - break; - } -} - -int main(int argc, char **argv) -{ - char *device = "/dev/vbi0"; - struct v4l2_format fmt; - v4l2_std_id std; - struct v4l2_sliced_vbi_data *buf; - int fh; - - if (argc == 2) - device = argv[1]; - fh = open(device, O_RDONLY); - - if (fh == -1) { - fprintf(stderr, "cannot open %s\n", device); - return 1; - } - - setbuf(stdout, NULL); - - ioctl(fh, VIDIOC_G_STD, &std); - fmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE; - fmt.fmt.sliced.service_set = (std & V4L2_STD_NTSC) ? V4L2_SLICED_VBI_525 : V4L2_SLICED_VBI_625; - fmt.fmt.sliced.reserved[0] = 0; - fmt.fmt.sliced.reserved[1] = 0; - if (ioctl(fh, VIDIOC_S_FMT, &fmt) < 0) { - perror("vbi"); - close(fh); - return 1; - } - - fprintf(stderr, "%08x, %d\n", fmt.fmt.sliced.service_set, fmt.fmt.sliced.io_size); - buf = malloc(fmt.fmt.sliced.io_size); - for (;;) { - int size = read(fh, buf, fmt.fmt.sliced.io_size); - int i; - - if (size <= 0) - break; - frames++; - for (i = 0; i < size / sizeof(struct v4l2_sliced_vbi_data); i++) { - process(&buf[i]); - } - } - close(fh); - return 0; -} |