831 lines
19 KiB
C
831 lines
19 KiB
C
/*
|
|
* libzvbi test
|
|
*
|
|
* Copyright (C) 2000, 2001, 2002 Michael H. Schimek
|
|
*
|
|
* 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., 51 Franklin Street, Fifth Floor, Boston,
|
|
* MA 02110-1301, USA.
|
|
*/
|
|
|
|
/* $Id: capture.c,v 1.39 2008/08/19 10:06:52 mschimek Exp $ */
|
|
|
|
/* For libzvbi version 0.2.x / 0.3.x. */
|
|
|
|
#undef NDEBUG
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
# include "config.h"
|
|
#endif
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
#include <locale.h>
|
|
#include <errno.h>
|
|
#include <assert.h>
|
|
#include <unistd.h>
|
|
#ifdef HAVE_GETOPT_LONG
|
|
#include <getopt.h>
|
|
#endif
|
|
|
|
#include "src/version.h"
|
|
#if 2 == VBI_VERSION_MINOR
|
|
# include "src/hamm.h"
|
|
# define SCANNING(sp) ((sp)->scanning)
|
|
#elif 3 == VBI_VERSION_MINOR
|
|
# include "src/vbi.h"
|
|
# include "src/zvbi.h"
|
|
# include "src/misc.h"
|
|
# define SCANNING(sp) \
|
|
(0 != ((sp)->videostd_set & VBI_VIDEOSTD_SET_525_60) ? 525 : 625)
|
|
#else
|
|
# error VBI_VERSION_MINOR == ?
|
|
#endif
|
|
|
|
#include "sliced.h"
|
|
|
|
#undef _
|
|
#define _(x) x /* TODO */
|
|
|
|
#define PROGRAM_NAME "zvbi-capture"
|
|
|
|
static const char * option_out_file_name;
|
|
static enum file_format option_out_file_format;
|
|
static unsigned int option_out_ts_pid;
|
|
|
|
static int option_read_not_pull;
|
|
static int option_strict;
|
|
static int option_dump_wss;
|
|
static int option_dump_sliced;
|
|
static int option_cc_test;
|
|
static int option_cc_test_test;
|
|
static vbi_bool option_raw_output;
|
|
static vbi_bool option_sliced_output;
|
|
static unsigned int option_sim_flags;
|
|
|
|
static struct stream * cst;
|
|
static struct stream * wst;
|
|
static const char ** sim_cc_streams;
|
|
static unsigned int n_sim_cc_streams;
|
|
|
|
struct frame {
|
|
vbi_sliced sliced[50];
|
|
unsigned int n_lines;
|
|
|
|
uint8_t * raw;
|
|
|
|
double sample_time;
|
|
int64_t stream_time;
|
|
};
|
|
|
|
static struct frame frame_buffers[5];
|
|
static unsigned int next_frame;
|
|
static unsigned int n_frames_buffered;
|
|
static unsigned int sliced_output_count;
|
|
static unsigned int raw_output_count;
|
|
|
|
/*
|
|
* Dump
|
|
*/
|
|
|
|
extern int vbi_printable (int);
|
|
|
|
static void
|
|
decode_wss_625 (const uint8_t * buf)
|
|
{
|
|
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",
|
|
"?"
|
|
};
|
|
int g1 = buf[0] & 15;
|
|
int parity;
|
|
|
|
if (option_dump_wss) {
|
|
parity = g1;
|
|
parity ^= parity >> 2;
|
|
parity ^= parity >> 1;
|
|
g1 &= 7;
|
|
|
|
printf ("WSS PAL: ");
|
|
if (!(parity & 1))
|
|
printf ("<parity error> ");
|
|
printf ("%s; %s mode; %s colour coding;\n"
|
|
" %s helper; reserved b7=%d; %s\n"
|
|
" open subtitles: %s; %scopyright %s; copying %s\n",
|
|
formats[g1],
|
|
(buf[0] & 0x10) ? "film" : "camera",
|
|
(buf[0] & 0x20) ? "MA/CP" : "standard",
|
|
(buf[0] & 0x40) ? "modulated" : "no",
|
|
!!(buf[0] & 0x80),
|
|
(buf[1] & 0x01) ? "have TTX subtitles; " : "",
|
|
subtitles[(buf[1] >> 1) & 3],
|
|
(buf[1] & 0x08) ? "surround sound; " : "",
|
|
(buf[1] & 0x10) ? "asserted" : "unknown",
|
|
(buf[1] & 0x20) ? "restricted" : "not restricted");
|
|
}
|
|
}
|
|
|
|
static void
|
|
decode_wss_cpr1204 (const uint8_t * buf)
|
|
{
|
|
if (option_dump_wss) {
|
|
const int poly = (1 << 6) + (1 << 1) + 1;
|
|
int g = (buf[0] << 12) + (buf[1] << 4) + buf[2];
|
|
int j, crc;
|
|
|
|
crc = g | (((1 << 6) - 1) << (14 + 6));
|
|
|
|
for (j = 14 + 6 - 1; j >= 0; j--) {
|
|
if (crc & ((1 << 6) << j))
|
|
crc ^= poly << j;
|
|
}
|
|
|
|
fprintf (stderr, "WSS CPR >> g=%08x crc=%08x\n", g, crc);
|
|
}
|
|
}
|
|
|
|
static void
|
|
decode_sliced (const vbi_sliced * s,
|
|
unsigned int n_lines,
|
|
double sample_time,
|
|
int64_t stream_time)
|
|
{
|
|
if (option_dump_sliced) {
|
|
const vbi_sliced *q = s;
|
|
unsigned int i;
|
|
|
|
printf ("Frame %f %010" PRId64 "\n",
|
|
sample_time, stream_time);
|
|
|
|
for (i = 0; i < n_lines; q++, i++) {
|
|
unsigned int j;
|
|
|
|
printf ("%08x %3d ", q->id, q->line);
|
|
|
|
for (j = 0; j < sizeof(q->data); j++) {
|
|
printf ("%02x ", 0xFF & q->data[j]);
|
|
}
|
|
|
|
putchar (' ');
|
|
|
|
for (j = 0; j < sizeof(q->data); j++) {
|
|
char c = _vbi_to_ascii (q->data[j]);
|
|
putchar (c);
|
|
}
|
|
|
|
putchar ('\n');
|
|
}
|
|
}
|
|
|
|
for (; n_lines > 0; s++, n_lines--) {
|
|
if (s->id == 0) {
|
|
continue;
|
|
} else if (s->id & (VBI_SLICED_VPS |
|
|
VBI_SLICED_TELETEXT_B |
|
|
VBI_SLICED_CAPTION_525 |
|
|
VBI_SLICED_CAPTION_625)) {
|
|
/* Nothing to do.
|
|
Use the 'decode' tool instead. */
|
|
} else if (s->id & VBI_SLICED_WSS_625) {
|
|
decode_wss_625 (s->data);
|
|
} else if (s->id & VBI_SLICED_WSS_CPR1204) {
|
|
decode_wss_cpr1204 (s->data);
|
|
} else {
|
|
fprintf (stderr, "Oops. Unhandled VBI service %08x\n",
|
|
s->id);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Purpose of this function is to record raw and sliced VBI data
|
|
around three kinds of events for remote examination:
|
|
- Frames without data,
|
|
- Lines which contain 0x00 0x00 instead of 0x80 0x80 bytes,
|
|
- Lines where the transmitted bytes have wrong parity.
|
|
The raw VBI data may be required to understand what happened,
|
|
and due to its volume we cannot record it unconditionally. */
|
|
static vbi_bool
|
|
cc_test (const vbi_sliced * sliced,
|
|
unsigned int n_lines)
|
|
{
|
|
static const unsigned int max_error_count[3] = { 5, 5, 5 };
|
|
static unsigned int error_count[3];
|
|
static unsigned int frame_count;
|
|
unsigned int error_set;
|
|
unsigned int i;
|
|
|
|
error_set = 0;
|
|
|
|
if (option_cc_test_test && 0 == rand() % 300)
|
|
n_lines = 0;
|
|
|
|
if (0 == n_lines) {
|
|
error_msg ("No data on this frame...");
|
|
if (error_count[0] < max_error_count[0]) {
|
|
++error_count[0];
|
|
error_set |= 1 << 0;
|
|
}
|
|
} else {
|
|
for (i = 0; i < n_lines; ++i) {
|
|
if (sliced[i].id & (VBI_SLICED_CAPTION_525 |
|
|
VBI_SLICED_CAPTION_625)) {
|
|
int b1, b2;
|
|
int c1, c2;
|
|
|
|
b1 = sliced[i].data[0];
|
|
b2 = sliced[i].data[1];
|
|
|
|
if (option_cc_test_test
|
|
&& 0 == rand() % 300) {
|
|
b1 = 0;
|
|
b2 = 0;
|
|
}
|
|
|
|
if (0x00 == b1 && 0x00 == b2) {
|
|
error_msg ("Null bytes...");
|
|
if (error_count[1]
|
|
< max_error_count[1]) {
|
|
++error_count[1];
|
|
error_set |= 1 << 1;
|
|
}
|
|
}
|
|
|
|
c1 = vbi_unpar8 (b1);
|
|
c2 = vbi_unpar8 (b2);
|
|
|
|
if (option_cc_test_test
|
|
&& 0 == rand() % 300) {
|
|
c2 = -1;
|
|
}
|
|
|
|
if ((c1 | c2) < 0) {
|
|
error_msg ("Parity error...");
|
|
if (error_count[2]
|
|
< max_error_count[2]) {
|
|
++error_count[2];
|
|
error_set |= 1 << 2;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (0 != error_set) {
|
|
unsigned int n_errors = 0;
|
|
unsigned int n_kinds = 0;
|
|
|
|
for (i = 0; i < N_ELEMENTS (error_count); ++i) {
|
|
n_errors += 5 - error_count[i];
|
|
n_kinds += (error_count[i] < 5);
|
|
}
|
|
|
|
if (0 == n_kinds) {
|
|
error_msg ("Done.");
|
|
return FALSE; /* terminate loop */
|
|
}
|
|
|
|
if (0 == frame_count % (5 * 30)) {
|
|
error_msg ("Waiting for %u errors of %u kinds...",
|
|
n_errors, n_kinds);
|
|
}
|
|
}
|
|
|
|
++frame_count;
|
|
|
|
if (option_raw_output != (0 != error_set)) {
|
|
option_sliced_output = (0 != error_set);
|
|
|
|
raw_output_count = N_ELEMENTS (frame_buffers) * 2;
|
|
|
|
if (sliced_output_count < raw_output_count)
|
|
sliced_output_count = raw_output_count;
|
|
}
|
|
|
|
return TRUE; /* success, continue loop */
|
|
}
|
|
|
|
static vbi_bool
|
|
decode_frame (const vbi_sliced * sliced,
|
|
unsigned int n_lines,
|
|
const uint8_t * raw,
|
|
const vbi_sampling_par *sp,
|
|
double sample_time,
|
|
int64_t stream_time)
|
|
{
|
|
if (option_dump_sliced || option_dump_wss)
|
|
decode_sliced (sliced, n_lines,
|
|
sample_time, stream_time);
|
|
|
|
if (option_cc_test) {
|
|
struct frame *f;
|
|
unsigned int size;
|
|
|
|
f = frame_buffers + next_frame;
|
|
|
|
if (n_frames_buffered >= N_ELEMENTS (frame_buffers)) {
|
|
write_stream_sliced (wst,
|
|
(sliced_output_count > 0) ?
|
|
f->sliced : NULL,
|
|
f->n_lines,
|
|
(raw_output_count > 0) ?
|
|
f->raw : NULL,
|
|
sp,
|
|
f->sample_time,
|
|
f->stream_time);
|
|
|
|
if (sliced_output_count > 0)
|
|
--sliced_output_count;
|
|
if (raw_output_count > 0)
|
|
--raw_output_count;
|
|
|
|
n_frames_buffered = N_ELEMENTS (frame_buffers) - 1;
|
|
}
|
|
|
|
assert (n_lines <= N_ELEMENTS (f->sliced));
|
|
|
|
memcpy (f->sliced, sliced, n_lines * sizeof (*sliced));
|
|
f->n_lines = n_lines;
|
|
|
|
size = (sp->count[0] + sp->count[1]) * sp->bytes_per_line;
|
|
memcpy (f->raw, raw, size);
|
|
|
|
f->sample_time = sample_time;
|
|
f->stream_time = stream_time;
|
|
|
|
if (++next_frame >= N_ELEMENTS (frame_buffers))
|
|
next_frame = 0;
|
|
|
|
++n_frames_buffered;
|
|
|
|
if (!cc_test (sliced, n_lines))
|
|
return FALSE;
|
|
|
|
} else if (option_raw_output || option_sliced_output) {
|
|
write_stream_sliced (wst,
|
|
option_sliced_output ? sliced : NULL,
|
|
n_lines,
|
|
option_raw_output ? raw : NULL,
|
|
sp,
|
|
sample_time,
|
|
stream_time);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
init_frame_buffers (const vbi_sampling_par *sp)
|
|
{
|
|
unsigned int size;
|
|
unsigned int i;
|
|
|
|
size = (sp->count[0] + sp->count[1]) * sp->bytes_per_line;
|
|
|
|
for (i = 0; i < N_ELEMENTS (frame_buffers); ++i) {
|
|
frame_buffers[i].raw = malloc (size);
|
|
if (NULL == frame_buffers[i].raw)
|
|
no_mem_exit ();
|
|
}
|
|
}
|
|
|
|
static void
|
|
usage (FILE * fp)
|
|
{
|
|
fprintf (fp, _("\
|
|
%s %s -- VBI capture tool\n\n\
|
|
Copyright (C) 2000-2007 Michael H. Schimek\n\
|
|
This program is licensed under GPLv2 or later. NO WARRANTIES.\n\n\
|
|
Usage: %s [options] > sliced VBI data\n\
|
|
-h | --help | --usage Print this message and exit\n\
|
|
-q | --quiet Suppress progress and error messages\n\
|
|
-v | --verbose Increase verbosity\n\
|
|
-V | --version Print the program version and exit\n\
|
|
Device options:\n\
|
|
-c | --sim-cc file Simulate a VBI device and load this Closed Caption\n\
|
|
test stream into the simulation\n\
|
|
-d | --device file Capture from this device (default %s)\n\
|
|
V4L/V4L2: /dev/vbi, /dev/vbi0, /dev/vbi1, ...\n\
|
|
Linux DVB: /dev/dvb/adapter0/demux0, ...\n\
|
|
*BSD bktr driver: /dev/vbi, /dev/vbi0, ...\n\
|
|
-i | --pid pid Capture the stream with this PID from a Linux\n\
|
|
DVB device\n\
|
|
-m | --sim-laced Simulate a VBI device capturing interlaced raw\n\
|
|
VBI data\n\
|
|
-n | --ntsc Video standard hint for V4L interface and\n\
|
|
simulated VBI device (default PAL/SECAM)\n\
|
|
-p | --pal | --secam Video standard hint for V4L interface\n\
|
|
-s | --sim Simulate a VBI device\n\
|
|
-u | --sim-unsync Simulate a VBI device with wrong/unknown field\n\
|
|
parity\n\
|
|
-w | --sim-noise Simulate a VBI device with noisy signal\n\
|
|
-x | --proxy Capture through the VBI proxy daemon\n\
|
|
Output options:\n\
|
|
-j | --dump Sliced VBI data (text)\n\
|
|
-l | --sliced Sliced VBI data (binary)\n\
|
|
-o | --output name Write the VBI data to this file instead of\n\
|
|
standard output\n"
|
|
/* later */ /*
|
|
"-r | --raw Raw VBI data (binary)\n"
|
|
*/
|
|
"-P | --pes DVB PES stream\n\
|
|
-T | --ts pid DVB TS stream\n\
|
|
"),
|
|
PROGRAM_NAME, VERSION, program_invocation_name,
|
|
option_dev_name);
|
|
}
|
|
|
|
static const char short_options[] = "c:d:hi:jlmno:pqr:suvwxPT:V";
|
|
|
|
#ifdef HAVE_GETOPT_LONG
|
|
static const struct option
|
|
long_options[] = {
|
|
{ "sim-cc", required_argument, NULL, 'c' },
|
|
{ "device", required_argument, NULL, 'd' },
|
|
{ "help", no_argument, NULL, 'h' },
|
|
{ "usage", no_argument, NULL, 'h' },
|
|
{ "pid", required_argument, NULL, 'i' },
|
|
{ "dump", no_argument, NULL, 'j' },
|
|
{ "sliced", no_argument, NULL, 'l' },
|
|
{ "sim-laced", no_argument, NULL, 'm' },
|
|
{ "ntsc", no_argument, NULL, 'n' },
|
|
{ "output", required_argument, NULL, 'o' },
|
|
{ "pal", no_argument, NULL, 'p' },
|
|
{ "secam", no_argument, NULL, 'p' },
|
|
{ "quiet", no_argument, NULL, 'q' },
|
|
{ "raw", optional_argument, NULL, 'r' },
|
|
{ "sim", no_argument, NULL, 's' },
|
|
{ "sim-unsync", no_argument, NULL, 'u' },
|
|
{ "verbose", no_argument, NULL, 'v' },
|
|
{ "sim-noise", optional_argument, NULL, 'w' },
|
|
{ "proxy", no_argument, NULL, 'x' },
|
|
{ "pes", no_argument, NULL, 'P' },
|
|
{ "ts", required_argument, NULL, 'T' },
|
|
{ "version", no_argument, NULL, 'V' },
|
|
{ "loose", no_argument, &option_strict, 0 },
|
|
{ "strict", no_argument, &option_strict, 2 },
|
|
{ "cc-test", no_argument, &option_cc_test, TRUE },
|
|
{ "cc-test-test", no_argument, &option_cc_test_test, TRUE },
|
|
{ "dump-wss", no_argument, &option_dump_wss, TRUE },
|
|
{ "read", no_argument, &option_read_not_pull, TRUE },
|
|
{ "pull", no_argument, &option_read_not_pull, FALSE },
|
|
{ NULL, 0, 0, 0 }
|
|
};
|
|
#else
|
|
#define getopt_long(ac, av, s, l, i) getopt(ac, av, s)
|
|
#endif
|
|
|
|
static int option_index;
|
|
|
|
static char *
|
|
load_string (const char * name)
|
|
{
|
|
FILE *fp;
|
|
char *buffer;
|
|
size_t buffer_size;
|
|
size_t done;
|
|
|
|
buffer = NULL;
|
|
buffer_size = 0;
|
|
done = 0;
|
|
|
|
fp = fopen (name, "r");
|
|
if (NULL == fp) {
|
|
exit (EXIT_FAILURE);
|
|
}
|
|
|
|
for (;;) {
|
|
char *new_buffer;
|
|
size_t new_size;
|
|
size_t space;
|
|
size_t actual;
|
|
|
|
new_size = 16384;
|
|
if (buffer_size > 0)
|
|
new_size = buffer_size * 2;
|
|
|
|
new_buffer = realloc (buffer, new_size);
|
|
if (NULL == new_buffer) {
|
|
free (buffer);
|
|
exit (EXIT_FAILURE);
|
|
}
|
|
|
|
buffer = new_buffer;
|
|
buffer_size = new_size;
|
|
|
|
space = buffer_size - done - 1;
|
|
actual = fread (buffer + done, 1, space, fp);
|
|
if ((size_t) -1 == actual) {
|
|
exit (EXIT_FAILURE);
|
|
}
|
|
done += actual;
|
|
if (actual < space)
|
|
break;
|
|
}
|
|
|
|
buffer[done] = 0;
|
|
|
|
fclose (fp);
|
|
|
|
return buffer;
|
|
}
|
|
|
|
static void
|
|
sim_load_caption (void)
|
|
{
|
|
unsigned int i;
|
|
|
|
for (i = 0; i < n_sim_cc_streams; ++i) {
|
|
char *buffer;
|
|
vbi_bool success;
|
|
|
|
fprintf (stderr, "Loading '%s'.\n", sim_cc_streams[i]);
|
|
|
|
buffer = load_string (sim_cc_streams[i]);
|
|
success = capture_stream_sim_load_caption
|
|
(cst, buffer, /* append */ (i > 0));
|
|
assert (success);
|
|
}
|
|
}
|
|
|
|
int
|
|
main (int argc,
|
|
char ** argv)
|
|
{
|
|
unsigned int interfaces;
|
|
unsigned int scanning;
|
|
unsigned int services;
|
|
vbi_bool sim_interlaced;
|
|
vbi_bool sim_synchronous;
|
|
|
|
init_helpers (argc, argv);
|
|
|
|
scanning = 625;
|
|
|
|
sim_interlaced = FALSE;
|
|
sim_synchronous = TRUE;
|
|
|
|
option_strict = 1;
|
|
option_dump_wss = FALSE;
|
|
option_read_not_pull = FALSE;
|
|
|
|
interfaces = (INTERFACE_V4L2 |
|
|
INTERFACE_V4L |
|
|
INTERFACE_BKTR);
|
|
|
|
for (;;) {
|
|
int c;
|
|
|
|
c = getopt_long (argc, argv, short_options,
|
|
long_options, &option_index);
|
|
if (-1 == c)
|
|
break;
|
|
|
|
switch (c) {
|
|
case 0: /* getopt_long() flag */
|
|
if (option_dump_wss) {
|
|
option_raw_output = FALSE;
|
|
option_sliced_output = FALSE;
|
|
}
|
|
break;
|
|
|
|
case 'c':
|
|
{
|
|
const char **pp;
|
|
|
|
pp = realloc (sim_cc_streams,
|
|
(n_sim_cc_streams + 1)
|
|
* sizeof (*pp));
|
|
assert (NULL != pp);
|
|
sim_cc_streams = pp;
|
|
sim_cc_streams[n_sim_cc_streams++] = optarg;
|
|
interfaces = INTERFACE_SIM;
|
|
break;
|
|
}
|
|
|
|
case 'd':
|
|
parse_option_dev_name ();
|
|
break;
|
|
|
|
case 'h':
|
|
usage (stdout);
|
|
exit (EXIT_SUCCESS);
|
|
|
|
case 'i':
|
|
parse_option_dvb_pid ();
|
|
interfaces = INTERFACE_DVB;
|
|
break;
|
|
|
|
case 'j':
|
|
option_dump_sliced = TRUE;
|
|
option_raw_output = FALSE;
|
|
option_sliced_output = FALSE;
|
|
break;
|
|
|
|
case 'l':
|
|
option_sliced_output = TRUE;
|
|
option_dump_sliced = FALSE;
|
|
option_dump_wss = FALSE;
|
|
if (FILE_FORMAT_XML != option_out_file_format)
|
|
option_out_file_format = FILE_FORMAT_SLICED;
|
|
break;
|
|
|
|
case 'm':
|
|
sim_interlaced = TRUE;
|
|
interfaces = INTERFACE_SIM;
|
|
break;
|
|
|
|
case 'n':
|
|
scanning = 525;
|
|
break;
|
|
|
|
case 'o':
|
|
assert (NULL != optarg);
|
|
option_out_file_name = optarg;
|
|
break;
|
|
|
|
case 'p':
|
|
scanning = 625;
|
|
break;
|
|
|
|
case 'q':
|
|
parse_option_quiet ();
|
|
break;
|
|
|
|
#if 0
|
|
case 'r':
|
|
/* Optional optarg: line numbers
|
|
(not implemented yet). */
|
|
option_raw_output = TRUE;
|
|
option_dump_sliced = FALSE;
|
|
option_dump_wss = FALSE;
|
|
option_out_file_format = FILE_FORMAT_XML;
|
|
break;
|
|
#endif
|
|
case 's':
|
|
interfaces = INTERFACE_SIM;
|
|
break;
|
|
|
|
case 'u':
|
|
sim_synchronous = FALSE;
|
|
interfaces = INTERFACE_SIM;
|
|
break;
|
|
|
|
case 'v':
|
|
parse_option_verbose ();
|
|
break;
|
|
|
|
case 'w':
|
|
/* Optional optarg: noise parameters
|
|
(not implemented yet). */
|
|
interfaces = INTERFACE_SIM;
|
|
option_sim_flags |= _VBI_RAW_NOISE_2;
|
|
break;
|
|
|
|
case 'x':
|
|
interfaces &= ~(INTERFACE_SIM | INTERFACE_DVB);
|
|
interfaces |= INTERFACE_PROXY;
|
|
break;
|
|
|
|
case 'P':
|
|
option_sliced_output = TRUE;
|
|
option_dump_sliced = FALSE;
|
|
option_dump_wss = FALSE;
|
|
option_out_file_format = FILE_FORMAT_DVB_PES;
|
|
break;
|
|
|
|
case 'T':
|
|
option_sliced_output = TRUE;
|
|
option_dump_sliced = FALSE;
|
|
option_dump_wss = FALSE;
|
|
option_out_ts_pid = parse_option_ts ();
|
|
option_out_file_format = FILE_FORMAT_DVB_TS;
|
|
break;
|
|
|
|
case 'V':
|
|
printf (PROGRAM_NAME " " VERSION "\n");
|
|
exit (EXIT_SUCCESS);
|
|
|
|
default:
|
|
usage (stderr);
|
|
exit (EXIT_FAILURE);
|
|
}
|
|
}
|
|
|
|
if (!(option_sliced_output
|
|
|| option_raw_output
|
|
|| option_dump_sliced
|
|
|| option_dump_wss)) {
|
|
error_msg (_("Give one of the -j, -l, -P or -T options\n"
|
|
"to enable output, or -h for help."));
|
|
exit (EXIT_FAILURE);
|
|
}
|
|
|
|
services = (VBI_SLICED_VBI_525 |
|
|
VBI_SLICED_VBI_625 |
|
|
VBI_SLICED_TELETEXT_B |
|
|
VBI_SLICED_CAPTION_525 |
|
|
VBI_SLICED_CAPTION_625 |
|
|
VBI_SLICED_VPS |
|
|
VBI_SLICED_VPS_F2 |
|
|
VBI_SLICED_WSS_625 |
|
|
VBI_SLICED_WSS_CPR1204);
|
|
|
|
switch (option_out_file_format) {
|
|
case FILE_FORMAT_DVB_PES:
|
|
case FILE_FORMAT_DVB_TS:
|
|
/* Other formats cannot be encoded. */
|
|
services &= (VBI_SLICED_TELETEXT_B |
|
|
VBI_SLICED_CAPTION_625 |
|
|
VBI_SLICED_VPS |
|
|
VBI_SLICED_WSS_625);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
cst = capture_stream_new (interfaces,
|
|
option_dev_name,
|
|
scanning,
|
|
services,
|
|
/* n_buffers (V4L2 mmap) */ 5,
|
|
option_dvb_pid,
|
|
sim_interlaced,
|
|
sim_synchronous,
|
|
option_raw_output,
|
|
option_read_not_pull,
|
|
option_strict,
|
|
decode_frame);
|
|
|
|
if (interfaces & INTERFACE_SIM) {
|
|
sim_load_caption ();
|
|
|
|
capture_stream_sim_set_flags (cst, option_sim_flags);
|
|
|
|
if (0 != option_sim_flags)
|
|
capture_stream_sim_decode_raw (cst, TRUE);
|
|
}
|
|
|
|
if (option_cc_test_test)
|
|
option_cc_test = TRUE;
|
|
|
|
if (option_cc_test) {
|
|
option_raw_output = FALSE;
|
|
option_sliced_output = TRUE;
|
|
option_dump_sliced = FALSE;
|
|
option_dump_wss = FALSE;
|
|
option_out_file_format = FILE_FORMAT_SLICED;
|
|
sliced_output_count = 2 * 60 * 30;
|
|
}
|
|
|
|
if (option_raw_output || option_sliced_output) {
|
|
vbi_sampling_par sp;
|
|
|
|
capture_stream_get_sampling_par (cst, &sp);
|
|
|
|
if (option_cc_test)
|
|
init_frame_buffers (&sp);
|
|
|
|
wst = write_stream_new (option_out_file_name,
|
|
option_out_file_format,
|
|
option_out_ts_pid,
|
|
SCANNING (&sp));
|
|
}
|
|
|
|
stream_loop (cst);
|
|
|
|
stream_delete (wst);
|
|
wst = NULL;
|
|
|
|
stream_delete (cst);
|
|
cst = NULL;
|
|
|
|
exit(EXIT_SUCCESS);
|
|
}
|