1 /*
2  *  atsc-cc -- ATSC Closed Caption decoder
3  *
4  *  Copyright (C) 2008 Michael H. Schimek <mschimek@users.sf.net>
5  *
6  *  Contains code from zvbi-ntsc-cc closed caption decoder written by
7  *  <timecop@japan.co.jp>, Mike Baker <mbm@linux.com>,
8  *  Mark K. Kim <dev@cbreak.org>.
9  *
10  *  Thanks to Karol Zapolski for his support.
11  *
12  *  This program is free software; you can redistribute it and/or modify
13  *  it under the terms of the GNU General Public License as published by
14  *  the Free Software Foundation; either version 2 of the License, or
15  *  (at your option) any later version.
16  *
17  *  This program is distributed in the hope that it will be useful,
18  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
19  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  *  GNU General Public License for more details.
21  *
22  *  You should have received a copy of the GNU General Public License
23  *  along with this program; if not, write to the Free Software
24  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
25  *  MA 02110-1301, USA.
26  */
27 
28 #ifdef HAVE_CONFIG_H
29 #  include "config.h"
30 #endif
31 
32 #define _GNU_SOURCE 1
33 
34 
35 #include <assert.h>
36 #include <ctype.h>
37 #include <dirent.h>
38 #include <errno.h>
39 #include <fcntl.h>
40 #include <inttypes.h>
41 #include <limits.h>
42 #include <locale.h>
43 #include <malloc.h>
44 #include <math.h>
45 #include <pthread.h>
46 #include <signal.h>
47 #include <stdarg.h>
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <string.h>
51 #include <sys/ioctl.h>
52 #include <sys/mman.h>
53 #include <sys/stat.h>
54 #include <sys/statvfs.h>
55 #include <sys/wait.h>
56 #include <time.h>
57 #include <unistd.h>
58 
59 #ifdef HAVE_GETOPT_LONG
60 #  include <getopt.h>
61 #endif
62 
63 #include "src/libzvbi.h"
64 
65 /* Linux DVB driver interface. */
66 #include "src/dvb/dmx.h"
67 #include "src/dvb/frontend.h"
68 
69 #undef PROGRAM
70 #define PROGRAM "ATSC-CC"
71 #undef VERSION
72 #define VERSION "0.5"
73 
74 #if __GNUC__ < 3
75 #  define likely(expr) (expr)
76 #  define unlikely(expr) (expr)
77 #else
78 #  define likely(expr) __builtin_expect(expr, 1)
79 #  define unlikely(expr) __builtin_expect(expr, 0)
80 #endif
81 
82 #define N_ELEMENTS(array) (sizeof (array) / sizeof ((array)[0]))
83 #define CLEAR(var) memset (&(var), 0, sizeof (var))
84 
85 /* FIXME __typeof__ is a GCC extension. */
86 #undef SWAP
87 #define SWAP(x, y)							\
88 do {									\
89 	__typeof__ (x) _x = x;						\
90 	x = y;								\
91 	y = _x;								\
92 } while (0)
93 
94 #undef MIN
95 #define MIN(x, y) ({							\
96 	__typeof__ (x) _x = (x);					\
97 	__typeof__ (y) _y = (y);					\
98 	(void)(&_x == &_y); /* warn if types do not match */		\
99 	/* return */ (_x < _y) ? _x : _y;				\
100 })
101 
102 #undef MAX
103 #define MAX(x, y) ({							\
104 	__typeof__ (x) _x = (x);					\
105 	__typeof__ (y) _y = (y);					\
106 	(void)(&_x == &_y); /* warn if types do not match */		\
107 	/* return */ (_x > _y) ? _x : _y;				\
108 })
109 
110 #undef PARENT
111 #define PARENT(_ptr, _type, _member) ({					\
112 	__typeof__ (&((_type *) 0)->_member) _p = (_ptr);		\
113 	(_p != 0) ? (_type *)(((char *) _p) - offsetof (_type,		\
114 	  _member)) : (_type *) 0;					\
115 })
116 
117 /* These should be defined in inttypes.h. */
118 #ifndef PRId64
119 #  define PRId64 "lld"
120 #endif
121 #ifndef PRIu64
122 #  define PRIu64 "llu"
123 #endif
124 #ifndef PRIx64
125 #  define PRIx64 "llx"
126 #endif
127 
128 /* EIA 608-B decoder. */
129 
130 enum field_num {
131 	FIELD_1 = 0,
132 	FIELD_2,
133 	MAX_FIELDS
134 };
135 
136 enum cc_mode {
137 	CC_MODE_UNKNOWN,
138 	CC_MODE_ROLL_UP,
139 	CC_MODE_POP_ON,
140 	CC_MODE_PAINT_ON,
141 	CC_MODE_TEXT
142 };
143 
144 /* EIA 608-B Section 4.1. */
145 #define VBI_CAPTION_CC1 1 /* primary synchronous caption service (F1) */
146 #define VBI_CAPTION_CC2 2 /* special non-synchronous use captions (F1) */
147 #define VBI_CAPTION_CC3 3 /* secondary synchronous caption service (F2) */
148 #define VBI_CAPTION_CC4 4 /* special non-synchronous use captions (F2) */
149 
150 #define VBI_CAPTION_T1 5 /* first text service (F1) */
151 #define VBI_CAPTION_T2 6 /* second text service (F1) */
152 #define VBI_CAPTION_T3 7 /* third text service (F2) */
153 #define VBI_CAPTION_T4 8 /* fourth text service (F2) */
154 
155 #define UNKNOWN_CC_CHANNEL 0
156 #define MAX_CC_CHANNELS 8
157 
158 /* 47 CFR 15.119 (d) Screen format. */
159 #define CC_FIRST_ROW		0
160 #define CC_LAST_ROW		14
161 #define CC_MAX_ROWS		15
162 
163 #define CC_FIRST_COLUMN		1
164 #define CC_LAST_COLUMN		32
165 #define CC_MAX_COLUMNS		32
166 
167 #define CC_ALL_ROWS_MASK ((1 << CC_MAX_ROWS) - 1)
168 
169 #define VBI_TRANSLUCENT VBI_SEMI_TRANSPARENT
170 
171 struct cc_timestamp {
172 	/* System time when the event occured, zero if no event
173 	   occured yet. */
174 	struct timeval		sys;
175 
176 	/* Presentation time stamp of the event. Only the 33 least
177 	   significant bits are valid. < 0 if no event occured yet. */
178 	int64_t			pts;
179 };
180 
181 struct cc_channel {
182 	/**
183 	 * [0] and [1] are the displayed and non-displayed buffer as
184 	 * defined in 47 CFR 15.119, and selected by displayed_buffer
185 	 * below. [2] is a snapshot of the displayed buffer at the
186 	 * last stream event.
187 	 *
188 	 * XXX Text channels don't need buffer[2] and buffer[3], we're
189 	 * wasting memory.
190 	 */
191 	uint16_t		buffer[3][CC_MAX_ROWS][1 + CC_MAX_COLUMNS];
192 
193 	/**
194 	 * For buffer[0 ... 2], if bit 1 << row is set this row
195 	 * contains displayable characters, spacing or non-spacing
196 	 * attributes. (Special character 0x1139 "transparent space"
197 	 * is not a displayable character.) This information is
198 	 * intended to speed up copying, erasing and formatting.
199 	 */
200 	unsigned int		dirty[3];
201 
202 	/** Index of displayed buffer, 0 or 1. */
203 	unsigned int		displayed_buffer;
204 
205 	/**
206 	 * Cursor position: FIRST_ROW ... LAST_ROW and
207 	 * FIRST_COLUMN ... LAST_COLUMN.
208 	 */
209 	unsigned int		curr_row;
210 	unsigned int		curr_column;
211 
212 	/**
213 	 * Text window height in CC_MODE_ROLL_UP. The first row of the
214 	 * window is curr_row - window_rows + 1, the last row is
215 	 * curr_row.
216 	 *
217 	 * Note: curr_row - window_rows + 1 may be < FIRST_ROW, this
218 	 * must be clipped before using window_rows:
219 	 *
220 	 * actual_rows = MIN (curr_row - FIRST_ROW + 1, window_rows);
221 	 *
222 	 * We won't do that at the RUx command because usually a PAC
223 	 * follows which may change curr_row.
224 	 */
225 	unsigned int		window_rows;
226 
227 	/* Most recently received PAC command. */
228 	unsigned int		last_pac;
229 
230 	/**
231 	 * This variable counts successive transmissions of the
232 	 * letters A to Z. It is reset to zero on reception of any
233 	 * letter a to z.
234 	 *
235 	 * Some stations do not transmit EIA 608-B extended characters
236 	 * and except for N with tilde the standard and special
237 	 * character sets contain only lower case accented
238 	 * characters. We force these characters to upper case if this
239 	 * variable indicates live caption, which is usually all upper
240 	 * case.
241 	 */
242 	unsigned int		uppercase_predictor;
243 
244 	/** Current caption mode or CC_MODE_UNKNOWN. */
245 	enum cc_mode		mode;
246 
247 	/**
248 	 * The time when we last received data for this
249 	 * channel. Intended to detect if this caption channel is
250 	 * active.
251 	 */
252 	struct cc_timestamp	timestamp;
253 
254 	/**
255 	 * The time when we received the first (but not necessarily
256 	 * leftmost) character in the current row. Unless the mode is
257 	 * CC_MODE_POP_ON the next stream event will carry this
258 	 * timestamp.
259 	 */
260 	struct cc_timestamp	timestamp_c0;
261 };
262 
263 struct cc_decoder {
264 	/**
265 	 * Decoder state. We decode all channels in parallel, this way
266 	 * clients can switch between channels without data loss, or
267 	 * capture multiple channels with a single decoder instance.
268 	 *
269 	 * Also 47 CFR 15.119 and EIA 608-C require us to remember the
270 	 * cursor position on each channel.
271 	 */
272 	struct cc_channel	channel[MAX_CC_CHANNELS];
273 
274 	/**
275 	 * Current channel, switched by caption control codes. Can be
276 	 * one of @c VBI_CAPTION_CC1 ... @c VBI_CAPTION_CC4 or @c
277 	 * VBI_CAPTION_T1 ... @c VBI_CAPTION_T4 or @c
278 	 * UNKNOWN_CC_CHANNEL if no channel number was received yet.
279 	 */
280 	vbi_pgno		curr_ch_num[MAX_FIELDS];
281 
282 	/**
283 	 * Caption control codes (two bytes) may repeat once for error
284 	 * correction. -1 if no repeated control code can be expected.
285 	 */
286 	int			expect_ctrl[MAX_FIELDS][2];
287 
288 	/** Receiving XDS data, as opposed to caption / ITV data. */
289 	vbi_bool		in_xds[MAX_FIELDS];
290 
291 	/**
292 	 * Pointer into the channel[] array if a display update event
293 	 * shall be sent at the end of this iteration, %c NULL
294 	 * otherwise. Purpose is to suppress an event for the first of
295 	 * two displayable characters in a caption byte pair.
296 	 */
297 	struct cc_channel *	event_pending;
298 
299 	/**
300 	 * Remembers past parity errors: One bit for each call of
301 	 * cc_feed(), most recent result in lsb. The idea is to
302 	 * disable the decoder if we detect too many errors.
303 	 */
304 	unsigned int		error_history;
305 
306 	/**
307 	 * The time when we last received data, including NUL bytes.
308 	 * Intended to detect if the station transmits any data on
309 	 * line 21 or 284 at all.
310 	 */
311 	struct cc_timestamp	timestamp;
312 };
313 
314 /* CEA 708-C decoder. */
315 
316 enum justify {
317 	JUSTIFY_LEFT = 0,
318 	JUSTIFY_RIGHT,
319 	JUSTIFY_CENTER,
320 	JUSTIFY_FULL
321 };
322 
323 enum direction {
324 	DIR_LEFT_RIGHT = 0,
325 	DIR_RIGHT_LEFT,
326 	DIR_TOP_BOTTOM,
327 	DIR_BOTTOM_TOP
328 };
329 
330 enum display_effect {
331 	DISPLAY_EFFECT_SNAP = 0,
332 	DISPLAY_EFFECT_FADE,
333 	DISPLAY_EFFECT_WIPE
334 };
335 
336 enum opacity {
337 	OPACITY_SOLID = 0,
338 	OPACITY_FLASH,
339 	OPACITY_TRANSLUCENT,
340 	OPACITY_TRANSPARENT
341 };
342 
343 enum edge {
344 	EDGE_NONE = 0,
345 	EDGE_RAISED,
346 	EDGE_DEPRESSED,
347 	EDGE_UNIFORM,
348 	EDGE_SHADOW_LEFT,
349 	EDGE_SHADOW_RIGHT
350 };
351 
352 enum pen_size {
353 	PEN_SIZE_SMALL = 0,
354 	PEN_SIZE_STANDARD,
355 	PEN_SIZE_LARGE
356 };
357 
358 enum font_style {
359 	FONT_STYLE_DEFAULT = 0,
360 	FONT_STYLE_MONO_SERIF,
361 	FONT_STYLE_PROP_SERIF,
362 	FONT_STYLE_MONO_SANS,
363 	FONT_STYLE_PROP_SANS,
364 	FONT_STYLE_CASUAL,
365 	FONT_STYLE_CURSIVE,
366 	FONT_STYLE_SMALL_CAPS
367 };
368 
369 enum text_tag {
370 	TEXT_TAG_DIALOG = 0,
371 	TEXT_TAG_SOURCE_ID,
372 	TEXT_TAG_DEVICE,
373 	TEXT_TAG_DIALOG_2,
374 	TEXT_TAG_VOICEOVER,
375 	TEXT_TAG_AUDIBLE_TRANSL,
376 	TEXT_TAG_SUBTITLE_TRANSL,
377 	TEXT_TAG_VOICE_DESCR,
378 	TEXT_TAG_LYRICS,
379 	TEXT_TAG_EFFECT_DESCR,
380 	TEXT_TAG_SCORE_DESCR,
381 	TEXT_TAG_EXPLETIVE,
382 	TEXT_TAG_NOT_DISPLAYABLE = 15
383 };
384 
385 enum offset {
386 	OFFSET_SUBSCRIPT = 0,
387 	OFFSET_NORMAL,
388 	OFFSET_SUPERSCRIPT
389 };
390 
391 /* RGB 2:2:2 (lsb = B). */
392 typedef uint8_t			dtvcc_color;
393 
394 /* Lsb = window 0, msb = window 7. */
395 typedef uint8_t			dtvcc_window_map;
396 
397 struct dtvcc_pen_style {
398 	enum pen_size			pen_size;
399 	enum font_style			font_style;
400 	enum offset			offset;
401 	vbi_bool			italics;
402 	vbi_bool			underline;
403 
404 	enum edge			edge_type;
405 
406 	dtvcc_color			fg_color;
407 	enum opacity			fg_opacity;
408 
409 	dtvcc_color			bg_color;
410 	enum opacity			bg_opacity;
411 
412 	dtvcc_color			edge_color;
413 };
414 
415 struct dtvcc_pen {
416 	enum text_tag			text_tag;
417 	struct dtvcc_pen_style		style;
418 };
419 
420 struct dtvcc_window_style {
421 	enum justify			justify;
422 	enum direction			print_direction;
423 	enum direction			scroll_direction;
424 	vbi_bool			wordwrap;
425 
426 	enum display_effect		display_effect;
427 	enum direction			effect_direction;
428 	unsigned int			effect_speed; /* 1/10 sec */
429 
430 	dtvcc_color			fill_color;
431 	enum opacity			fill_opacity;
432 
433 	enum edge			border_type;
434 	dtvcc_color			border_color;
435 };
436 
437 struct dtvcc_window {
438 	/* EIA 708-C window state. */
439 
440 	uint16_t			buffer[16][42];
441 
442 	vbi_bool			visible;
443 
444 	/* 0 = highest ... 7 = lowest. */
445 	unsigned int			priority;
446 
447 	unsigned int			anchor_point;
448 	unsigned int			anchor_horizontal;
449 	unsigned int			anchor_vertical;
450 	vbi_bool			anchor_relative;
451 
452 	unsigned int			row_count;
453 	unsigned int			column_count;
454 
455 	vbi_bool			row_lock;
456 	vbi_bool			column_lock;
457 
458 	unsigned int			curr_row;
459 	unsigned int			curr_column;
460 
461 	struct dtvcc_pen		curr_pen;
462 
463 	struct dtvcc_window_style	style;
464 
465 	/* Our stuff. */
466 
467 	/**
468 	 * If bit 1 << row is set we already sent a stream event for
469 	 * this row.
470 	 */
471 	unsigned int			streamed;
472 
473 	/**
474 	 * The time when we received the first (but not necessarily
475 	 * leftmost) character in the current row. Unless a
476 	 * DisplayWindow or ToggleWindow command completed the line
477 	 * the next stream event will carry this timestamp.
478 	 */
479 	struct cc_timestamp		timestamp_c0;
480 };
481 
482 struct dtvcc_service {
483 	/* Interpretation Layer. */
484 
485 	struct dtvcc_window		window[8];
486 
487 	struct dtvcc_window *		curr_window;
488 
489 	dtvcc_window_map		created;
490 
491 	/* For debugging. */
492 	unsigned int			error_line;
493 
494 	/* Service Layer. */
495 
496 	uint8_t				service_data[128];
497 	unsigned int			service_data_in;
498 
499 	/** The time when we last received data for this service. */
500 	struct cc_timestamp		timestamp;
501 };
502 
503 struct dtvcc_decoder {
504 	struct dtvcc_service		service[2];
505 
506 	/* Packet Layer. */
507 
508 	uint8_t				packet[128];
509 	unsigned int			packet_size;
510 
511 	/* Next expected DTVCC packet sequence_number. Only the two
512 	   most significant bits are valid. < 0 if no sequence_number
513 	   has been received yet. */
514 	int				next_sequence_number;
515 
516 	/** The time when we last received data. */
517 	struct cc_timestamp		timestamp;
518 };
519 
520 /* ATSC A/53 Part 4:2007 Closed Caption Data decoder. */
521 
522 enum cc_type {
523 	NTSC_F1 = 0,
524 	NTSC_F2 = 1,
525 	DTVCC_DATA = 2,
526 	DTVCC_START = 3,
527 };
528 
529 struct cc_data_decoder {
530 	/* Test tap. */
531 	const char *			option_cc_data_tap_file_name;
532 
533 	FILE *				cc_data_tap_fp;
534 
535 	/* For debugging. */
536 	int64_t				last_pts;
537 };
538 
539 /* Caption recorder. */
540 
541 enum cc_attr {
542 	VBI_UNDERLINE	= (1 << 0),
543 	VBI_ITALIC	= (1 << 2),
544 	VBI_FLASH	= (1 << 3)
545 };
546 
547 struct cc_pen {
548 	uint8_t				attr;
549 
550 	uint8_t				fg_color;
551 	uint8_t				fg_opacity;
552 
553 	uint8_t				bg_color;
554 	uint8_t				bg_opacity;
555 
556 	uint8_t				edge_type;
557 	uint8_t				edge_color;
558 	uint8_t				edge_opacity;
559 
560 	uint8_t				pen_size;
561 	uint8_t				font_style;
562 
563 	uint8_t				reserved[6];
564 };
565 
566 enum caption_format {
567 	FORMAT_PLAIN,
568 	FORMAT_VT100,
569 	FORMAT_NTSC_CC
570 };
571 
572 struct caption_recorder {
573 	/* Caption stream filter:
574 	   NTSC CC1 ... CC4	(1 << 0 ... 1 << 3),
575 	   NTSC T1 ... T4	(1 << 4 ... 1 << 7),
576 	   ATSC Service 1 ... 2	(1 << 8 ... 1 << 9). */
577 	unsigned int			option_caption_mask;
578 
579 	/* Output file name for caption stream. */
580 	const char *			option_caption_file_name[10];
581 
582 	/* Output file name for XDS data. */
583 	const char *			option_xds_output_file_name;
584 
585 	vbi_bool			option_caption_timestamps;
586 
587 	enum caption_format		option_caption_format;
588 
589 /* old options */
590 char usexds;
591 char usecc;
592 char usesen;
593 char usewebtv;
594 
595 	struct cc_data_decoder		ccd;
596 
597 	struct cc_decoder		cc;
598 
599 	struct dtvcc_decoder		dtvcc;
600 
601 //XDSdecode
602 unsigned int field;
603 struct {
604 	char				packet[34];
605 	uint8_t				length;
606 	int				print : 1;
607 }				info[2][8][25];
608 char	newinfo[2][8][25][34];
609 char	*infoptr;
610 int	mode,type;
611 char	infochecksum;
612 const char *		xds_info_prefix;
613 const char *		xds_info_suffix;
614 FILE *			xds_fp;
615 
616 	uint16_t *			ucs_buffer;
617 	unsigned int			ucs_buffer_length;
618 	unsigned int			ucs_buffer_capacity;
619 
620 	FILE *				caption_fp[10];
621 
622 	int				minicut_min[10];
623 };
624 
625 /* Video recorder. */
626 
627 enum start_code {
628 	PICTURE_START_CODE = 0x00,
629 	/* 0x01 ... 0xAF slice_start_code */
630 	/* 0xB0 reserved */
631 	/* 0xB1 reserved */
632 	USER_DATA_START_CODE = 0xB2,
633 	SEQUENCE_HEADER_CODE = 0xB3,
634 	SEQUENCE_ERROR_CODE = 0xB4,
635 	EXTENSION_START_CODE = 0xB5,
636 	/* 0xB6 reserved */
637 	SEQUENCE_END_CODE = 0xB7,
638 	GROUP_START_CODE = 0xB8,
639 	/* 0xB9 ... 0xFF system start codes */
640 	PRIVATE_STREAM_1 = 0xBD,
641 	PADDING_STREAM = 0xBE,
642 	PRIVATE_STREAM_2 = 0xBF,
643 	AUDIO_STREAM_0 = 0xC0,
644 	AUDIO_STREAM_31 = 0xDF,
645 	VIDEO_STREAM_0 = 0xE0,
646 	VIDEO_STREAM_15 = 0xEF,
647 };
648 
649 enum extension_start_code_identifier {
650 	/* 0x0 reserved */
651 	SEQUENCE_EXTENSION_ID = 0x1,
652 	SEQUENCE_DISPLAY_EXTENSION_ID = 0x2,
653 	QUANT_MATRIX_EXTENSION_ID = 0x3,
654 	COPYRIGHT_EXTENSION_ID = 0x4,
655 	SEQUENCE_SCALABLE_EXTENSION_ID = 0x5,
656 	/* 0x6 reserved */
657 	PICTURE_DISPLAY_EXTENSION_ID = 0x7,
658 	PICTURE_CODING_EXTENSION_ID = 0x8,
659 	PICTURE_SPATIAL_SCALABLE_EXTENSION_ID = 0x9,
660 	PICTURE_TEMPORAL_SCALABLE_EXTENSION_ID = 0xA,
661 	/* 0xB ... 0xF reserved */
662 };
663 
664 enum picture_coding_type {
665 	/* 0 forbidden */
666 	I_TYPE = 1,
667 	P_TYPE = 2,
668 	B_TYPE = 3,
669 	D_TYPE = 4,
670 	/* 5 ... 7 reserved */
671 };
672 
673 enum picture_structure {
674 	/* 0 reserved */
675 	TOP_FIELD = 1,
676 	BOTTOM_FIELD = 2,
677 	FRAME_PICTURE = 3
678 };
679 
680 /* PTSs and DTSs are 33 bits wide. */
681 #define TIMESTAMP_MASK (((int64_t) 1 << 33) - 1)
682 
683 struct packet {
684 	/* Offset in bytes from the buffer start. */
685 	unsigned int			offset;
686 
687 	/* Packet and payload size in bytes. */
688 	unsigned int			size;
689 	unsigned int			payload;
690 
691 	/* Decoding and presentation time stamp and display duration
692 	   of this packet. */
693 	int64_t				dts;
694 	int64_t				pts;
695 	int64_t				duration;
696 
697 	/* Cut the stream at this packet. */
698 	vbi_bool			splice;
699 
700 	/* Data is missing before this packet but the producer will
701 	   correct that later. */
702 	vbi_bool			data_lost;
703 };
704 
705 struct buffer {
706 	uint8_t *			base;
707 
708 	/* Capacity of the buffer in bytes. */
709 	unsigned int			capacity;
710 
711 	/* Offset in bytes from base where the next data will be
712 	   stored. */
713 	unsigned int			in;
714 
715 	/* Offset in bytes from base where the next data will be
716 	   removed. */
717 	unsigned int			out;
718 };
719 
720 #define MAX_PACKETS 64
721 
722 struct pes_buffer {
723 	uint8_t *			base;
724 
725 	/* Capacity of the buffer in bytes. */
726 	unsigned int			capacity;
727 
728 	/* Offset in bytes from base where the next data will be stored. */
729 	unsigned int			in;
730 
731 	/* Information about the packets in the buffer.
732 	   packet[0].offset is the offset in bytes from base
733 	   where the next data will be removed. */
734 	struct packet			packet[MAX_PACKETS];
735 
736 	/* Number of packets in the packet[] array. packet[0] must not
737 	   be removed unless n_packets >= 2. */
738 	unsigned int			n_packets;
739 };
740 
741 struct pes_multiplexer {
742 	vbi_bool			new_file;
743 	unsigned int			b_state;
744 
745 	time_t				minicut_end;
746 
747 	FILE *				minicut_fp;
748 };
749 
750 struct audio_es_packetizer {
751 	/* Test tap. */
752 	const char *			option_audio_es_tap_file_name;
753 	FILE *				audio_es_tap_fp;
754 
755 	struct buffer			ac3_buffer;
756 	struct pes_buffer		pes_buffer;
757 
758 	/* Number of bytes we want to examine at pes_buffer.in. */
759 	unsigned int			need;
760 
761 	/* Estimated PTS of the next/current AC3 frame (pts or
762 	   pes_packet_pts plus previous frame duration), -1 if no PTS
763 	   was received yet. */
764 	int64_t				pts;
765 
766 	/* Next/current AC3 frame is the first received frame. */
767 	vbi_bool			first_frame;
768 
769 	/* Data may have been lost between the previous and
770 	   next/current AC3 frame. */
771 	vbi_bool			data_lost;
772 
773 	uint64_t			pes_audio_bit_rate;
774 };
775 
776 struct video_es_packetizer {
777 	struct pes_buffer		pes_buffer;
778 	int				sequence_header_offset;
779 	unsigned int			packet_filled;
780 	uint8_t				pes_packet_header_6;
781 	uint64_t			pes_video_bit_rate;
782 	vbi_bool			aligned;
783 };
784 
785 struct audio_pes_decoder {
786 	struct buffer			buffer;
787 
788 	unsigned int			need;
789 	unsigned int			look_ahead;
790 };
791 
792 struct video_recorder {
793 	struct audio_pes_decoder	apesd;
794 
795 	struct video_es_packetizer	vesp;
796 
797 	struct audio_es_packetizer	aesp;
798 
799 	struct pes_multiplexer		pm;
800 
801 	/* TS recorder */
802 
803 	unsigned int			pat_cc;
804 	unsigned int			pmt_cc;
805 
806 	time_t				minicut_end;
807 	FILE *				minicut_fp;
808 };
809 
810 enum received_blocks {
811 	RECEIVED_PES_PACKET		= (1 << 0),
812 	RECEIVED_PICTURE		= (1 << 1),
813 	RECEIVED_PICTURE_EXT		= (1 << 2),
814 	RECEIVED_MPEG_CC_DATA		= (1 << 3)
815 };
816 
817 struct video_es_decoder {
818 	/* Test tap. */
819 	const char *			option_video_es_all_tap_file_name;
820 	const char *			option_video_es_tap_file_name;
821 
822 	FILE *				video_es_tap_fp;
823 
824 	/* Video elementary stream buffer. */
825 	struct buffer			buffer;
826 
827 	unsigned int			min_bytes_valid;
828 
829 	/* Number of bytes after buffer.out which have already
830 	   been scanned for a start code prefix. */
831 	unsigned int			skip;
832 
833 	/* Last received start code, < 0 if none. If valid
834 	   buffer.out points at the first start code prefix
835 	   byte. */
836 	enum start_code			last_start_code;
837 
838 	/* The decoding and presentation time stamp of the
839 	   current picture. Only the lowest 33 bits are
840 	   valid. < 0 if no PTS or DTS was received or the PES
841 	   packet header was malformed. */
842 	int64_t				pts;
843 	int64_t				dts;
844 
845 	/* For debugging. */
846 	uint64_t			n_pictures_received;
847 
848 	/* Parameters of the current picture. */
849 	enum picture_coding_type	picture_coding_type;
850 	enum picture_structure		picture_structure;
851 	unsigned int			picture_temporal_reference;
852 
853 	/* Set of the data blocks we received so far. */
854 	enum received_blocks		received_blocks;
855 
856 	/* Describes the contents of the reorder_buffer[]:
857 	   Bit 0 - a top field in reorder_buffer[0],
858 	   Bit 1 - a bottom field in reorder_buffer[1],
859 	   Bit 2 - a frame in reorder_buffer[0]. Only the
860 	   combinations 0, 1, 2, 3, 4 are valid. */
861 	unsigned int			reorder_pictures;
862 
863 	/* The PTS (as above) of the data in the reorder_buffer. */
864 	int64_t				reorder_pts[2];
865 
866 	unsigned int			reorder_n_bytes[2];
867 
868 	/* Buffer to convert picture user data from coded
869 	   order to display order, for the top and bottom
870 	   field. Maximum size required: 11 + cc_count * 3,
871 	   where cc_count = 0 ... 31. */
872 	uint8_t				reorder_buffer[2][128];
873 };
874 
875 struct ts_decoder {
876 	/* TS PID of the video [0] and audio [1] stream. */
877 	unsigned int			pid[2];
878 
879 	/* Next expected video and audio TS packet continuity
880 	   counter. Only the lowest four bits are valid. < 0
881 	   if no continuity counter has been received yet. */
882 	int				next_ts_cc[2];
883 
884 	/* One or more TS packets were lost. */
885 	vbi_bool			data_lost;
886 }					tsd;
887 
888 struct program {
889 	const char *			option_station_name;
890 
891 	/* Convert the captured video and audio data to PES format,
892 	   cut the stream into one minute long fragments and save them
893 	   with file name
894 	   <option_minicut_dir_name>/yyyymmddhh0000/yyyymmddhhmm00.mpg
895 	   One minute is measured in real time, yyyymmddhhmm is the
896 	   system time in the UTC zone when the data was received and
897 	   decoded. */
898 	const char *			option_minicut_dir_name;
899 
900 	struct timeval			now;
901 
902 	int64_t				first_dts;
903 
904 	struct ts_decoder		tsd;
905 
906 	struct video_es_decoder		vesd;
907 
908 	struct video_recorder		vr;
909 
910 	struct caption_recorder		cr;
911 };
912 
913 struct station {
914 	struct station *		next;
915 	char *				name;
916 	enum fe_type			type;
917 	unsigned long			frequency;
918 	unsigned int			video_pid;
919 	unsigned int			audio_pid;
920 	union {
921 		struct {
922 			enum fe_modulation		modulation;
923 		}				atsc;
924 		struct {
925 			enum fe_spectral_inversion	inversion;
926 			enum fe_bandwidth		bandwidth;
927 			enum fe_code_rate		code_rate_HP;
928 			enum fe_code_rate		code_rate_LP;
929 			enum fe_modulation		constellation;
930 			enum fe_transmit_mode		transm_mode;
931 			enum fe_guard_interval		guard_interval;
932 			enum fe_hierarchy		hierarchy;
933 		}				dvb_t;
934 	}				u;
935 };
936 
937 enum debug {
938 	DEBUG_VESD_START_CODE		= (1 << 0),
939 	DEBUG_VESD_PES_PACKET		= (1 << 1),
940 	DEBUG_VESD_PIC_HDR		= (1 << 2),
941 	DEBUG_VESD_PIC_EXT		= (1 << 3),
942 	DEBUG_VESD_USER_DATA		= (1 << 5),
943 	DEBUG_VESD_CC_DATA		= (1 << 6),
944 	DEBUG_CC_DATA			= (1 << 7),
945 	DEBUG_CC_F1			= (1 << 8),
946 	DEBUG_CC_F2			= (1 << 9),
947 	DEBUG_CC_DECODER		= (1 << 10),
948 	DEBUG_DTVCC_PACKET		= (1 << 11),
949 	DEBUG_DTVCC_SE			= (1 << 12),
950 	DEBUG_DTVCC_PUT_CHAR		= (1 << 13),
951 	DEBUG_DTVCC_STREAM_EVENT	= (1 << 14),
952 	DEBUG_CONFIG			= (1 << 15)
953 };
954 
955 enum source {
956 	SOURCE_DVB_DEVICE = 1,
957 	SOURCE_STDIN_TS,
958 
959 	/* Not implemented yet. */
960 	SOURCE_STDIN_PES,
961 
962 	/* For tests only. */
963 	SOURCE_STDIN_VIDEO_ES,
964 	SOURCE_STDIN_CC_DATA
965 };
966 
967 static const char *		my_name;
968 
969 static unsigned int		option_verbosity;
970 static unsigned int		option_debug;
971 
972 /* Input. */
973 
974 static enum source		option_source;
975 
976 /* DVB device. */
977 
978 static enum fe_type		option_dvb_type;
979 static unsigned long		option_dvb_adapter_num;
980 static unsigned long		option_dvb_frontend_id;
981 static unsigned long		option_dvb_demux_id;
982 static unsigned long		option_dvb_dvr_id;
983 
984 static const char *		option_channel_conf_file_name;
985 
986 /* Test taps. */
987 const char *			option_ts_all_tap_file_name;
988 const char *			option_ts_tap_file_name;
989 
990 static vbi_bool			option_minicut_test;
991 
992 static const char *		locale_codeset;
993 
994 /* DVB devices. */
995 static int			fe_fd;		/* frontend */
996 static int			dvr_fd;		/* data stream */
997 static int			dmx_fd;		/* demultiplexer */
998 
999 /* Capture thread. */
1000 
1001 static pthread_t		capture_thread_id;
1002 
1003 /* The read buffer of the capture thread. */
1004 static uint8_t *		ct_buffer;
1005 static unsigned int		ct_buffer_capacity;
1006 
1007 /* For debugging. */
1008 static uint64_t			ct_n_bytes_in;
1009 
1010 /* Transport stream decoder. */
1011 
1012 /* static pthread_t		demux_thread_id; */
1013 
1014 /* Transport stream buffer. The capture thread stores TS packets at
1015    ts_buffer_in, the TS decoder removes packets from ts_buffer_out,
1016    and increments the respective pointer by the number of bytes
1017    transferred. The input and output pointers jump back to the start
1018    of the buffer before they would exceed ts_buffer_capacity (wraps at
1019    packet, not byte granularity).  The buffer is empty if ts_buffer_in
1020    equals ts_buffer_out. */
1021 static uint8_t *		ts_buffer;
1022 static unsigned int		ts_buffer_capacity;
1023 static volatile unsigned int	ts_buffer_in;
1024 static volatile unsigned int	ts_buffer_out;
1025 
1026 static uint8_t			ts_error;
1027 
1028 /* For debugging. */
1029 static uint64_t			ts_n_packets_in;
1030 
1031 /* Test tap into the transport stream. */
1032 static FILE *			ts_tap_fp;
1033 
1034 /* Notifies the TS decoder when data is available in the ts_buffer. */
1035 static pthread_mutex_t		dx_mutex;
1036 static pthread_cond_t		dx_cond;
1037 
1038 /* If pid_map[].program < 0, no TS packet with PID n is needed and the
1039    capture thread will drop the packet. Otherwise pid_map[].program is
1040    an index into the programs[] table. This information is used by the
1041    TS decoder to separate multiple video streams. */
1042 static struct {
1043 	int8_t				program;
1044 } 				pid_map[0x2000];
1045 
1046 /* The programs we want to record. */
1047 static struct program		program_table[12];
1048 static unsigned int		n_programs;
1049 
1050 /* A list of stations found in the channel.conf file. */
1051 static struct station *		station_list;
1052 
1053 /* Any station on the selected transponder. */
1054 static struct station *		station;
1055 
1056 static void
1057 list_stations			(void);
1058 static void
1059 init_cc_decoder			(struct cc_decoder *	cd);
1060 static void
1061 init_dtvcc_decoder		(struct dtvcc_decoder *	dc);
1062 static void
1063 init_cc_data_decoder		(struct cc_data_decoder *cd);
1064 
1065 #define CASE(x) case x: return #x;
1066 
1067 static const char *
picture_coding_type_name(enum picture_coding_type t)1068 picture_coding_type_name	(enum picture_coding_type t)
1069 {
1070 	switch (t) {
1071 	CASE (I_TYPE)
1072 	CASE (P_TYPE)
1073 	CASE (B_TYPE)
1074 	CASE (D_TYPE)
1075 	}
1076 
1077 	return "invalid";
1078 }
1079 
1080 static const char *
picture_structure_name(enum picture_structure t)1081 picture_structure_name		(enum picture_structure	t)
1082 {
1083 	switch (t) {
1084 	CASE (TOP_FIELD)
1085 	CASE (BOTTOM_FIELD)
1086 	CASE (FRAME_PICTURE)
1087 	}
1088 
1089 	return "invalid";
1090 }
1091 
1092 static const char *
cc_type_name(enum cc_type t)1093 cc_type_name			(enum cc_type		t)
1094 {
1095 	switch (t) {
1096 	CASE (NTSC_F1)
1097 	CASE (NTSC_F2)
1098 	CASE (DTVCC_DATA)
1099 	CASE (DTVCC_START)
1100 	}
1101 
1102 	return "invalid";
1103 }
1104 
1105 #undef CASE
1106 
1107 static int
printable(int c)1108 printable			(int			c)
1109 {
1110 	if ((c & 0x7F) < 0x20)
1111 		return '.';
1112 	else
1113 		return c & 0x7F;
1114 }
1115 
1116 static void
1117 dump				(FILE *			fp,
1118 				 const uint8_t *	buf,
1119 				 unsigned int		n_bytes)
1120   _vbi_unused;
1121 
1122 static void
dump(FILE * fp,const uint8_t * buf,unsigned int n_bytes)1123 dump				(FILE *			fp,
1124 				 const uint8_t *	buf,
1125 				 unsigned int		n_bytes)
1126 {
1127 	const unsigned int width = 16;
1128 	unsigned int i;
1129 
1130 	for (i = 0; i < n_bytes; i += width) {
1131 		unsigned int end;
1132 		unsigned int j;
1133 
1134 		end = MIN (i + width, n_bytes);
1135 		for (j = i; j < end; ++j)
1136 			fprintf (fp, "%02x ", buf[j]);
1137 		for (; j < i + width; ++j)
1138 			fputs ("   ", fp);
1139 		fputc (' ', fp);
1140 		for (j = i; j < end; ++j) {
1141 			int c = buf[j];
1142 			fputc (printable (c), fp);
1143 		}
1144 		fputc ('\n', fp);
1145 	}
1146 }
1147 
1148 #define log(verb, templ, args...) \
1149 	log_message (verb, /* print_errno */ FALSE, templ , ##args)
1150 
1151 #define log_errno(verb, templ, args...) \
1152 	log_message (verb, /* print_errno */ TRUE, templ , ##args)
1153 
1154 #define bug(templ, args...) \
1155 	log_message (1, /* print_errno */ FALSE, "BUG: " templ , ##args)
1156 
1157 static void
1158 log_message			(unsigned int		verbosity,
1159 				 vbi_bool		print_errno,
1160 				 const char *		templ,
1161 				 ...)
1162   _vbi_format ((printf, 3, 4));
1163 
1164 static void
log_message(unsigned int verbosity,vbi_bool print_errno,const char * templ,...)1165 log_message			(unsigned int		verbosity,
1166 				 vbi_bool		print_errno,
1167 				 const char *		templ,
1168 				 ...)
1169 {
1170 	if (verbosity <= option_verbosity) {
1171 		va_list ap;
1172 
1173 		va_start (ap, templ);
1174 
1175 		fprintf (stderr, "%s: ", my_name);
1176 		vfprintf (stderr, templ, ap);
1177 
1178 		if (print_errno) {
1179 			fprintf (stderr, ": %s.\n",
1180 				 strerror (errno));
1181 		}
1182 
1183 		va_end (ap);
1184 	}
1185 }
1186 
1187 #define error_exit(templ, args...) \
1188 	error_message_exit (/* print_errno */ FALSE, templ , ##args)
1189 
1190 #define errno_exit(templ, args...) \
1191 	error_message_exit (/* print_errno */ TRUE, templ , ##args)
1192 
1193 static void
1194 error_message_exit		(vbi_bool		print_errno,
1195 				 const char *		templ,
1196 				 ...)
1197   _vbi_format ((printf, 2, 3));
1198 
1199 static void
error_message_exit(vbi_bool print_errno,const char * templ,...)1200 error_message_exit		(vbi_bool		print_errno,
1201 				 const char *		templ,
1202 				 ...)
1203 {
1204 	if (option_verbosity > 0) {
1205 		va_list ap;
1206 
1207 		va_start (ap, templ);
1208 
1209 		fprintf (stderr, "%s: ", my_name);
1210 		vfprintf (stderr, templ, ap);
1211 
1212 		if (print_errno) {
1213 			fprintf (stderr, ": %s.\n",
1214 				 strerror (errno));
1215 		}
1216 
1217 		va_end (ap);
1218 	}
1219 
1220 	exit (EXIT_FAILURE);
1221 }
1222 
1223 static void
no_mem_exit(void)1224 no_mem_exit			(void)
1225 {
1226 	error_exit ("Out of memory.");
1227 }
1228 
1229 static void *
xmalloc(size_t size)1230 xmalloc				(size_t			size)
1231 {
1232 	void *p;
1233 
1234 	p = malloc (size);
1235 	if (NULL == p) {
1236 		no_mem_exit ();
1237 	}
1238 
1239 	return p;
1240 }
1241 
1242 static char *
1243 xasprintf			(const char *		templ,
1244 				 ...)
1245   _vbi_format ((printf, 1, 2));
1246 
1247 static char *
xasprintf(const char * templ,...)1248 xasprintf			(const char *		templ,
1249 				 ...)
1250 {
1251 	va_list ap;
1252 	char *s;
1253 	int r;
1254 
1255 	va_start (ap, templ);
1256 
1257 	r = vasprintf (&s, templ, ap);
1258 	if (r < 0 || NULL == s) {
1259 		no_mem_exit ();
1260 	}
1261 
1262 	va_end (ap);
1263 
1264 	return s;
1265 }
1266 
1267 static int
xioctl_may_fail(int fd,int request,void * arg)1268 xioctl_may_fail			(int			fd,
1269 				 int			request,
1270 				 void *			arg)
1271 {
1272 	int r;
1273 
1274 	do r = ioctl (fd, request, arg);
1275 	while (-1 == r && EINTR == errno);
1276 
1277 	return r;
1278 }
1279 
1280 #define xioctl(fd, request, arg)					\
1281 do {									\
1282 	int r;								\
1283 									\
1284 	r = xioctl_may_fail (fd, request, arg);				\
1285 	if (-1 == r) {							\
1286 		errno_exit (#request " failed");			\
1287 	}								\
1288 } while (0)
1289 
1290 static FILE *
open_output_file(const char * name)1291 open_output_file		(const char *		name)
1292 {
1293 	FILE *fp;
1294 
1295 	if (NULL == name || 0 == strcmp (name, "-")) {
1296 		fp = stdout;
1297 	} else {
1298 		fp = fopen (name, "a");
1299 		if (NULL == fp) {
1300 			errno_exit ("Cannot open output file '%s'",
1301 				    name);
1302 		}
1303 	}
1304 
1305 	return fp;
1306 }
1307 
1308 static FILE *
open_test_file(const char * name)1309 open_test_file			(const char *		name)
1310 {
1311 	FILE *fp;
1312 
1313 	if (NULL == name || 0 == strcmp (name, "-")) {
1314 		fp = stdin;
1315 	} else {
1316 		fp = fopen (name, "r");
1317 		if (NULL == fp) {
1318 			errno_exit ("Cannot open test file '%s'",
1319 				    name);
1320 		}
1321 	}
1322 
1323 	return fp;
1324 }
1325 
1326 static FILE *
open_minicut_file(struct program * pr,const struct tm * tm,const char * file_name,const char * extension)1327 open_minicut_file		(struct program *	pr,
1328 				 const struct tm *	tm,
1329 				 const char *		file_name,
1330 				 const char *		extension)
1331 {
1332 	char dir_name[32];
1333 	size_t base_len;
1334 	size_t dir_len;
1335 	char *buf;
1336 	struct stat st;
1337 	unsigned int i;
1338 	FILE *fp;
1339 
1340 	base_len = strlen (pr->option_minicut_dir_name);
1341 
1342 	dir_len = snprintf (dir_name, sizeof (dir_name),
1343 			    "/%04u%02u%02u%02u0000",
1344 			    tm->tm_year + 1900,
1345 			    tm->tm_mon + 1,
1346 			    tm->tm_mday,
1347 			    tm->tm_hour);
1348 
1349 	buf = xmalloc (base_len + dir_len
1350 		       + strlen (file_name) + 2
1351 		       + strlen (extension) + 1);
1352 
1353 	strcpy (buf, pr->option_minicut_dir_name);
1354 	if (0 != stat (buf, &st)) {
1355 		errno_exit ("Cannot open '%s'", buf);
1356 	} else if (!S_ISDIR(st.st_mode)) {
1357 		error_exit ("'%s' is not a directory.\n", buf);
1358 	}
1359 
1360 	strcpy (buf + base_len, dir_name);
1361 	if (0 != stat (buf, &st)) {
1362 		if (ENOENT != errno)
1363 			errno_exit ("Cannot open '%s'", buf);
1364 		if (-1 == mkdir (buf, /* mode */ 0777))
1365 			errno_exit ("Cannot create '%s'", buf);
1366 	} else if (!S_ISDIR(st.st_mode)) {
1367 		error_exit ("'%s' is not a directory.\n", buf);
1368 	}
1369 
1370 	for (i = 0; i < 100; ++i) {
1371 		int fd;
1372 
1373 		if (0 == i) {
1374 			sprintf (buf + base_len + dir_len,
1375 				 "%s%s",
1376 				 file_name, extension);
1377 		} else {
1378 			sprintf (buf + base_len + dir_len,
1379 				 "%s-%u%s",
1380 				 file_name, i, extension);
1381 		}
1382 
1383 		fd = open64 (buf, (O_CREAT | O_EXCL |
1384 				   O_LARGEFILE | O_WRONLY), 0666);
1385 		if (fd >= 0) {
1386 			fp = fdopen (fd, "w");
1387 			if (NULL == fp)
1388 				goto failed;
1389 
1390 			log (2, "Opened '%s'.\n", buf);
1391 
1392 			free (buf);
1393 
1394 			return fp;
1395 		}
1396 
1397 		if (EEXIST == errno)
1398 			continue;
1399 		if (ENOSPC == errno)
1400 			break;
1401 
1402 	failed:
1403 		errno_exit ("Cannot open output file '%s'", buf);
1404 	}
1405 
1406 	free (buf);
1407 
1408 	/* Will try again later. */
1409 	log_errno (1, "Cannot open output file '%s'", buf);
1410 
1411 	return NULL;
1412 }
1413 
1414 static unsigned int
station_num(struct program * pr)1415 station_num			(struct program *	pr)
1416 {
1417 	return (pr - program_table) + 1;
1418 }
1419 
1420 /* Caption recorder */
1421 
1422 static const char *
1423 cr_file_name_suffix [10] = {
1424 	"-cc1", "-cc2", "-cc3", "-cc4",
1425 	"-t1", "-t2", "-t3", "-t4",
1426 	"-s1", "-s2"
1427 };
1428 
1429 static void
cr_grow_buffer(struct caption_recorder * cr,unsigned int n_chars)1430 cr_grow_buffer			(struct caption_recorder *cr,
1431 				 unsigned int		n_chars)
1432 {
1433 	uint16_t *new_buffer;
1434 	size_t min_size;
1435 	size_t new_size;
1436 
1437 	if (likely (cr->ucs_buffer_length + n_chars
1438 		    <= cr->ucs_buffer_capacity))
1439 		return;
1440 
1441 	min_size = (cr->ucs_buffer_length + n_chars) * 2;
1442 	min_size = MAX ((size_t) 64, min_size);
1443 	new_size = MAX (min_size, (size_t) cr->ucs_buffer_capacity * 4);
1444 
1445 	new_buffer = realloc (cr->ucs_buffer, new_size);
1446 	if (NULL == new_buffer)
1447 		no_mem_exit ();
1448 
1449 	cr->ucs_buffer = new_buffer;
1450 	cr->ucs_buffer_capacity = new_size / 2;
1451 }
1452 
1453 static void
cr_putuc(struct caption_recorder * cr,uint16_t uc)1454 cr_putuc			(struct caption_recorder *cr,
1455 				 uint16_t		uc)
1456 {
1457 	cr_grow_buffer (cr, 1);
1458 	cr->ucs_buffer[cr->ucs_buffer_length++] = uc;
1459 }
1460 
1461 static void
cr_puts(struct caption_recorder * cr,const char * s)1462 cr_puts				(struct caption_recorder *cr,
1463 				 const char *		s)
1464 {
1465 	while (0 != *s)
1466 		cr_putuc (cr, *s++);
1467 }
1468 
1469 _vbi_inline void
vbi_char_copy_attr(struct vbi_char * cp1,struct vbi_char * cp2,unsigned int attr)1470 vbi_char_copy_attr		(struct vbi_char *	cp1,
1471 				 struct vbi_char *	cp2,
1472 				 unsigned int		attr)
1473 {
1474 	if (attr & VBI_UNDERLINE)
1475 		cp1->underline = cp2->underline;
1476 	if (attr & VBI_ITALIC)
1477 		cp1->italic = cp2->italic;
1478 	if (attr & VBI_FLASH)
1479 		cp1->flash = cp2->flash;
1480 }
1481 
1482 _vbi_inline void
vbi_char_clear_attr(struct vbi_char * cp,unsigned int attr)1483 vbi_char_clear_attr		(struct vbi_char *	cp,
1484 				 unsigned int		attr)
1485 {
1486 	if (attr & VBI_UNDERLINE)
1487 		cp->underline = 0;
1488 	if (attr & VBI_ITALIC)
1489 		cp->italic = 0;
1490 	if (attr & VBI_FLASH)
1491 		cp->flash = 0;
1492 }
1493 
1494 _vbi_inline void
vbi_char_set_attr(struct vbi_char * cp,unsigned int attr)1495 vbi_char_set_attr		(struct vbi_char *	cp,
1496 				 unsigned int		attr)
1497 {
1498 	if (attr & VBI_UNDERLINE)
1499 		cp->underline = 1;
1500 	if (attr & VBI_ITALIC)
1501 		cp->italic = 1;
1502 	if (attr & VBI_FLASH)
1503 		cp->flash = 1;
1504 }
1505 
1506 _vbi_inline unsigned int
vbi_char_has_attr(struct vbi_char * cp,unsigned int attr)1507 vbi_char_has_attr		(struct vbi_char *	cp,
1508 				 unsigned int		attr)
1509 {
1510 	attr &= (VBI_UNDERLINE | VBI_ITALIC | VBI_FLASH);
1511 
1512 	if (0 == cp->underline)
1513 		attr &= ~VBI_UNDERLINE;
1514 	if (0 == cp->italic)
1515 		attr &= ~VBI_ITALIC;
1516 	if (0 == cp->flash)
1517 		attr &= ~VBI_FLASH;
1518 
1519 	return attr;
1520 }
1521 
1522 _vbi_inline unsigned int
vbi_char_xor_attr(struct vbi_char * cp1,struct vbi_char * cp2,unsigned int attr)1523 vbi_char_xor_attr		(struct vbi_char *	cp1,
1524 				 struct vbi_char *	cp2,
1525 				 unsigned int		attr)
1526 {
1527 	attr &= (VBI_UNDERLINE | VBI_ITALIC | VBI_FLASH);
1528 
1529 	if (0 == (cp1->underline ^ cp2->underline))
1530 		attr &= ~VBI_UNDERLINE;
1531 	if (0 == (cp1->italic ^ cp2->italic))
1532 		attr &= ~VBI_ITALIC;
1533 	if (0 == (cp1->flash ^ cp2->flash))
1534 		attr &= ~VBI_FLASH;
1535 
1536 	return attr;
1537 }
1538 
1539 static vbi_bool
cr_put_attr(struct caption_recorder * cr,vbi_char * prev,vbi_char curr)1540 cr_put_attr			(struct caption_recorder *cr,
1541 				 vbi_char *		prev,
1542 				 vbi_char		curr)
1543 {
1544 	uint16_t *d;
1545 
1546 	switch (cr->option_caption_format) {
1547 	case FORMAT_PLAIN:
1548 		return TRUE;
1549 
1550 	case FORMAT_NTSC_CC:
1551 		/* Same output as the [zvbi-]ntsc-cc app. */
1552 
1553 		curr.opacity = VBI_OPAQUE;
1554 
1555 		/* Use the default foreground and background color of
1556 		   the terminal. */
1557 		curr.foreground = -1;
1558 		curr.background = -1;
1559 
1560 		if (vbi_char_has_attr (&curr, VBI_ITALIC))
1561 			curr.foreground = VBI_CYAN;
1562 
1563 		vbi_char_clear_attr (&curr, VBI_ITALIC | VBI_FLASH);
1564 
1565 		break;
1566 
1567 	case FORMAT_VT100:
1568 		break;
1569 	}
1570 
1571 	cr_grow_buffer (cr, 32);
1572 
1573 	d = cr->ucs_buffer + cr->ucs_buffer_length;
1574 
1575 	/* Control sequences based on ECMA-48,
1576 	   http://www.ecma-international.org/ */
1577 
1578 	/* SGR sequence */
1579 
1580 	d[0] = 27; /* CSI */
1581 	d[1] = '[';
1582 	d += 2;
1583 
1584 	switch (curr.opacity) {
1585 	case VBI_TRANSPARENT_SPACE:
1586 		vbi_char_clear_attr (&curr, -1);
1587 		curr.foreground = -1;
1588 		curr.background = -1;
1589 		break;
1590 
1591 	case VBI_TRANSPARENT_FULL:
1592 		curr.background = -1;
1593 		break;
1594 
1595 	case VBI_SEMI_TRANSPARENT:
1596 	case VBI_OPAQUE:
1597 		break;
1598 	}
1599 
1600 	if ((prev->foreground != curr.foreground
1601 	     && (uint8_t) -1 == curr.foreground)
1602 	    || (prev->background != curr.background
1603 		&& (uint8_t) -1 == curr.background)) {
1604 		*d++ = ';'; /* "[0m;" reset */
1605 		vbi_char_clear_attr (prev, -1);
1606 		prev->foreground = -1;
1607 		prev->background = -1;
1608 	}
1609 
1610 	if (vbi_char_xor_attr (prev, &curr, VBI_ITALIC)) {
1611 		if (!vbi_char_has_attr (&curr, VBI_ITALIC))
1612 			*d++ = '2'; /* off */
1613 		d[0] = '3'; /* italic */
1614 		d[1] = ';';
1615 		d += 2;
1616 	}
1617 
1618 	if (vbi_char_xor_attr (prev, &curr, VBI_UNDERLINE)) {
1619 		if (!vbi_char_has_attr (&curr, VBI_UNDERLINE))
1620 			*d++ = '2'; /* off */
1621 		d[0] = '4'; /* underline */
1622 		d[1] = ';';
1623 		d += 2;
1624 	}
1625 
1626 	if (vbi_char_xor_attr (prev, &curr, VBI_FLASH)) {
1627 		if (!vbi_char_has_attr (&curr, VBI_FLASH))
1628 			*d++ = '2'; /* steady */
1629 		d[0] = '5'; /* slowly blinking */
1630 		d[1] = ';';
1631 		d += 2;
1632 	}
1633 
1634 	if (prev->foreground != curr.foreground) {
1635 		d[0] = '3';
1636 		d[1] = curr.foreground + '0';
1637 		d[2] = ';';
1638 		d += 3;
1639 	}
1640 
1641 	if (prev->background != curr.background) {
1642 		d[0] = '4';
1643 		d[1] = curr.background + '0';
1644 		d[2] = ';';
1645 		d += 3;
1646 	}
1647 
1648 	vbi_char_copy_attr (prev, &curr, -1);
1649 	prev->foreground = curr.foreground;
1650 	prev->background = curr.background;
1651 
1652 	if ('[' == d[-1])
1653 		d -= 2; /* no change, remove CSI */
1654 	else
1655 		d[-1] = 'm'; /* replace last semicolon */
1656 
1657 	cr->ucs_buffer_length = d - cr->ucs_buffer;
1658 
1659 	return TRUE;
1660 }
1661 
1662 static void
cr_timestamp(struct caption_recorder * cr,struct tm * tm,time_t t)1663 cr_timestamp			(struct caption_recorder *cr,
1664 				 struct tm *		tm,
1665 				 time_t			t)
1666 {
1667 	char time_str[32];
1668 
1669 	if (!cr->option_caption_timestamps)
1670 		return;
1671 
1672 	if (tm->tm_mday <= 0) {
1673 		if (NULL == gmtime_r (&t, tm)) {
1674 			/* Should not happen. */
1675 			error_exit ("System time invalid.\n");
1676 		}
1677 	}
1678 
1679 	snprintf (time_str, sizeof (time_str),
1680 		  "%04u%02u%02u%02u%02u%02u|",
1681 		  tm->tm_year + 1900, tm->tm_mon + 1,
1682 		  tm->tm_mday, tm->tm_hour,
1683 		  tm->tm_min, tm->tm_sec);
1684 
1685 	cr_puts (cr, time_str);
1686 }
1687 
1688 static void
cr_minicut(struct caption_recorder * cr,struct tm * tm,time_t t,vbi_pgno channel)1689 cr_minicut			(struct caption_recorder *cr,
1690 				 struct tm *		tm,
1691 				 time_t			t,
1692 				 vbi_pgno		channel)
1693 {
1694 	struct program *pr = PARENT (cr, struct program, cr);
1695 
1696 	if (NULL == pr->option_minicut_dir_name)
1697 		return;
1698 
1699 	if (NULL != cr->option_caption_file_name[channel - 1])
1700 		return;
1701 
1702 	if (tm->tm_mday <= 0) {
1703 		if (NULL == gmtime_r (&t, tm)) {
1704 			/* Should not happen. */
1705 			error_exit ("System time invalid.\n");
1706 		}
1707 	}
1708 
1709 	if (tm->tm_min != cr->minicut_min[channel - 1]) {
1710 		char file_name[32];
1711 		FILE *fp;
1712 
1713 		fp = cr->caption_fp[channel - 1];
1714 		if (NULL != fp) {
1715 			if (0 != fclose (fp)) {
1716 				log_errno (1, "Station %u CC file "
1717 					   "write error",
1718 					   station_num (pr));
1719 			}
1720 		}
1721 
1722 		snprintf (file_name, sizeof (file_name),
1723 			  "/%04u%02u%02u%02u%02u00%s",
1724 			  tm->tm_year + 1900, tm->tm_mon + 1,
1725 			  tm->tm_mday, tm->tm_hour, tm->tm_min,
1726 			  cr_file_name_suffix [channel - 1]);
1727 
1728 		/* Note: May be NULL. */
1729 		cr->caption_fp[channel - 1] =
1730 			open_minicut_file (pr, tm, file_name, ".txt");
1731 
1732 		cr->minicut_min[channel - 1] = tm->tm_min;
1733 	}
1734 }
1735 
1736 static void
cr_new_line(struct caption_recorder * cr,struct cc_timestamp * ts,vbi_pgno channel,const vbi_char text[42],unsigned int length)1737 cr_new_line			(struct caption_recorder *cr,
1738 				 struct cc_timestamp *	ts,
1739 				 vbi_pgno		channel,
1740 				 const vbi_char		text[42],
1741 				 unsigned int		length)
1742 {
1743 	FILE *fp;
1744 
1745 	if (0 == (ts->sys.tv_sec | ts->sys.tv_usec)
1746 	    || channel >= 10 || length < 32)
1747 		return;
1748 
1749 	if (0 == (cr->option_caption_mask & (1 << (channel - 1))))
1750 		return;
1751 
1752 	cr->ucs_buffer_length = 0;
1753 
1754 	if (cr->usesen) {
1755 		unsigned int uc[3];
1756 		unsigned int column;
1757 		unsigned int end;
1758 		unsigned int separator;
1759 
1760 		end = length;
1761 
1762 		/* Eat trailing spaces. */
1763 		while (end > 0 && ' ' == text[end - 1].unicode)
1764 			--end;
1765 
1766 		uc[2] = ' ';
1767 		separator = 0;
1768 
1769 		for (column = 0; column < end + 1; ++column) {
1770 			uc[0] = uc[1];
1771 			uc[1] = uc[2];
1772 			uc[2] = 0;
1773 			if (column < end)
1774 				uc[2] = text[column].unicode;
1775 
1776 			if (0 == separator && ' ' == uc[1])
1777 				continue;
1778 			cr_putuc (cr, uc[1]);
1779 			separator = ' ';
1780 
1781 			switch (uc[1]) {
1782 			case '"':
1783 				if ('.' != uc[0] && '!' != uc[0]
1784 				    && '?' != uc[0])
1785 					continue;
1786 				break;
1787 
1788 			case '.':
1789 				if ('.' == uc[0] || '.' == uc[2])
1790 					continue;
1791 				/* fall through */
1792 
1793 			case '!':
1794 			case '?':
1795 				if ('"' == uc[2])
1796 					continue;
1797 				if (0 != uc[2] && ' ' != uc[2])
1798 					continue;
1799 				break;
1800 
1801 			default:
1802 				continue;
1803 			}
1804 
1805 			cr_putuc (cr, '\n');
1806 			separator = 0;
1807 		}
1808 
1809 		if (0 != separator)
1810 			cr_putuc (cr, separator);
1811 	} else {
1812 		struct tm tm;
1813 		vbi_char prev_char;
1814 		unsigned int column;
1815 
1816 		tm.tm_mday = 0;
1817 		cr_minicut (cr, &tm, (time_t) ts->sys.tv_sec, channel);
1818 		cr_timestamp (cr, &tm, (time_t) ts->sys.tv_sec);
1819 
1820 		vbi_char_clear_attr (&prev_char, -1);
1821 		prev_char.foreground = -1;
1822 		prev_char.background = -1;
1823 
1824 		for (column = 0; column < length; ++column) {
1825 			cr_put_attr (cr, &prev_char, text[column]);
1826 			cr_putuc (cr, text[column].unicode);
1827 		}
1828 
1829 		if (0 != vbi_char_has_attr (&prev_char, -1)
1830 		    || (uint8_t) -1 != prev_char.foreground
1831 		    || (uint8_t) -1 != prev_char.background) {
1832 			static const char end_seq[] = {
1833 				27, '[', 'm', '\n', 0
1834 			};
1835 
1836 			cr_puts (cr, end_seq);
1837 		} else {
1838 			cr_putuc (cr, '\n');
1839 		}
1840 	}
1841 
1842 	fp = cr->caption_fp[channel - 1];
1843 
1844 	/* May be NULL due to a bug or a temporary failure of
1845 	   open_minicut_file(). */
1846 	if (NULL != fp) {
1847 		vbi_fputs_iconv_ucs2 (fp, locale_codeset,
1848 				      cr->ucs_buffer,
1849 				      cr->ucs_buffer_length,
1850 				      /* repl_char */ '?');
1851 	}
1852 }
1853 
1854 static void
init_caption_recorder(struct caption_recorder * cr)1855 init_caption_recorder		(struct caption_recorder *cr)
1856 {
1857 	CLEAR (*cr);
1858 
1859 	cr->option_xds_output_file_name = "-";
1860 
1861 	init_cc_data_decoder (&cr->ccd);
1862 	init_cc_decoder (&cr->cc);
1863 	init_dtvcc_decoder (&cr->dtvcc);
1864 
1865 	cr->infoptr = cr->newinfo[0][0][0];
1866 	cr->xds_info_prefix = "\33[33m% ";
1867 	cr->xds_info_suffix = "\33[0m\n";
1868 	cr->usewebtv = 1;
1869 
1870 	memset (cr->minicut_min, -1, sizeof (cr->minicut_min));
1871 }
1872 
1873 /* EIA 608-B Closed Caption decoder. */
1874 
1875 static void
cc_timestamp_reset(struct cc_timestamp * ts)1876 cc_timestamp_reset		(struct cc_timestamp *	ts)
1877 {
1878 	CLEAR (ts->sys);
1879 	ts->pts = -1;
1880 }
1881 
1882 static vbi_bool
cc_timestamp_isset(struct cc_timestamp * ts)1883 cc_timestamp_isset		(struct cc_timestamp *	ts)
1884 {
1885 	return (ts->pts >= 0 || 0 != (ts->sys.tv_sec | ts->sys.tv_usec));
1886 }
1887 
1888 static const vbi_color
1889 cc_color_map [8] = {
1890 	VBI_WHITE, VBI_GREEN, VBI_BLUE, VBI_CYAN,
1891 	VBI_RED, VBI_YELLOW, VBI_MAGENTA, VBI_BLACK
1892 };
1893 
1894 static const int8_t
1895 cc_pac_row_map [16] = {
1896 	/* 0 */ 10,			/* 0x1040 */
1897 	/* 1 */ -1,			/* no function */
1898 	/* 2 */ 0, 1, 2, 3,		/* 0x1140 ... 0x1260 */
1899 	/* 6 */ 11, 12, 13, 14,		/* 0x1340 ... 0x1460 */
1900 	/* 10 */ 4, 5, 6, 7, 8, 9	/* 0x1540 ... 0x1760 */
1901 };
1902 
1903 static void
dump_cc(FILE * fp,unsigned int index,unsigned int cc_count,unsigned int cc_valid,unsigned int cc_type,unsigned int c1,unsigned int c2)1904 dump_cc				(FILE *			fp,
1905 				 unsigned int		index,
1906 				 unsigned int		cc_count,
1907 				 unsigned int		cc_valid,
1908 				 unsigned int		cc_type,
1909 				 unsigned int		c1,
1910 				 unsigned int		c2)
1911 {
1912 	uint16_t ucs2_str[2];
1913 	unsigned int ch;
1914 	unsigned int a7;
1915 	unsigned int f;
1916 	unsigned int b7;
1917 	unsigned int u;
1918 
1919 	fprintf (fp,
1920 		 "%s%u/%u %d %s %02X%02X %02X%c%02X%c",
1921 		 (NTSC_F2 == cc_type) ? "\t\t\t\t\t\t\t\t" : "",
1922 		 index, cc_count, !!cc_valid,
1923 		 cc_type_name (cc_type), c1, c2,
1924 		 c1 & 0x7F, vbi_unpar8 (c1) < 0 ? '*' : ' ',
1925 		 c2 & 0x7F, vbi_unpar8 (c2) < 0 ? '*' : ' ');
1926 
1927 	c1 &= 0x7F;
1928 	c2 &= 0x7F;
1929 
1930 	if (0 == c1) {
1931 		fputs (" null\n", fp);
1932 		return;
1933 	} else if (c1 < 0x10) {
1934 		fputc ('\n', fp);
1935 		return;
1936 	} else if (c1 >= 0x20) {
1937 		fputs (" '", fp);
1938 		ucs2_str[0] = vbi_caption_unicode (c1, /* to_upper */ FALSE);
1939 		ucs2_str[1] = vbi_caption_unicode (c2, /* to_upper */ FALSE);
1940 		vbi_fputs_iconv_ucs2 (fp, locale_codeset,
1941 				      ucs2_str, 2,
1942 				      /* repl_char */ '?');
1943 		fputs ("'\n", fp);
1944 		return;
1945 	} else if (c2 < 0x20) {
1946 		fputs (" INVALID\n", fp);
1947 		return;
1948 	}
1949 
1950 	/* Some common bit groups. */
1951 
1952 	ch = (c1 >> 3) & 1; /* channel */
1953 	a7 = c1 & 7;
1954 	f = c1 & 1; /* field */
1955 	b7 = (c2 >> 1) & 7;
1956 	u = c2 & 1; /* underline */
1957 
1958 	if (c2 >= 0x40) {
1959 		unsigned int row;
1960 
1961 		/* Preamble Address Codes -- 001 crrr  1ri bbbu */
1962 
1963 		row = cc_pac_row_map [a7 * 2 + ((c2 >> 5) & 1)];
1964 		if (c2 & 0x10)
1965 			fprintf (fp, " PAC ch=%u row=%d column=%u u=%u\n",
1966 				 ch, row, b7 * 4, u);
1967 		else
1968 			fprintf (fp, " PAC ch=%u row=%d color=%u u=%u\n",
1969 				 ch, row, b7, u);
1970 		return;
1971 	}
1972 
1973 	/* Control codes -- 001 caaa  01x bbbu */
1974 
1975 	switch (a7) {
1976 	case 0:
1977 		if (c2 < 0x30) {
1978 			static const char mnemo [16 * 4] =
1979 				"BWO\0BWS\0BGO\0BGS\0"
1980 				"BBO\0BBS\0BCO\0BCS\0"
1981 				"BRO\0BRS\0BYO\0BYS\0"
1982 				"BMO\0BMS\0BAO\0BAS";
1983 
1984 			fprintf (fp, " %s ch=%u\n",
1985 				 mnemo + (c2 & 0xF) * 4, ch);
1986 			return;
1987 		}
1988 		break;
1989 
1990 	case 1:
1991 		if (c2 < 0x30) {
1992 			fprintf (fp, " mid-row ch=%u color=%u u=%u\n",
1993 				 ch, b7, u);
1994 		} else {
1995 			fprintf (fp, " special character ch=%u '", ch);
1996 			ucs2_str[0] = vbi_caption_unicode
1997 				(0x1100 | c2, /* to_upper */ FALSE);
1998 			vbi_fputs_iconv_ucs2 (fp, locale_codeset,
1999 					      ucs2_str, 1,
2000 					      /* repl_char */ '?');
2001 			fputs ("'\n", fp);
2002 		}
2003 		return;
2004 
2005 	case 2: /* first group */
2006 	case 3: /* second group */
2007 		fprintf (fp, " extended character ch=%u '", ch);
2008 		ucs2_str[0] = vbi_caption_unicode
2009 			(c1 * 256 + c2, /* to_upper */ FALSE);
2010 		vbi_fputs_iconv_ucs2 (fp, locale_codeset,
2011 				      ucs2_str, 1,
2012 				      /* repl_char */ '?');
2013 		fputs ("'\n", fp);
2014 		return;
2015 
2016 	case 4: /* f=0 */
2017 	case 5: /* f=1 */
2018 		if (c2 < 0x30) {
2019 			static const char mnemo [16 * 4] =
2020 				"RCL\0BS \0AOF\0AON\0"
2021 				"DER\0RU2\0RU3\0RU4\0"
2022 				"FON\0RDC\0TR \0RTD\0"
2023 				"EDM\0CR \0ENM\0EOC";
2024 
2025 			fprintf (fp, " %s ch=%u f=%u\n",
2026 				 mnemo + (c2 & 0xF) * 4, ch, f);
2027 			return;
2028 		}
2029 		break;
2030 
2031 	case 6:
2032 		fprintf (fp, " reserved\n");
2033 		return;
2034 
2035 	case 7:
2036 		switch (c2) {
2037 		case 0x21 ... 0x23:
2038 			fprintf (fp, " TO%u ch=%u\n", c2 - 0x20, ch);
2039 			return;
2040 
2041 		case 0x2D:
2042 			fprintf (fp, " BT ch=%u\n", ch);
2043 			return;
2044 
2045 		case 0x2E:
2046 			fprintf (fp, " FA ch=%u\n", ch);
2047 			return;
2048 
2049 		case 0x2F:
2050 			fprintf (fp, " FAU ch=%u\n", ch);
2051 			return;
2052 
2053 		default:
2054 			break;
2055 		}
2056 		break;
2057 	}
2058 
2059 	fprintf (fp, " unknown\n");
2060 }
2061 
2062 static void
2063 cc_reset			(struct cc_decoder *	cd);
2064 
2065 static vbi_pgno
cc_channel_num(struct cc_decoder * cd,struct cc_channel * ch)2066 cc_channel_num			(struct cc_decoder *	cd,
2067 				 struct cc_channel *	ch)
2068 {
2069 	return (ch - cd->channel) + 1;
2070 }
2071 
2072 /* Note 47 CFR 15.119 (h) Character Attributes: "(1) Transmission of
2073    Attributes. A character may be transmitted with any or all of four
2074    attributes: Color, italics, underline, and flash. All of these
2075    attributes are set by control codes included in the received
2076    data. An attribute will remain in effect until changed by another
2077    control code or until the end of the row is reached. Each row
2078    begins with a control code which sets the color and underline
2079    attributes. (White non-underlined is the default display attribute
2080    if no Preamble Address Code is received before the first character
2081    on an empty row.) Attributes are not affected by transparent spaces
2082    within a row. (i) All Mid-Row Codes and the Flash On command are
2083    spacing attributes which appear in the display just as if a
2084    standard space (20h) had been received. Preamble Address Codes are
2085    non-spacing and will not alter any attributes when used to position
2086    the cursor in the midst of a row of characters. (ii) The color
2087    attribute has the highest priority and can only be changed by the
2088    Mid-Row Code of another color. Italics has the next highest
2089    priority. If characters with both color and italics are desired,
2090    the italics Mid-Row Code must follow the color assignment. Any
2091    color Mid-Row Code will turn off italics. If the least significant
2092    bit of a Preamble Address Code or of a color or italics Mid-Row
2093    Code is a 1 (high), underlining is turned on. If that bit is a 0
2094    (low), underlining is off. (iii) The flash attribute is transmitted
2095    as a Miscellaneous Control Code. The Flash On command will not
2096    alter the status of the color, italics, or underline
2097    attributes. However, any coloror italics Mid-Row Code will turn off
2098    flash. (iv) Thus, for example, if a red, italicized, underlined,
2099    flashing character is desired, the attributes must be received in
2100    the following order: a red Mid-Row or Preamble Address Code, an
2101    italics Mid-Row Code with underline bit, and the Flash On
2102    command. The character will then be preceded by three spaces (two
2103    if red was assigned via a Preamble Address Code)."
2104 
2105    EIA 608-B Annex C.7 Preamble Address Codes and Tab Offsets
2106    (Regulatory/Preferred): "In general, Preamble Address Codes (PACs)
2107    have no immediate effect on the display. A major exception is the
2108    receipt of a PAC during roll-up captioning. In that case, if the
2109    base row designated in the PAC is not the same as the current base
2110    row, the display shall be moved immediately to the new base
2111    row. [...] An indenting PAC carries the attributes of white,
2112    non-italicized, and it sets underlining on or off. Tab Offset
2113    commands do not change these attributes. If an indenting PAC with
2114    underline ON is received followed by a Tab Offset and by text, the
2115    text shall be underlined (except as noted below). When a
2116    displayable character is received, it is deposited at the current
2117    cursor position. If there is already a displayable character in the
2118    column immediately to the left, the new character assumes the
2119    attributes of that character. The new character may be arriving as
2120    the result of an indenting PAC (with or without a Tab Offset), and
2121    that PAC may designate other attributes, but the new character is
2122    forced to assume the attributes of the character immediately to its
2123    left, and the PAC's attributes are ignored. If, when a displayable
2124    character is received, it overwrites an existing PAC or mid-row
2125    code, and there are already characters to the right of the new
2126    character, these existing characters shall assume the same
2127    attributes as the new character. This adoption can result in a
2128    whole caption row suddenly changing color, underline, italics,
2129    and/or flash attributes."
2130 
2131    EIA 608-B Annex C.14 Special Cases Regarding Attributes
2132    (Normative): "In most cases, Preamble Address Codes shall set
2133    attributes for the caption elements they address. It is
2134    theoretically possible for a service provider to use an indenting
2135    PAC to start a row at Column 5 or greater, and then to use
2136    Backspace to move the cursor to the left of the PAC into an area to
2137    which no attributes have been assigned. It is also possible for a
2138    roll-up row, having been created by a Carriage Return, to receive
2139    characters with no PAC used to set attributes. In these cases, and
2140    in any other case where no explicit attributes have been assigned,
2141    the display shall be white, non-underlined, non-italicized, and
2142    non-flashing. In case new displayable characters are received
2143    immediately after a Delete to End of Row (DER), the display
2144    attributes of the first deleted character shall remain in effect if
2145    there is a displayable character to the left of the cursor;
2146    otherwise, the most recently received PAC shall set the display
2147    attributes."
2148 
2149    47 CFR 15.119 (n) Glossary of terms: "(6) Displayable character:
2150    Any letter, number or symbol which is defined for on-screen
2151    display, plus the 20h space. [...] (13) Special characters:
2152    Displayable characters (except for "transparent space") [...]" */
2153 
2154 static void
cc_format_row(struct cc_decoder * cd,struct vbi_char * cp,struct cc_channel * ch,unsigned int buffer,unsigned int row,vbi_bool to_upper,vbi_bool padding)2155 cc_format_row			(struct cc_decoder *	cd,
2156 				 struct vbi_char *	cp,
2157 				 struct cc_channel *	ch,
2158 				 unsigned int		buffer,
2159 				 unsigned int		row,
2160 				 vbi_bool		to_upper,
2161 				 vbi_bool		padding)
2162 {
2163 	struct vbi_char ac;
2164 	unsigned int i;
2165 
2166 	cd = cd; /* unused */
2167 
2168 	/* 47 CFR 15.119 (h)(1). EIA 608-B Section 6.4. */
2169 	CLEAR (ac);
2170 	ac.foreground = VBI_WHITE;
2171 	ac.background = VBI_BLACK;
2172 
2173 	/* Shortcut. */
2174 	if (0 == (ch->dirty[buffer] & (1 << row))) {
2175 		vbi_char *end;
2176 
2177 		ac.unicode = 0x20;
2178 		ac.opacity = VBI_TRANSPARENT_SPACE;
2179 
2180 		end = cp + CC_MAX_COLUMNS;
2181 		if (padding)
2182 			end += 2;
2183 
2184 		while (cp < end)
2185 			*cp++ = ac;
2186 
2187 		return;
2188 	}
2189 
2190 	if (padding) {
2191 		ac.unicode = 0x20;
2192 		ac.opacity = VBI_TRANSPARENT_SPACE;
2193 		*cp++ = ac;
2194 	}
2195 
2196 	/* EIA 608-B Section 6.4. */
2197 	ac.opacity = VBI_OPAQUE;
2198 
2199 	for (i = CC_FIRST_COLUMN - 1; i <= CC_LAST_COLUMN; ++i) {
2200 		unsigned int color;
2201 		unsigned int c;
2202 
2203 		ac.unicode = 0x20;
2204 
2205 		c = ch->buffer[buffer][row][i];
2206 		if (0 == c) {
2207 			if (padding
2208 			    && VBI_TRANSPARENT_SPACE != cp[-1].opacity
2209 			    && 0x20 != cp[-1].unicode) {
2210 				/* Append a space with the same colors
2211 				   and opacity (opaque or
2212 				   transp. backgr.) as the text to the
2213 				   left of it. */
2214 				*cp++ = ac;
2215 				/* We don't underline spaces, see
2216 				   below. */
2217 				vbi_char_clear_attr (cp - 1, -1);
2218 			} else if (i > 0) {
2219 				*cp++ = ac;
2220 				cp[-1].opacity = VBI_TRANSPARENT_SPACE;
2221 			}
2222 
2223 			continue;
2224 		} else if (c < 0x1040) {
2225 			if (padding
2226 			    && VBI_TRANSPARENT_SPACE == cp[-1].opacity) {
2227 				/* Prepend a space with the same
2228 				   colors and opacity (opaque or
2229 				   transp. backgr.) as the text to the
2230 				   right of it. */
2231 				cp[-1] = ac;
2232 				/* We don't underline spaces, see
2233 				   below. */
2234 				vbi_char_clear_attr (cp - 1, -1);
2235 			}
2236 
2237 			if ((c >= 'a' && c <= 'z')
2238 			    || 0x7E == c /* n with tilde */) {
2239 				/* We do not force these characters to
2240 				   upper case because the standard
2241 				   character set includes upper case
2242 				   versions of these characters and
2243 				   lower case was probably
2244 				   deliberately transmitted. */
2245 				ac.unicode = vbi_caption_unicode
2246 					(c, /* to_upper */ FALSE);
2247 			} else {
2248 				ac.unicode = vbi_caption_unicode
2249 					(c, to_upper);
2250 			}
2251 		} else if (c < 0x1120) {
2252 			/* Preamble Address Codes -- 001 crrr  1ri xxxu */
2253 
2254 			/* PAC is a non-spacing attribute and only
2255 			   stored in the buffer at the addressed
2256 			   column minus one if it replaces a
2257 			   transparent space (EIA 608-B Annex C.7,
2258 			   C.14). There's always a transparent space
2259 			   to the left of the first column but we show
2260 			   this zeroth column only if padding is
2261 			   enabled. */
2262 			if (padding
2263 			    && VBI_TRANSPARENT_SPACE != cp[-1].opacity
2264 			    && 0x20 != cp[-1].unicode) {
2265 				/* See 0 == c. */
2266 				*cp++ = ac;
2267 				vbi_char_clear_attr (cp - 1, -1);
2268 			} else if (i > 0) {
2269 				*cp++ = ac;
2270 				cp[-1].opacity = VBI_TRANSPARENT_SPACE;
2271 			}
2272 
2273 			vbi_char_clear_attr (&ac, VBI_UNDERLINE | VBI_ITALIC);
2274 			if (c & 0x0001)
2275 				vbi_char_set_attr (&ac, VBI_UNDERLINE);
2276 			if (c & 0x0010) {
2277 				ac.foreground = VBI_WHITE;
2278 			} else {
2279 				color = (c >> 1) & 7;
2280 				if (7 == color) {
2281 					ac.foreground = VBI_WHITE;
2282 					vbi_char_set_attr (&ac, VBI_ITALIC);
2283 				} else {
2284 					ac.foreground = cc_color_map[color];
2285 				}
2286 			}
2287 
2288 			continue;
2289 		} else if (c < 0x1130) {
2290 			/* Mid-Row Codes -- 001 c001  010 xxxu */
2291 			/* 47 CFR 15.119 Mid-Row Codes table,
2292 			   (h)(1)(ii), (h)(1)(iii). */
2293 
2294 			/* 47 CFR 15.119 (h)(1)(i), EIA 608-B Section
2295 			   6.2: Mid-Row codes, FON, BT, FA and FAU are
2296 			   set-at spacing attributes. */
2297 
2298 			vbi_char_clear_attr (&ac, -1);
2299 			if (c & 0x0001)
2300 				vbi_char_set_attr (&ac, VBI_UNDERLINE);
2301 			color = (c >> 1) & 7;
2302 			if (7 == color) {
2303 				vbi_char_set_attr (&ac, VBI_ITALIC);
2304 			} else {
2305 				ac.foreground = cc_color_map[color];
2306 			}
2307 		} else if (c < 0x1220) {
2308 			/* Special Characters -- 001 c001  011 xxxx */
2309 			/* 47 CFR 15.119 Character Set Table. */
2310 
2311 			if (padding
2312 			    && VBI_TRANSPARENT_SPACE == cp[-1].opacity) {
2313 				cp[-1] = ac;
2314 				vbi_char_clear_attr (cp - 1, -1);
2315 			}
2316 
2317 			/* Note we already stored 0 instead of 0x1139
2318 			   (transparent space) in the ch->buffer. */
2319 			ac.unicode = vbi_caption_unicode (c, to_upper);
2320 		} else if (c < 0x1428) {
2321 			/* Extended Character Set -- 001 c01x  01x xxxx */
2322 			/* EIA 608-B Section 6.4.2 */
2323 
2324 			if (padding
2325 			    && VBI_TRANSPARENT_SPACE == cp[-1].opacity) {
2326 				cp[-1] = ac;
2327 				vbi_char_clear_attr (cp - 1, -1);
2328 			}
2329 
2330 			/* We do not force these characters to upper
2331 			   case because the extended character set
2332 			   includes upper case versions of all letters
2333 			   and lower case was probably deliberately
2334 			   transmitted. */
2335 			ac.unicode = vbi_caption_unicode
2336 				(c, /* to_upper */ FALSE);
2337 		} else if (c < 0x172D) {
2338 			/* FON Flash On -- 001 c10f  010 1000 */
2339 			/* 47 CFR 15.119 (h)(1)(iii). */
2340 
2341 			vbi_char_set_attr (&ac, VBI_FLASH);
2342 		} else if (c < 0x172E) {
2343 			/* BT Background Transparent -- 001 c111  010 1101 */
2344 			/* EIA 608-B Section 6.4. */
2345 
2346 			ac.opacity = VBI_TRANSPARENT_FULL;
2347 		} else if (c <= 0x172F) {
2348 			/* FA Foreground Black -- 001 c111  010 111u */
2349 			/* EIA 608-B Section 6.4. */
2350 
2351 			if (c & 0x0001)
2352 				vbi_char_set_attr (&ac, VBI_UNDERLINE);
2353 			ac.foreground = VBI_BLACK;
2354 		}
2355 
2356 		*cp++ = ac;
2357 
2358 		/* 47 CFR 15.119 and EIA 608-B are silent about
2359 		   underlined spaces, but considering the example in
2360 		   47 CFR (h)(1)(iv) which would produce something
2361 		   ugly like "__text" I suppose we should not
2362 		   underline them. For good measure we also clear the
2363 		   invisible italic and flash attribute. */
2364 		if (0x20 == ac.unicode)
2365 			vbi_char_clear_attr (cp - 1, -1);
2366 	}
2367 
2368 	if (padding) {
2369 		ac.unicode = 0x20;
2370 		vbi_char_clear_attr (&ac, -1);
2371 
2372 		if (VBI_TRANSPARENT_SPACE != cp[-1].opacity
2373 		    && 0x20 != cp[-1].unicode) {
2374 			*cp = ac;
2375 		} else {
2376 			ac.opacity = VBI_TRANSPARENT_SPACE;
2377 			*cp = ac;
2378 		}
2379 	}
2380 }
2381 
2382 typedef enum {
2383 	/**
2384 	 * 47 CFR Section 15.119 requires caption decoders to roll
2385 	 * caption smoothly: Nominally each character cell has a
2386 	 * height of 13 field lines. When this flag is set the current
2387 	 * caption should be displayed with a vertical offset of 12
2388 	 * field lines, and after every 1001 / 30000 seconds the
2389 	 * caption overlay should move up by one field line until the
2390 	 * offset is zero. The roll rate should be no more than 0.433
2391 	 * seconds/row for other character cell heights.
2392 	 *
2393 	 * The flag may be set again before the offset returned to
2394 	 * zero. The caption overlay should jump to offset 12 in this
2395 	 * case regardless.
2396 	 */
2397 	VBI_START_ROLLING	= (1 << 0)
2398 } vbi_cc_page_flags;
2399 
2400 static void
cc_display_event(struct cc_decoder * cd,struct cc_channel * ch,vbi_cc_page_flags flags)2401 cc_display_event		(struct cc_decoder *	cd,
2402 				 struct cc_channel *	ch,
2403 				 vbi_cc_page_flags	flags)
2404 {
2405 	cd = cd; /* unused */
2406 	ch = ch;
2407 	flags = flags;
2408 }
2409 
2410 /* This decoder is mainly designed to overlay caption onto live video,
2411    but to create transcripts we also offer an event every time a line
2412    of caption is complete. The event occurs when certain control codes
2413    are received.
2414 
2415    In POP_ON mode we send the event upon reception of EOC, which swaps
2416    the displayed and non-displayed memory.
2417 
2418    In ROLL_UP and TEXT mode captioners are not expected to display new
2419    text by erasing and overwriting a row with PAC, TOx, BS and DER so
2420    we ignore these codes. In ROLL_UP mode CR, EDM, EOC, RCL and RDC
2421    complete a line. CR moves the cursor to a new row, EDM erases the
2422    displayed memory. The remaining codes switch to POP_ON or PAINT_ON
2423    mode. In TEXT mode CR and TR are our line completion indicators. CR
2424    works as above and TR erases the displayed memory. EDM, EOC, RDC,
2425    RCL and RUx have no effect on TEXT buffers.
2426 
2427    In PAINT_ON mode RDC never erases the displayed memory and CR has
2428    no function. Instead captioners can freely position the cursor and
2429    erase or overwrite (parts of) rows with PAC, TOx, BS and DER, or
2430    erase all rows with EDM. We send an event on PAC, EDM, EOC, RCL and
2431    RUx, provided the characters (including spacing attributes) in the
2432    current row changed since the last event. PAC is the only control
2433    code which can move the cursor to the left and/or to a new row, and
2434    likely to introduce a new line. EOC, RCL and RUx switch to POP_ON
2435    or ROLL_UP mode. */
2436 
2437 static void
cc_stream_event(struct cc_decoder * cd,struct cc_channel * ch,unsigned int first_row,unsigned int last_row)2438 cc_stream_event			(struct cc_decoder *	cd,
2439 				 struct cc_channel *	ch,
2440 				 unsigned int		first_row,
2441 				 unsigned int		last_row)
2442 {
2443 	vbi_pgno channel;
2444 	unsigned int row;
2445 
2446 	channel = cc_channel_num (cd, ch);
2447 
2448 	for (row = first_row; row <= last_row; ++row) {
2449 		struct vbi_char text[36];
2450 		unsigned int end;
2451 
2452 		cc_format_row (cd, text, ch,
2453 			       ch->displayed_buffer,
2454 			       row, /* to_upper */ FALSE,
2455 			       /* padding */ FALSE);
2456 
2457 		for (end = 32; end > 0; --end) {
2458 			if (VBI_TRANSPARENT_SPACE != text[end - 1].opacity)
2459 				break;
2460 		}
2461 
2462 		if (0 == end)
2463 			continue;
2464 
2465 		{
2466 			struct program *pr;
2467 
2468 			pr = PARENT (cd, struct program, cr.cc);
2469 			cr_new_line (&pr->cr, &ch->timestamp_c0,
2470 				     channel, text, /* length */ 32);
2471 		}
2472 	}
2473 
2474 	cc_timestamp_reset (&ch->timestamp_c0);
2475 }
2476 
2477 static void
cc_put_char(struct cc_decoder * cd,struct cc_channel * ch,int c,vbi_bool displayable,vbi_bool backspace)2478 cc_put_char			(struct cc_decoder *	cd,
2479 				 struct cc_channel *	ch,
2480 				 int			c,
2481 				 vbi_bool		displayable,
2482 				 vbi_bool		backspace)
2483 {
2484 	uint16_t *text;
2485 	unsigned int curr_buffer;
2486 	unsigned int row;
2487 	unsigned int column;
2488 
2489 	/* 47 CFR Section 15.119 (f)(1), (f)(2), (f)(3). */
2490 	curr_buffer = ch->displayed_buffer
2491 		^ (CC_MODE_POP_ON == ch->mode);
2492 
2493 	row = ch->curr_row;
2494 	column = ch->curr_column;
2495 
2496 	if (unlikely (backspace)) {
2497 		/* 47 CFR 15.119 (f)(1)(vi), (f)(2)(ii),
2498 		   (f)(3)(i). EIA 608-B Section 6.4.2, 7.4. */
2499 		if (column > CC_FIRST_COLUMN)
2500 			--column;
2501 	} else {
2502 		/* 47 CFR 15.119 (f)(1)(v), (f)(1)(vi), (f)(2)(ii),
2503 		   (f)(3)(i). EIA 608-B Section 7.4. */
2504 		if (column < CC_LAST_COLUMN)
2505 			ch->curr_column = column + 1;
2506 	}
2507 
2508 	text = &ch->buffer[curr_buffer][row][0];
2509 	text[column] = c;
2510 
2511 	/* Send a display update event when the displayed buffer of
2512 	   the current channel changed, but no more than once for each
2513 	   pair of Closed Caption bytes. */
2514 	/* XXX This may not be a visible change, but such cases are
2515 	   rare and we'd need something close to format_row() to be
2516 	   sure. */
2517 	if (CC_MODE_POP_ON != ch->mode) {
2518 		cd->event_pending = ch;
2519 	}
2520 
2521 	if (likely (displayable)) {
2522 		/* Note EIA 608-B Annex C.7, C.14. */
2523 		if (CC_FIRST_COLUMN == column
2524 		    || 0 == text[column - 1]) {
2525 			/* Note last_pac may be 0 as well. */
2526 			text[column - 1] = ch->last_pac;
2527 		}
2528 
2529 		if (c >= 'a' && c <= 'z') {
2530 			ch->uppercase_predictor = 0;
2531 		} else if (c >= 'A' && c <= 'Z') {
2532 			unsigned int up;
2533 
2534 			up = ch->uppercase_predictor + 1;
2535 			if (up > 0)
2536 				ch->uppercase_predictor = up;
2537 		}
2538 	} else if (unlikely (0 == c)) {
2539 		unsigned int i;
2540 
2541 		/* This is Special Character "Transparent space". */
2542 
2543 		for (i = CC_FIRST_COLUMN; i <= CC_LAST_COLUMN; ++i)
2544 			c |= ch->buffer[curr_buffer][row][i];
2545 
2546 		ch->dirty[curr_buffer] &= ~((0 == c) << row);
2547 
2548 		return;
2549 	}
2550 
2551 	assert (sizeof (ch->dirty[0]) * 8 - 1 >= CC_MAX_ROWS);
2552 	ch->dirty[curr_buffer] |= 1 << row;
2553 
2554 	if (ch->timestamp_c0.pts < 0
2555 	    && 0 == (ch->timestamp_c0.sys.tv_sec
2556 		     | ch->timestamp_c0.sys.tv_usec)) {
2557 		ch->timestamp_c0 = cd->timestamp;
2558 	}
2559 }
2560 
2561 static void
cc_ext_control_code(struct cc_decoder * cd,struct cc_channel * ch,unsigned int c2)2562 cc_ext_control_code		(struct cc_decoder *	cd,
2563 				 struct cc_channel *	ch,
2564 				 unsigned int		c2)
2565 {
2566 	unsigned int column;
2567 
2568 	switch (c2) {
2569 	case 0x21: /* TO1 */
2570 	case 0x22: /* TO2 */
2571 	case 0x23: /* TO3 Tab Offset -- 001 c111  010 00xx */
2572 		/* 47 CFR 15.119 (e)(1)(ii). EIA 608-B Section 7.4,
2573 		   Annex C.7. */
2574 		column = ch->curr_column + (c2 & 3);
2575 		ch->curr_column = MIN (column,
2576 				       (unsigned int) CC_LAST_COLUMN);
2577 		break;
2578 
2579 	case 0x24: /* Select standard character set in normal size */
2580 	case 0x25: /* Select standard character set in double size */
2581 	case 0x26: /* Select first private character set */
2582 	case 0x27: /* Select second private character set */
2583 	case 0x28: /* Select character set GB 2312-80 (Chinese) */
2584 	case 0x29: /* Select character set KSC 5601-1987 (Korean) */
2585 	case 0x2A: /* Select first registered character set. */
2586 		/* EIA 608-B Section 6.3 Closed Group Extensions. */
2587 		break;
2588 
2589 	case 0x2D: /* BT Background Transparent -- 001 c111  010 1101 */
2590 	case 0x2E: /* FA Foreground Black -- 001 c111  010 1110 */
2591 	case 0x2F: /* FAU Foregr. Black Underl. -- 001 c111  010 1111 */
2592 		/* EIA 608-B Section 6.2. */
2593 		cc_put_char (cd, ch, 0x1700 | c2,
2594 			     /* displayable */ FALSE,
2595 			     /* backspace */ TRUE);
2596 		break;
2597 
2598 	default:
2599 		/* 47 CFR Section 15.119 (j): Ignore. */
2600 		break;
2601 	}
2602 }
2603 
2604 /* Send a stream event if the current row has changed since the last
2605    stream event. This is necessary in paint-on mode where CR has no
2606    function and captioners can freely position the cursor to erase or
2607    overwrite (parts of) rows. */
2608 static void
cc_stream_event_if_changed(struct cc_decoder * cd,struct cc_channel * ch)2609 cc_stream_event_if_changed	(struct cc_decoder *	cd,
2610 				 struct cc_channel *	ch)
2611 {
2612 	unsigned int curr_buffer;
2613 	unsigned int row;
2614 	unsigned int i;
2615 
2616 	curr_buffer = ch->displayed_buffer;
2617 	row = ch->curr_row;
2618 
2619 	if (0 == (ch->dirty[curr_buffer] & (1 << row)))
2620 		return;
2621 
2622 	for (i = CC_FIRST_COLUMN; i <= CC_LAST_COLUMN; ++i) {
2623 		unsigned int c1;
2624 		unsigned int c2;
2625 
2626 		c1 = ch->buffer[curr_buffer][row][i];
2627 		if (c1 >= 0x1040) {
2628 			if (c1 < 0x1120) {
2629 				c1 = 0; /* PAC -- non-spacing */
2630 			} else if (c1 < 0x1130 || c1 >= 0x1428) {
2631 				/* MR, FON, BT, FA, FAU -- spacing */
2632 				c1 = 0x20;
2633 			}
2634 		}
2635 
2636 		c2 = ch->buffer[2][row][i];
2637 		if (c2 >= 0x1040) {
2638 			if (c2 < 0x1120) {
2639 				c2 = 0;
2640 			} else if (c2 < 0x1130 || c2 >= 0x1428) {
2641 				c1 = 0x20;
2642 			}
2643 		}
2644 
2645 		if (c1 != c2) {
2646 			cc_stream_event (cd, ch, row, row);
2647 
2648 			memcpy (ch->buffer[2][row],
2649 				ch->buffer[curr_buffer][row],
2650 				sizeof (ch->buffer[0][0]));
2651 
2652 			ch->dirty[2] = ch->dirty[curr_buffer];
2653 
2654 			return;
2655 		}
2656 	}
2657 }
2658 
2659 static void
cc_end_of_caption(struct cc_decoder * cd,struct cc_channel * ch)2660 cc_end_of_caption		(struct cc_decoder *	cd,
2661 				 struct cc_channel *	ch)
2662 {
2663 	unsigned int curr_buffer;
2664 	unsigned int row;
2665 
2666 	/* EOC End Of Caption -- 001 c10f  010 1111 */
2667 
2668 	curr_buffer = ch->displayed_buffer;
2669 
2670 	switch (ch->mode) {
2671 	case CC_MODE_UNKNOWN:
2672 	case CC_MODE_POP_ON:
2673 		break;
2674 
2675 	case CC_MODE_ROLL_UP:
2676 		row = ch->curr_row;
2677 		if (0 != (ch->dirty[curr_buffer] & (1 << row)))
2678 			cc_stream_event (cd, ch, row, row);
2679 		break;
2680 
2681 	case CC_MODE_PAINT_ON:
2682 		cc_stream_event_if_changed (cd, ch);
2683 		break;
2684 
2685 	case CC_MODE_TEXT:
2686 		/* Not reached. (ch is a caption channel.) */
2687 		return;
2688 	}
2689 
2690 	ch->displayed_buffer = curr_buffer ^= 1;
2691 
2692 	/* 47 CFR Section 15.119 (f)(2). */
2693 	ch->mode = CC_MODE_POP_ON;
2694 
2695 	if (0 != ch->dirty[curr_buffer]) {
2696 		ch->timestamp_c0 = cd->timestamp;
2697 
2698 		cc_stream_event (cd, ch,
2699 				 CC_FIRST_ROW,
2700 				 CC_LAST_ROW);
2701 
2702 		cc_display_event (cd, ch, 0);
2703 	}
2704 }
2705 
2706 static void
cc_carriage_return(struct cc_decoder * cd,struct cc_channel * ch)2707 cc_carriage_return		(struct cc_decoder *	cd,
2708 				 struct cc_channel *	ch)
2709 {
2710 	unsigned int curr_buffer;
2711 	unsigned int row;
2712 	unsigned int window_rows;
2713 	unsigned int first_row;
2714 
2715 	/* CR Carriage Return -- 001 c10f  010 1101 */
2716 
2717 	curr_buffer = ch->displayed_buffer;
2718 	row = ch->curr_row;
2719 
2720 	switch (ch->mode) {
2721 	case CC_MODE_UNKNOWN:
2722 		return;
2723 
2724 	case CC_MODE_ROLL_UP:
2725 		/* 47 CFR Section 15.119 (f)(1)(iii). */
2726 		ch->curr_column = CC_FIRST_COLUMN;
2727 
2728 		/* 47 CFR 15.119 (f)(1): "The cursor always remains on
2729 		   the base row." */
2730 
2731 		/* XXX Spec? */
2732 		ch->last_pac = 0;
2733 
2734 		/* No event if the buffer contains only
2735 		   TRANSPARENT_SPACEs. */
2736 		if (0 == ch->dirty[curr_buffer])
2737 			return;
2738 
2739 		window_rows = MIN (row + 1 - CC_FIRST_ROW,
2740 				   ch->window_rows);
2741 		break;
2742 
2743 	case CC_MODE_POP_ON:
2744 	case CC_MODE_PAINT_ON:
2745 		/* 47 CFR 15.119 (f)(2)(i), (f)(3)(i): No effect. */
2746 		return;
2747 
2748 	case CC_MODE_TEXT:
2749 		/* 47 CFR Section 15.119 (f)(1)(iii). */
2750 		ch->curr_column = CC_FIRST_COLUMN;
2751 
2752 		/* XXX Spec? */
2753 		ch->last_pac = 0;
2754 
2755 		/* EIA 608-B Section 7.4: "When Text Mode has
2756 		   initially been selected and the specified Text
2757 		   memory is empty, the cursor starts at the topmost
2758 		   row, Column 1, and moves down to Column 1 on the
2759 		   next row each time a Carriage Return is received
2760 		   until the last available row is reached. A variety
2761 		   of methods may be used to accomplish the scrolling,
2762 		   provided that the text is legible while moving. For
2763 		   example, as soon as all of the available rows of
2764 		   text are on the screen, Text Mode switches to the
2765 		   standard roll-up type of presentation." */
2766 
2767 		if (CC_LAST_ROW != row) {
2768 			if (0 != (ch->dirty[curr_buffer] & (1 << row))) {
2769 				cc_stream_event (cd, ch, row, row);
2770 			}
2771 
2772 			ch->curr_row = row + 1;
2773 
2774 			return;
2775 		}
2776 
2777 		/* No event if the buffer contains all
2778 		   TRANSPARENT_SPACEs. */
2779 		if (0 == ch->dirty[curr_buffer])
2780 			return;
2781 
2782 		window_rows = CC_MAX_ROWS;
2783 
2784 		break;
2785 	}
2786 
2787 	/* 47 CFR Section 15.119 (f)(1)(iii). In roll-up mode: "Each
2788 	   time a Carriage Return is received, the text in the top row
2789 	   of the window is erased from memory and from the display or
2790 	   scrolled off the top of the window. The remaining rows of
2791 	   text are each rolled up into the next highest row in the
2792 	   window, leaving the base row blank and ready to accept new
2793 	   text." */
2794 
2795 	if (0 != (ch->dirty[curr_buffer] & (1 << row))) {
2796 		cc_stream_event (cd, ch, row, row);
2797 	}
2798 
2799 	first_row = row + 1 - window_rows;
2800 	memmove (ch->buffer[curr_buffer][first_row],
2801 		 ch->buffer[curr_buffer][first_row + 1],
2802 		 (window_rows - 1) * sizeof (ch->buffer[0][0]));
2803 
2804 	ch->dirty[curr_buffer] >>= 1;
2805 
2806 	memset (ch->buffer[curr_buffer][row], 0,
2807 		sizeof (ch->buffer[0][0]));
2808 
2809 	cc_display_event (cd, ch, VBI_START_ROLLING);
2810 }
2811 
2812 static void
cc_erase_memory(struct cc_decoder * cd,struct cc_channel * ch,unsigned int buffer)2813 cc_erase_memory			(struct cc_decoder *	cd,
2814 				 struct cc_channel *	ch,
2815 				 unsigned int		buffer)
2816 {
2817 	if (0 != ch->dirty[buffer]) {
2818 		CLEAR (ch->buffer[buffer]);
2819 
2820 		ch->dirty[buffer] = 0;
2821 
2822 		if (buffer == ch->displayed_buffer)
2823 			cc_display_event (cd, ch, 0);
2824 	}
2825 }
2826 
2827 static void
cc_erase_displayed_memory(struct cc_decoder * cd,struct cc_channel * ch)2828 cc_erase_displayed_memory	(struct cc_decoder *	cd,
2829 				 struct cc_channel *	ch)
2830 {
2831 	unsigned int row;
2832 
2833 	/* EDM Erase Displayed Memory -- 001 c10f  010 1100 */
2834 
2835 	switch (ch->mode) {
2836 	case CC_MODE_UNKNOWN:
2837 		/* We have not received EOC, RCL, RDC or RUx yet, but
2838 		   ch is valid. */
2839 		break;
2840 
2841 	case CC_MODE_ROLL_UP:
2842 		row = ch->curr_row;
2843 		if (0 != (ch->dirty[ch->displayed_buffer] & (1 << row)))
2844 			cc_stream_event (cd, ch, row, row);
2845 		break;
2846 
2847 	case CC_MODE_PAINT_ON:
2848 		cc_stream_event_if_changed (cd, ch);
2849 		break;
2850 
2851 	case CC_MODE_POP_ON:
2852 		/* Nothing to do. */
2853 		break;
2854 
2855 	case CC_MODE_TEXT:
2856 		/* Not reached. (ch is a caption channel.) */
2857 		return;
2858 	}
2859 
2860 	/* May send a display event. */
2861 	cc_erase_memory (cd, ch, ch->displayed_buffer);
2862 }
2863 
2864 static void
cc_text_restart(struct cc_decoder * cd,struct cc_channel * ch)2865 cc_text_restart			(struct cc_decoder *	cd,
2866 				 struct cc_channel *	ch)
2867 {
2868 	unsigned int curr_buffer;
2869 	unsigned int row;
2870 
2871 	/* TR Text Restart -- 001 c10f  010 1010 */
2872 
2873 	curr_buffer = ch->displayed_buffer;
2874 	row = ch->curr_row;
2875 
2876 	/* ch->mode is invariably CC_MODE_TEXT. */
2877 
2878 	if (0 != (ch->dirty[curr_buffer] & (1 << row))) {
2879 		cc_stream_event (cd, ch, row, row);
2880 	}
2881 
2882 	/* EIA 608-B Section 7.4. */
2883 	/* May send a display event. */
2884 	cc_erase_memory (cd, ch, ch->displayed_buffer);
2885 
2886 	/* EIA 608-B Section 7.4. */
2887 	ch->curr_row = CC_FIRST_ROW;
2888 	ch->curr_column = CC_FIRST_COLUMN;
2889 }
2890 
2891 static void
cc_resume_direct_captioning(struct cc_decoder * cd,struct cc_channel * ch)2892 cc_resume_direct_captioning	(struct cc_decoder *	cd,
2893 				 struct cc_channel *	ch)
2894 {
2895 	unsigned int curr_buffer;
2896 	unsigned int row;
2897 
2898 	/* RDC Resume Direct Captioning -- 001 c10f  010 1001 */
2899 
2900 	/* 47 CFR 15.119 (f)(1)(x), (f)(2)(vi) and EIA 608-B Annex
2901 	   B.7: Does not erase memory, does not move the cursor when
2902 	   resuming after a Text transmission.
2903 
2904 	   XXX If ch->mode is unknown, roll-up or pop-on, what shall
2905 	   we do if no PAC is received between RDC and the text? */
2906 
2907 	curr_buffer = ch->displayed_buffer;
2908 	row = ch->curr_row;
2909 
2910 	switch (ch->mode) {
2911 	case CC_MODE_ROLL_UP:
2912 		if (0 != (ch->dirty[curr_buffer] & (1 << row)))
2913 			cc_stream_event (cd, ch, row, row);
2914 
2915 		/* fall through */
2916 
2917 	case CC_MODE_UNKNOWN:
2918 	case CC_MODE_POP_ON:
2919 		/* No change since last stream_event(). */
2920 		memcpy (ch->buffer[2], ch->buffer[curr_buffer],
2921 			sizeof (ch->buffer[2]));
2922 		break;
2923 
2924 	case CC_MODE_PAINT_ON:
2925 		/* Mode continues. */
2926 		break;
2927 
2928 	case CC_MODE_TEXT:
2929 		/* Not reached. (ch is a caption channel.) */
2930 		return;
2931 	}
2932 
2933 	ch->mode = CC_MODE_PAINT_ON;
2934 }
2935 
2936 static void
cc_resize_window(struct cc_decoder * cd,struct cc_channel * ch,unsigned int new_rows)2937 cc_resize_window		(struct cc_decoder *	cd,
2938 				 struct cc_channel *	ch,
2939 				 unsigned int		new_rows)
2940 {
2941 	unsigned int curr_buffer;
2942 	unsigned int max_rows;
2943 	unsigned int old_rows;
2944 	unsigned int row1;
2945 
2946 	curr_buffer = ch->displayed_buffer;
2947 
2948 	/* No event if the buffer contains all TRANSPARENT_SPACEs. */
2949 	if (0 == ch->dirty[curr_buffer])
2950 		return;
2951 
2952 	row1 = ch->curr_row + 1;
2953 	max_rows = row1 - CC_FIRST_ROW;
2954 	old_rows = MIN (ch->window_rows, max_rows);
2955 	new_rows = MIN (new_rows, max_rows);
2956 
2957 	/* Nothing to do unless the window shrinks. */
2958 	if (0 == new_rows || new_rows >= old_rows)
2959 		return;
2960 
2961 	memset (&ch->buffer[curr_buffer][row1 - old_rows][0], 0,
2962 		(old_rows - new_rows)
2963 		* sizeof (ch->buffer[0][0]));
2964 
2965 	ch->dirty[curr_buffer] &= -1 << (row1 - new_rows);
2966 
2967 	cc_display_event (cd, ch, 0);
2968 }
2969 
2970 static void
cc_roll_up_caption(struct cc_decoder * cd,struct cc_channel * ch,unsigned int c2)2971 cc_roll_up_caption		(struct cc_decoder *	cd,
2972 				 struct cc_channel *	ch,
2973 				 unsigned int		c2)
2974 {
2975 	unsigned int window_rows;
2976 
2977 	/* Roll-Up Captions -- 001 c10f  010 01xx */
2978 
2979 	window_rows = (c2 & 7) - 3; /* 2, 3, 4 */
2980 
2981 	switch (ch->mode) {
2982 	case CC_MODE_ROLL_UP:
2983 		/* 47 CFR 15.119 (f)(1)(iv). */
2984 		/* May send a display event. */
2985 		cc_resize_window (cd, ch, window_rows);
2986 
2987 		/* fall through */
2988 
2989 	case CC_MODE_UNKNOWN:
2990 		ch->mode = CC_MODE_ROLL_UP;
2991 		ch->window_rows = window_rows;
2992 
2993 		/* 47 CFR 15.119 (f)(1)(ix): No cursor movements,
2994 		   no memory erasing. */
2995 
2996 		break;
2997 
2998 	case CC_MODE_PAINT_ON:
2999 		cc_stream_event_if_changed (cd, ch);
3000 
3001 		/* fall through */
3002 
3003 	case CC_MODE_POP_ON:
3004 		ch->mode = CC_MODE_ROLL_UP;
3005 		ch->window_rows = window_rows;
3006 
3007 		/* 47 CFR 15.119 (f)(1)(ii). */
3008 		ch->curr_row = CC_LAST_ROW;
3009 		ch->curr_column = CC_FIRST_COLUMN;
3010 
3011 		/* 47 CFR 15.119 (f)(1)(x). */
3012 		/* May send a display event. */
3013 		cc_erase_memory (cd, ch, ch->displayed_buffer);
3014 		cc_erase_memory (cd, ch, ch->displayed_buffer ^ 1);
3015 
3016 		break;
3017 
3018 	case CC_MODE_TEXT:
3019 		/* Not reached. (ch is a caption channel.) */
3020 		return;
3021 	}
3022 }
3023 
3024 static void
cc_delete_to_end_of_row(struct cc_decoder * cd,struct cc_channel * ch)3025 cc_delete_to_end_of_row		(struct cc_decoder *	cd,
3026 				 struct cc_channel *	ch)
3027 {
3028 	unsigned int curr_buffer;
3029 	unsigned int row;
3030 
3031 	/* DER Delete To End Of Row -- 001 c10f  010 0100 */
3032 
3033 	/* 47 CFR 15.119 (f)(1)(vii), (f)(2)(iii), (f)(3)(ii) and EIA
3034 	   608-B Section 7.4: In all caption modes and Text mode
3035 	   "[the] Delete to End of Row command will erase from memory
3036 	   any characters or control codes starting at the current
3037 	   cursor location and in all columns to its right on the same
3038 	   row." */
3039 
3040 	curr_buffer = ch->displayed_buffer
3041 		^ (CC_MODE_POP_ON == ch->mode);
3042 
3043 	row = ch->curr_row;
3044 
3045 	/* No event if the row contains only TRANSPARENT_SPACEs. */
3046 	if (0 != (ch->dirty[curr_buffer] & (1 << row))) {
3047 		unsigned int column;
3048 		unsigned int i;
3049 		uint16_t c;
3050 
3051 		column = ch->curr_column;
3052 
3053 		memset (&ch->buffer[curr_buffer][row][column], 0,
3054 			(CC_LAST_COLUMN - column + 1)
3055 			* sizeof (ch->buffer[0][0][0]));
3056 
3057 		c = 0;
3058 		for (i = CC_FIRST_COLUMN; i < column; ++i)
3059 			c |= ch->buffer[curr_buffer][row][i];
3060 
3061 		ch->dirty[curr_buffer] &= ~((0 == c) << row);
3062 
3063 		cc_display_event (cd, ch, 0);
3064 	}
3065 }
3066 
3067 static void
cc_backspace(struct cc_decoder * cd,struct cc_channel * ch)3068 cc_backspace			(struct cc_decoder *	cd,
3069 				 struct cc_channel *	ch)
3070 {
3071 	unsigned int curr_buffer;
3072 	unsigned int row;
3073 	unsigned int column;
3074 
3075 	/* BS Backspace -- 001 c10f  010 0001 */
3076 
3077 	/* 47 CFR Section 15.119 (f)(1)(vi), (f)(2)(ii), (f)(3)(i) and
3078 	   EIA 608-B Section 7.4. */
3079 	column = ch->curr_column;
3080 	if (column <= CC_FIRST_COLUMN)
3081 		return;
3082 
3083 	ch->curr_column = --column;
3084 
3085 	curr_buffer = ch->displayed_buffer
3086 		^ (CC_MODE_POP_ON == ch->mode);
3087 
3088 	row = ch->curr_row;
3089 
3090 	/* No event if there's no visible effect. */
3091 	if (0 != ch->buffer[curr_buffer][row][column]) {
3092 		unsigned int i;
3093 		uint16_t c;
3094 
3095 		/* 47 CFR 15.119 (f), (f)(1)(vi), (f)(2)(ii) and EIA
3096 		   608-B Section 7.4. */
3097 		ch->buffer[curr_buffer][row][column] = 0;
3098 
3099 		c = 0;
3100 		for (i = CC_FIRST_COLUMN; i <= CC_LAST_COLUMN; ++i)
3101 			c |= ch->buffer[curr_buffer][row][i];
3102 
3103 		ch->dirty[curr_buffer] &= ~((0 == c) << row);
3104 
3105 		cc_display_event (cd, ch, 0);
3106 	}
3107 }
3108 
3109 static void
cc_resume_caption_loading(struct cc_decoder * cd,struct cc_channel * ch)3110 cc_resume_caption_loading	(struct cc_decoder *	cd,
3111 				 struct cc_channel *	ch)
3112 {
3113 	unsigned int row;
3114 
3115 	/* RCL Resume Caption Loading -- 001 c10f  010 0000 */
3116 
3117 	switch (ch->mode) {
3118 	case CC_MODE_UNKNOWN:
3119 	case CC_MODE_POP_ON:
3120 		break;
3121 
3122 	case CC_MODE_ROLL_UP:
3123 		row = ch->curr_row;
3124 		if (0 != (ch->dirty[ch->displayed_buffer] & (1 << row)))
3125 			cc_stream_event (cd, ch, row, row);
3126 		break;
3127 
3128 	case CC_MODE_PAINT_ON:
3129 		cc_stream_event_if_changed (cd, ch);
3130 		break;
3131 
3132 	case CC_MODE_TEXT:
3133 		/* Not reached. (ch is a caption channel.) */
3134 		return;
3135 	}
3136 
3137 	/* 47 CFR 15.119 (f)(1)(x): Does not erase memory.
3138 	   (f)(2)(iv): Cursor position remains unchanged. */
3139 
3140 	ch->mode = CC_MODE_POP_ON;
3141 }
3142 
3143 
3144 
3145 /* Note curr_ch is invalid if UNKNOWN_CC_CHANNEL == cd->cc.curr_ch_num. */
3146 static struct cc_channel *
cc_switch_channel(struct cc_decoder * cd,struct cc_channel * curr_ch,vbi_pgno new_ch_num,enum field_num f)3147 cc_switch_channel		(struct cc_decoder *	cd,
3148 				 struct cc_channel *	curr_ch,
3149 				 vbi_pgno		new_ch_num,
3150 				 enum field_num		f)
3151 {
3152 	struct cc_channel *new_ch;
3153 
3154 	if (UNKNOWN_CC_CHANNEL != cd->curr_ch_num[f]
3155 	    && CC_MODE_UNKNOWN != curr_ch->mode) {
3156 		/* XXX Force a display update if we do not send events
3157 		   on every display change. */
3158 	}
3159 
3160 	cd->curr_ch_num[f] = new_ch_num;
3161 	new_ch = &cd->channel[new_ch_num - VBI_CAPTION_CC1];
3162 
3163 	return new_ch;
3164 }
3165 
3166 /* Note ch is invalid if UNKNOWN_CC_CHANNEL == cd->cc.curr_ch_num[f]. */
3167 static void
cc_misc_control_code(struct cc_decoder * cd,struct cc_channel * ch,unsigned int c2,unsigned int ch_num0,enum field_num f)3168 cc_misc_control_code		(struct cc_decoder *	cd,
3169 				 struct cc_channel *	ch,
3170 				 unsigned int		c2,
3171 				 unsigned int		ch_num0,
3172 				 enum field_num		f)
3173 {
3174 	unsigned int new_ch_num;
3175 
3176 	/* Misc Control Codes -- 001 c10f  010 xxxx */
3177 
3178 	/* c = channel (0 -> CC1/CC3/T1/T3, 1 -> CC2/CC4/T2/T4)
3179 	     -- 47 CFR Section 15.119, EIA 608-B Section 7.7.
3180 	   f = field (0 -> F1, 1 -> F2)
3181 	     -- EIA 608-B Section 8.4, 8.5. */
3182 
3183 	/* XXX The f flag is intended to detect accidential field
3184 	   swapping and we should use it for that purpose. */
3185 
3186 	switch (c2 & 15) {
3187 	case 0:	/* RCL Resume Caption Loading -- 001 c10f  010 0000 */
3188 		/* 47 CFR 15.119 (f)(2) and EIA 608-B Section 7.7. */
3189 		new_ch_num = VBI_CAPTION_CC1 + (ch_num0 & 3);
3190 		ch = cc_switch_channel (cd, ch, new_ch_num, f);
3191 		cc_resume_caption_loading (cd, ch);
3192 		break;
3193 
3194 	case 1: /* BS Backspace -- 001 c10f  010 0001 */
3195 		if (UNKNOWN_CC_CHANNEL == cd->curr_ch_num[f]
3196 		    || CC_MODE_UNKNOWN == ch->mode)
3197 			break;
3198 		cc_backspace (cd, ch);
3199 		break;
3200 
3201 	case 2: /* reserved (formerly AOF Alarm Off) */
3202 	case 3: /* reserved (formerly AON Alarm On) */
3203 		break;
3204 
3205 	case 4: /* DER Delete To End Of Row -- 001 c10f  010 0100 */
3206 		if (UNKNOWN_CC_CHANNEL == cd->curr_ch_num[f]
3207 		    || CC_MODE_UNKNOWN == ch->mode)
3208 			break;
3209 		cc_delete_to_end_of_row (cd, ch);
3210 		break;
3211 
3212 	case 5: /* RU2 */
3213 	case 6: /* RU3 */
3214 	case 7: /* RU4 Roll-Up Captions -- 001 c10f  010 01xx */
3215 		/* 47 CFR 15.119 (f)(1) and EIA 608-B Section 7.7. */
3216 		new_ch_num = VBI_CAPTION_CC1 + (ch_num0 & 3);
3217 		ch = cc_switch_channel (cd, ch, new_ch_num, f);
3218 		cc_roll_up_caption (cd, ch, c2);
3219 		break;
3220 
3221 	case 8: /* FON Flash On -- 001 c10f  010 1000 */
3222 		if (UNKNOWN_CC_CHANNEL == cd->curr_ch_num[f]
3223 		    || CC_MODE_UNKNOWN == ch->mode)
3224 			break;
3225 
3226 		/* 47 CFR 15.119 (h)(1)(i): Spacing attribute. */
3227 		cc_put_char (cd, ch, 0x1428,
3228 			     /* displayable */ FALSE,
3229 			     /* backspace */ FALSE);
3230 		break;
3231 
3232 	case 9: /* RDC Resume Direct Captioning -- 001 c10f  010 1001 */
3233 		/* 47 CFR 15.119 (f)(3) and EIA 608-B Section 7.7. */
3234 		new_ch_num = VBI_CAPTION_CC1 + (ch_num0 & 3);
3235 		ch = cc_switch_channel (cd, ch, new_ch_num, f);
3236 		cc_resume_direct_captioning (cd, ch);
3237 		break;
3238 
3239 	case 10: /* TR Text Restart -- 001 c10f  010 1010 */
3240 		/* EIA 608-B Section 7.4. */
3241 		new_ch_num = VBI_CAPTION_T1 + (ch_num0 & 3);
3242 		ch = cc_switch_channel (cd, ch, new_ch_num, f);
3243 		cc_text_restart (cd, ch);
3244 		break;
3245 
3246 	case 11: /* RTD Resume Text Display -- 001 c10f  010 1011 */
3247 		/* EIA 608-B Section 7.4. */
3248 		new_ch_num = VBI_CAPTION_T1 + (ch_num0 & 3);
3249 		ch = cc_switch_channel (cd, ch, new_ch_num, f);
3250 		/* ch->mode is invariably CC_MODE_TEXT. */
3251 		break;
3252 
3253 	case 12: /* EDM Erase Displayed Memory -- 001 c10f  010 1100 */
3254 		/* 47 CFR 15.119 (f). EIA 608-B Section 7.7 and Annex
3255 		   B.7: "[The] command shall be acted upon as
3256 		   appropriate for caption processing without
3257 		   terminating the Text Mode data stream." */
3258 
3259 		/* We need not check cd->curr_ch_num because bit 2 is
3260 		   implied, bit 1 is the known field number and bit 0
3261 		   is coded in the control code. */
3262 		ch = &cd->channel[ch_num0 & 3];
3263 
3264 		cc_erase_displayed_memory (cd, ch);
3265 
3266 		break;
3267 
3268 	case 13: /* CR Carriage Return -- 001 c10f  010 1101 */
3269 		if (UNKNOWN_CC_CHANNEL == cd->curr_ch_num[f])
3270 			break;
3271 		cc_carriage_return (cd, ch);
3272 		break;
3273 
3274 	case 14: /* ENM Erase Non-Displayed Memory -- 001 c10f  010 1110 */
3275 		/* 47 CFR 15.119 (f)(2)(v). EIA 608-B Section 7.7 and
3276 		   Annex B.7: "[The] command shall be acted upon as
3277 		   appropriate for caption processing without
3278 		   terminating the Text Mode data stream." */
3279 
3280 		/* See EDM. */
3281 		ch = &cd->channel[ch_num0 & 3];
3282 
3283 		cc_erase_memory (cd, ch, ch->displayed_buffer ^ 1);
3284 
3285 		break;
3286 
3287 	case 15: /* EOC End Of Caption -- 001 c10f  010 1111 */
3288 		/* 47 CFR 15.119 (f), (f)(2), (f)(3)(iv) and EIA 608-B
3289 		   Section 7.7, Annex C.11. */
3290 		new_ch_num = VBI_CAPTION_CC1 + (ch_num0 & 3);
3291 		ch = cc_switch_channel (cd, ch, new_ch_num, f);
3292 		cc_end_of_caption (cd, ch);
3293 		break;
3294 	}
3295 }
3296 
3297 static void
cc_move_window(struct cc_decoder * cd,struct cc_channel * ch,unsigned int new_base_row)3298 cc_move_window			(struct cc_decoder *	cd,
3299 				 struct cc_channel *	ch,
3300 				 unsigned int		new_base_row)
3301 {
3302 	uint8_t *base;
3303 	unsigned int curr_buffer;
3304 	unsigned int bytes_per_row;
3305 	unsigned int old_max_rows;
3306 	unsigned int new_max_rows;
3307 	unsigned int copy_bytes;
3308 	unsigned int erase_begin;
3309 	unsigned int erase_end;
3310 
3311 	curr_buffer = ch->displayed_buffer;
3312 
3313 	/* No event if we do not move the window or the buffer
3314 	   contains only TRANSPARENT_SPACEs. */
3315 	if (new_base_row == ch->curr_row
3316 	    || 0 == ch->dirty[curr_buffer])
3317 		return;
3318 
3319 	base = (void *) &ch->buffer[curr_buffer][CC_FIRST_ROW][0];
3320 	bytes_per_row = sizeof (ch->buffer[0][0]);
3321 
3322 	old_max_rows = ch->curr_row + 1 - CC_FIRST_ROW;
3323 	new_max_rows = new_base_row + 1 - CC_FIRST_ROW;
3324 	copy_bytes = MIN (MIN (old_max_rows, new_max_rows),
3325 			  ch->window_rows) * bytes_per_row;
3326 
3327 	if (new_base_row < ch->curr_row) {
3328 		erase_begin = (new_base_row + 1) * bytes_per_row;
3329 		erase_end = (ch->curr_row + 1) * bytes_per_row;
3330 
3331 		memmove (base + erase_begin - copy_bytes,
3332 			 base + erase_end - copy_bytes, copy_bytes);
3333 
3334 		ch->dirty[curr_buffer] >>= ch->curr_row - new_base_row;
3335 	} else {
3336 		erase_begin = (ch->curr_row + 1) * bytes_per_row
3337 			- copy_bytes;
3338 		erase_end = (new_base_row + 1) * bytes_per_row
3339 			- copy_bytes;
3340 
3341 		memmove (base + erase_end,
3342 			 base + erase_begin, copy_bytes);
3343 
3344 		ch->dirty[curr_buffer] <<= new_base_row - ch->curr_row;
3345 		ch->dirty[curr_buffer] &= CC_ALL_ROWS_MASK;
3346 	}
3347 
3348 	memset (base + erase_begin, 0, erase_end - erase_begin);
3349 
3350 	cc_display_event (cd, ch, 0);
3351 }
3352 
3353 static void
cc_preamble_address_code(struct cc_decoder * cd,struct cc_channel * ch,unsigned int c1,unsigned int c2)3354 cc_preamble_address_code	(struct cc_decoder *	cd,
3355 				 struct cc_channel *	ch,
3356 				 unsigned int		c1,
3357 				 unsigned int		c2)
3358 {
3359 	unsigned int row;
3360 
3361 	/* PAC Preamble Address Codes -- 001 crrr  1ri xxxu */
3362 
3363 	row = cc_pac_row_map[(c1 & 7) * 2 + ((c2 >> 5) & 1)];
3364 	if ((int) row < 0)
3365 		return;
3366 
3367 	switch (ch->mode) {
3368 	case CC_MODE_UNKNOWN:
3369 		return;
3370 
3371 	case CC_MODE_ROLL_UP:
3372 		/* EIA 608-B Annex C.4. */
3373 		if (ch->window_rows > row + 1)
3374 			row = ch->window_rows - 1;
3375 
3376 		/* 47 CFR Section 15.119 (f)(1)(ii). */
3377 		/* May send a display event. */
3378 		cc_move_window (cd, ch, row);
3379 
3380 		ch->curr_row = row;
3381 
3382 		break;
3383 
3384 	case CC_MODE_PAINT_ON:
3385 		cc_stream_event_if_changed (cd, ch);
3386 
3387 		/* fall through */
3388 
3389 	case CC_MODE_POP_ON:
3390 		/* XXX 47 CFR 15.119 (f)(2)(i), (f)(3)(i): In Pop-on
3391 		   and paint-on mode "Preamble Address Codes can be
3392 		   used to move the cursor around the screen in random
3393 		   order to place captions on Rows 1 to 15." We do not
3394 		   have a limit on the number of displayable rows, but
3395 		   as EIA 608-B Annex C.6 points out, if more than
3396 		   four rows must be displayed they were probably
3397 		   received in error and we should respond
3398 		   accordingly. */
3399 
3400 		/* 47 CFR Section 15.119 (d)(1)(i) and EIA 608-B Annex
3401 		   C.7. */
3402 		ch->curr_row = row;
3403 
3404 		break;
3405 
3406 	case CC_MODE_TEXT:
3407 		/* 47 CFR 15.119 (e)(1) and EIA 608-B Section 7.4:
3408 		   Does not change the cursor row. */
3409 		break;
3410 	}
3411 
3412 	if (c2 & 0x10) {
3413 		/* 47 CFR 15.119 (e)(1)(i) and EIA 608-B Table 71. */
3414 		ch->curr_column = CC_FIRST_COLUMN + (c2 & 0x0E) * 2;
3415 	}
3416 
3417 	/* PAC is a non-spacing attribute for the next character, see
3418 	   cc_put_char(). */
3419 	ch->last_pac = 0x1000 | c2;
3420 }
3421 
3422 static void
cc_control_code(struct cc_decoder * cd,unsigned int c1,unsigned int c2,enum field_num f)3423 cc_control_code			(struct cc_decoder *	cd,
3424 				 unsigned int		c1,
3425 				 unsigned int		c2,
3426 				 enum field_num		f)
3427 {
3428 	struct cc_channel *ch;
3429 	unsigned int ch_num0;
3430 
3431 	if (option_debug & DEBUG_CC_DECODER) {
3432 		fprintf (stderr, "%s %02x %02x %d\n",
3433 			 __FUNCTION__, c1, c2, f);
3434 	}
3435 
3436 	/* Caption / text, field 1 / 2, primary / secondary channel. */
3437 	ch_num0 = (((cd->curr_ch_num[f] - VBI_CAPTION_CC1) & 4)
3438 		   + f * 2
3439 		   + ((c1 >> 3) & 1));
3440 
3441 	/* Note ch is invalid if UNKNOWN_CC_CHANNEL ==
3442 	   cd->curr_ch_num[f]. */
3443 	ch = &cd->channel[ch_num0];
3444 
3445 	if (c2 >= 0x40) {
3446 		/* Preamble Address Codes -- 001 crrr  1ri xxxu */
3447 		if (UNKNOWN_CC_CHANNEL != cd->curr_ch_num[f])
3448 			cc_preamble_address_code (cd, ch, c1, c2);
3449 		return;
3450 	}
3451 
3452 	switch (c1 & 7) {
3453 	case 0:
3454 		if (UNKNOWN_CC_CHANNEL == cd->curr_ch_num[f]
3455 		    || CC_MODE_UNKNOWN == ch->mode)
3456 			break;
3457 
3458 		if (c2 < 0x30) {
3459 			/* Backgr. Attr. Codes -- 001 c000  010 xxxt */
3460 			/* EIA 608-B Section 6.2. */
3461 			cc_put_char (cd, ch, 0x1000 | c2,
3462 				     /* displayable */ FALSE,
3463 				     /* backspace */ TRUE);
3464 		} else {
3465 			/* Undefined. */
3466 		}
3467 
3468 		break;
3469 
3470 	case 1:
3471 		if (UNKNOWN_CC_CHANNEL == cd->curr_ch_num[f]
3472 		    || CC_MODE_UNKNOWN == ch->mode)
3473 			break;
3474 
3475 		if (c2 < 0x30) {
3476 			/* Mid-Row Codes -- 001 c001  010 xxxu */
3477 			/* 47 CFR 15.119 (h)(1)(i): Spacing attribute. */
3478 			cc_put_char (cd, ch, 0x1100 | c2,
3479 				     /* displayable */ FALSE,
3480 				     /* backspace */ FALSE);
3481 		} else {
3482 			/* Special Characters -- 001 c001  011 xxxx */
3483 			if (0x39 == c2) {
3484 				/* Transparent space. */
3485 				cc_put_char (cd, ch, 0,
3486 					     /* displayable */ FALSE,
3487 					     /* backspace */ FALSE);
3488 			} else {
3489 				cc_put_char (cd, ch, 0x1100 | c2,
3490 					     /* displayable */ TRUE,
3491 					     /* backspace */ FALSE);
3492 			}
3493 		}
3494 
3495 		break;
3496 
3497 	case 2:
3498 	case 3: /* Extended Character Set -- 001 c01x  01x xxxx */
3499 		if (UNKNOWN_CC_CHANNEL == cd->curr_ch_num[f]
3500 		    || CC_MODE_UNKNOWN == ch->mode)
3501 			break;
3502 
3503 		/* EIA 608-B Section 6.4.2. */
3504 		cc_put_char (cd, ch, (c1 * 256 + c2) & 0x777F,
3505 			     /* displayable */ TRUE,
3506 			     /* backspace */ TRUE);
3507 		break;
3508 
3509 	case 4:
3510 	case 5:
3511 		if (c2 < 0x30) {
3512 			/* Misc. Control Codes -- 001 c10f  010 xxxx */
3513 			cc_misc_control_code (cd, ch, c2, ch_num0, f);
3514 		} else {
3515 			/* Undefined. */
3516 		}
3517 
3518 		break;
3519 
3520 	case 6: /* reserved */
3521 		break;
3522 
3523 	case 7:	/* Extended control codes -- 001 c111  01x xxxx */
3524 		if (UNKNOWN_CC_CHANNEL == cd->curr_ch_num[f]
3525 		    || CC_MODE_UNKNOWN == ch->mode)
3526 			break;
3527 
3528 		cc_ext_control_code (cd, ch, c2);
3529 
3530 		break;
3531 	}
3532 }
3533 
3534 static vbi_bool
cc_characters(struct cc_decoder * cd,struct cc_channel * ch,int c)3535 cc_characters			(struct cc_decoder *	cd,
3536 				 struct cc_channel *	ch,
3537 				 int			c)
3538 {
3539 	if (option_debug & DEBUG_CC_DECODER) {
3540 		fprintf (stderr, "%s %02x '%c'\n",
3541 			 __FUNCTION__, c, printable (c));
3542 	}
3543 
3544 	if (0 == c) {
3545 		if (CC_MODE_UNKNOWN == ch->mode)
3546 			return TRUE;
3547 
3548 		/* XXX After x NUL characters (presumably a caption
3549 		   pause), force a display update if we do not send
3550 		   events on every display change. */
3551 
3552 		return TRUE;
3553 	}
3554 
3555 	if (c < 0x20) {
3556 		/* Parity error or invalid data. */
3557 
3558 		if (c < 0 && CC_MODE_UNKNOWN != ch->mode) {
3559 			/* 47 CFR Section 15.119 (j)(1). */
3560 			cc_put_char (cd, ch, 0x7F,
3561 				     /* displayable */ TRUE,
3562 				     /* backspace */ FALSE);
3563 		}
3564 
3565 		return FALSE;
3566 	}
3567 
3568 	if (CC_MODE_UNKNOWN != ch->mode) {
3569 		cc_put_char (cd, ch, c,
3570 			     /* displayable */ TRUE,
3571 			     /* backspace */ FALSE);
3572 	}
3573 
3574 	return TRUE;
3575 }
3576 
3577 static vbi_bool
cc_feed(struct cc_decoder * cd,const uint8_t buffer[2],unsigned int line,const struct timeval * tv,int64_t pts)3578 cc_feed				(struct cc_decoder *	cd,
3579 				 const uint8_t		buffer[2],
3580 				 unsigned int		line,
3581 				 const struct timeval *	tv,
3582 				 int64_t		pts)
3583 {
3584 	int c1, c2;
3585 	enum field_num f;
3586 	vbi_bool all_successful;
3587 
3588 	assert (NULL != cd);
3589 
3590 	if (option_debug & DEBUG_CC_DECODER) {
3591 		fprintf (stderr, "%s %02x %02x '%c%c' "
3592 			 "%3d %f %" PRId64 "\n",
3593 			 __FUNCTION__,
3594 			 buffer[0] & 0x7F,
3595 			 buffer[1] & 0x7F,
3596 			 printable (buffer[0]),
3597 			 printable (buffer[1]),
3598 			 line,
3599 			 tv->tv_sec + tv->tv_usec * (1 / 1e6),
3600 			 pts);
3601 	}
3602 
3603 	f = FIELD_1;
3604 
3605 	switch (line) {
3606 	case 21: /* NTSC */
3607 	case 22: /* PAL/SECAM */
3608 		break;
3609 
3610 	case 284: /* NTSC */
3611 		f = FIELD_2;
3612 		break;
3613 
3614 	default:
3615 		return FALSE;
3616 	}
3617 
3618 	cd->timestamp.sys = *tv;
3619 	cd->timestamp.pts = pts;
3620 
3621 	/* FIXME deferred reset here */
3622 
3623 	c1 = vbi_unpar8 (buffer[0]);
3624 	c2 = vbi_unpar8 (buffer[1]);
3625 
3626 	all_successful = TRUE;
3627 
3628 	/* 47 CFR 15.119 (2)(i)(4): "If the first transmission of a
3629 	   control code pair passes parity, it is acted upon within
3630 	   one video frame. If the next frame contains a perfect
3631 	   repeat of the same pair, the redundant code is ignored. If,
3632 	   however, the next frame contains a different but also valid
3633 	   control code pair, this pair, too, will be acted upon (and
3634 	   the receiver will expect a repeat of this second pair in
3635 	   the next frame).  If the first byte of the expected
3636 	   redundant control code pair fails the parity check and the
3637 	   second byte is identical to the second byte in the
3638 	   immediately preceding pair, then the expected redundant
3639 	   code is ignored. If there are printing characters in place
3640 	   of the redundant code, they will be processed normally."
3641 
3642 	   EIA 608-B Section 8.3: Caption control codes on field 2 may
3643 	   repeat as on field 1. Section 8.6.2: XDS control codes
3644 	   shall not repeat. */
3645 
3646 	if (unlikely (c1 < 0)) {
3647 		goto parity_error;
3648 	} else if (c1 == cd->expect_ctrl[f][0]
3649 		   && c2 == cd->expect_ctrl[f][1]) {
3650 		/* Already acted upon. */
3651 		cd->expect_ctrl[f][0] = -1;
3652 		goto finish;
3653 	}
3654 
3655 	if (c1 >= 0x10 && c1 < 0x20) {
3656 		/* Caption control code. */
3657 
3658 		/* There's no XDS on field 1, we just
3659 		   use an array to save a branch. */
3660 		cd->in_xds[f] = FALSE;
3661 
3662 		/* 47 CFR Section 15.119 (i)(1), (i)(2). */
3663 		if (c2 < 0x20) {
3664 			/* Parity error or invalid control code.
3665 			   Let's hope it repeats. */
3666 			goto parity_error;
3667 		}
3668 
3669 		cc_control_code (cd, c1, c2, f);
3670 
3671 		if (cd->event_pending) {
3672 			cc_display_event (cd, cd->event_pending, 0);
3673 			cd->event_pending = NULL;
3674 		}
3675 
3676 		cd->expect_ctrl[f][0] = c1;
3677 		cd->expect_ctrl[f][1] = c2;
3678 	} else {
3679 		cd->expect_ctrl[f][0] = -1;
3680 
3681 		if (c1 < 0x10) {
3682 			if (FIELD_1 == f) {
3683 				/* 47 CFR Section 15.119 (i)(1): "If the
3684 				   non-printing character in the pair is
3685 				   in the range 00h to 0Fh, that character
3686 				   alone will be ignored and the second
3687 				   character will be treated normally." */
3688 				c1 = 0;
3689 			} else if (0x0F == c1) {
3690 				/* XDS packet terminator. */
3691 				cd->in_xds[FIELD_2] = FALSE;
3692 				goto finish;
3693 			} else if (c1 >= 0x01) {
3694 				/* XDS packet start or continuation.
3695 				   EIA 608-B Section 7.7, 8.5: Also
3696 				   interrupts a Text mode
3697 				   transmission. */
3698 				cd->in_xds[FIELD_2] = TRUE;
3699 				goto finish;
3700 			}
3701 		}
3702 
3703 		{
3704 			struct cc_channel *ch;
3705 			vbi_pgno ch_num;
3706 
3707 			ch_num = cd->curr_ch_num[f];
3708 			if (UNKNOWN_CC_CHANNEL == ch_num)
3709 				goto finish;
3710 
3711 			ch_num = ((ch_num - VBI_CAPTION_CC1) & 5) + f * 2;
3712 			ch = &cd->channel[ch_num];
3713 
3714 			all_successful &= cc_characters (cd, ch, c1);
3715 			all_successful &= cc_characters (cd, ch, c2);
3716 
3717 			if (cd->event_pending) {
3718 				cc_display_event (cd, cd->event_pending, 0);
3719 				cd->event_pending = NULL;
3720 			}
3721 		}
3722 	}
3723 
3724  finish:
3725 	cd->error_history = cd->error_history * 2 + all_successful;
3726 
3727 	return all_successful;
3728 
3729  parity_error:
3730 	cd->expect_ctrl[f][0] = -1;
3731 
3732 	/* XXX Some networks stupidly transmit 0x0000 instead of
3733 	   0x8080 as filler. Perhaps we shouldn't take that as a
3734 	   serious parity error. */
3735 	cd->error_history *= 2;
3736 
3737 	return FALSE;
3738 }
3739 
3740 static void
cc_reset(struct cc_decoder * cd)3741 cc_reset			(struct cc_decoder *	cd)
3742 {
3743 	unsigned int ch_num;
3744 
3745 	assert (NULL != cd);
3746 
3747 	if (option_debug & DEBUG_CC_DECODER) {
3748 		fprintf (stderr, "%s\n", __FUNCTION__);
3749 	}
3750 
3751 	for (ch_num = 0; ch_num < MAX_CC_CHANNELS; ++ch_num) {
3752 		struct cc_channel *ch;
3753 
3754 		ch = &cd->channel[ch_num];
3755 
3756 		if (ch_num <= 3) {
3757 			ch->mode = CC_MODE_UNKNOWN;
3758 
3759 			/* Something suitable for roll-up mode. */
3760 			ch->curr_row = CC_LAST_ROW;
3761 			ch->curr_column = CC_FIRST_COLUMN;
3762 			ch->window_rows = 4;
3763 		} else {
3764 			ch->mode = CC_MODE_TEXT; /* invariable */
3765 
3766 			/* EIA 608-B Section 7.4: "When Text Mode has
3767 			   initially been selected and the specified
3768 			   Text memory is empty, the cursor starts at
3769 			   the topmost row, Column 1." */
3770 			ch->curr_row = CC_FIRST_ROW;
3771 			ch->curr_column = CC_FIRST_COLUMN;
3772 			ch->window_rows = 0; /* n/a */
3773 		}
3774 
3775 		ch->displayed_buffer = 0;
3776 
3777 		ch->last_pac = 0;
3778 
3779 		CLEAR (ch->buffer);
3780 		CLEAR (ch->dirty);
3781 
3782 		cc_timestamp_reset (&ch->timestamp);
3783 		cc_timestamp_reset (&ch->timestamp_c0);
3784 	}
3785 
3786 	cd->curr_ch_num[0] = UNKNOWN_CC_CHANNEL;
3787 	cd->curr_ch_num[1] = UNKNOWN_CC_CHANNEL;
3788 
3789 	memset (cd->expect_ctrl, -1, sizeof (cd->expect_ctrl));
3790 
3791 	CLEAR (cd->in_xds);
3792 
3793 	cd->event_pending = NULL;
3794 }
3795 
3796 static void
init_cc_decoder(struct cc_decoder * cd)3797 init_cc_decoder			(struct cc_decoder *	cd)
3798 {
3799 	cc_reset (cd);
3800 
3801 	cd->error_history = 0;
3802 
3803 	cc_timestamp_reset (&cd->timestamp);
3804 }
3805 
3806 /* Some code left over from ntsc-cc, to be replaced. */
3807 
3808 const char * const ratings[] = {
3809 	"(NOT RATED)","TV-Y","TV-Y7","TV-G",
3810 	"TV-PG","TV-14","TV-MA","(NOT RATED)"};
3811 const char * const modes[]={
3812 	"current","future","channel","miscellaneous","public service",
3813 	"reserved","invalid","invalid","invalid","invalid"};
3814 
3815 static void
print_xds_info(struct caption_recorder * cr,unsigned int mode,unsigned int type)3816 print_xds_info			(struct caption_recorder *cr,
3817 				 unsigned int		mode,
3818 				 unsigned int		type)
3819 {
3820 	const char *infoptr;
3821 
3822 	if (!cr->info[0][mode][type].print)
3823 		return;
3824 
3825 	infoptr = cr->info[cr->field][mode][type].packet;
3826 
3827 	switch ((mode << 8) + type) {
3828 	case 0x0101:
3829 		fprintf (cr->xds_fp,
3830 			 "%sTIMECODE: %d/%02d %d:%02d%s",
3831 			 cr->xds_info_prefix,
3832 			 infoptr[3]&0x0f,infoptr[2]&0x1f,
3833 			 infoptr[1]&0x1f,infoptr[0]&0x3f,
3834 			 cr->xds_info_suffix);
3835 	case 0x0102:
3836 		if ((infoptr[1]&0x3f)>5)
3837 			break;
3838 		fprintf (cr->xds_fp,
3839 			 "%s  LENGTH: %d:%02d:%02d of %d:%02d:00%s",
3840 			 cr->xds_info_prefix,
3841 			 infoptr[3]&0x3f,infoptr[2]&0x3f,
3842 			 infoptr[4]&0x3f,infoptr[1]&0x3f,
3843 			 infoptr[0]&0x3f,
3844 			 cr->xds_info_suffix);
3845 		break;
3846 	case 0x0103:
3847 		fprintf (cr->xds_fp,
3848 			 "%s   TITLE: %s%s",
3849 			 cr->xds_info_prefix,
3850 			 infoptr,
3851 			 cr->xds_info_suffix);
3852 		break;
3853 	case 0x0105:
3854 		fprintf (cr->xds_fp,
3855 			 "%s  RATING: %s (%d)",
3856 			 cr->xds_info_prefix,
3857 			 ratings[infoptr[0]&0x07],infoptr[0]);
3858 		if ((infoptr[0]&0x07)>0) {
3859 			if (infoptr[0]&0x20) fputs (" VIOLENCE", cr->xds_fp);
3860 			if (infoptr[0]&0x10) fputs (" SEXUAL", cr->xds_fp);
3861 			if (infoptr[0]&0x08) fputs (" LANGUAGE", cr->xds_fp);
3862 		}
3863 		fputs (cr->xds_info_suffix, cr->xds_fp);
3864 		break;
3865 	case 0x0501:
3866 		fprintf (cr->xds_fp,
3867 			 "%s NETWORK: %s%s",
3868 			 cr->xds_info_prefix,
3869 			 infoptr,
3870 			 cr->xds_info_suffix);
3871 		break;
3872 	case 0x0502:
3873 		fprintf (cr->xds_fp,
3874 			 "%s    CALL: %s%s",
3875 			 cr->xds_info_prefix,
3876 			 infoptr,
3877 			 cr->xds_info_suffix);
3878 		break;
3879 	case 0x0701:
3880 		fprintf (cr->xds_fp,
3881 			 "%sCUR.TIME: %d:%02d %d/%02d/%04d UTC%s",
3882 			 cr->xds_info_prefix,
3883 			 infoptr[1]&0x1F,infoptr[0]&0x3f,
3884 			 infoptr[3]&0x0f,infoptr[2]&0x1f,
3885 			 (infoptr[5]&0x3f)+1990,
3886 			 cr->xds_info_suffix);
3887 		break;
3888 	case 0x0704: //timezone
3889 		fprintf (cr->xds_fp,
3890 			 "%sTIMEZONE: UTC-%d%s",
3891 			 cr->xds_info_prefix,
3892 			 infoptr[0]&0x1f,
3893 			 cr->xds_info_suffix);
3894 		break;
3895 	case 0x0104: //program genere
3896 		break;
3897 	case 0x0110:
3898 	case 0x0111:
3899 	case 0x0112:
3900 	case 0x0113:
3901 	case 0x0114:
3902 	case 0x0115:
3903 	case 0x0116:
3904 	case 0x0117:
3905 		fprintf (cr->xds_fp,
3906 			 "%s    DESC: %s%s",
3907 			 cr->xds_info_prefix,
3908 			 infoptr,
3909 			 cr->xds_info_suffix);
3910 		break;
3911 	}
3912 
3913 	fflush (cr->xds_fp);
3914 }
3915 
XDSdecode(struct caption_recorder * cr,int data)3916 static int XDSdecode(struct caption_recorder *cr, int data)
3917 {
3918 	static vbi_bool in_xds[2];
3919 	int b1, b2, length;
3920 
3921 	if (data == -1)
3922 		return -1;
3923 
3924 	b1 = data & 0x7F;
3925 	b2 = (data>>8) & 0x7F;
3926 
3927 	if (0 == b1) {
3928 		/* Filler, discard. */
3929 		return -1;
3930 	}
3931 	else if (b1 < 15) // start packet
3932 	{
3933 		cr->mode = b1;
3934 		cr->type = b2;
3935 		cr->infochecksum = b1 + b2 + 15;
3936 		if (cr->mode > 8 || cr->type > 20)
3937 		{
3938 //			printf("%% Unsupported mode %s(%d) [%d]\n",modes[(mode-1)>>1],mode,type);
3939 			cr->mode=0; cr->type=0;
3940 		}
3941 		cr->infoptr = cr->newinfo[cr->field][cr->mode][cr->type];
3942 		in_xds[cr->field] = TRUE;
3943 	}
3944 	else if (b1 == 15) // eof (next byte is checksum)
3945 	{
3946 #if 0 //debug
3947 		if (mode == 0)
3948 		{
3949 			length=infoptr - newinfo[cr->field][0][0];
3950 			infoptr[1]=0;
3951 			printf("LEN: %d\n",length);
3952 			for (y=0;y<length;y++)
3953 				printf(" %03d",newinfo[cr->field][0][0][y]);
3954 			printf(" --- %s\n",newinfo[cr->field][0][0]);
3955 		}
3956 #endif
3957 		if (cr->mode == 0) return 0;
3958 		if (b2 != 128-((cr->infochecksum%128)&0x7F)) return 0;
3959 
3960 		length = cr->infoptr - cr->newinfo[cr->field][cr->mode][cr->type];
3961 
3962 		//don't bug the user with repeated data
3963 		//only parse it if it's different
3964 		if (cr->info[cr->field][cr->mode][cr->type].length != length
3965 		    || 0 != memcmp (cr->info[cr->field][cr->mode][cr->type].packet,
3966 				    cr->newinfo[cr->field][cr->mode][cr->type],
3967 				    length))
3968 		{
3969 			memcpy (cr->info[cr->field][cr->mode][cr->type].packet,
3970 				cr->newinfo[cr->field][cr->mode][cr->type], 32);
3971 			cr->info[cr->field][cr->mode][cr->type].packet[length] = 0;
3972 			cr->info[cr->field][cr->mode][cr->type].length = length;
3973 			if (0)
3974 				fprintf (stderr, "XDS %d %d %d %d %d\n",
3975 					 cr->field, cr->mode, cr->type, length,
3976 					 cr->info[0][cr->mode][cr->type].print);
3977 			print_xds_info (cr, cr->mode, cr->type);
3978 		}
3979 		cr->mode = 0; cr->type = 0;
3980 		in_xds[cr->field] = FALSE;
3981 	} else if (b1 <= 31) {
3982 		/* Caption control code. */
3983 		in_xds[cr->field] = FALSE;
3984 	} else if (in_xds[cr->field]) {
3985 		if (cr->infoptr >= &cr->newinfo[cr->field][cr->mode][cr->type][32]) {
3986 			/* Bad packet. */
3987 			cr->mode = 0;
3988 			cr->type = 0;
3989 			in_xds[cr->field] = 0;
3990 		} else {
3991 			cr->infoptr[0] = b1; cr->infoptr++;
3992 			cr->infoptr[0] = b2; cr->infoptr++;
3993 			cr->infochecksum += b1 + b2;
3994 		}
3995 	}
3996 	return 0;
3997 }
3998 
3999 #if 0 /* to be replaced */
4000 
4001 static int webtv_check(struct caption_recorder *cr, char * buf,int len)
4002 {
4003 	unsigned long   sum;
4004 	unsigned long   nwords;
4005 	unsigned short  csum=0;
4006 	char temp[9];
4007 	int nbytes=0;
4008 
4009 	while (buf[0]!='<' && len > 6)  //search for the start
4010 	{
4011 		buf++; len--;
4012 	}
4013 
4014 	if (len == 6) //failure to find start
4015 		return 0;
4016 
4017 
4018 	while (nbytes+6 <= len)
4019 	{
4020 		//look for end of object checksum, it's enclosed in []'s and there shouldn't be any [' after
4021 		if (buf[nbytes] == '[' && buf[nbytes+5] == ']' && buf[nbytes+6] != '[')
4022 			break;
4023 		else
4024 			nbytes++;
4025 	}
4026 	if (nbytes+6>len) //failure to find end
4027 		return 0;
4028 
4029 	nwords = nbytes >> 1; sum = 0;
4030 
4031 	//add up all two byte words
4032 	while (nwords-- > 0) {
4033 		sum += *buf++ << 8;
4034 		sum += *buf++;
4035 	}
4036 	if (nbytes & 1) {
4037 		sum += *buf << 8;
4038 	}
4039 	csum = (unsigned short)(sum >> 16);
4040 	while(csum !=0) {
4041 		sum = csum + (sum & 0xffff);
4042 		csum = (unsigned short)(sum >> 16);
4043 	}
4044 	sprintf(temp,"%04X\n",(int)~sum&0xffff);
4045 	buf++;
4046 	if(!strncmp(buf,temp,4))
4047 	{
4048 		buf[5]=0;
4049 		if (cr->cur_ch[cr->field] >= 0 && cr->cc_fp[cr->cur_ch[cr->field]]) {
4050 		if (!cr->plain)
4051 			fprintf(cr->cc_fp[cr->cur_ch[cr->field]], "\33[35mWEBTV: %s\33[0m\n",buf-nbytes-1);
4052 		else
4053 			fprintf(cr->cc_fp[cr->cur_ch[cr->field]], "WEBTV: %s\n",buf-nbytes-1);
4054 		fflush (cr->cc_fp[cr->cur_ch[cr->field]]);
4055 		}
4056 	}
4057 	return 0;
4058 }
4059 
4060 #endif /* 0 */
4061 
4062 static void
xds_filter_option(struct caption_recorder * cr,const char * optarg)4063 xds_filter_option		(struct caption_recorder *cr,
4064 				 const char *		optarg)
4065 {
4066 	const char *s;
4067 
4068 	/* Attention: may be called repeatedly. */
4069 
4070 	if (NULL == optarg
4071 	    || 0 == strcasecmp (optarg, "all")) {
4072 		unsigned int i;
4073 
4074 		for (i = 0; i < (N_ELEMENTS (cr->info[0])
4075 				 * N_ELEMENTS (cr->info[0][0])); ++i) {
4076 			cr->info[0][0][i].print = TRUE;
4077 		}
4078 
4079 		return;
4080 	}
4081 
4082 	s = optarg;
4083 
4084 	while (0 != *s) {
4085 		char buf[16];
4086 		unsigned int len;
4087 
4088 		for (;;) {
4089 			if (0 == *s)
4090 				return;
4091 			if (isalnum (*s))
4092 				break;
4093 			++s;
4094 		}
4095 
4096 		for (len = 0; len < N_ELEMENTS (buf) - 1; ++len) {
4097 			if (!isalnum (*s))
4098 				break;
4099 			buf[len] = *s++;
4100 		}
4101 
4102 		buf[len] = 0;
4103 
4104 		if (0 == strcasecmp (buf, "timecode")) {
4105 			cr->info[0][1][1].print = TRUE;
4106 		} else if (0 == strcasecmp (buf, "length")) {
4107 			cr->info[0][1][2].print = TRUE;
4108 		} else if (0 == strcasecmp (buf, "title")) {
4109 			cr->info[0][1][3].print = TRUE;
4110 		} else if (0 == strcasecmp (buf, "rating")) {
4111 			cr->info[0][1][5].print = TRUE;
4112 		} else if (0 == strcasecmp (buf, "network")) {
4113 			cr->info[0][5][1].print = TRUE;
4114 		} else if (0 == strcasecmp (buf, "call")) {
4115 			cr->info[0][5][2].print = TRUE;
4116 		} else if (0 == strcasecmp (buf, "time")) {
4117 			cr->info[0][7][1].print = TRUE;
4118 		} else if (0 == strcasecmp (buf, "timezone")) {
4119 			cr->info[0][7][4].print = TRUE;
4120 		} else if (0 == strcasecmp (buf, "desc")) {
4121 			cr->info[0][1][0x10].print = TRUE;
4122 			cr->info[0][1][0x11].print = TRUE;
4123 			cr->info[0][1][0x12].print = TRUE;
4124 			cr->info[0][1][0x13].print = TRUE;
4125 			cr->info[0][1][0x14].print = TRUE;
4126 			cr->info[0][1][0x15].print = TRUE;
4127 			cr->info[0][1][0x16].print = TRUE;
4128 			cr->info[0][1][0x17].print = TRUE;
4129 		} else {
4130 			fprintf (stderr, "Unknown XDS info '%s'\n", buf);
4131 		}
4132 	}
4133 }
4134 
4135 /* CEA 708-C Digital TV Closed Caption decoder. */
4136 
4137 static const uint8_t
4138 dtvcc_c0_length [4] = {
4139 	1, 1, 2, 3
4140 };
4141 
4142 static const uint8_t
4143 dtvcc_c1_length [32] = {
4144 	/* 0x80 CW0 ... CW7 */ 1, 1, 1, 1,  1, 1, 1, 1,
4145 	/* 0x88 CLW */ 2,
4146 	/* 0x89 DSW */ 2,
4147 	/* 0x8A HDW */ 2,
4148 	/* 0x8B TGW */ 2,
4149 
4150 	/* 0x8C DLW */ 2,
4151 	/* 0x8D DLY */ 2,
4152 	/* 0x8E DLC */ 1,
4153 	/* 0x8F RST */ 1,
4154 
4155 	/* 0x90 SPA */ 3,
4156 	/* 0x91 SPC */ 4,
4157 	/* 0x92 SPL */ 3,
4158 	/* CEA 708-C Section 7.1.5.1: 0x93 ... 0x96 are
4159 	   reserved one byte codes. */ 1, 1, 1, 1,
4160 	/* 0x97 SWA */ 5,
4161 	/* 0x98 DF0 ... DF7 */ 7, 7, 7, 7,  7, 7, 7, 7
4162 };
4163 
4164 static const uint16_t
4165 dtvcc_g2 [96] = {
4166 	/* Note Unicode defines no transparent spaces. */
4167 	0x0020, /* 0x1020 Transparent space */
4168 	0x00A0, /* 0x1021 Non-breaking transparent space */
4169 
4170 	0,      /* 0x1022 reserved */
4171 	0,
4172 	0,
4173 	0x2026, /* 0x1025 Horizontal ellipsis */
4174 	0,
4175 	0,
4176 	0,
4177 	0,
4178 	0x0160, /* 0x102A S with caron */
4179 	0,
4180 	0x0152, /* 0x102C Ligature OE */
4181 	0,
4182 	0,
4183 	0,
4184 
4185 	/* CEA 708-C Section 7.1.8: "The character (0x30) is a solid
4186 	   block which fills the entire character position with the
4187 	   text foreground color." */
4188 	0x2588, /* 0x1030 Full block */
4189 
4190 	0x2018, /* 0x1031 Left single quotation mark */
4191 	0x2019, /* 0x1032 Right single quotation mark */
4192 	0x201C, /* 0x1033 Left double quotation mark */
4193 	0x201D, /* 0x1034 Right double quotation mark */
4194 	0,
4195 	0,
4196 	0,
4197 	0x2122, /* 0x1039 Trademark sign */
4198 	0x0161, /* 0x103A s with caron */
4199 	0,
4200 	0x0153, /* 0x103C Ligature oe */
4201 	0x2120, /* 0x103D Service mark */
4202 	0,
4203 	0x0178, /* 0x103F Y with diaeresis */
4204 
4205 	/* Code points 0x1040 ... 0x106F reserved. */
4206 	0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,
4207 	0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,
4208 	0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,
4209 
4210 	0,      /* 0x1070 reserved */
4211 	0,
4212 	0,
4213 	0,
4214 	0,
4215 	0,
4216 	0x215B, /* 0x1076 1/8 */
4217 	0x215C, /* 0x1077 3/8 */
4218 	0x215D, /* 0x1078 5/8 */
4219 	0x215E, /* 0x1079 7/8 */
4220 	0x2502, /* 0x107A Box drawings vertical */
4221 	0x2510, /* 0x107B Box drawings down and left */
4222 	0x2514, /* 0x107C Box drawings up and right */
4223 	0x2500, /* 0x107D Box drawings horizontal */
4224 	0x2518, /* 0x107E Box drawings up and left */
4225 	0x250C  /* 0x107F Box drawings down and right */
4226 };
4227 
4228 static unsigned int
dtvcc_unicode(unsigned int c)4229 dtvcc_unicode			(unsigned int		c)
4230 {
4231 	if (unlikely (0 == (c & 0x60))) {
4232 		/* C0, C1, C2, C3 */
4233 		return 0;
4234 	} else if (likely (c < 0x100)) {
4235 		/* G0, G1 */
4236 		if (unlikely (0x7F == c))
4237 			return 0x266A; /* music note */
4238 		else
4239 			return c;
4240 	} else if (c < 0x1080) {
4241 		if (unlikely (c < 0x1020))
4242 			return 0;
4243 		else
4244 			return dtvcc_g2[c - 0x1020];
4245 	} else if (0x10A0 == c) {
4246 		/* We map all G2/G3 characters which are not
4247 		   representable in Unicode to private code U+E900
4248 		   ... U+E9FF. */
4249 		return 0xE9A0; /* caption icon */
4250 	}
4251 
4252 	return 0;
4253 }
4254 
4255 static void
dump_dtvcc_se(FILE * fp,const uint8_t * buf,unsigned int n_bytes)4256 dump_dtvcc_se			(FILE *			fp,
4257 				 const uint8_t *	buf,
4258 				 unsigned int		n_bytes)
4259 {
4260 	uint16_t ucs2_str[1];
4261 	unsigned int se_length;
4262 	unsigned int c;
4263 	unsigned int i;
4264 
4265 	if (0 == n_bytes)
4266 		return;
4267 
4268 	c = buf[0];
4269 	if (0 != (c & 0x60)) {
4270 		ucs2_str[0] = dtvcc_unicode (c);
4271 		fprintf (fp, "G0/G1 0x%02X U+%04X '",
4272 			 c, ucs2_str[0]);
4273 		vbi_fputs_iconv_ucs2 (fp, locale_codeset,
4274 				      ucs2_str, 1,
4275 				      /* repl_char */ '?');
4276 		fputs ("'\n", fp);
4277 		return;
4278 	} else if ((int8_t) c < 0) {
4279 		static const char *mnemo [32] = {
4280 			"CW0", "CW1", "CW2", "CW3",
4281 			"CW4", "CW5", "CW6", "CW7",
4282 			"CLW", "DSW", "HDW", "TGW",
4283 			"DLW", "DLY", "DLC", "RST",
4284 			"SPA", "SPC", "SPL", "93",
4285 			"reserved", "reserved",
4286 			"reserved", "SWA",
4287 			"DF0", "DF1", "DF2", "DF3",
4288 			"DF4", "DF5", "DF6", "DF7"
4289 		};
4290 		static const char *opacity_name [4] = {
4291 			"Solid", "Flash", "Transl", "Transp"
4292 		};
4293 		static const char *edge_name [8] = {
4294 			"None", "Raised", "Depressed",
4295 			"Uniform", "ShadowL", "ShadowR",
4296 			"INVALID", "INVALID"
4297 		};
4298 
4299 		fprintf (fp, "C1 0x%02X %s", c, mnemo[c & 31]);
4300 
4301 		se_length = dtvcc_c1_length[c - 0x80];
4302 		if (n_bytes < se_length) {
4303 			fputs (" incomplete\n", fp);
4304 			return;
4305 		}
4306 
4307 		switch (c) {
4308 		case 0x80 ... 0x87: /* CWx */
4309 		case 0x8E: /* DLC */
4310 		case 0x8F: /* RST */
4311 		case 0x93 ... 0x96: /* reserved */
4312 			fputc ('\n', fp);
4313 			return;
4314 
4315 		case 0x88: /* CLW */
4316 		case 0x89: /* DSW */
4317 		case 0x8A: /* HDW */
4318 		case 0x8B: /* TGW */
4319 		case 0x8C: /* DLW */
4320 			fputs (" 0b", fp);
4321 			for (i = 0; i < 8; ++i) {
4322 				unsigned int bit;
4323 
4324 				bit = !!(buf[1] & (0x80 >> i));
4325 				fputc ('0' + bit, fp);
4326 			}
4327 			fputc ('\n', fp);
4328 			return;
4329 
4330 		case 0x8D: /* DLY */
4331 			fprintf (fp, " t=%u\n", buf[1]);
4332 			return;
4333 
4334 		case 0x90: /* SPA */
4335 		{
4336 			static const char *s_name [4] = {
4337 				"Small", "Std", "Large", "INVALID"
4338 			};
4339 			static const char *fs_name [8] = {
4340 				"Default", "MonoSerif", "PropSerif",
4341 				"MonoSans", "PropSans", "Casual",
4342 				"Cursive", "SmallCaps"
4343 			};
4344 			static const char *tt_name [16] = {
4345 				"Dialog", "SourceID", "Device",
4346 				"Dialog2", "Voiceover", "AudTransl",
4347 				"SubTransl", "VoiceDescr", "Lyrics",
4348 				"EffectDescr", "ScoreDescr",
4349 				"Expletive", "INVALID", "INVALID",
4350 				"INVALID", "NotDisplayable"
4351 			};
4352 			static const char *o_name [4] = {
4353 				"Sub", "Normal", "Super", "INVALID"
4354 			};
4355 
4356 			fprintf (fp, " s=%s fs=%s tt=%s o=%s i=%u "
4357 				 "u=%u et=%s\n",
4358 				 s_name[buf[1] & 3],
4359 				 fs_name[buf[2] & 7],
4360 				 tt_name[(buf[1] >> 4) & 15],
4361 				 o_name[(buf[1] >> 2) & 3],
4362 				 !!(buf[2] & 0x80),
4363 				 !!(buf[2] & 0x40),
4364 				 edge_name[(buf[2] >> 3) & 7]);
4365 			return;
4366 		}
4367 
4368 		case 0x91: /* SPC */
4369 		{
4370 			fprintf (fp, " fg=%u%u%u fo=%s bg=%u%u%u bo=%s "
4371 				 "edge=%u%u%u\n",
4372 				 (buf[1] >> 4) & 3, (buf[1] >> 2) & 3,
4373 				 buf[1] & 3,
4374 				 opacity_name[(buf[1] >> 6) & 3],
4375 				 (buf[2] >> 4) & 3, (buf[2] >> 2) & 3,
4376 				 buf[2] & 3,
4377 				 opacity_name[(buf[2] >> 6) & 3],
4378 				 (buf[3] >> 4) & 3, (buf[3] >> 2) & 3,
4379 				 buf[3] & 3);
4380 			return;
4381 		}
4382 
4383 		case 0x92: /* SPL */
4384 			fprintf (fp, " r=%u c=%u\n",
4385 				 buf[1] & 0x0F,
4386 				 buf[2] & 0x3F);
4387 			return;
4388 
4389 		case 0x97: /* SWA */
4390 		{
4391 			static const char *j_name [4] = {
4392 				"L", "R", "C", "F"
4393 			};
4394 			static const char *pd_sd_ed_name [4] = {
4395 				"LR", "RL", "TB", "BT"
4396 			};
4397 			static const char *de_name [4] = {
4398 				"Snap", "Fade", "Wipe", "INVALID"
4399 			};
4400 
4401 			fprintf (fp, " j=%s pd=%s sd=%s ww=%u de=%s "
4402 				 "ed=%s es=%u fill=%u%u%u fo=%s "
4403 				 "bt=%s border=%u%u%u\n",
4404 				 j_name [buf[3] & 3],
4405 				 pd_sd_ed_name [(buf[3] >> 4) & 3],
4406 				 pd_sd_ed_name [(buf[3] >> 2) & 3],
4407 				 !!(buf[3] & 0x40),
4408 				 de_name [buf[4] & 3],
4409 				 pd_sd_ed_name [(buf[4] >> 2) & 3],
4410 				 (buf[4] >> 4) & 15,
4411 				 (buf[1] >> 4) & 3, (buf[1] >> 2) & 3,
4412 				 buf[1] & 3,
4413 				 opacity_name[(buf[1] >> 6) & 3],
4414 				 edge_name[(buf[2] >> 6) & 3],
4415 				 (buf[2] >> 4) & 3, (buf[2] >> 2) & 3,
4416 				 buf[2] & 3);
4417 			return;
4418 		}
4419 
4420 		case 0x98 ... 0x9F: /* DFx */
4421 		{
4422 			static const char *ap_name [16] = {
4423 				"TL", "TC", "TR",
4424 				"CL", "C", "CR",
4425 				"BL", "BC", "BR",
4426 				"INVALID", "INVALID", "INVALID",
4427 				"INVALID", "INVALID", "INVALID",
4428 				"INVALID"
4429 			};
4430 			static const char *ws_name [8] = {
4431 				"0", "PopUp", "TranspPopUp",
4432 				"CentPopUp", "RollUp", "TranspRollUp",
4433 				"CentRollUp", "Ticker"
4434 			};
4435 			static const char *ps_name [8] = {
4436 				"0", "NTSC", "NTSCMonoSerif",
4437 				"NTSCPropSerif", "NTSCMonoSans",
4438 				"NTSCPropSans", "MonoSans",
4439 				"PropSans"
4440 			};
4441 
4442 			fprintf (fp, " p=%u ap=%s rp=%u av=%u ah=%u "
4443 				 "rc=%u cc=%u rl=%u cl=%u v=%u "
4444 				 "ws=%s ps=%s\n",
4445 				 buf[1] & 7,
4446 				 ap_name[(buf[4] >> 4) & 15],
4447 				 !!(buf[2] & 0x80),
4448 				 buf[2] & 0x7F,
4449 				 buf[3],
4450 				 buf[4] & 0x0F,
4451 				 buf[5] & 0x3F,
4452 				 !!(buf[1] & 0x10),
4453 				 !!(buf[1] & 0x08),
4454 				 !!(buf[1] & 0x20),
4455 				 ws_name [(buf[6] >> 3) & 7],
4456 				 ps_name [buf[6] & 7]);
4457 			return;
4458 		}
4459 
4460 		} /* switch */
4461 	} else {
4462 		static const char *mnemo [32] = {
4463 			"NUL", "reserved", "reserved",
4464 			"ETX", "reserved", "reserved",
4465 			"reserved", "reserved",
4466 			"BS", "reserved", "reserved",
4467 			"reserved", "FF", "CR", "HCR",
4468 			"reserved", "EXT1", "reserved",
4469 			"reserved", "reserved",	"reserved",
4470 			"reserved", "reserved", "reserved",
4471 			"P16", "reserved", "reserved",
4472 			"reserved", "reserved", "reserved",
4473 			"reserved", "reserved"
4474 		};
4475 
4476 		/* C0 code. */
4477 
4478 		fprintf (fp, "C0 0x%02X %s", c, mnemo [c]);
4479 
4480 		se_length = dtvcc_c0_length[c >> 3];
4481 		if (n_bytes < se_length) {
4482 			fputs (" incomplete\n", fp);
4483 			return;
4484 		}
4485 
4486 		if (0x10 != c) {
4487 			if (se_length > 1)
4488 				fprintf (fp, " 0x%02X", buf[1]);
4489 			if (se_length > 2)
4490 				fprintf (fp, " 0x%02X", buf[2]);
4491 			fputc ('\n', fp);
4492 			return;
4493 		}
4494 	}
4495 
4496 	/* Two-byte codes. */
4497 
4498 	c = buf[1];
4499 	if (0 != (c & 0x60)) {
4500 		ucs2_str[0] = dtvcc_unicode (0x1000 | c);
4501 		fprintf (fp, "G2/G3 0x10%02X U+%04X '",
4502 			 c, ucs2_str[0]);
4503 		vbi_fputs_iconv_ucs2 (fp, locale_codeset,
4504 				      ucs2_str, 1,
4505 				      /* repl_char */ '?');
4506 		fputs ("'\n", fp);
4507 		return;
4508 	} else if ((int8_t) c >= 0) {
4509 		/* C2 code. */
4510 
4511 		se_length = (c >> 3) + 2;
4512 		fprintf (fp, "C2 0x10%02X reserved", c);
4513 	} else if (c < 0x90) {
4514 		/* C3 Fixed Length Commands. */
4515 
4516 		se_length = (c >> 3) - 10;
4517 		fprintf (fp, "C3 0x10%02X reserved", c);
4518 	} else {
4519 		/* C3 Variable Length Commands. */
4520 
4521 		if (n_bytes < 3) {
4522 			fprintf (fp, "C3 0x10%02X incomplete\n", c);
4523 			return;
4524 		}
4525 
4526 		/* type [2], zero_bit [1],
4527 		   length [5] */
4528 		se_length = (buf[2] & 0x1F) + 3;
4529 
4530 		fprintf (fp, "C3 0x10%02X%02X reserved",
4531 			 c, buf[2]);
4532 	}
4533 
4534 	for (i = 2; i < se_length; ++i)
4535 		fprintf (fp, " 0x%02X", buf[i]);
4536 
4537 	fputc ('\n', fp);
4538 }
4539 
4540 static void
dump_dtvcc_buffer(FILE * fp,struct dtvcc_window * dw)4541 dump_dtvcc_buffer		(FILE *			fp,
4542 				 struct dtvcc_window *	dw)
4543 {
4544 	unsigned int row;
4545 	unsigned int column;
4546 
4547 	for (row = 0; row < dw->row_count; ++row) {
4548 		uint16_t ucs2_str[42];
4549 
4550 		fprintf (fp, "%02u '", row);
4551 
4552 		for (column = 0; column < dw->column_count; ++column) {
4553 			unsigned int c;
4554 
4555 			c = dw->buffer[row][column];
4556 			if (0 == c) {
4557 				ucs2_str[column] = 0x20;
4558 				continue;
4559 			}
4560 			c = dtvcc_unicode (c);
4561 			if (0 == c) {
4562 				ucs2_str[column] = '?';
4563 				continue;
4564 			}
4565 			ucs2_str[column] = c;
4566 		}
4567 
4568 		vbi_fputs_iconv_ucs2 (fp, locale_codeset,
4569 				      ucs2_str, dw->column_count,
4570 				      /* repl_char */ '?');
4571 		fputs ("'\n", fp);
4572 	}
4573 }
4574 
4575 static void
4576 dtvcc_reset			(struct dtvcc_decoder *	cd);
4577 static void
4578 dtvcc_reset_service		(struct dtvcc_service *	ds);
4579 
4580 static unsigned int
dtvcc_window_id(struct dtvcc_service * ds,struct dtvcc_window * dw)4581 dtvcc_window_id			(struct dtvcc_service *	ds,
4582 				 struct dtvcc_window *	dw)
4583 {
4584 	return dw - ds->window;
4585 }
4586 
4587 static unsigned int
dtvcc_service_num(struct dtvcc_decoder * dc,struct dtvcc_service * ds)4588 dtvcc_service_num		(struct dtvcc_decoder *	dc,
4589 				 struct dtvcc_service *	ds)
4590 {
4591 	return ds - dc->service + 1;
4592 }
4593 
4594 /* Up to eight windows can be visible at once, so which one displays
4595    the caption? Let's take a guess. */
4596 static struct dtvcc_window *
dtvcc_caption_window(struct dtvcc_service * ds)4597 dtvcc_caption_window		(struct dtvcc_service *	ds)
4598 {
4599 	struct dtvcc_window *dw;
4600 	unsigned int max_priority;
4601 	unsigned int window_id;
4602 
4603 	dw = NULL;
4604 	max_priority = 8;
4605 
4606 	for (window_id = 0; window_id < 8; ++window_id) {
4607 		if (0 == (ds->created & (1 << window_id)))
4608 			continue;
4609 		if (!ds->window[window_id].visible)
4610 			continue;
4611 		if (DIR_BOTTOM_TOP
4612 		    != ds->window[window_id].style.scroll_direction)
4613 			continue;
4614 		if (ds->window[window_id].priority < max_priority) {
4615 			dw = &ds->window[window_id];
4616 			max_priority = ds->window[window_id].priority;
4617 		}
4618 	}
4619 
4620 	return dw;
4621 }
4622 
4623 static void
dtvcc_stream_event(struct dtvcc_decoder * dc,struct dtvcc_service * ds,struct dtvcc_window * dw,unsigned int row)4624 dtvcc_stream_event		(struct dtvcc_decoder *	dc,
4625 				 struct dtvcc_service *	ds,
4626 				 struct dtvcc_window *	dw,
4627 				 unsigned int		row)
4628 {
4629 	vbi_char text[48];
4630 	vbi_char ac;
4631 	unsigned int column;
4632 
4633 	if (NULL == dw || dw != dtvcc_caption_window (ds))
4634 		return;
4635 
4636 	if (option_debug & DEBUG_DTVCC_STREAM_EVENT) {
4637 		fprintf (stderr, "%s row=%u streamed=%08x\n",
4638 			 __FUNCTION__, row, dw->streamed);
4639 		dump_dtvcc_buffer (stderr, dw);
4640 	}
4641 
4642 	/* Note we only stream windows with scroll direction
4643 	   upwards. */
4644 	if (0 != (dw->streamed & (1 << row))
4645 	    || !cc_timestamp_isset (&dw->timestamp_c0))
4646 		return;
4647 
4648 	dw->streamed |= 1 << row;
4649 
4650 	for (column = 0; column < dw->column_count; ++column) {
4651 		if (0 != dw->buffer[row][column])
4652 			break;
4653 	}
4654 
4655 	/* Row contains only transparent spaces. */
4656 	if (column >= dw->column_count)
4657 		return;
4658 
4659 	/* TO DO. */
4660 	CLEAR (ac);
4661 	ac.foreground = VBI_WHITE;
4662 	ac.background = VBI_BLACK;
4663 	ac.opacity = VBI_OPAQUE;
4664 
4665 	for (column = 0; column < dw->column_count; ++column) {
4666 		unsigned int c;
4667 
4668 		c = dw->buffer[row][column];
4669 		if (0 == c) {
4670 			ac.unicode = 0x20;
4671 		} else {
4672 			ac.unicode = dtvcc_unicode (c);
4673 			if (0 == ac.unicode) {
4674 				ac.unicode = 0x20;
4675 			}
4676 		}
4677 		text[column] = ac;
4678 	}
4679 
4680 	{
4681 		struct program *pr;
4682 
4683 		pr = PARENT (dc, struct program, cr.dtvcc);
4684 		cr_new_line (&pr->cr, &dw->timestamp_c0,
4685 			     /* channel */ dtvcc_service_num (dc, ds) + 8,
4686 			     text, /* length */ dw->column_count);
4687 	}
4688 
4689 	cc_timestamp_reset (&dw->timestamp_c0);
4690 }
4691 
4692 static vbi_bool
dtvcc_put_char(struct dtvcc_decoder * dc,struct dtvcc_service * ds,unsigned int c)4693 dtvcc_put_char			(struct dtvcc_decoder *	dc,
4694 				 struct dtvcc_service *	ds,
4695 				 unsigned int		c)
4696 {
4697 	struct dtvcc_window *dw;
4698 	unsigned int row;
4699 	unsigned int column;
4700 
4701 	dc = dc; /* unused */
4702 
4703 	dw = ds->curr_window;
4704 	if (NULL == dw) {
4705 		ds->error_line = __LINE__;
4706 		return FALSE;
4707 	}
4708 
4709 	row = dw->curr_row;
4710 	column = dw->curr_column;
4711 
4712 	/* FIXME how should we handle TEXT_TAG_NOT_DISPLAYABLE? */
4713 
4714 	dw->buffer[row][column] = c;
4715 
4716 	if (option_debug & DEBUG_DTVCC_PUT_CHAR) {
4717 		fprintf (stderr, "%s row=%u/%u column=%u/%u\n",
4718 			 __FUNCTION__,
4719 			 row, dw->row_count,
4720 			 column, dw->column_count);
4721 		dump_dtvcc_buffer (stderr, dw);
4722 	}
4723 
4724 	switch (dw->style.print_direction) {
4725 	case DIR_LEFT_RIGHT:
4726 		dw->streamed &= ~(1 << row);
4727 		if (!cc_timestamp_isset (&dw->timestamp_c0))
4728 			dw->timestamp_c0 = ds->timestamp;
4729 		if (++column >= dw->column_count)
4730 			return TRUE;
4731 		break;
4732 
4733 	case DIR_RIGHT_LEFT:
4734 		dw->streamed &= ~(1 << row);
4735 		if (!cc_timestamp_isset (&dw->timestamp_c0))
4736 			dw->timestamp_c0 = ds->timestamp;
4737 		if (column-- <= 0)
4738 			return TRUE;
4739 		break;
4740 
4741 	case DIR_TOP_BOTTOM:
4742 		dw->streamed &= ~(1 << column);
4743 		if (!cc_timestamp_isset (&dw->timestamp_c0))
4744 			dw->timestamp_c0 = ds->timestamp;
4745 		if (++row >= dw->row_count)
4746 			return TRUE;
4747 		break;
4748 
4749 	case DIR_BOTTOM_TOP:
4750 		dw->streamed &= ~(1 << column);
4751 		if (!cc_timestamp_isset (&dw->timestamp_c0))
4752 			dw->timestamp_c0 = ds->timestamp;
4753 		if (row-- <= 0)
4754 			return TRUE;
4755 		break;
4756 	}
4757 
4758 	dw->curr_row = row;
4759 	dw->curr_column = column;
4760 
4761 	return TRUE;
4762 }
4763 
4764 static vbi_bool
dtvcc_set_pen_location(struct dtvcc_decoder * dc,struct dtvcc_service * ds,const uint8_t * buf)4765 dtvcc_set_pen_location		(struct dtvcc_decoder *	dc,
4766 				 struct dtvcc_service *	ds,
4767 				 const uint8_t *	buf)
4768 {
4769 	struct dtvcc_window *dw;
4770 	unsigned int row;
4771 	unsigned int column;
4772 
4773 	dw = ds->curr_window;
4774 	if (NULL == dw) {
4775 		ds->error_line = __LINE__;
4776 		return FALSE;
4777 	}
4778 
4779 	row = buf[1];
4780 	/* We check the top four zero bits. */
4781 	if (row >= 16) {
4782 		ds->error_line = __LINE__;
4783 		return FALSE;
4784 	}
4785 
4786 	column = buf[2];
4787 	/* We also check the top two zero bits. */
4788 	if (column >= 42) {
4789 		ds->error_line = __LINE__;
4790 		return FALSE;
4791 	}
4792 
4793 	if (row > dw->row_count)
4794 		row = dw->row_count - 1;
4795 	if (column > dw->column_count)
4796 		column = dw->column_count - 1;
4797 
4798 	if (row != dw->curr_row) {
4799 		dtvcc_stream_event (dc, ds, dw, dw->curr_row);
4800 	}
4801 
4802 	/* FIXME there's more. */
4803 	dw->curr_row = row;
4804 	dw->curr_column = column;
4805 
4806 	return TRUE;
4807 }
4808 
4809 static vbi_bool
dtvcc_set_pen_color(struct dtvcc_service * ds,const uint8_t * buf)4810 dtvcc_set_pen_color		(struct dtvcc_service *	ds,
4811 				 const uint8_t *	buf)
4812 {
4813 	struct dtvcc_window *dw;
4814 	unsigned int c;
4815 
4816 	dw = ds->curr_window;
4817 	if (NULL == dw) {
4818 		ds->error_line = __LINE__;
4819 		return FALSE;
4820 	}
4821 
4822 	c = buf[3];
4823 	if (0 != (c & 0xC0)) {
4824 		ds->error_line = __LINE__;
4825 		return FALSE;
4826 	}
4827 
4828 	dw->curr_pen.style.edge_color = c;
4829 	c = buf[1];
4830 	dw->curr_pen.style.fg_opacity = c >> 6;
4831 	dw->curr_pen.style.fg_color = c & 0x3F;
4832 	c = buf[2];
4833 	dw->curr_pen.style.bg_opacity = c >> 6;
4834 	dw->curr_pen.style.bg_color = c & 0x3F;
4835 
4836 	return TRUE;
4837 }
4838 
4839 static vbi_bool
dtvcc_set_pen_attributes(struct dtvcc_service * ds,const uint8_t * buf)4840 dtvcc_set_pen_attributes	(struct dtvcc_service *	ds,
4841 				 const uint8_t *	buf)
4842 {
4843 	struct dtvcc_window *dw;
4844 	unsigned int c;
4845 	enum pen_size pen_size;
4846 	enum offset offset;
4847 	enum edge edge_type;
4848 
4849 	dw = ds->curr_window;
4850 	if (NULL == dw) {
4851 		ds->error_line = __LINE__;
4852 		return FALSE;
4853 	}
4854 
4855 	c = buf[1];
4856 	offset = (c >> 2) & 3;
4857 	pen_size = c & 3;
4858 	if ((offset | pen_size) >= 3) {
4859 		ds->error_line = __LINE__;
4860 		return FALSE;
4861 	}
4862 
4863 	c = buf[2];
4864 	edge_type = (c >> 3) & 7;
4865 	if (edge_type >= 6) {
4866 		ds->error_line = __LINE__;
4867 		return FALSE;
4868 	}
4869 
4870 	c = buf[1];
4871 	dw->curr_pen.text_tag = c >> 4;
4872 	dw->curr_pen.style.offset = offset;
4873 	dw->curr_pen.style.pen_size = pen_size;
4874 	c = buf[2];
4875 	dw->curr_pen.style.italics = c >> 7;
4876 	dw->curr_pen.style.underline = (c >> 6) & 1;
4877 	dw->curr_pen.style.edge_type = edge_type;
4878 	dw->curr_pen.style.font_style = c & 7;
4879 
4880 	return TRUE;
4881 }
4882 
4883 static vbi_bool
dtvcc_set_window_attributes(struct dtvcc_service * ds,const uint8_t * buf)4884 dtvcc_set_window_attributes	(struct dtvcc_service *	ds,
4885 				 const uint8_t *	buf)
4886 {
4887 	struct dtvcc_window *dw;
4888 	unsigned int c;
4889 	enum edge border_type;
4890 	enum display_effect display_effect;
4891 
4892 	dw = ds->curr_window;
4893 	if (NULL == dw)
4894 		return FALSE;
4895 
4896 	c = buf[2];
4897 	border_type = ((buf[3] >> 5) & 0x04) | (c >> 6);
4898 	if (border_type >= 6)
4899 		return FALSE;
4900 
4901 	c = buf[4];
4902 	display_effect = c & 3;
4903 	if (display_effect >= 3)
4904 		return FALSE;
4905 
4906 	c = buf[1];
4907 	dw->style.fill_opacity = c >> 6;
4908 	dw->style.fill_color = c & 0x3F;
4909 	c = buf[2];
4910 	dw->style.border_type = border_type;
4911 	dw->style.border_color = c & 0x3F;
4912 	c = buf[3];
4913 	dw->style.wordwrap = (c >> 6) & 1;
4914 	dw->style.print_direction = (c >> 4) & 3;
4915 	dw->style.scroll_direction = (c >> 2) & 3;
4916 	dw->style.justify = c & 3;
4917 	c = buf[4];
4918 	dw->style.effect_speed = c >> 4;
4919 	dw->style.effect_direction = (c >> 2) & 3;
4920 	dw->style.display_effect = display_effect;
4921 
4922 	return TRUE;
4923 }
4924 
4925 static vbi_bool
dtvcc_clear_windows(struct dtvcc_decoder * dc,struct dtvcc_service * ds,dtvcc_window_map window_map)4926 dtvcc_clear_windows		(struct dtvcc_decoder *	dc,
4927 				 struct dtvcc_service *	ds,
4928 				 dtvcc_window_map	window_map)
4929 {
4930 	unsigned int i;
4931 
4932 	window_map &= ds->created;
4933 
4934 	for (i = 0; i < 8; ++i) {
4935 		struct dtvcc_window *dw;
4936 
4937 		if (0 == (window_map & (1 << i)))
4938 			continue;
4939 
4940 		dw = &ds->window[i];
4941 
4942 		dtvcc_stream_event (dc, ds, dw, dw->curr_row);
4943 
4944 		memset (dw->buffer, 0, sizeof (dw->buffer));
4945 
4946 		dw->streamed = 0;
4947 
4948 		/* FIXME CEA 708-C Section 7.1.4 (Form Feed)
4949 		   and 8.10.5.3 confuse me. */
4950 		if (0) {
4951 			dw->curr_column = 0;
4952 			dw->curr_row = 0;
4953 		}
4954 	}
4955 
4956 	return TRUE;
4957 }
4958 
4959 static vbi_bool
dtvcc_define_window(struct dtvcc_decoder * dc,struct dtvcc_service * ds,uint8_t * buf)4960 dtvcc_define_window		(struct dtvcc_decoder *	dc,
4961 				 struct dtvcc_service *	ds,
4962 				 uint8_t *		buf)
4963 {
4964 	static const struct dtvcc_window_style window_styles [7] = {
4965 		{
4966 			JUSTIFY_LEFT, DIR_LEFT_RIGHT, DIR_BOTTOM_TOP,
4967 			FALSE, DISPLAY_EFFECT_SNAP, 0, 0, 0,
4968 			OPACITY_SOLID, EDGE_NONE, 0
4969 		}, {
4970 			JUSTIFY_LEFT, DIR_LEFT_RIGHT, DIR_BOTTOM_TOP,
4971 			FALSE, DISPLAY_EFFECT_SNAP, 0, 0, 0,
4972 			OPACITY_TRANSPARENT, EDGE_NONE, 0
4973 		}, {
4974 			JUSTIFY_CENTER, DIR_LEFT_RIGHT, DIR_BOTTOM_TOP,
4975 			FALSE, DISPLAY_EFFECT_SNAP, 0, 0, 0,
4976 			OPACITY_SOLID, EDGE_NONE, 0
4977 		}, {
4978 			JUSTIFY_LEFT, DIR_LEFT_RIGHT, DIR_BOTTOM_TOP,
4979 			TRUE, DISPLAY_EFFECT_SNAP, 0, 0, 0,
4980 			OPACITY_SOLID, EDGE_NONE, 0
4981 		}, {
4982 			JUSTIFY_LEFT, DIR_LEFT_RIGHT, DIR_BOTTOM_TOP,
4983 			TRUE, DISPLAY_EFFECT_SNAP, 0, 0, 0,
4984 			OPACITY_TRANSPARENT, EDGE_NONE, 0
4985 		}, {
4986 			JUSTIFY_CENTER, DIR_LEFT_RIGHT, DIR_BOTTOM_TOP,
4987 			TRUE, DISPLAY_EFFECT_SNAP, 0, 0, 0,
4988 			OPACITY_SOLID, EDGE_NONE, 0
4989 		}, {
4990 			JUSTIFY_LEFT, DIR_TOP_BOTTOM, DIR_RIGHT_LEFT,
4991 			FALSE, DISPLAY_EFFECT_SNAP, 0, 0, 0,
4992 			OPACITY_SOLID, EDGE_NONE, 0
4993 		}
4994 	};
4995 	static const struct dtvcc_pen_style pen_styles [7] = {
4996 		{
4997 			PEN_SIZE_STANDARD, 0, OFFSET_NORMAL, FALSE,
4998 			FALSE, EDGE_NONE, 0x3F, OPACITY_SOLID,
4999 			0x00, OPACITY_SOLID, 0
5000 		}, {
5001 			PEN_SIZE_STANDARD, 1, OFFSET_NORMAL, FALSE,
5002 			FALSE, EDGE_NONE, 0x3F, OPACITY_SOLID,
5003 			0x00, OPACITY_SOLID, 0
5004 		}, {
5005 			PEN_SIZE_STANDARD, 2, OFFSET_NORMAL, FALSE,
5006 			FALSE, EDGE_NONE, 0x3F, OPACITY_SOLID,
5007 			0x00, OPACITY_SOLID, 0
5008 		}, {
5009 			PEN_SIZE_STANDARD, 3, OFFSET_NORMAL, FALSE,
5010 			FALSE, EDGE_NONE, 0x3F, OPACITY_SOLID,
5011 			0x00, OPACITY_SOLID, 0
5012 		}, {
5013 			PEN_SIZE_STANDARD, 4, OFFSET_NORMAL, FALSE,
5014 			FALSE, EDGE_NONE, 0x3F, OPACITY_SOLID,
5015 			0x00, OPACITY_SOLID, 0
5016 		}, {
5017 			PEN_SIZE_STANDARD, 3, OFFSET_NORMAL, FALSE,
5018 			FALSE, EDGE_UNIFORM, 0x3F, OPACITY_SOLID,
5019 			0, OPACITY_TRANSPARENT, 0x00
5020 		}, {
5021 			PEN_SIZE_STANDARD, 4, OFFSET_NORMAL, FALSE,
5022 			FALSE, EDGE_UNIFORM, 0x3F, OPACITY_SOLID,
5023 			0, OPACITY_TRANSPARENT, 0x00
5024 		}
5025 	};
5026 	struct dtvcc_window *dw;
5027 	dtvcc_window_map window_map;
5028 	vbi_bool anchor_relative;
5029 	unsigned int anchor_vertical;
5030 	unsigned int anchor_horizontal;
5031 	unsigned int anchor_point;
5032 	unsigned int column_count_m1;
5033 	unsigned int window_id;
5034 	unsigned int window_style_id;
5035 	unsigned int pen_style_id;
5036 	unsigned int c;
5037 
5038 	if (0 != ((buf[1] | buf[6]) & 0xC0)) {
5039 		ds->error_line = __LINE__;
5040 		return FALSE;
5041 	}
5042 
5043 	c = buf[2];
5044 	anchor_relative = (c >> 7) & 1;
5045 	anchor_vertical = c & 0x7F;
5046 	anchor_horizontal = buf[3];
5047 	if (0 == anchor_relative) {
5048 		if (unlikely (anchor_vertical >= 75
5049 			      || anchor_horizontal >= 210)) {
5050 			ds->error_line = __LINE__;
5051 			return FALSE;
5052 		}
5053 	} else {
5054 		if (unlikely (anchor_vertical >= 100
5055 			      || anchor_horizontal >= 100)) {
5056 			ds->error_line = __LINE__;
5057 			return FALSE;
5058 		}
5059 	}
5060 
5061 	c = buf[4];
5062 	anchor_point = c >> 4;
5063 	if (unlikely (anchor_point >= 9)) {
5064 		ds->error_line = __LINE__;
5065 		return FALSE;
5066 	}
5067 
5068 	column_count_m1 = buf[5];
5069 	/* We also check the top two zero bits. */
5070 	if (unlikely (column_count_m1 >= 41)) {
5071 		ds->error_line = __LINE__;
5072 		return FALSE;
5073 	}
5074 
5075 	window_id = buf[0] & 7;
5076 	dw = &ds->window[window_id];
5077 	window_map = 1 << window_id;
5078 
5079 	ds->curr_window = dw;
5080 
5081 	c = buf[1];
5082 	dw->visible = (c >> 5) & 1;
5083 	dw->row_lock = (c >> 4) & 1;
5084 	dw->column_lock = (c >> 4) & 1;
5085 	dw->priority = c & 7;
5086 
5087 	dw->anchor_relative = anchor_relative;
5088 	dw->anchor_vertical = anchor_vertical;
5089 	dw->anchor_horizontal = anchor_horizontal;
5090 	dw->anchor_point = anchor_point;
5091 
5092 	c = buf[4];
5093 	dw->row_count = (c & 15) + 1;
5094 	dw->column_count = column_count_m1 + 1;
5095 
5096 	c = buf[6];
5097 	window_style_id = (c >> 3) & 7;
5098 	pen_style_id = c & 7;
5099 
5100 	if (window_style_id > 0) {
5101 		dw->style = window_styles[window_style_id];
5102 	} else if (0 == (ds->created & window_map)) {
5103 		dw->style = window_styles[1];
5104 	}
5105 
5106 	if (pen_style_id > 0) {
5107 		dw->curr_pen.style = pen_styles[pen_style_id];
5108 	} else if (0 == (ds->created & window_map)) {
5109 		dw->curr_pen.style = pen_styles[1];
5110 	}
5111 
5112 	if (0 != (ds->created & window_map))
5113 		return TRUE;
5114 
5115 	/* Has to be something, no? */
5116 	dw->curr_pen.text_tag = TEXT_TAG_NOT_DISPLAYABLE;
5117 
5118 	dw->curr_column = 0;
5119 	dw->curr_row = 0;
5120 
5121 	dw->streamed = 0;
5122 
5123 	cc_timestamp_reset (&dw->timestamp_c0);
5124 
5125 	ds->created |= window_map;
5126 
5127 	return dtvcc_clear_windows (dc, ds, window_map);
5128 }
5129 
5130 static vbi_bool
dtvcc_display_windows(struct dtvcc_decoder * dc,struct dtvcc_service * ds,unsigned int c,dtvcc_window_map window_map)5131 dtvcc_display_windows		(struct dtvcc_decoder *	dc,
5132 				 struct dtvcc_service *	ds,
5133 				 unsigned int		c,
5134 				 dtvcc_window_map	window_map)
5135 {
5136 	unsigned int i;
5137 
5138 	window_map &= ds->created;
5139 
5140 	for (i = 0; i < 8; ++i) {
5141 		struct dtvcc_window *dw;
5142 		vbi_bool was_visible;
5143 
5144 		if (0 == (window_map & (1 << i)))
5145 			continue;
5146 
5147 		dw = &ds->window[i];
5148 		was_visible = dw->visible;
5149 
5150 		switch (c) {
5151 		case 0x89: /* DSW DisplayWindows */
5152 			dw->visible = TRUE;
5153 			break;
5154 
5155 		case 0x8A: /* HDW HideWindows */
5156 			dw->visible = FALSE;
5157 			break;
5158 
5159 		case 0x8B: /* TGW ToggleWindows */
5160 			dw->visible = was_visible ^ TRUE;
5161 			break;
5162 		}
5163 
5164 		if (!was_visible) {
5165 			unsigned int row;
5166 
5167 			dw->timestamp_c0 = ds->timestamp;
5168 			for (row = 0; row < dw->row_count; ++row) {
5169 				dtvcc_stream_event (dc, ds, dw, row);
5170 			}
5171 		}
5172 	}
5173 
5174 	return TRUE;
5175 }
5176 
5177 static vbi_bool
dtvcc_carriage_return(struct dtvcc_decoder * dc,struct dtvcc_service * ds)5178 dtvcc_carriage_return		(struct dtvcc_decoder *	dc,
5179 				 struct dtvcc_service *	ds)
5180 {
5181 	struct dtvcc_window *dw;
5182 	unsigned int row;
5183 	unsigned int column;
5184 
5185 	dw = ds->curr_window;
5186 	if (NULL == dw) {
5187 		ds->error_line = __LINE__;
5188 		return FALSE;
5189 	}
5190 
5191 	dtvcc_stream_event (dc, ds, dw, dw->curr_row);
5192 
5193 	row = dw->curr_row;
5194 	column = dw->curr_column;
5195 
5196 	switch (dw->style.scroll_direction) {
5197 	case DIR_LEFT_RIGHT:
5198 		dw->curr_row = 0;
5199 		if (column > 0) {
5200 			dw->curr_column = column - 1;
5201 			break;
5202 		}
5203 		dw->streamed = (dw->streamed << 1)
5204 			& ~(1 << dw->column_count);
5205 		for (row = 0; row < dw->row_count; ++row) {
5206 			for (column = dw->column_count - 1;
5207 			     column > 0; --column) {
5208 				dw->buffer[row][column] =
5209 					dw->buffer[row][column - 1];
5210 			}
5211 			dw->buffer[row][column] = 0;
5212 		}
5213 		break;
5214 
5215 	case DIR_RIGHT_LEFT:
5216 		dw->curr_row = 0;
5217 		if (column + 1 < dw->row_count) {
5218 			dw->curr_column = column + 1;
5219 			break;
5220 		}
5221 		dw->streamed >>= 1;
5222 		for (row = 0; row < dw->row_count; ++row) {
5223 			for (column = 0;
5224 			     column < dw->column_count - 1; ++column) {
5225 				dw->buffer[row][column] =
5226 					dw->buffer[row][column + 1];
5227 			}
5228 			dw->buffer[row][column] = 0;
5229 		}
5230 		break;
5231 
5232 	case DIR_TOP_BOTTOM:
5233 		dw->curr_column = 0;
5234 		if (row > 0) {
5235 			dw->curr_row = row - 1;
5236 			break;
5237 		}
5238 		dw->streamed = (dw->streamed << 1)
5239 			& ~(1 << dw->row_count);
5240 		memmove (&dw->buffer[1], &dw->buffer[0],
5241 			 sizeof (dw->buffer[0]) * (dw->row_count - 1));
5242 		memset (&dw->buffer[0], 0, sizeof (dw->buffer[0]));
5243 		break;
5244 
5245 	case DIR_BOTTOM_TOP:
5246 		dw->curr_column = 0;
5247 		if (row + 1 < dw->row_count) {
5248 			dw->curr_row = row + 1;
5249 			break;
5250 		}
5251 		dw->streamed >>= 1;
5252 		memmove (&dw->buffer[0], &dw->buffer[1],
5253 			 sizeof (dw->buffer[0]) * (dw->row_count - 1));
5254 		memset (&dw->buffer[row], 0, sizeof (dw->buffer[0]));
5255 		break;
5256 	}
5257 
5258 	return TRUE;
5259 }
5260 
5261 static vbi_bool
dtvcc_form_feed(struct dtvcc_decoder * dc,struct dtvcc_service * ds)5262 dtvcc_form_feed			(struct dtvcc_decoder *	dc,
5263 				 struct dtvcc_service *	ds)
5264 {
5265 	struct dtvcc_window *dw;
5266 	dtvcc_window_map window_map;
5267 
5268 	dw = ds->curr_window;
5269 	if (NULL == dw) {
5270 		ds->error_line = __LINE__;
5271 		return FALSE;
5272 	}
5273 
5274 	window_map = 1 << dtvcc_window_id (ds, dw);
5275 
5276 	if (!dtvcc_clear_windows (dc, ds, window_map))
5277 		return FALSE;
5278 
5279 	dw->curr_row = 0;
5280 	dw->curr_column = 0;
5281 
5282 	return TRUE;
5283 }
5284 
5285 static vbi_bool
dtvcc_backspace(struct dtvcc_decoder * dc,struct dtvcc_service * ds)5286 dtvcc_backspace			(struct dtvcc_decoder *	dc,
5287 				 struct dtvcc_service *	ds)
5288 {
5289 	struct dtvcc_window *dw;
5290 	unsigned int row;
5291 	unsigned int column;
5292 	unsigned int mask;
5293 
5294 	dc = dc; /* unused */
5295 
5296 	dw = ds->curr_window;
5297 	if (NULL == dw) {
5298 		ds->error_line = __LINE__;
5299 		return FALSE;
5300 	}
5301 
5302 	row = dw->curr_row;
5303 	column = dw->curr_column;
5304 
5305 	switch (dw->style.print_direction) {
5306 	case DIR_LEFT_RIGHT:
5307 		mask = 1 << row;
5308 		if (column-- <= 0)
5309 			return TRUE;
5310 		break;
5311 
5312 	case DIR_RIGHT_LEFT:
5313 		mask = 1 << row;
5314 		if (++column >= dw->column_count)
5315 			return TRUE;
5316 		break;
5317 
5318 	case DIR_TOP_BOTTOM:
5319 		mask = 1 << column;
5320 		if (row-- <= 0)
5321 			return TRUE;
5322 		break;
5323 
5324 	case DIR_BOTTOM_TOP:
5325 		mask = 1 << column;
5326 		if (++row >= dw->row_count)
5327 			return TRUE;
5328 		break;
5329 	}
5330 
5331 	if (0 != dw->buffer[row][column]) {
5332 		dw->streamed &= ~mask;
5333 		dw->buffer[row][column] = 0;
5334 	}
5335 
5336 	dw->curr_row = row;
5337 	dw->curr_column = column;
5338 
5339 	return TRUE;
5340 }
5341 
5342 static vbi_bool
dtvcc_hor_carriage_return(struct dtvcc_decoder * dc,struct dtvcc_service * ds)5343 dtvcc_hor_carriage_return	(struct dtvcc_decoder *	dc,
5344 				 struct dtvcc_service *	ds)
5345 {
5346 	struct dtvcc_window *dw;
5347 	unsigned int row;
5348 	unsigned int column;
5349 	unsigned int mask;
5350 
5351 	dc = dc; /* unused */
5352 
5353 	dw = ds->curr_window;
5354 	if (NULL == dw) {
5355 		ds->error_line = __LINE__;
5356 		return FALSE;
5357 	}
5358 
5359 	row = dw->curr_row;
5360 	column = dw->curr_column;
5361 
5362 	switch (dw->style.print_direction) {
5363 	case DIR_LEFT_RIGHT:
5364 	case DIR_RIGHT_LEFT:
5365 		mask = 1 << row;
5366 		memset (&dw->buffer[row][0], 0,
5367 			sizeof (dw->buffer[0]));
5368 		if (DIR_LEFT_RIGHT == dw->style.print_direction)
5369 			dw->curr_column = 0;
5370 		else
5371 			dw->curr_column = dw->column_count - 1;
5372 		break;
5373 
5374 	case DIR_TOP_BOTTOM:
5375 	case DIR_BOTTOM_TOP:
5376 		mask = 1 << column;
5377 		for (row = 0; row < dw->column_count; ++row)
5378 			dw->buffer[row][column] = 0;
5379 		if (DIR_TOP_BOTTOM == dw->style.print_direction)
5380 			dw->curr_row = 0;
5381 		else
5382 			dw->curr_row = dw->row_count - 1;
5383 		break;
5384 	}
5385 
5386 	dw->streamed &= ~mask;
5387 
5388 	return TRUE;
5389 }
5390 
5391 static vbi_bool
dtvcc_delete_windows(struct dtvcc_decoder * dc,struct dtvcc_service * ds,dtvcc_window_map window_map)5392 dtvcc_delete_windows		(struct dtvcc_decoder *	dc,
5393 				 struct dtvcc_service *	ds,
5394 				 dtvcc_window_map	window_map)
5395 {
5396 	struct dtvcc_window *dw;
5397 
5398 	dw = ds->curr_window;
5399 	if (NULL != dw) {
5400 		unsigned int window_id;
5401 
5402 		window_id = dtvcc_window_id (ds, dw);
5403 		if (0 != (window_map & (1 << window_id))) {
5404 			dtvcc_stream_event (dc, ds, dw, dw->curr_row);
5405 			ds->curr_window = NULL;
5406 		}
5407 	}
5408 
5409 	ds->created &= ~window_map;
5410 
5411 	return TRUE;
5412 }
5413 
5414 static vbi_bool
dtvcc_command(struct dtvcc_decoder * dc,struct dtvcc_service * ds,unsigned int * se_length,uint8_t * buf,unsigned int n_bytes)5415 dtvcc_command			(struct dtvcc_decoder *	dc,
5416 				 struct dtvcc_service *	ds,
5417 				 unsigned int *		se_length,
5418 				 uint8_t *		buf,
5419 				 unsigned int		n_bytes)
5420 {
5421 	unsigned int c;
5422 	unsigned int window_id;
5423 
5424 	c = buf[0];
5425 	if ((int8_t) c < 0) {
5426 		*se_length = dtvcc_c1_length[c - 0x80];
5427 	} else {
5428 		*se_length = dtvcc_c0_length[c >> 3];
5429 	}
5430 
5431 	if (*se_length > n_bytes) {
5432 		ds->error_line = __LINE__;
5433 		return FALSE;
5434 	}
5435 
5436 	switch (c) {
5437 	case 0x08: /* BS Backspace */
5438 		return dtvcc_backspace (dc, ds);
5439 
5440 	case 0x0C: /* FF Form Feed */
5441 		return dtvcc_form_feed (dc, ds);
5442 
5443 	case 0x0D: /* CR Carriage Return */
5444 		return dtvcc_carriage_return (dc, ds);
5445 
5446 	case 0x0E: /* HCR Horizontal Carriage Return */
5447 		return dtvcc_hor_carriage_return (dc, ds);
5448 
5449 	case 0x80 ... 0x87: /* CWx SetCurrentWindow */
5450 		window_id = c & 7;
5451 		if (0 == (ds->created & (1 << window_id))) {
5452 			ds->error_line = __LINE__;
5453 			return FALSE;
5454 		}
5455 		ds->curr_window = &ds->window[window_id];
5456 		return TRUE;
5457 
5458 	case 0x88: /* CLW ClearWindows */
5459 		return dtvcc_clear_windows (dc, ds, buf[1]);
5460 
5461 	case 0x89: /* DSW DisplayWindows */
5462 		return dtvcc_display_windows (dc, ds, c, buf[1]);
5463 
5464 	case 0x8A: /* HDW HideWindows */
5465 		return dtvcc_display_windows (dc, ds, c, buf[1]);
5466 
5467 	case 0x8B: /* TGW ToggleWindows */
5468 		return dtvcc_display_windows (dc, ds, c, buf[1]);
5469 
5470 	case 0x8C: /* DLW DeleteWindows */
5471 		return dtvcc_delete_windows (dc, ds, buf[1]);
5472 
5473 	case 0x8F: /* RST Reset */
5474 		dtvcc_reset_service (ds);
5475 		return TRUE;
5476 
5477 	case 0x90: /* SPA SetPenAttributes */
5478 		return dtvcc_set_pen_attributes (ds, buf);
5479 
5480 	case 0x91: /* SPC SetPenColor */
5481 		return dtvcc_set_pen_color (ds, buf);
5482 
5483 	case 0x92: /* SPL SetPenLocation */
5484 		return dtvcc_set_pen_location (dc, ds, buf);
5485 
5486 	case 0x97: /* SWA SetWindowAttributes */
5487 		return dtvcc_set_window_attributes (ds, buf);
5488 
5489 	case 0x98 ... 0x9F: /* DFx DefineWindow */
5490 		return dtvcc_define_window (dc, ds, buf);
5491 
5492 	default:
5493 		return TRUE;
5494 	}
5495 }
5496 
5497 static vbi_bool
dtvcc_decode_se(struct dtvcc_decoder * dc,struct dtvcc_service * ds,unsigned int * se_length,uint8_t * buf,unsigned int n_bytes)5498 dtvcc_decode_se			(struct dtvcc_decoder *	dc,
5499 				 struct dtvcc_service *	ds,
5500 				 unsigned int *		se_length,
5501 				 uint8_t *		buf,
5502 				 unsigned int		n_bytes)
5503 {
5504 	unsigned int c;
5505 
5506 	c = buf[0];
5507 	if (likely (0 != (c & 0x60))) {
5508 		/* G0/G1 character. */
5509 		*se_length = 1;
5510 		return dtvcc_put_char (dc, ds, c);
5511 	}
5512 
5513 	if (0x10 != c) {
5514 		/* C0/C1 control code. */
5515 		return dtvcc_command (dc, ds, se_length,
5516 				      buf, n_bytes);
5517 	}
5518 
5519 	if (unlikely (n_bytes < 2)) {
5520 		ds->error_line = __LINE__;
5521 		return FALSE;
5522 	}
5523 
5524 	c = buf[1];
5525 	if (likely (0 != (c & 0x60))) {
5526 		/* G2/G3 character. */
5527 		*se_length = 2;
5528 		return dtvcc_put_char (dc, ds, 0x1000 | c);
5529 	}
5530 
5531 	/* CEA 708-C defines no C2 or C3 commands. */
5532 
5533 	if ((int8_t) c >= 0) {
5534 		/* C2 code. */
5535 		*se_length = (c >> 3) + 2;
5536 	} else if (c < 0x90) {
5537 		/* C3 Fixed Length Commands. */
5538 		*se_length = (c >> 3) - 10;
5539 	} else {
5540 		/* C3 Variable Length Commands. */
5541 
5542 		if (unlikely (n_bytes < 3)) {
5543 			ds->error_line = __LINE__;
5544 			return FALSE;
5545 		}
5546 
5547 		/* type [2], zero_bit [1],
5548 		   length [5] */
5549 		*se_length = (buf[2] & 0x1F) + 3;
5550 	}
5551 
5552 	if (unlikely (n_bytes < *se_length)) {
5553 		ds->error_line = __LINE__;
5554 		return FALSE;
5555 	}
5556 
5557 	return TRUE;
5558 }
5559 
5560 static vbi_bool
dtvcc_decode_syntactic_elements(struct dtvcc_decoder * dc,struct dtvcc_service * ds,uint8_t * buf,unsigned int n_bytes)5561 dtvcc_decode_syntactic_elements	(struct dtvcc_decoder *	dc,
5562 				 struct dtvcc_service *	ds,
5563 				 uint8_t *		buf,
5564 				 unsigned int		n_bytes)
5565 {
5566 	ds->timestamp = dc->timestamp;
5567 
5568 	while (n_bytes > 0) {
5569 		unsigned int se_length;
5570 
5571 		if (option_debug & DEBUG_DTVCC_SE) {
5572 			fprintf (stderr, "S%u ",
5573 				 dtvcc_service_num (dc, ds));
5574 			dump_dtvcc_se (stderr, buf, n_bytes);
5575 		}
5576 
5577 		if (0x8D /* DLY */ == *buf
5578 		    || 0x8E /* DLC */ == *buf) {
5579 			/* FIXME ignored for now. */
5580 			++buf;
5581 			--n_bytes;
5582 			continue;
5583 		}
5584 
5585 		if (!dtvcc_decode_se (dc, ds,
5586 				      &se_length,
5587 				      buf, n_bytes)) {
5588 			return FALSE;
5589 		}
5590 
5591 		buf += se_length;
5592 		n_bytes -= se_length;
5593 	}
5594 
5595 	return TRUE;
5596 }
5597 
5598 static void
dtvcc_decode_packet(struct dtvcc_decoder * dc,const struct timeval * tv,int64_t pts)5599 dtvcc_decode_packet		(struct dtvcc_decoder *	dc,
5600 				 const struct timeval *	tv,
5601 				 int64_t		pts)
5602 {
5603 	unsigned int packet_size_code;
5604 	unsigned int packet_size;
5605 	unsigned int i;
5606 
5607 	dc->timestamp.sys = *tv;
5608 	dc->timestamp.pts = pts;
5609 
5610 	/* Packet Layer. */
5611 
5612 	/* sequence_number [2], packet_size_code [6],
5613 	   packet_data [n * 8] */
5614 
5615 	if (dc->next_sequence_number >= 0
5616 	    && 0 != ((dc->packet[0] ^ dc->next_sequence_number) & 0xC0)) {
5617 		struct program *pr;
5618 
5619 		pr = PARENT (dc, struct program, cr.dtvcc);
5620 		log (4, "Station %u DTVCC packet lost.\n",
5621 		     station_num (pr));
5622 		dtvcc_reset (dc);
5623 		return;
5624 	}
5625 
5626 	dc->next_sequence_number = dc->packet[0] + 0x40;
5627 
5628 	packet_size_code = dc->packet[0] & 0x3F;
5629 	packet_size = 128;
5630 	if (packet_size_code > 0)
5631 		packet_size = packet_size_code * 2;
5632 
5633 	if (option_debug & DEBUG_DTVCC_PACKET) {
5634 		unsigned int sequence_number;
5635 
5636 		sequence_number = (dc->packet[0] >> 6) & 3;
5637 		fprintf (stderr, "DTVCC packet packet_size=%u "
5638 			 "(transmitted %u), sequence_number %u\n",
5639 			 packet_size, dc->packet_size,
5640 			 sequence_number);
5641 		dump (stderr, dc->packet, dc->packet_size);
5642 	}
5643 
5644 	/* CEA 708-C Section 5: Apparently packet_size need not be
5645 	   equal to the actually transmitted amount of data. */
5646 	if (packet_size > dc->packet_size) {
5647 		struct program *pr;
5648 
5649 		pr = PARENT (dc, struct program, cr.dtvcc);
5650 		log (4, "Station %u DTVCC packet incomplete (%u/%u).\n",
5651 		     station_num (pr),
5652 		     dc->packet_size, packet_size);
5653 		dtvcc_reset (dc);
5654 		return;
5655 	}
5656 
5657 	/* Service Layer. */
5658 
5659 	/* CEA 708-C Section 6.2.5, 6.3: Service Blocks and syntactic
5660 	   elements must not cross Caption Channel Packet
5661 	   boundaries. */
5662 
5663 	for (i = 1; i < packet_size;) {
5664 		unsigned int service_number;
5665 		unsigned int block_size;
5666 		unsigned int header_size;
5667 		unsigned int c;
5668 
5669 		header_size = 1;
5670 
5671 		/* service_number [3], block_size [5],
5672 		   (null_fill [2], extended_service_number [6]),
5673 		   (Block_data [n * 8]) */
5674 
5675 		c = dc->packet[i];
5676 		service_number = (c & 0xE0) >> 5;
5677 
5678 		/* CEA 708-C Section 6.3: Ignore block_size if
5679 		   service_number is zero. */
5680 		if (0 == service_number) {
5681 			/* NULL Service Block Header, no more data in
5682 			   this Caption Channel Packet. */
5683 			break;
5684 		}
5685 
5686 		/* CEA 708-C Section 6.2.1: Apparently block_size zero
5687 		   is valid, although properly it should only occur in
5688 		   NULL Service Block Headers. */
5689 		block_size = c & 0x1F;
5690 
5691 		if (7 == service_number) {
5692 			if (i + 1 > packet_size)
5693 				goto service_block_incomplete;
5694 
5695 			header_size = 2;
5696 			c = dc->packet[i + 1];
5697 
5698 			/* We also check the null_fill bits. */
5699 			if (c < 7 || c > 63)
5700 				goto invalid_service_block;
5701 
5702 			service_number = c;
5703 		}
5704 
5705 		if (i + header_size + block_size > packet_size)
5706 			goto service_block_incomplete;
5707 
5708 		if (service_number <= 2) {
5709 			struct dtvcc_service *ds;
5710 			unsigned int in;
5711 
5712 			ds = &dc->service[service_number - 1];
5713 			in = ds->service_data_in;
5714 			memcpy (ds->service_data + in,
5715 				dc->packet + i + header_size,
5716 				block_size);
5717 			ds->service_data_in = in + block_size;
5718 		}
5719 
5720 		i += header_size + block_size;
5721 	}
5722 
5723 	for (i = 0; i < 2; ++i) {
5724 		struct dtvcc_service *ds;
5725 		struct program *pr;
5726 		vbi_bool success;
5727 
5728 		ds = &dc->service[i];
5729 		if (0 == ds->service_data_in)
5730 			continue;
5731 
5732 		success = dtvcc_decode_syntactic_elements
5733 			(dc, ds, ds->service_data, ds->service_data_in);
5734 
5735 		ds->service_data_in = 0;
5736 
5737 		if (success)
5738 			continue;
5739 
5740 		pr = PARENT (dc, struct program, cr.dtvcc);
5741 		log (4, "Station %u DTVCC invalid "
5742 		     "syntactic element (%u).\n",
5743 		     station_num (pr), ds->error_line);
5744 
5745 		if (option_debug & DEBUG_DTVCC_PACKET) {
5746 			fprintf (stderr, "Packet (%d/%d):\n",
5747 				 packet_size, dc->packet_size);
5748 			dump (stderr, dc->packet, packet_size);
5749 			fprintf (stderr, "Service Data:\n");
5750 			dump (stderr, ds->service_data,
5751 			      ds->service_data_in);
5752 		}
5753 
5754 		dtvcc_reset_service (ds);
5755 	}
5756 
5757 	return;
5758 
5759  invalid_service_block:
5760 	{
5761 		struct program *pr;
5762 
5763 		pr = PARENT (dc, struct program, cr.dtvcc);
5764 		log (4, "Station %u DTVCC invalid "
5765 		     "service block (%u).\n",
5766 		     station_num (pr), i);
5767 		if (option_debug & DEBUG_DTVCC_PACKET) {
5768 			fprintf (stderr, "Packet (%d/%d):\n",
5769 				 packet_size, dc->packet_size);
5770 			dump (stderr, dc->packet, packet_size);
5771 		}
5772 		dtvcc_reset (dc);
5773 		return;
5774 	}
5775 
5776  service_block_incomplete:
5777 	{
5778 		struct program *pr;
5779 
5780 		pr = PARENT (dc, struct program, cr.dtvcc);
5781 		log (4, "Station %u DTVCC incomplete "
5782 		     "service block (%u).\n",
5783 		     station_num (pr), i);
5784 		if (option_debug & DEBUG_DTVCC_PACKET) {
5785 			fprintf (stderr, "Packet (%d/%d):\n",
5786 				 packet_size, dc->packet_size);
5787 			dump (stderr, dc->packet, packet_size);
5788 		}
5789 		dtvcc_reset (dc);
5790 		return;
5791 	}
5792 
5793 }
5794 
5795 static void
dtvcc_reset_service(struct dtvcc_service * ds)5796 dtvcc_reset_service		(struct dtvcc_service *	ds)
5797 {
5798 	ds->curr_window = NULL;
5799 	ds->created = 0;
5800 
5801 	cc_timestamp_reset (&ds->timestamp);
5802 }
5803 
5804 static void
dtvcc_reset(struct dtvcc_decoder * dc)5805 dtvcc_reset			(struct dtvcc_decoder *	dc)
5806 {
5807 	dtvcc_reset_service (&dc->service[0]);
5808 	dtvcc_reset_service (&dc->service[1]);
5809 
5810 	dc->packet_size = 0;
5811 	dc->next_sequence_number = -1;
5812 }
5813 
5814 static void
init_dtvcc_decoder(struct dtvcc_decoder * dc)5815 init_dtvcc_decoder		(struct dtvcc_decoder *	dc)
5816 {
5817 	dtvcc_reset (dc);
5818 
5819 	cc_timestamp_reset (&dc->timestamp);
5820 }
5821 
5822 /* ATSC A/53 Part 4:2007 Closed Caption Data decoder */
5823 
5824 static void
dump_cc_data_pair(FILE * fp,unsigned int index,const uint8_t buf[3])5825 dump_cc_data_pair		(FILE *			fp,
5826 				 unsigned int		index,
5827 				 const uint8_t		buf[3])
5828 {
5829 	unsigned int one_bit;
5830 	unsigned int reserved;
5831 	unsigned int cc_valid;
5832 	enum cc_type cc_type;
5833 	unsigned int cc_data_1;
5834 	unsigned int cc_data_2;
5835 
5836 	/* Was marker_bits: "11111". */
5837 	one_bit = (buf[0] >> 7) & 1;
5838 	reserved = (buf[0] >> 3) & 15;
5839 
5840 	cc_valid = (buf[0] >> 2) & 1;
5841 	cc_type = (enum cc_type)(buf[0] & 3);
5842 	cc_data_1 = buf[1];
5843 	cc_data_2 = buf[2];
5844 
5845 	fprintf (fp, "  %2u '1F'=%u%X%s valid=%u type=%s "
5846 		 "%02x %02x '%c%c'\n",
5847 		 index, one_bit, reserved,
5848 		 (1 != one_bit || 0xF != reserved) ? "*" : "",
5849 		 cc_valid, cc_type_name (cc_type),
5850 		 cc_data_1, cc_data_2,
5851 		 printable (cc_data_1), printable (cc_data_2));
5852 }
5853 
5854 static void
dump_cc_data(FILE * fp,const uint8_t * buf,unsigned int n_bytes,int64_t pts,int64_t last_pts)5855 dump_cc_data			(FILE *			fp,
5856 				 const uint8_t *	buf,
5857 				 unsigned int		n_bytes,
5858 				 int64_t		pts,
5859 				 int64_t		last_pts)
5860 {
5861 	unsigned int reserved1;
5862 	unsigned int process_cc_data_flag;
5863 	unsigned int zero_bit;
5864 	unsigned int cc_count;
5865 	unsigned int reserved2;
5866 	unsigned int same;
5867 	unsigned int marker_bits;
5868 	unsigned int i;
5869 
5870 	/* Was process_em_data_flag: "This flag is set to
5871 	   indicate whether it is necessary to process the em_data. If
5872 	   it is set to 1, the em_data has to be parsed and its
5873 	   meaning has to be processed. When it is set to 0, the
5874 	   em_data can be discarded." */
5875 	reserved1 = (buf[9] >> 7) & 1;
5876 
5877 	process_cc_data_flag = (buf[9] >> 6) & 1;
5878 
5879 	/* Was: additional_cc_data. */
5880 	zero_bit = (buf[9] >> 5) & 1;
5881 
5882 	cc_count = buf[9] & 0x1F;
5883 
5884 	/* Was em_data: "Eight bits for representing emergency
5885 	   message." */
5886 	reserved2 = buf[10];
5887 
5888 	fprintf (fp, "cc_data pts=%" PRId64 " (%+" PRId64 ") "
5889 		 "'1'=%u%s process_cc_data_flag=%u "
5890 		 "'0'=%u%s cc_count=%u 'FF'=0x%02X%s:\n",
5891 		 pts, pts - last_pts, reserved1,
5892 		 (1 != reserved1) ? "*" : "", process_cc_data_flag,
5893 		 zero_bit, (0 != zero_bit) ? "*" : "",
5894 		 cc_count, reserved2,
5895 		 (0xFF != reserved2) ? "*" : "");
5896 
5897 	same = 0;
5898 	for (i = 0; i <= cc_count; ++i) {
5899 		if (i > 0 && i < cc_count
5900 		    && 0 == memcmp (&buf[11 + i * 3],
5901 				    &buf[ 8 + i * 3], 3)) {
5902 			++same;
5903 		} else {
5904 			if (same > 1) {
5905 				fprintf (fp, "  %2u-%u as above\n",
5906 					 i - same, i - 1);
5907 			} else if (same > 0) {
5908 				dump_cc_data_pair (fp, i - 1, &buf[8 + i * 3]);
5909 			}
5910 			if (i < cc_count)
5911 				dump_cc_data_pair (fp, i, &buf[11 + i * 3]);
5912 			same = 0;
5913 		}
5914 	}
5915 
5916 	marker_bits = buf[11 + cc_count * 3];
5917 
5918 	fprintf (fp, "  marker_bits=0x%02X%s\n",
5919 		 marker_bits, (0xFF != marker_bits) ? "*" : "");
5920 
5921 	if (n_bytes > 12 + cc_count * 3) {
5922 		fprintf (fp, "  extraneous");
5923 		for (i = 12 + cc_count * 3; i < n_bytes; ++i)
5924 			fprintf (stderr, " %02x", buf[i]);
5925 		fputc ('\n', stderr);
5926 	}
5927 }
5928 
5929 /* Note pts may be < 0 if no PTS was received. */
5930 static void
decode_cc_data(struct program * pr,int64_t pts,const uint8_t * buf,unsigned int n_bytes)5931 decode_cc_data			(struct program *	pr,
5932 				 int64_t		pts,
5933 				 const uint8_t *	buf,
5934 				 unsigned int		n_bytes)
5935 {
5936 	unsigned int process_cc_data_flag;
5937 	unsigned int cc_count;
5938 	unsigned int i;
5939 	vbi_bool dtvcc;
5940 
5941 	if (option_debug & DEBUG_CC_DATA) {
5942 		static int64_t last_pts = 0; /* XXX */
5943 
5944 		dump_cc_data (stderr, buf, n_bytes, pts, last_pts);
5945 		last_pts = pts;
5946 	}
5947 
5948 	process_cc_data_flag = buf[9] & 0x40;
5949 	if (!process_cc_data_flag)
5950 		return;
5951 
5952 	cc_count = buf[9] & 0x1F;
5953 	dtvcc = FALSE;
5954 
5955 	if (NULL != pr->cr.ccd.cc_data_tap_fp) {
5956 		static uint8_t output_buffer [8 + 11 + 31 * 3];
5957 		unsigned int in;
5958 		unsigned int out;
5959 		unsigned int n_bytes;
5960 
5961 		for (in = 0; in < 8; ++in)
5962 			output_buffer[in] = pts >> (56 - in * 8);
5963 		n_bytes = 11 + cc_count * 3;
5964 		memcpy (output_buffer + in, buf, n_bytes);
5965 		in += n_bytes;
5966 		out = sizeof (output_buffer);
5967 		memset (output_buffer + in, 0, out - in);
5968 
5969 		if (out != fwrite (output_buffer, 1, out,
5970 				   pr->cr.ccd.cc_data_tap_fp)) {
5971 			errno_exit ("cc_data tap write error");
5972 		}
5973 	}
5974 
5975 	for (i = 0; i < cc_count; ++i) {
5976 		unsigned int b0;
5977 		unsigned int cc_valid;
5978 		enum cc_type cc_type;
5979 		unsigned int cc_data_1;
5980 		unsigned int cc_data_2;
5981 		unsigned int j;
5982 
5983 		b0 = buf[11 + i * 3];
5984 		cc_valid = b0 & 4;
5985 		cc_type = (enum cc_type)(b0 & 3);
5986 		cc_data_1 = buf[12 + i * 3];
5987 		cc_data_2 = buf[13 + i * 3];
5988 
5989 		switch (cc_type) {
5990 		case NTSC_F1:
5991 		case NTSC_F2:
5992 			/* Note CEA 708-C Table 4: Only one NTSC pair
5993 			   will be present in field picture user_data
5994 			   or in progressive video pictures, and up to
5995 			   three can occur if the frame rate < 30 Hz
5996 			   or repeat_first_field = 1. */
5997 			if (!cc_valid || i >= 3 || dtvcc) {
5998 				/* Illegal, invalid or filler. */
5999 				break;
6000 			}
6001 
6002 			if (option_debug & (DEBUG_CC_F1 | DEBUG_CC_F2)) {
6003 				if ((NTSC_F1 == cc_type
6004 				     && 0 != (option_debug & DEBUG_CC_F1))
6005 				    || (NTSC_F2 == cc_type
6006 					&& 0 != (option_debug & DEBUG_CC_F2)))
6007 					dump_cc (stderr, i, cc_count,
6008 						 cc_valid, cc_type,
6009 						 cc_data_1, cc_data_2);
6010 			}
6011 
6012 			cc_feed (&pr->cr.cc, &buf[12 + i * 3],
6013 				 /* line */ (NTSC_F1 == cc_type) ? 21 : 284,
6014 				 &pr->now, pts);
6015 
6016 			/* XXX replace me. */
6017 			if (NTSC_F1 == cc_type) {
6018 				pr->cr.field = 0;
6019 				if (pr->cr.usexds) /* fields swapped? */
6020 					XDSdecode(&pr->cr, cc_data_1
6021 						  + cc_data_2 * 256);
6022 			} else {
6023 				pr->cr.field = 1;
6024 				if (pr->cr.usexds)
6025 					XDSdecode(&pr->cr, cc_data_1
6026 						  + cc_data_2 * 256);
6027 			}
6028 
6029 			break;
6030 
6031 		case DTVCC_DATA:
6032 			j = pr->cr.dtvcc.packet_size;
6033 			if (j <= 0) {
6034 				/* Missed packet start. */
6035 				break;
6036 			} else if (!cc_valid) {
6037 				/* End of DTVCC packet. */
6038 				dtvcc_decode_packet (&pr->cr.dtvcc,
6039 						     &pr->now, pts);
6040 				pr->cr.dtvcc.packet_size = 0;
6041 			} else if (j >= 128) {
6042 				/* Packet buffer overflow. */
6043 				dtvcc_reset (&pr->cr.dtvcc);
6044 				pr->cr.dtvcc.packet_size = 0;
6045 			} else {
6046 				pr->cr.dtvcc.packet[j] = cc_data_1;
6047 				pr->cr.dtvcc.packet[j + 1] = cc_data_2;
6048 				pr->cr.dtvcc.packet_size = j + 2;
6049 			}
6050 			break;
6051 
6052 		case DTVCC_START:
6053 			dtvcc = TRUE;
6054 			j = pr->cr.dtvcc.packet_size;
6055 			if (j > 0) {
6056 				/* End of DTVCC packet. */
6057 				dtvcc_decode_packet (&pr->cr.dtvcc,
6058 						     &pr->now, pts);
6059 			}
6060 			if (!cc_valid) {
6061 				/* No new data. */
6062 				pr->cr.dtvcc.packet_size = 0;
6063 			} else {
6064 				pr->cr.dtvcc.packet[0] = cc_data_1;
6065 				pr->cr.dtvcc.packet[1] = cc_data_2;
6066 				pr->cr.dtvcc.packet_size = 2;
6067 			}
6068 			break;
6069 		}
6070 	}
6071 }
6072 
6073 static void
init_cc_data_decoder(struct cc_data_decoder * cd)6074 init_cc_data_decoder		(struct cc_data_decoder *cd)
6075 {
6076 	CLEAR (*cd);
6077 }
6078 
6079 static void
cc_data_test_loop(struct program * pr,const char * test_file_name)6080 cc_data_test_loop		(struct program *	pr,
6081 				 const char *		test_file_name)
6082 {
6083 	FILE *test_fp;
6084 
6085 	test_fp = open_test_file (test_file_name);
6086 
6087 	for (;;) {
6088 		static uint8_t buffer[8 + 11 + 31 * 3];
6089 		size_t todo;
6090 		size_t actual;
6091 
6092 		todo = sizeof (buffer);
6093 		actual = fread (buffer, 1, todo, test_fp);
6094 		if (likely (actual == todo)) {
6095 			int64_t pts;
6096 			unsigned int i;
6097 
6098 			pts = 0;
6099 			for (i = 0; i < 8; ++i) {
6100 				pts |= buffer[i] << (56 - i * 8);
6101 			}
6102 			decode_cc_data (pr, pts, &buffer[8], actual);
6103 			continue;
6104 		}
6105 
6106 		if (ferror (test_fp)) {
6107 			errno_exit ("CC data file read error");
6108 		} else {
6109 			log (1, "End of CC data file.\n");
6110 			fclose (test_fp);
6111 			return;
6112 		}
6113 	}
6114 }
6115 
6116 /* DVB capture functions and transport stream decoding. */
6117 
6118 static void
init_buffer(struct buffer * b,unsigned int capacity)6119 init_buffer			(struct buffer *	b,
6120 				 unsigned int		capacity)
6121 {
6122 	b->capacity = capacity;
6123 	b->base = xmalloc (capacity);
6124 	b->in = 0;
6125 	b->out = 0;
6126 }
6127 
6128 static void
6129 dump_pes_buffer			(FILE *			fp,
6130 				 const struct pes_buffer *b,
6131 				 const char *		name)
6132   _vbi_unused;
6133 
6134 static void
dump_pes_buffer(FILE * fp,const struct pes_buffer * b,const char * name)6135 dump_pes_buffer			(FILE *			fp,
6136 				 const struct pes_buffer *b,
6137 				 const char *		name)
6138 {
6139 	unsigned int i;
6140 
6141 	fprintf (fp, "%s PES buffer:\n", name);
6142 
6143 	for (i = 0; i < b->n_packets; ++i) {
6144 		fprintf (fp, "%2u: offs=%5u size=%u/%u "
6145 			 "dts=%" PRId64 " (%+" PRId64 ") "
6146 			 "duration=%" PRId64 " splice=%d lost=%d\n",
6147 			 i,
6148 			 b->packet[i].offset,
6149 			 b->packet[i].payload,
6150 			 b->packet[i].size,
6151 			 b->packet[i].dts,
6152 			 (i > 0) ? (b->packet[i].dts
6153 				    - b->packet[i - 1].dts) : 0,
6154 			 b->packet[i].duration,
6155 			 b->packet[i].splice,
6156 			 b->packet[i].data_lost);
6157 	}
6158 }
6159 
6160 
6161 
6162 static vbi_bool
decode_time_stamp(int64_t * ts,const uint8_t * buf,unsigned int marker)6163 decode_time_stamp		(int64_t *		ts,
6164 				 const uint8_t *	buf,
6165 				 unsigned int		marker)
6166 {
6167 	/* ISO 13818-1 Section 2.4.3.6 */
6168 
6169 	if (0 != ((marker ^ buf[0]) & 0xF1))
6170 		return FALSE;
6171 
6172 	if (NULL != ts) {
6173 		unsigned int a, b, c;
6174 
6175 		/* marker [4], TS [32..30], marker_bit,
6176 		   TS [29..15], marker_bit,
6177 		   TS [14..0], marker_bit */
6178 		a = (buf[0] >> 1) & 0x7;
6179 		b = (buf[1] * 256 + buf[2]) >> 1;
6180 		c = (buf[3] * 256 + buf[4]) >> 1;
6181 
6182 		*ts = ((int64_t) a << 30) + (b << 15) + (c << 0);
6183 	}
6184 
6185 	return TRUE;
6186 }
6187 
6188 
6189 static void
dump_pes_packet_header(FILE * fp,const uint8_t * buf)6190 dump_pes_packet_header		(FILE *			fp,
6191 				 const uint8_t *	buf)
6192 {
6193 	unsigned int packet_start_code_prefix;
6194 	unsigned int stream_id;
6195 	unsigned int PES_packet_length;
6196 	unsigned int PES_scrambling_control;
6197 	unsigned int PES_priority;
6198 	unsigned int data_alignment_indicator;
6199 	unsigned int copyright;
6200 	unsigned int original_or_copy;
6201 	unsigned int PTS_DTS_flags;
6202 	unsigned int ESCR_flag;
6203 	unsigned int ES_rate_flag;
6204 	unsigned int DSM_trick_mode_flag;
6205 	unsigned int additional_copy_info_flag;
6206 	unsigned int PES_CRC_flag;
6207 	unsigned int PES_extension_flag;
6208 	unsigned int PES_header_data_length;
6209 	int64_t ts;
6210 
6211 	/* ISO 13818-1 Section 2.4.3.6. */
6212 
6213 	packet_start_code_prefix  = buf[0] * 65536 + buf[1] * 256 + buf[2];
6214 	stream_id		  = buf[3];
6215 	PES_packet_length	  = buf[4] * 256 + buf[5];
6216 	/* '10' */
6217 	PES_scrambling_control	  = (buf[6] & 0x30) >> 4;
6218 	PES_priority		  = buf[6] & 0x08;
6219 	data_alignment_indicator  = buf[6] & 0x04;
6220 	copyright		  = buf[6] & 0x02;
6221 	original_or_copy	  = buf[6] & 0x01;
6222 	PTS_DTS_flags		  = (buf[7] & 0xC0) >> 6;
6223 	ESCR_flag		  = buf[7] & 0x20;
6224 	ES_rate_flag		  = buf[7] & 0x10;
6225 	DSM_trick_mode_flag	  = buf[7] & 0x08;
6226 	additional_copy_info_flag = buf[7] & 0x04;
6227 	PES_CRC_flag		  = buf[7] & 0x02;
6228 	PES_extension_flag	  = buf[7] & 0x01;
6229 	PES_header_data_length	  = buf[8];
6230 
6231 	fprintf (fp, "PES %06X%02X %5u "
6232 		 "%u%u%u%c%c%c%c%u%c%c%c%c%c%c %u",
6233 		 packet_start_code_prefix, stream_id,
6234 		 PES_packet_length,
6235 		 !!(buf[6] & 0x80),
6236 		 !!(buf[6] & 0x40),
6237 		 PES_scrambling_control,
6238 		 PES_priority ? 'P' : '-',
6239 		 data_alignment_indicator ? 'A' : '-',
6240 		 copyright ? 'C' : '-',
6241 		 original_or_copy ? 'O' : 'C',
6242 		 PTS_DTS_flags,
6243 		 ESCR_flag ? 'E' : '-',
6244 		 ES_rate_flag ? 'E' : '-',
6245 		 DSM_trick_mode_flag ? 'D' : '-',
6246 		 additional_copy_info_flag ? 'A' : '-',
6247 		 PES_CRC_flag ? 'C' : '-',
6248 		 PES_extension_flag ? 'X' : '-',
6249 		 PES_header_data_length);
6250 
6251 	switch (PTS_DTS_flags) {
6252 	case 0: /* no timestamps */
6253 	case 1: /* forbidden */
6254 		fputc ('\n', fp);
6255 		break;
6256 
6257 	case 2: /* PTS only */
6258 		if (decode_time_stamp (&ts, &buf[9], 0x21))
6259 			fprintf (fp, " %" PRId64 "\n", ts);
6260 		else
6261 			fputs (" PTS?\n", fp);
6262 		break;
6263 
6264 	case 3: /* PTS and DTS */
6265 		if (decode_time_stamp (&ts, &buf[9], 0x31))
6266 			fprintf (fp, " %" PRId64, ts);
6267 		else
6268 			fputs (" PTS?", fp);
6269 		if (decode_time_stamp (&ts, &buf[14], 0x11))
6270 			fprintf (fp, " %" PRId64 "\n", ts);
6271 		else
6272 			fputs (" DTS?\n", fp);
6273 		break;
6274 	}
6275 }
6276 
6277 
6278 static void
close_ts_file(struct video_recorder * vr)6279 close_ts_file			(struct video_recorder *vr)
6280 {
6281 	if (NULL != vr->minicut_fp) {
6282 		if (0 != fclose (vr->minicut_fp)) {
6283 			struct program *pr;
6284 
6285 			pr = PARENT (vr, struct program, vr);
6286 			log_errno (1, "TS stream %u close error",
6287 				   (unsigned int)(pr - program_table));
6288 		}
6289 
6290 		vr->minicut_fp = NULL;
6291 	}
6292 }
6293 
6294 static unsigned int
mpeg2_crc(const uint8_t * buf,unsigned int n_bytes)6295 mpeg2_crc			(const uint8_t *	buf,
6296 				 unsigned int		n_bytes)
6297 {
6298 	static uint32_t crc_table[256];
6299 	unsigned int crc;
6300 	unsigned int i;
6301 
6302 	/* ISO 13818-1 Annex B. */
6303 
6304 	if (unlikely (0 == crc_table[255])) {
6305 		const unsigned int poly =
6306 			((1 << 26) | (1 << 23) | (1 << 22) | (1 << 16) |
6307 			 (1 << 12) | (1 << 11) | (1 << 10) | (1 << 8) |
6308 			 (1 << 7) | (1 << 5) | (1 << 4) | (1 << 2) |
6309 			 (1 << 1) | 1);
6310 		unsigned int c, j;
6311 
6312 		for (i = 0; i < 256; ++i) {
6313 			c = i << 24;
6314 			for (j = 0; j < 8; ++j) {
6315 				if (c & (1 << 31))
6316 					c = (c << 1) ^ poly;
6317 				else
6318 					c <<= 1;
6319 			}
6320 			crc_table[i] = c;
6321 		}
6322 		assert (0 != crc_table[255]);
6323 	}
6324 
6325 	crc = -1;
6326 	for (i = 0; i < n_bytes; ++i)
6327 		crc = crc_table[(buf[i] ^ (crc >> 24)) & 0xFF] ^ (crc << 8);
6328 
6329 	return crc & 0xFFFFFFFFUL;
6330 }
6331 
6332 static const unsigned int	pmt_pid = 0x5A5;
6333 
6334 static void
init_pmt(uint8_t buf[188],struct video_recorder * vr,const struct ts_decoder * td)6335 init_pmt			(uint8_t		buf[188],
6336 				 struct video_recorder *vr,
6337 				 const struct ts_decoder *td)
6338 {
6339 	uint32_t CRC_32;
6340 
6341 	/* sync_byte [8], transport_error_indicator,
6342 	   payload_unit_start_indicator, transport_priority, PID [13],
6343 	   transport_scrambling_control [2], adaptation_field_control
6344 	   [2], continuity_counter [4] */
6345 	buf[0] = 0x47;
6346 	buf[1] = 0x40 | ((pmt_pid & 0x1FFF) >> 8);
6347 	buf[2] = pmt_pid;
6348 	buf[3] = 0x10 | (vr->pmt_cc & 0x0F);
6349 	++vr->pmt_cc;
6350 
6351 	/* pointer_field */
6352 	buf[4] = 0x00;
6353 
6354 	/* table_id [8] */
6355 	buf[5] = 0x02; /* TS_program_map_section */
6356 
6357 	/* section_syntax_indicator, '0', reserved [2], section_length
6358 	   [12] */
6359 	buf[6] = 0xB0;
6360 	buf[7] = 31 - 8;
6361 
6362 	/* program_number [16] */
6363 	buf[8] = 0x00;
6364 	buf[9] = 0x01;
6365 
6366 	/* reserved [2], version_number [5], current_next_indicator */
6367 	buf[10] = 0xC1;
6368 
6369 	/* section_number [8], last_section_number [8] */
6370 	buf[11] = 0x00;
6371 	buf[12] = 0x00;
6372 
6373 	/* reserved [3], PCR_PID [13] */
6374 	buf[13] = 0xE0 | (td->pid[0] >> 8);
6375 	buf[14] = td->pid[0];
6376 
6377 	/* reserved [4], program_info_length [12] */
6378 	buf[15] = 0xF0;
6379 	buf[16] = 0x00;
6380 
6381 	/* stream_type [8], reserved [3], elementary_PID [13],
6382 	   reserved [4], ES_info_length [12] */
6383 	buf[17] = 0x02; /* MPEG-2 video */
6384 	buf[18] = 0xE0 | (td->pid[0] >> 8);
6385 	buf[19] = td->pid[0];
6386 	buf[20] = 0xF0;
6387 	buf[21] = 0x00;
6388 
6389 	buf[22] = 0x81; /* AC3 audio */
6390 	buf[23] = 0xE0 | (td->pid[1] >> 8);
6391 	buf[24] = td->pid[1];
6392 	buf[25] = 0xF0;
6393 	buf[26] = 0x00;
6394 
6395 	CRC_32 = mpeg2_crc (buf + 5, 27 - 5);
6396 	buf[27] = CRC_32 >> 24;
6397 	buf[28] = CRC_32 >> 16;
6398 	buf[29] = CRC_32 >> 8;
6399 	buf[30] = CRC_32;
6400 
6401 	memset (buf + 31, -1, 188 - 31);
6402 }
6403 
6404 static void
init_pat(uint8_t buf[188],struct video_recorder * vr)6405 init_pat			(uint8_t		buf[188],
6406 				 struct video_recorder *vr)
6407 {
6408 	uint32_t CRC_32;
6409 
6410 	/* sync_byte [8], transport_error_indicator,
6411 	   payload_unit_start_indicator, transport_priority, PID [13],
6412 	   transport_scrambling_control [2], adaptation_field_control
6413 	   [2], continuity_counter [4] */
6414 	buf[0] = 0x47;
6415 	buf[1] = 0x40;
6416 	buf[2] = 0x00;
6417 	buf[3] = 0x10 | (vr->pat_cc & 0x0F);
6418 	++vr->pat_cc;
6419 
6420 	/* pointer_field [8] */
6421 	buf[4] = 0x00;
6422 
6423 	/* table_id [8] */
6424 	buf[5] = 0x00; /* program_association_section */
6425 
6426 	/* section_syntax_indicator, '0', reserved [2],
6427 	   section_length [12] */
6428 	buf[6] = 0xB0;
6429 	buf[7] = 21 - 8;
6430 
6431 	/* transport_stream_id [16] */
6432 	buf[8] = 0x00;
6433 	buf[9] = 0x01;
6434 
6435 	/* reserved [2], version_number [5], current_next_indicator */
6436 	buf[10] = 0xC1;
6437 
6438 	/* section_number [8], last_section_number [8] */
6439 	buf[11] = 0x00;
6440 	buf[12] = 0x00;
6441 
6442 	/* program_number [16] */
6443 	buf[13] = 0x00;
6444 	buf[14] = 0x01;
6445 
6446 	/* reserved [3], program_map_PID [13] */
6447 	buf[15] = 0xE0 | ((pmt_pid & 0x1FFF) >> 8);
6448 	buf[16] = pmt_pid;
6449 
6450 	CRC_32 = mpeg2_crc (buf + 5, 17 - 5);
6451 	buf[17] = CRC_32 >> 24;
6452 	buf[18] = CRC_32 >> 16;
6453 	buf[19] = CRC_32 >> 8;
6454 	buf[20] = CRC_32;
6455 
6456 	memset (buf + 21, -1, 188 - 21);
6457 }
6458 
6459 static void
video_recorder(struct video_recorder * vr,const uint8_t buf[188])6460 video_recorder			(struct video_recorder *vr,
6461 				 const uint8_t		buf[188])
6462 {
6463 	struct program *pr = PARENT (vr, struct program, vr);
6464 	size_t actual;
6465 
6466 	if (NULL == pr->option_minicut_dir_name)
6467 		return; /* no video recording */
6468 
6469 	/* The TS packet rate is too high to call time() here. We do
6470 	   that when a picture arrives, some 24 to 60 times/second. */
6471 	if (0 == (pr->now.tv_sec | pr->now.tv_usec))
6472 		return; /* no picture received yet */
6473 
6474 	/* Note minicut_end is initially zero. */
6475 	if (pr->now.tv_sec >= vr->minicut_end) {
6476 		char file_name[32];
6477 		struct tm tm;
6478 		time_t t;
6479 
6480 		t = pr->now.tv_sec;
6481 		if (NULL == gmtime_r (&t, &tm)) {
6482 			/* Should not happen. */
6483 			error_exit ("System time invalid.\n");
6484 		}
6485 
6486 		vr->minicut_end = t + (60 - tm.tm_sec);
6487 
6488 		if (option_minicut_test) {
6489 			tm.tm_sec = 0;
6490 		} else if (1) {
6491 			tm.tm_sec = 0;
6492 		} else {
6493 			if (0 != tm.tm_sec)
6494 				return;
6495 		}
6496 
6497 		close_ts_file (vr);
6498 
6499 		snprintf (file_name, sizeof (file_name),
6500 			  "/%04u%02u%02u%02u%02u%02u",
6501 			  tm.tm_year + 1900,
6502 			  tm.tm_mon + 1,
6503 			  tm.tm_mday,
6504 			  tm.tm_hour,
6505 			  tm.tm_min,
6506 			  tm.tm_sec);
6507 
6508 		vr->minicut_fp = open_minicut_file (pr, &tm, file_name, ".ts");
6509 		if (NULL != vr->minicut_fp) {
6510 			uint8_t buf[2 * 188];
6511 
6512 			init_pat (buf, vr);
6513 			init_pmt (buf + 188, vr, &pr->tsd);
6514 
6515 			actual = fwrite (buf, 1, 2 * 188, vr->minicut_fp);
6516 			if (2 * 188 != actual) {
6517 				log_errno (1, "TS stream %u write error",
6518 					   station_num (pr));
6519 			}
6520 		}
6521 	}
6522 
6523 	if (NULL == vr->minicut_fp)
6524 		return;
6525 
6526 	actual = fwrite (buf, 1, 188, vr->minicut_fp);
6527 	if (188 != actual) {
6528 		log_errno (1, "TS stream %u write error",
6529 			   station_num (pr));
6530 	}
6531 }
6532 
6533 
6534 static void
init_video_recorder(struct video_recorder * vr)6535 init_video_recorder		(struct video_recorder *vr)
6536 {
6537 
6538 
6539 
6540 
6541 
6542 	vr->pat_cc = 0;
6543 	vr->pmt_cc = 0;
6544 
6545 	vr->minicut_end = 0;
6546 	vr->minicut_fp = NULL;
6547 }
6548 
6549 /* Video elementary stream decoder. */
6550 
6551 static void
vesd_reorder_decode_cc_data(struct video_es_decoder * vd,const uint8_t * buf,unsigned int n_bytes)6552 vesd_reorder_decode_cc_data	(struct video_es_decoder *vd,
6553 				 const uint8_t *	buf,
6554 				 unsigned int		n_bytes)
6555 {
6556 	struct program *pr = PARENT (vd, struct program, vesd);
6557 
6558 	n_bytes = MIN (n_bytes, (unsigned int)
6559 		       sizeof (vd->reorder_buffer[0]));
6560 
6561 	switch (vd->picture_structure) {
6562 	case FRAME_PICTURE:
6563 		if (0 != vd->reorder_pictures) {
6564 			if (vd->reorder_pictures & 5) {
6565 				/* Top field or top and bottom field. */
6566 				decode_cc_data (pr, vd->reorder_pts[0],
6567 						vd->reorder_buffer[0],
6568 						vd->reorder_n_bytes[0]);
6569 			}
6570 			if (vd->reorder_pictures & 2) {
6571 				/* Bottom field. */
6572 				decode_cc_data (pr, vd->reorder_pts[1],
6573 						vd->reorder_buffer[1],
6574 						vd->reorder_n_bytes[1]);
6575 			}
6576 		}
6577 
6578 		memcpy (vd->reorder_buffer[0], buf, n_bytes);
6579 		vd->reorder_n_bytes[0] = n_bytes;
6580 		vd->reorder_pts[0] = vd->pts;
6581 
6582 		/* We have a frame. */
6583 		vd->reorder_pictures = 4;
6584 
6585 		break;
6586 
6587 	case TOP_FIELD:
6588 		if (vd->reorder_pictures >= 3) {
6589 			/* Top field or top and bottom field. */
6590 			decode_cc_data (pr, vd->reorder_pts[0],
6591 					vd->reorder_buffer[0],
6592 					vd->reorder_n_bytes[0]);
6593 
6594 			vd->reorder_pictures &= 2;
6595 		} else if (1 == vd->reorder_pictures) {
6596 			/* Apparently we missed a bottom field. */
6597 		}
6598 
6599 		memcpy (vd->reorder_buffer[0], buf, n_bytes);
6600 		vd->reorder_n_bytes[0] = n_bytes;
6601 		vd->reorder_pts[0] = vd->pts;
6602 
6603 		/* We have a top field. */
6604 		vd->reorder_pictures |= 1;
6605 
6606 		break;
6607 
6608 	case BOTTOM_FIELD:
6609 		if (vd->reorder_pictures >= 3) {
6610 			if (vd->reorder_pictures >= 4) {
6611 				/* Top and bottom field. */
6612 				decode_cc_data (pr, vd->reorder_pts[0],
6613 						vd->reorder_buffer[0],
6614 						vd->reorder_n_bytes[0]);
6615 			} else {
6616 				/* Bottom field. */
6617 				decode_cc_data (pr, vd->reorder_pts[1],
6618 						vd->reorder_buffer[1],
6619 						vd->reorder_n_bytes[1]);
6620 			}
6621 
6622 			vd->reorder_pictures &= 1;
6623 		} else if (2 == vd->reorder_pictures) {
6624 			/* Apparently we missed a top field. */
6625 		}
6626 
6627 		memcpy (vd->reorder_buffer[1], buf, n_bytes);
6628 		vd->reorder_n_bytes[1] = n_bytes;
6629 		vd->reorder_pts[1] = vd->pts;
6630 
6631 		/* We have a bottom field. */
6632 		vd->reorder_pictures |= 2;
6633 
6634 		break;
6635 
6636 	default: /* invalid */
6637 		break;
6638 	}
6639 }
6640 
6641 static void
vesd_user_data(struct video_es_decoder * vd,const uint8_t * buf,unsigned int min_bytes_valid)6642 vesd_user_data			(struct video_es_decoder *vd,
6643 				 const uint8_t *	buf,
6644 				 unsigned int		min_bytes_valid)
6645 {
6646 	unsigned int ATSC_identifier;
6647 	unsigned int user_data_type_code;
6648 	unsigned int cc_count;
6649 
6650 	/* ATSC A/53 Part 4:2007 Section 6.2.2 */
6651 
6652 	if (unlikely (option_debug & DEBUG_VESD_USER_DATA)) {
6653 		unsigned int i;
6654 
6655 		fprintf (stderr, "VES UD: %s %s ref=%u "
6656 			 "dts=%" PRId64 " pts=%" PRId64,
6657 			 picture_coding_type_name (vd->picture_coding_type),
6658 			 picture_structure_name (vd->picture_structure),
6659 			 vd->picture_temporal_reference,
6660 			 vd->dts, vd->pts);
6661 		for (i = 0; i < min_bytes_valid; ++i)
6662 			fprintf (stderr, " %02x", buf[i]);
6663 		fputc (' ', stderr);
6664 		for (i = 0; i < min_bytes_valid; ++i)
6665 			fputc (printable (buf[i]), stderr);
6666 		fputc ('\n', stderr);
6667 	}
6668 
6669 	/* NB. the PES packet header is optional and we may receive
6670 	   more than one user_data structure. */
6671 	if ((RECEIVED_PICTURE |
6672 	     RECEIVED_PICTURE_EXT)
6673 	    != (vd->received_blocks & (RECEIVED_PICTURE |
6674 				       RECEIVED_PICTURE_EXT))) {
6675 		/* Either sequence or group user_data, or we missed
6676 		   the picture_header. */
6677 		vd->received_blocks &= ~RECEIVED_PES_PACKET;
6678 		return;
6679 	}
6680 
6681 	if (NULL == buf) {
6682 		/* No user_data received on this field or frame. */
6683 
6684 		if (option_debug & DEBUG_VESD_CC_DATA) {
6685 			fprintf (stderr, "DTVCC coding=%s structure=%s "
6686 				 "pts=%" PRId64 " no data\n",
6687 				 picture_coding_type_name
6688 				 (vd->picture_coding_type),
6689 				 picture_structure_name
6690 				 (vd->picture_structure),
6691 				 vd->pts);
6692 		}
6693 	} else {
6694 		/* start_code_prefix [24], start_code [8],
6695 		   ATSC_identifier [32], user_data_type_code [8] */
6696 		if (min_bytes_valid < 9)
6697 			return;
6698 
6699 		ATSC_identifier = ((buf[4] << 24) | (buf[5] << 16) |
6700 				   (buf[6] << 8) | buf[7]);
6701 		if (0x47413934 != ATSC_identifier)
6702 			return;
6703 
6704 		user_data_type_code = buf[8];
6705 		if (0x03 != user_data_type_code)
6706 			return;
6707 
6708 		/* ATSC A/53 Part 4:2007 Section 6.2.1: "No more than one
6709 		   user_data() structure using the same user_data_type_code
6710 		   [...] shall be present following any given picture
6711 		   header." */
6712 		if (vd->received_blocks & RECEIVED_MPEG_CC_DATA) {
6713 			/* Too much data lost. */
6714 			return;
6715 		}
6716 
6717 		vd->received_blocks |= RECEIVED_MPEG_CC_DATA;
6718 
6719 		/* reserved, process_cc_data_flag, zero_bit, cc_count [5],
6720 		   reserved [8] */
6721 		if (min_bytes_valid < 11)
6722 			return;
6723 
6724 		/* one_bit, reserved [4], cc_valid, cc_type [2],
6725 		   cc_data_1 [8], cc_data_2 [8] */
6726 		cc_count = buf[9] & 0x1F;
6727 
6728 		/* CEA 708-C Section 4.4 permits padding, so we have to see
6729 		   all cc_data elements. */
6730 		if (min_bytes_valid < 11 + cc_count * 3)
6731 			return;
6732 
6733 		if (option_debug & DEBUG_VESD_CC_DATA) {
6734 			char text[0x1F * 2 + 1];
6735 			unsigned int i;
6736 			vbi_bool ooo;
6737 
6738 			for (i = 0; i < cc_count; ++i) {
6739 				text[i * 2 + 0] = printable (buf[12 + i * 3]);
6740 				text[i * 2 + 1] = printable (buf[13 + i * 3]);
6741 			}
6742 			text[cc_count * 2] = 0;
6743 
6744 			ooo = (B_TYPE == vd->picture_coding_type
6745 			       && vd->reorder_pictures < 3);
6746 
6747 			fprintf (stderr, "DTVCC coding=%s structure=%s "
6748 				 "pts=%" PRId64 " cc_count=%u "
6749 				 "n_bytes=%u '%s'%s\n",
6750 				 picture_coding_type_name
6751 				 (vd->picture_coding_type),
6752 				 picture_structure_name
6753 				 (vd->picture_structure),
6754 				 vd->pts, cc_count, min_bytes_valid,
6755 				 text, ooo ? " (out of order)" : "");
6756 		}
6757 	}
6758 
6759 	/* CEA 708-C Section 4.4.1.1 */
6760 
6761 	switch (vd->picture_coding_type) {
6762 	case I_TYPE:
6763 	case P_TYPE:
6764 		vesd_reorder_decode_cc_data (vd, buf, min_bytes_valid);
6765 		break;
6766 
6767 	case B_TYPE:
6768 		/* To prevent a gap in the caption stream we must not
6769 		   decode B pictures until we have buffered both
6770 		   fields of the temporally following I or P picture. */
6771 		if (vd->reorder_pictures < 3) {
6772 			vd->reorder_pictures = 0;
6773 			break;
6774 		}
6775 
6776 		/* To do: If a B picture appears to have a higher
6777 		   temporal_reference than the picture it forward
6778 		   references we lost that I or P picture. */
6779 		{
6780 			struct program *pr;
6781 
6782 			pr = PARENT (vd, struct program, vesd);
6783 			decode_cc_data (pr, vd->pts, buf,
6784 					min_bytes_valid);
6785 		}
6786 
6787 		break;
6788 
6789 	default: /* invalid */
6790 		break;
6791 	}
6792 }
6793 
6794 static void
vesd_extension(struct video_es_decoder * vd,const uint8_t * buf,unsigned int min_bytes_valid)6795 vesd_extension			(struct video_es_decoder *vd,
6796 				 const uint8_t *	buf,
6797 				 unsigned int		min_bytes_valid)
6798 {
6799 	enum extension_start_code_identifier extension_start_code_identifier;
6800 
6801 	/* extension_start_code [32],
6802 	   extension_start_code_identifier [4],
6803 	   f_code [4][4], intra_dc_precision [2],
6804 	   picture_structure [2], ... */
6805 	if (min_bytes_valid < 7)
6806 		return;
6807 
6808 	extension_start_code_identifier =
6809 		(enum extension_start_code_identifier)(buf[4] >> 4);
6810 	if (PICTURE_CODING_EXTENSION_ID
6811 	    != extension_start_code_identifier)
6812 		return;
6813 
6814 	if (0 == (vd->received_blocks & RECEIVED_PICTURE)) {
6815 		/* We missed the picture_header. */
6816 		vd->received_blocks = 0;
6817 		return;
6818 	}
6819 
6820 	vd->picture_structure = (enum picture_structure)(buf[6] & 3);
6821 
6822 	if (option_debug & DEBUG_VESD_PIC_EXT) {
6823 		fprintf (stderr, "VES PIC EXT structure=%s\n",
6824 			 picture_structure_name (vd->picture_structure));
6825 	}
6826 
6827 	vd->received_blocks |= RECEIVED_PICTURE_EXT;
6828 }
6829 
6830 static void
vesd_picture_header(struct video_es_decoder * vd,const uint8_t * buf,unsigned int min_bytes_valid)6831 vesd_picture_header		(struct video_es_decoder *vd,
6832 				 const uint8_t *	buf,
6833 				 unsigned int		min_bytes_valid)
6834 {
6835 	unsigned int c;
6836 
6837 	/* picture_start_code [32],
6838 	   picture_temporal_reference [10],
6839 	   picture_coding_type [3], ... */
6840 	/* XXX consider estimating the PTS if none transmitted. */
6841  	if (min_bytes_valid < 6
6842 	    /* || vd->received_blocks != RECEIVED_PES_PACKET */) {
6843 		/* Too much data lost. */
6844 		vd->received_blocks = 0;
6845 		return;
6846 	}
6847 
6848 	c = buf[4] * 256 + buf[5];
6849 	vd->picture_temporal_reference = (c >> 6) & 0x3FF;
6850 	vd->picture_coding_type = (enum picture_coding_type)((c >> 3) & 7);
6851 
6852 	if (option_debug & DEBUG_VESD_PIC_HDR) {
6853 		fprintf (stderr, "VES PIC HDR ref=%d type=%ss\n",
6854 			 vd->picture_temporal_reference,
6855 			 picture_coding_type_name
6856 			 (vd->picture_coding_type));
6857 	}
6858 
6859  	++vd->n_pictures_received;
6860 
6861 	vd->received_blocks |= RECEIVED_PICTURE;
6862 }
6863 
6864 static void
vesd_pes_packet_header(struct video_es_decoder * vd,const uint8_t * buf,unsigned int min_bytes_valid)6865 vesd_pes_packet_header		(struct video_es_decoder *vd,
6866 				 const uint8_t *	buf,
6867 				 unsigned int		min_bytes_valid)
6868 {
6869 	unsigned int PES_packet_length;
6870 	unsigned int PTS_DTS_flags;
6871 	int64_t pts;
6872 
6873 	if (unlikely (option_debug & DEBUG_VESD_PES_PACKET)) {
6874 		dump_pes_packet_header (stderr, buf);
6875 	}
6876 
6877 	vd->pts = -1;
6878 	vd->dts = -1;
6879 
6880 	vd->received_blocks = 0;
6881 
6882 	/* packet_start_code_prefix [24], stream_id [8],
6883 	   PES_packet_length [16],
6884 
6885 	   '10', PES_scrambling_control [2], PES_priority,
6886 	   data_alignment_indicator, copyright, original_or_copy,
6887 
6888 	   PTS_DTS_flags [2], ESCR_flag, ES_rate_flag,
6889 	   DSM_trick_mode_flag, additional_copy_info_flag,
6890 	   PES_CRC_flag, PES_extension_flag,
6891 
6892 	   PES_header_data_length [8] */
6893 	if (min_bytes_valid < 9)
6894 		return;
6895 
6896 	PES_packet_length = buf[4] * 256 + buf[5];
6897 	PTS_DTS_flags = (buf[7] & 0xC0) >> 6;
6898 
6899 	/* ISO 13818-1 Section 2.4.3.7: In transport streams video PES
6900 	   packets do not carry data, they only contain the DTS/PTS of
6901 	   the following picture and PES_packet_length must be
6902 	   zero. */
6903 	if (0 != PES_packet_length)
6904 		return;
6905 
6906 	switch (PTS_DTS_flags) {
6907 	case 0: /* no timestamps */
6908 		return;
6909 
6910 	case 1: /* forbidden */
6911 		return;
6912 
6913 	case 2: /* PTS only */
6914 		if (min_bytes_valid < 14)
6915 			return;
6916 		if (!decode_time_stamp (&vd->pts, &buf[9], 0x21))
6917 			return;
6918 		break;
6919 
6920 	case 3: /* PTS and DTS */
6921 		if (min_bytes_valid < 19)
6922 			return;
6923 		if (!decode_time_stamp (&pts, &buf[9], 0x31))
6924 			return;
6925 		if (!decode_time_stamp (&vd->dts, &buf[14], 0x11))
6926 			return;
6927 		vd->pts = pts;
6928 		break;
6929 	}
6930 
6931 	if (unlikely (option_minicut_test)) {
6932 		struct program *pr;
6933 		int64_t dts;
6934 
6935 		pr = PARENT (vd, struct program, vesd);
6936 
6937 		dts = vd->dts;
6938 		if (dts < 0)
6939 			dts = vd->pts;
6940 
6941 		if (pr->first_dts < 0) {
6942 			pr->first_dts = dts;
6943 		} else if (dts < pr->first_dts) {
6944 			dts += TIMESTAMP_MASK + 1;
6945 		}
6946 
6947 		pr->now.tv_sec = (dts - pr->first_dts) / 90000;
6948 		pr->now.tv_usec = (dts - pr->first_dts) % 90000 * 100 / 9;
6949 	} else {
6950 		struct program *pr;
6951 
6952 		pr = PARENT (vd, struct program, vesd);
6953 		gettimeofday (&pr->now, /* tz */ NULL);
6954 	}
6955 
6956 	vd->received_blocks = RECEIVED_PES_PACKET;
6957 }
6958 
6959 static void
vesd_decode_block(struct video_es_decoder * vd,unsigned int start_code,const uint8_t * buf,unsigned int n_bytes,unsigned int min_bytes_valid,vbi_bool data_lost)6960 vesd_decode_block		(struct video_es_decoder *vd,
6961 				 unsigned int		start_code,
6962 				 const uint8_t *	buf,
6963 				 unsigned int		n_bytes,
6964 				 unsigned int		min_bytes_valid,
6965 				 vbi_bool		data_lost)
6966 {
6967 	if (unlikely (option_debug & DEBUG_VESD_START_CODE)) {
6968 		fprintf (stderr, "VES 0x000001%02X %u %u\n",
6969 			 start_code, min_bytes_valid, n_bytes);
6970 	}
6971 
6972 	/* The CEA 608-C and 708-C Close Caption data is encoded in
6973 	   picture user data fields. ISO 13818-2 requires the start
6974 	   code sequence 0x00, 0xB5/8, (0xB5?, 0xB2?)*. To properly
6975 	   convert from coded order to display order we also need the
6976 	   picture_coding_type and picture_structure fields. */
6977 
6978 	if (likely (start_code <= 0xAF)) {
6979 		if (!data_lost
6980 		    && (vd->received_blocks == (RECEIVED_PICTURE |
6981 						RECEIVED_PICTURE_EXT)
6982 			|| vd->received_blocks == (RECEIVED_PES_PACKET |
6983 						   RECEIVED_PICTURE |
6984 						   RECEIVED_PICTURE_EXT))) {
6985 			/* No user data received for this picture. */
6986 			vesd_user_data (vd, NULL, 0);
6987 		}
6988 
6989 		if (unlikely (0x00 == start_code) && !data_lost) {
6990 			vesd_picture_header (vd, buf, min_bytes_valid);
6991 		} else {
6992 			/* slice_start_code, or data lost in or after
6993 			   the picture_header. */
6994 
6995 			/* For all we care the picture data is just
6996 			   useless filler prior to the next PES packet
6997 			   header, and we need an uninterrupted
6998 			   sequence from there to the next picture
6999 			   user_data to ensure the PTS, DTS,
7000 			   picture_temporal_reference,
7001 			   picture_coding_type, picture_structure and
7002 			   cc_data belong together. */
7003 
7004 			vd->received_blocks = 0;
7005 			vd->pts = -1;
7006 			vd->dts = -1;
7007 		}
7008 	} else if (USER_DATA_START_CODE == start_code) {
7009 		vesd_user_data (vd, buf, min_bytes_valid);
7010 	} else if (data_lost) {
7011 		/* Data lost in or after this block. */
7012 		vd->received_blocks = 0;
7013 	} else if (EXTENSION_START_CODE == start_code) {
7014 		vesd_extension (vd, buf, min_bytes_valid);
7015 	} else if (start_code >= VIDEO_STREAM_0
7016 		   && start_code <= VIDEO_STREAM_15) {
7017 		if (!data_lost
7018 		    && (vd->received_blocks == (RECEIVED_PICTURE |
7019 						RECEIVED_PICTURE_EXT)
7020 			|| vd->received_blocks == (RECEIVED_PES_PACKET |
7021 						   RECEIVED_PICTURE |
7022 						   RECEIVED_PICTURE_EXT))) {
7023 			/* No user data received for previous picture. */
7024 			vesd_user_data (vd, NULL, 0);
7025 		}
7026 
7027 		/* Start of a new picture. */
7028 		vesd_pes_packet_header (vd, buf, min_bytes_valid);
7029 	} else {
7030 		/* Should be a sequence_header or
7031 		   group_of_pictures_header. */
7032 
7033 		vd->received_blocks &= RECEIVED_PES_PACKET;
7034 	}
7035 
7036 	/* Not all of this data is relevant for caption decoding but
7037 	   we may need it to debug the video ES decoder. Without the
7038 	   actual picture data it should be highly repetitive and
7039 	   compress rather well. */
7040 	if (unlikely (NULL != vd->video_es_tap_fp)) {
7041 		unsigned int n = n_bytes;
7042 
7043 		if (start_code >= 0x01 && start_code <= 0xAF) {
7044 			if (NULL == vd->option_video_es_all_tap_file_name)
7045 				n = MIN (n, 8u);
7046 		}
7047 		if (n != fwrite (buf, 1, n, vd->video_es_tap_fp)) {
7048 			errno_exit ("Video ES tap write error");
7049 		}
7050 	}
7051 }
7052 
7053 static unsigned int
vesd_make_room(struct video_es_decoder * vd,unsigned int required)7054 vesd_make_room			(struct video_es_decoder *vd,
7055 				 unsigned int		required)
7056 {
7057 	struct buffer *b;
7058 	unsigned int capacity;
7059 	unsigned int in;
7060 
7061 	b = &vd->buffer;
7062 	capacity = b->capacity;
7063 	in = b->in;
7064 
7065 	if (unlikely (in + required > capacity)) {
7066 		unsigned int consumed;
7067 		unsigned int unconsumed;
7068 
7069 		consumed = b->out;
7070 		unconsumed = in - consumed;
7071 		if (required > capacity - unconsumed) {
7072 			/* XXX make this a recoverable error. */
7073 			error_exit ("Video ES buffer overflow.\n");
7074 		}
7075 		memmove (b->base, b->base + consumed, unconsumed);
7076 		in = unconsumed;
7077 		b->out = 0;
7078 	}
7079 
7080 	return in;
7081 }
7082 
7083 static void
video_es_decoder(struct video_es_decoder * vd,const uint8_t * buf,unsigned int n_bytes,vbi_bool data_lost)7084 video_es_decoder		(struct video_es_decoder *vd,
7085 				 const uint8_t *	buf,
7086 				 unsigned int		n_bytes,
7087 				 vbi_bool		data_lost)
7088 {
7089 	const uint8_t *s;
7090 	const uint8_t *e;
7091 	const uint8_t *e_max;
7092 	unsigned int in;
7093 
7094 	/* This code searches for a start code and then decodes the
7095 	   data between the previous and the current start code. */
7096 
7097 	in = vesd_make_room (vd, n_bytes);
7098 
7099 	memcpy (vd->buffer.base + in, buf, n_bytes);
7100 	vd->buffer.in = in + n_bytes;
7101 
7102 	s = vd->buffer.base + vd->buffer.out + vd->skip;
7103 	e = vd->buffer.base + in + n_bytes - 4;
7104 	e_max = e;
7105 
7106 	if (unlikely (data_lost)) {
7107 		if (vd->min_bytes_valid >= UINT_MAX) {
7108 			vd->min_bytes_valid =
7109 				in - vd->buffer.out;
7110 		}
7111 
7112 		/* Data is missing after vd->buffer.base + in, so
7113 		   we must ignore apparent start codes crossing that
7114 		   boundary. */
7115 		e -= n_bytes;
7116 	}
7117 
7118 	for (;;) {
7119 		const uint8_t *b;
7120 		enum start_code start_code;
7121 		unsigned int n_bytes;
7122 		unsigned int min_bytes_valid;
7123 
7124 		for (;;) {
7125 			if (s >= e) {
7126 				/* Need more data. */
7127 
7128 				if (unlikely (s < e_max)) {
7129 					/* Skip over the lost data. */
7130 					s = e + 4;
7131 					e = e_max;
7132 					continue;
7133 				}
7134 
7135 				/* In the next iteration skip the
7136 				   bytes we already scanned. */
7137 				vd->skip = s - vd->buffer.base
7138 					- vd->buffer.out;
7139 
7140 				return;
7141 			}
7142 
7143 			if (likely (0 != (s[2] & ~1))) {
7144 				/* Not 000001 or xx0000 or xxxx00. */
7145 				s += 3;
7146 			} else if (0 != (s[0] | s[1]) || 1 != s[2]) {
7147 				++s;
7148 			} else {
7149 				break;
7150 			}
7151 		}
7152 
7153 		b = vd->buffer.base + vd->buffer.out;
7154 		n_bytes = s - b;
7155 		min_bytes_valid = n_bytes;
7156 		data_lost = FALSE;
7157 
7158 		if (unlikely (vd->min_bytes_valid < UINT_MAX)) {
7159 			if (n_bytes < vd->min_bytes_valid) {
7160 				/* We found a new start code before
7161 				   the missing data. */
7162 				vd->min_bytes_valid -= n_bytes;
7163 			} else {
7164 				min_bytes_valid = vd->min_bytes_valid;
7165 				vd->min_bytes_valid = UINT_MAX;
7166 
7167 				/* Need a flag in case we lost data just
7168 				   before the next start code. */
7169 				data_lost = TRUE;
7170 			}
7171 		}
7172 
7173 		start_code = vd->last_start_code;
7174 		if (likely ((int) start_code >= 0)) {
7175 			vesd_decode_block (vd, start_code, b,
7176 					   n_bytes, min_bytes_valid,
7177 					   data_lost);
7178 		}
7179 
7180 		/* Remove the data we just decoded from the
7181 		   buffer. Remember the position of the new start code
7182 		   we found, skip it and continue the search. */
7183 		vd->buffer.out = s - vd->buffer.base;
7184 		vd->last_start_code = (enum start_code) s[3];
7185 		s += 4;
7186 	}
7187 }
7188 
7189 static void
reset_video_es_decoder(struct video_es_decoder * vd)7190 reset_video_es_decoder		(struct video_es_decoder *vd)
7191 {
7192 	vd->buffer.in = 0;
7193 	vd->buffer.out = 0;
7194 
7195 	vd->min_bytes_valid = UINT_MAX;
7196 	vd->skip = 0;
7197 	vd->last_start_code = (enum start_code) -1;
7198 
7199 	vd->pts = -1;
7200 	vd->dts = -1;
7201 	vd->picture_coding_type = (enum picture_coding_type) -1;
7202 	vd->picture_structure = (enum picture_structure) -1;
7203 	vd->received_blocks = 0;
7204 	vd->reorder_pictures = 0;
7205 }
7206 
7207 static void
init_video_es_decoder(struct video_es_decoder * vd)7208 init_video_es_decoder		(struct video_es_decoder *vd)
7209 {
7210 	CLEAR (*vd);
7211 
7212 	init_buffer (&vd->buffer, /* capacity */ 1 << 20);
7213 	reset_video_es_decoder (vd);
7214 }
7215 
7216 static void
video_es_test_loop(struct program * pr,const char * test_file_name)7217 video_es_test_loop		(struct program *	pr,
7218 				 const char *		test_file_name)
7219 {
7220 	FILE *test_fp;
7221 
7222 	assert (NULL != ts_buffer);
7223 
7224 	test_fp = open_test_file (test_file_name);
7225 
7226 	for (;;) {
7227 		size_t todo;
7228 		size_t actual;
7229 
7230 		todo = 4096;
7231 		actual = fread (ts_buffer, 1, todo, test_fp);
7232 		if (likely (actual == todo)) {
7233 			video_es_decoder (&pr->vesd, ts_buffer,
7234 					  /* n_bytes */ actual,
7235 					  /* data_lost */ FALSE);
7236 		} else if (ferror (test_fp)) {
7237 			errno_exit ("Video ES read error");
7238 		} else {
7239 			log (1, "End of video ES file.\n");
7240 			fclose (test_fp);
7241 			return;
7242 		}
7243 	}
7244 }
7245 
7246 static void
dump_ts_packet_header(FILE * fp,const uint8_t buf[188])7247 dump_ts_packet_header		(FILE *			fp,
7248 				 const uint8_t		buf[188])
7249 {
7250 	unsigned int sync_byte;
7251 	unsigned int transport_error_indicator;
7252 	unsigned int payload_unit_start_indicator;
7253 	unsigned int transport_priority;
7254 	unsigned int PID;
7255 	unsigned int transport_scrambling_control;
7256 	unsigned int adaptation_field_control;
7257 	unsigned int continuity_counter;
7258 	unsigned int header_length;
7259 
7260 	sync_byte			= buf[0];
7261 	transport_error_indicator	= buf[1] & 0x80;
7262 	payload_unit_start_indicator	= buf[1] & 0x40;
7263 	transport_priority		= buf[1] & 0x20;
7264 	PID				= (buf[1] * 256 + buf[2]) & 0x1FFF;
7265 	transport_scrambling_control	= (buf[3] & 0xC0) >> 6;
7266 	adaptation_field_control	= (buf[3] & 0x30) >> 4;
7267 	continuity_counter		= buf[3] & 0x0F;
7268 
7269 	if (adaptation_field_control >= 2) {
7270 		unsigned int adaptation_field_length;
7271 
7272 		adaptation_field_length = buf[4];
7273 		header_length = 5 + adaptation_field_length;
7274 	} else {
7275 		header_length = 4;
7276 	}
7277 
7278 	fprintf (fp,
7279 		 "TS %02x %c%c%c %04x %u%u%x %u\n",
7280 		 sync_byte,
7281 		 transport_error_indicator ? 'E' : '-',
7282 		 payload_unit_start_indicator ? 'S' : '-',
7283 		 transport_priority ? 'P' : '-',
7284 		 PID,
7285 		 transport_scrambling_control,
7286 		 adaptation_field_control,
7287 		 continuity_counter,
7288 		 header_length);
7289 }
7290 
7291 static void
tsd_program(struct program * pr,const uint8_t buf[188],unsigned int pid,unsigned int es_num)7292 tsd_program			(struct program *	pr,
7293 				 const uint8_t		buf[188],
7294 				 unsigned int		pid,
7295 				 unsigned int		es_num)
7296 {
7297 	unsigned int adaptation_field_control;
7298 	unsigned int header_length;
7299 	unsigned int payload_length;
7300 	vbi_bool data_lost;
7301 
7302 	adaptation_field_control = (buf[3] & 0x30) >> 4;
7303 	if (likely (1 == adaptation_field_control)) {
7304 		header_length = 4;
7305 	} else if (3 == adaptation_field_control) {
7306 		unsigned int adaptation_field_length;
7307 
7308 		adaptation_field_length = buf[4];
7309 
7310 		/* Zero length is used for stuffing. */
7311 		if (adaptation_field_length > 0) {
7312 			unsigned int discontinuity_indicator;
7313 
7314 			/* ISO 13818-1 Section 2.4.3.5. Also the code
7315 			   below would be rather upset if
7316 			   header_length > packet_size. */
7317 			if (adaptation_field_length > 182) {
7318 				log (2, "Invalid TS header "
7319 				     "on station %u, stream %u.\n",
7320 				     station_num (pr), pid);
7321 				/* Possibly. */
7322 				pr->tsd.data_lost = TRUE;
7323 				return;
7324 			}
7325 
7326 			/* ISO 13818-1 Section 2.4.3.5 */
7327 			discontinuity_indicator = buf[5] & 0x80;
7328 			if (discontinuity_indicator)
7329 				pr->tsd.next_ts_cc[es_num] = -1;
7330 		}
7331 
7332 		header_length = 5 + adaptation_field_length;
7333 	} else {
7334 		/* 0 == adaptation_field_control: invalid;
7335 		   2 == adaptation_field_control: no payload. */
7336 		/* ISO 13818-1 Section 2.4.3.3:
7337 		   continuity_counter shall not increment. */
7338 		return;
7339 	}
7340 
7341 	payload_length = 188 - header_length;
7342 
7343 	data_lost = pr->tsd.data_lost;
7344 
7345 	if (unlikely (0 != ((pr->tsd.next_ts_cc[es_num]
7346 			     ^ buf[3]) & 0x0F))) {
7347 		/* Continuity counter mismatch. */
7348 
7349 		if (pr->tsd.next_ts_cc[es_num] < 0) {
7350 			/* First TS packet. */
7351 		} else if (0 == (((pr->tsd.next_ts_cc[es_num] - 1)
7352 				  ^ buf[3]) & 0x0F)) {
7353 			/* ISO 13818-1 Section 2.4.3.3: Repeated packet. */
7354 			return;
7355 		} else {
7356 			log (2, "TS continuity error "
7357 			     "on station %u, stream %u.\n",
7358 			     station_num (pr), pid);
7359 			data_lost = TRUE;
7360 		}
7361 	}
7362 
7363 	pr->tsd.next_ts_cc[es_num] = buf[3] + 1;
7364 	pr->tsd.data_lost = FALSE;
7365 
7366 	if (NULL != pr->option_minicut_dir_name)
7367 		video_recorder (&pr->vr, buf);
7368 
7369 	if (0 == es_num) {
7370 		video_es_decoder (&pr->vesd, buf + header_length,
7371 				  payload_length, data_lost);
7372 	}
7373 }
7374 
7375 static void
ts_decoder(const uint8_t buf[188])7376 ts_decoder			(const uint8_t		buf[188])
7377 {
7378 	unsigned int pid;
7379 	unsigned int i;
7380 
7381 	if (0) {
7382 		dump_ts_packet_header (stderr, buf);
7383 	}
7384 
7385 	if (unlikely (NULL != ts_tap_fp)) {
7386 		if (188 != fwrite (buf, 1, 188, ts_tap_fp)) {
7387 			errno_exit ("TS tap write error");
7388 		}
7389 	}
7390 
7391 	if (unlikely (buf[1] & 0x80)) {
7392 		log (2, "TS transmission error.\n");
7393 
7394 		/* The PID may be wrong, we don't know how much data
7395 		   was lost, and continuity counters match by chance
7396 		   with 1:16 probability. */
7397 		for (i = 0; i < n_programs; ++i) {
7398 			video_recorder (&program_table[i].vr, buf);
7399 			program_table[i].tsd.data_lost = TRUE;
7400 		}
7401 
7402 		return;
7403 	}
7404 
7405 	pid = (buf[1] * 256 + buf[2]) & 0x1FFF;
7406 
7407 	/* Note two or more programs may share one elementary stream
7408 	   (e.g. radio programs with a dummy video stream). */
7409 	for (i = 0; i < n_programs; ++i) {
7410 		struct program *pr;
7411 		unsigned int es_num;
7412 
7413 		pr = program_table + i;
7414 
7415 		es_num = 0;
7416 		if (pid == pr->tsd.pid[1]) {
7417 			es_num = 1;
7418 		} else if (pid != pr->tsd.pid[0]) {
7419 			continue;
7420 		}
7421 
7422 		tsd_program (pr, buf, pid, es_num);
7423 	}
7424 }
7425 
7426 static void
init_ts_decoder(struct ts_decoder * td)7427 init_ts_decoder			(struct ts_decoder *	td)
7428 {
7429 	CLEAR (*td);
7430 
7431 	memset (&td->next_ts_cc, -1, sizeof (td->next_ts_cc));
7432 }
7433 
7434 static void
ts_test_loop(const char * test_file_name)7435 ts_test_loop			(const char *		test_file_name)
7436 {
7437 	FILE *test_fp;
7438 
7439 	assert (NULL != ts_buffer);
7440 
7441 	test_fp = open_test_file (test_file_name);
7442 
7443 	for (;;) {
7444 		size_t todo;
7445 		size_t actual;
7446 
7447 		todo = 188;
7448 		actual = fread (ts_buffer, 1, todo, test_fp);
7449 		if (likely (actual == todo)) {
7450 			ts_decoder (ts_buffer);
7451 		} else if (ferror (test_fp)) {
7452 			errno_exit ("TS read error");
7453 		} else {
7454 			log (1, "End of TS file.\n");
7455 			fclose (test_fp);
7456 			return;
7457 		}
7458 	}
7459 }
7460 
7461 static void *
demux_thread(void * arg)7462 demux_thread			(void *			arg)
7463 {
7464 	unsigned int in;
7465 	unsigned int out;
7466 
7467 	arg = arg; /* unused */
7468 
7469 	assert (0 == ts_buffer_capacity % 188);
7470 
7471 	out = ts_buffer_out;
7472 
7473 	/* We don't actually need the mutex but pthread_cond_wait()
7474 	   won't work without it. */
7475 	pthread_mutex_lock (&dx_mutex);
7476 
7477 	for (;;) {
7478 		unsigned int avail;
7479 
7480 		in = ts_buffer_in;
7481 
7482 		avail = in - out;
7483 		if (in < out)
7484 			avail += ts_buffer_capacity;
7485 
7486 		if (avail <= 0) {
7487 			/* Yield the CPU if the buffer is empty. */
7488 			pthread_cond_wait (&dx_cond, &dx_mutex);
7489 			continue;
7490 		}
7491 
7492 		if (0) {
7493 			fputc (',', stderr);
7494 			fflush (stderr);
7495 		} else {
7496 			ts_decoder (ts_buffer + out);
7497 		}
7498 
7499 		out += 188;
7500 		if (out >= ts_buffer_capacity)
7501 			out = 0;
7502 
7503 		ts_buffer_out = out;
7504 	}
7505 
7506 	pthread_mutex_unlock (&dx_mutex);
7507 
7508 	return NULL;
7509 }
7510 
7511 static void
init_program(struct program * pr)7512 init_program			(struct program *	pr)
7513 {
7514 	CLEAR (*pr);
7515 
7516 	pr->first_dts = -1;
7517 
7518 	init_ts_decoder (&pr->tsd);
7519 	init_video_es_decoder (&pr->vesd);
7520 	init_video_recorder (&pr->vr);
7521 	init_caption_recorder (&pr->cr);
7522 }
7523 
7524 static void
destroy_demux_state(void)7525 destroy_demux_state		(void)
7526 {
7527 	free (ts_buffer);
7528 
7529 	ts_buffer = NULL;
7530 	ts_buffer_capacity = 0;
7531 
7532 	pthread_cond_destroy (&dx_cond);
7533 	pthread_mutex_destroy (&dx_mutex);
7534 }
7535 
7536 static void
init_demux_state(void)7537 init_demux_state		(void)
7538 {
7539 	pthread_mutex_init (&dx_mutex, /* attr */ NULL);
7540 	pthread_cond_init (&dx_cond, /* attr */ NULL);
7541 
7542 	/* This buffer prevents data loss if disk activity blocks
7543 	   a printf() in the caption decoder. Actually we need to
7544 	   buffer only CC data which trickles in at 9600 bits/s but I
7545 	   don't want to burden the capture thread with TS and PES
7546 	   demultiplexing and avoid the overhead of another thread. */
7547 	ts_buffer_capacity = 20000 * 188;
7548 	ts_buffer = xmalloc (ts_buffer_capacity);
7549 
7550 	/* Copy-on-write and lock the pages. */
7551 	memset (ts_buffer, -1, ts_buffer_capacity);
7552 
7553 	ts_error = 0x00;
7554 
7555 	ts_buffer_in = 0;
7556 	ts_buffer_out = 0;
7557 
7558 	ts_n_packets_in = 0;
7559 }
7560 
7561 /* Capture thread */
7562 
7563 static const char *
fe_type_name(enum fe_type t)7564 fe_type_name			(enum fe_type		t)
7565 {
7566 #undef CASE
7567 #define CASE(x) case FE_##x: return #x;
7568 
7569 	switch (t) {
7570 	CASE (QPSK)
7571 	CASE (QAM)
7572 	CASE (OFDM)
7573 	CASE (ATSC)
7574 	}
7575 
7576 	return "invalid";
7577 }
7578 
7579 static const char *
fe_spectral_inversion_name(enum fe_spectral_inversion t)7580 fe_spectral_inversion_name	(enum fe_spectral_inversion t)
7581 {
7582 #undef CASE
7583 #define CASE(x) case INVERSION_##x: return #x;
7584 
7585 	switch (t) {
7586 	CASE (OFF)
7587 	CASE (ON)
7588 	CASE (AUTO)
7589 	}
7590 
7591 	return "invalid";
7592 }
7593 
7594 static const char *
fe_code_rate_name(enum fe_code_rate t)7595 fe_code_rate_name		(enum fe_code_rate	t)
7596 {
7597 #undef CASE
7598 #define CASE(x) case FEC_##x: return #x;
7599 
7600 	switch (t) {
7601 	CASE (NONE)
7602 	CASE (1_2)
7603 	CASE (2_3)
7604 	CASE (3_4)
7605 	CASE (4_5)
7606 	CASE (5_6)
7607 	CASE (6_7)
7608 	CASE (7_8)
7609 	CASE (8_9)
7610 	CASE (AUTO)
7611 	}
7612 
7613 	return "invalid";
7614 }
7615 
7616 static const char *
fe_modulation_name(enum fe_modulation t)7617 fe_modulation_name		(enum fe_modulation	t)
7618 {
7619 #undef CASE
7620 #define CASE(x) case x: return #x;
7621 
7622 	switch (t) {
7623 	CASE (QPSK)
7624 	CASE (QAM_16)
7625 	CASE (QAM_32)
7626 	CASE (QAM_64)
7627 	CASE (QAM_128)
7628 	CASE (QAM_256)
7629 	CASE (QAM_AUTO)
7630 	CASE (VSB_8)
7631 	CASE (VSB_16)
7632 	}
7633 
7634 	return "invalid";
7635 }
7636 
7637 static const char *
fe_transmit_mode_name(enum fe_transmit_mode t)7638 fe_transmit_mode_name		(enum fe_transmit_mode t)
7639 {
7640 #undef CASE
7641 #define CASE(x) case TRANSMISSION_MODE_##x: return #x;
7642 
7643 	switch (t) {
7644 	CASE (2K)
7645 	CASE (8K)
7646 	CASE (AUTO)
7647 	}
7648 
7649 	return "invalid";
7650 }
7651 
7652 static const char *
fe_bandwidth_name(enum fe_bandwidth t)7653 fe_bandwidth_name		(enum fe_bandwidth	t)
7654 {
7655 #undef CASE
7656 #define CASE(x) case BANDWIDTH_##x: return #x;
7657 
7658 	switch (t) {
7659 	CASE (8_MHZ)
7660 	CASE (7_MHZ)
7661 	CASE (6_MHZ)
7662 	CASE (AUTO)
7663 	}
7664 
7665 	return "invalid";
7666 }
7667 
7668 static const char *
fe_guard_interval_name(enum fe_guard_interval t)7669 fe_guard_interval_name		(enum fe_guard_interval	t)
7670 {
7671 #undef CASE
7672 #define CASE(x) case GUARD_INTERVAL_##x: return #x;
7673 
7674 	switch (t) {
7675 	CASE (1_32)
7676 	CASE (1_16)
7677 	CASE (1_8)
7678 	CASE (1_4)
7679 	CASE (AUTO)
7680 	}
7681 
7682 	return "invalid";
7683 }
7684 
7685 static const char *
fe_hierarchy_name(enum fe_hierarchy t)7686 fe_hierarchy_name		(enum fe_hierarchy	t)
7687 {
7688 #undef CASE
7689 #define CASE(x) case HIERARCHY_##x: return #x;
7690 
7691 	switch (t) {
7692 	CASE (NONE)
7693 	CASE (1)
7694 	CASE (2)
7695 	CASE (4)
7696 	CASE (AUTO)
7697 	}
7698 
7699 	return "invalid";
7700 }
7701 
7702 #undef CASE
7703 
7704 static vbi_bool
same_transponder(struct station * s1,struct station * s2)7705 same_transponder		(struct station *	s1,
7706 				 struct station *	s2)
7707 {
7708 	if (s1->frequency != s2->frequency)
7709 		return FALSE;
7710 
7711 	if (s1->type != s2->type)
7712 		return FALSE;
7713 
7714 	switch (s1->type) {
7715 	case FE_ATSC:
7716 		if (s1->u.atsc.modulation != s1->u.atsc.modulation)
7717 			return FALSE;
7718 		break;
7719 
7720 	case FE_OFDM:
7721 		if (s1->u.dvb_t.inversion != s2->u.dvb_t.inversion ||
7722 		    s1->u.dvb_t.bandwidth != s2->u.dvb_t.bandwidth ||
7723 		    s1->u.dvb_t.code_rate_HP != s2->u.dvb_t.code_rate_HP ||
7724 		    s1->u.dvb_t.code_rate_LP != s2->u.dvb_t.code_rate_LP ||
7725 		    s1->u.dvb_t.constellation != s2->u.dvb_t.constellation ||
7726 		    s1->u.dvb_t.transm_mode != s2->u.dvb_t.transm_mode ||
7727 		    s1->u.dvb_t.guard_interval != s2->u.dvb_t.guard_interval ||
7728 		    s1->u.dvb_t.hierarchy != s2->u.dvb_t.hierarchy)
7729 			return FALSE;
7730 		break;
7731 
7732 	case FE_QPSK:
7733 	case FE_QAM:
7734 		assert (0);
7735 	}
7736 
7737 	return TRUE;
7738 }
7739 
7740 /* We use a FIFO because the caption decoder may block for
7741    extended periods due to disk activity, and buffering in
7742    the kernel driver is unreliable in my experience. */
7743 
7744 static void
ct_filter(const uint8_t buf[188])7745 ct_filter			(const uint8_t		buf[188])
7746 {
7747 	unsigned int in;
7748 	unsigned int out;
7749 	unsigned int free;
7750 
7751 	/* Supposedly all modern CPUs read and write ints
7752 	   atomically so we can avoid the mutex locking
7753 	   overhead. */
7754 	in = ts_buffer_in;
7755 	out = ts_buffer_out;
7756 
7757 	assert (in < ts_buffer_capacity);
7758 	assert (out < ts_buffer_capacity);
7759 
7760 	if (likely (0 == (buf[1] & 0x80))) {
7761 		unsigned int pid;
7762 
7763 		pid = (buf[1] * 256 + buf[2]) & 0x1FFF;
7764 
7765 		if (0) {
7766 			fprintf (stderr, "CT TS 0x%04x = %u\n", pid, pid);
7767 			return;
7768 		}
7769 
7770 		if (pid_map[pid].program < 0) {
7771 			if (NULL == option_ts_all_tap_file_name)
7772 				return;
7773 		}
7774 	}
7775 
7776 	free = out - in;
7777 	if (out <= in)
7778 		free += ts_buffer_capacity;
7779 
7780 	if (unlikely (free <= 188)) {
7781 		ts_error = 0x80;
7782 		return;
7783 	}
7784 
7785 	memcpy (ts_buffer + in, buf, 188);
7786 
7787 	ts_buffer[in + 1] |= ts_error;
7788 	ts_error = 0;
7789 
7790 	++ts_n_packets_in;
7791 
7792 	in += 188;
7793 	if (in >= ts_buffer_capacity)
7794     		in = 0;
7795 
7796 	ts_buffer_in = in;
7797 
7798 	/* Hm. This delays the output. */
7799 	if (1 || free < (ts_buffer_capacity / 2)) {
7800 		pthread_cond_signal (&dx_cond);
7801 	}
7802 }
7803 
7804 static unsigned int
ct_resync(const uint8_t buf[2* 188])7805 ct_resync			(const uint8_t		buf[2 * 188])
7806 {
7807 	unsigned int i;
7808 
7809 	for (i = 1; i < 188; ++i) {
7810 		if (0x47 == buf[i] && 0x47 == buf[i + 188])
7811 			return i;
7812 	}
7813 
7814 	log (1, "Capture thread cannot synchronize.\n");
7815 
7816 	capture_thread_id = 0;
7817 	pthread_exit (NULL);
7818 
7819 	return 0;
7820 }
7821 
7822 static vbi_bool
ct_read(uint8_t * buffer,ssize_t todo)7823 ct_read				(uint8_t *		buffer,
7824 				 ssize_t		todo)
7825 {
7826 	unsigned int retry = 100;
7827 
7828 	do {
7829 		ssize_t actual;
7830 
7831 		actual = read (dvr_fd, buffer, todo);
7832 		if (likely (actual == todo))
7833 			return TRUE;
7834 
7835 		if (actual > 0) {
7836 			if (unlikely (actual >= todo)) {
7837 				log (1, "DVB device read size "
7838 				     "error.\n");
7839 				return FALSE;
7840 			}
7841 
7842 			buffer += actual;
7843 			todo -= actual;
7844 
7845 			continue;
7846 		} else if (actual < 0) {
7847 			int saved_errno;
7848 
7849 			saved_errno = errno;
7850 
7851 			if (EINTR == saved_errno)
7852 				continue;
7853 
7854 			log_errno (1, "DVB device read error");
7855 
7856 			errno = saved_errno;
7857 
7858 			return FALSE;
7859 		} else {
7860 			log (2, "EOF from DVB device (ignored).\n");
7861 			return FALSE;
7862 		}
7863 	} while (--retry > 0);
7864 
7865 	log (2, "DVB device read error: EINTR or "
7866 	     "read size problem.\n");
7867 
7868 	errno = EINTR;
7869 
7870 	return FALSE;
7871 }
7872 
7873 static void *
capture_thread(void * arg)7874 capture_thread			(void *			arg)
7875 {
7876 	uint8_t *start;
7877 	uint8_t *end;
7878 	const uint8_t *s;
7879 	const uint8_t *e;
7880 	unsigned int left;
7881 	ssize_t size;
7882 
7883 	arg = arg; /* unused */
7884 
7885 	log (2, "Capture thread ready.\n");
7886 
7887 	/* Don't swap out any code or data pages. If the capture
7888 	   thread is delayed we may lose packets. Errors ignored. */
7889 	mlockall (MCL_CURRENT | MCL_FUTURE);
7890 
7891 	pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, /* old */ NULL);
7892 	pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, /* old */ NULL);
7893 
7894 	/* Page aligned reads are not required, but who knows, it
7895 	   may allow some DMA magic or speed up copying. */
7896 	start = ct_buffer + 4096;
7897 	size = ct_buffer_capacity - 4096;
7898 	left = 0;
7899 
7900 	assert (ct_buffer_capacity > 4096);
7901 	assert (0 == ct_buffer_capacity % 4096);
7902 
7903 	xioctl (dmx_fd, DMX_START, 0);
7904 
7905 	for (;;) {
7906 		if (!ct_read (start, size))
7907 			continue;
7908 
7909 		ct_n_bytes_in += size;
7910 
7911 		end = start + size;
7912 
7913 		s = start - left;
7914 		e = end - 4096;
7915 
7916 		while (s < e) {
7917 			if (0x47 != s[0] || 0x47 != s[188]) {
7918 				if (ts_n_packets_in > 0) {
7919 					log (2, "Capture thread "
7920 					     "lost sync.\n");
7921 				}
7922 
7923 				s += ct_resync (s);
7924 			}
7925 
7926 			if (0) {
7927 				fputc ('.', stderr);
7928 				fflush (stderr);
7929 			} else {
7930 				ct_filter (s);
7931 			}
7932 
7933 			s += 188;
7934 		}
7935 
7936 		left = end - s;
7937 		memcpy (start - left, s, left);
7938 	}
7939 
7940 	return NULL;
7941 }
7942 
7943 static void
destroy_capture_state(void)7944 destroy_capture_state		(void)
7945 {
7946 	/* FIXME this a glibc feature. */
7947 	free (ct_buffer);
7948 
7949 	ct_buffer = NULL;
7950 	ct_buffer_capacity = 0;
7951 }
7952 
7953 #ifdef HAVE_POSIX_MEMALIGN
7954 
7955 /* posix_memalign() was introduced in POSIX 1003.1d and may not be
7956    implemented on all systems. */
7957 static void *
my_memalign(size_t boundary,size_t size)7958 my_memalign			(size_t			boundary,
7959 				 size_t			size)
7960 {
7961 	void *p;
7962 	int err;
7963 
7964 	/* boundary must be a power of two. */
7965 	if (0 != (boundary & (boundary - 1)))
7966 		return malloc (size);
7967 
7968 	err = posix_memalign (&p, boundary, size);
7969 	if (0 == err)
7970 		return p;
7971 
7972 	errno = err;
7973 	return NULL;
7974 }
7975 
7976 #elif defined HAVE_MEMALIGN
7977 /* memalign() is a GNU extension. Due to the DVB driver interface
7978    this program currently runs on Linux only, but it can't hurt
7979    to be prepared. */
7980 #  define my_memalign memalign
7981 #else
7982 #  define my_memalign(boundary, size) malloc (size)
7983 #endif
7984 
7985 static void
init_capture_state(void)7986 init_capture_state		(void)
7987 {
7988 	ct_buffer_capacity = 32 * 1024;
7989 	ct_buffer = my_memalign (4096, ct_buffer_capacity);
7990 
7991 	if (NULL == ct_buffer) {
7992 		no_mem_exit ();
7993 	}
7994 
7995 	/* Copy-on-write and lock the pages. */
7996 	memset (ct_buffer, -1, ct_buffer_capacity);
7997 
7998 	ct_n_bytes_in = 0;
7999 }
8000 
8001 static int
xopen_device(const char * dev_name,int flags)8002 xopen_device			(const char *		dev_name,
8003 				 int			flags)
8004 {
8005 	struct stat st;
8006 	int fd;
8007 
8008 	if (-1 == stat (dev_name, &st)) {
8009 		goto open_failed;
8010 	}
8011 
8012 	if (!S_ISCHR (st.st_mode)) {
8013 		error_exit ("'%s' is not a DVB device.\n",
8014 			    dev_name);
8015 	}
8016 
8017 	fd = open (dev_name, flags, /* mode */ 0);
8018 	if (-1 == fd) {
8019 		goto open_failed;
8020 	}
8021 
8022 	return fd;
8023 
8024  open_failed:
8025 	errno_exit ("Cannot open '%s'", dev_name);
8026 
8027 	return -1; /* not reached */
8028 }
8029 
8030 static void
close_device(void)8031 close_device			(void)
8032 {
8033 	log (2, "Closing DVB device.\n");
8034 
8035 	if (0 != capture_thread_id) {
8036 		pthread_cancel (capture_thread_id);
8037 		pthread_join (capture_thread_id, NULL);
8038 
8039 		capture_thread_id = 0;
8040 	}
8041 
8042 	destroy_capture_state ();
8043 
8044 	if (-1 != dmx_fd) {
8045 		close (dmx_fd);
8046 		dmx_fd = -1;
8047 	}
8048 
8049 	if (-1 != dvr_fd) {
8050 		close (dvr_fd);
8051 		dvr_fd = -1;
8052 	}
8053 
8054 	if (-1 != fe_fd) {
8055 		close (fe_fd);
8056 		fe_fd = -1;
8057 	}
8058 }
8059 
8060 static void
open_device(void)8061 open_device			(void)
8062 {
8063 	struct dvb_frontend_info fe_info;
8064 	struct dvb_frontend_parameters fe_param;
8065 	struct dmx_pes_filter_params filter;
8066 	char *dev_name;
8067 	unsigned int retry;
8068 
8069 	dev_name = NULL;
8070 
8071 	init_capture_state ();
8072 
8073 	/* Front end. */
8074 
8075 	log (2, "Opening dvb/adapter%lu.\n",
8076 	     option_dvb_adapter_num);
8077 
8078 	dev_name = xasprintf ("/dev/dvb/adapter%lu/frontend%lu",
8079 			      option_dvb_adapter_num,
8080 			      option_dvb_frontend_id);
8081 
8082 	fe_fd = xopen_device (dev_name, O_RDWR);
8083 
8084 	CLEAR (fe_info);
8085 
8086 	xioctl (fe_fd, FE_GET_INFO, &fe_info);
8087 
8088 	switch (fe_info.type) {
8089 	case FE_ATSC:
8090 	case FE_OFDM:
8091 		if (fe_info.type != station->type) {
8092 			error_exit ("'%s' is not %s device.\n",
8093 				    dev_name,
8094 				    (FE_ATSC == station->type) ?
8095 				    "an ATSC" : "a DVB-T");
8096 		}
8097 		break;
8098 
8099 	case FE_QPSK:
8100 	case FE_QAM:
8101 		error_exit ("'%s' is not an ATSC device.\n",
8102 			    dev_name);
8103 		break;
8104 	}
8105 
8106 	CLEAR (fe_param);
8107 
8108 	fe_param.frequency = station->frequency;
8109 
8110 	switch (fe_info.type) {
8111 	case FE_ATSC:
8112 		fe_param.u.vsb.modulation =
8113 			station->u.atsc.modulation;
8114 		break;
8115 
8116 	case FE_OFDM:
8117 		fe_param.inversion =
8118 			station->u.dvb_t.inversion;
8119 		fe_param.u.ofdm.bandwidth =
8120 			station->u.dvb_t.bandwidth;
8121 		fe_param.u.ofdm.code_rate_HP =
8122 			station->u.dvb_t.code_rate_HP;
8123 		fe_param.u.ofdm.code_rate_LP =
8124 			station->u.dvb_t.code_rate_LP;
8125 		fe_param.u.ofdm.constellation =
8126 			station->u.dvb_t.constellation;
8127 		fe_param.u.ofdm.transmission_mode =
8128 			station->u.dvb_t.transm_mode;
8129 		fe_param.u.ofdm.guard_interval =
8130 			station->u.dvb_t.guard_interval;
8131 		fe_param.u.ofdm.hierarchy_information =
8132 			station->u.dvb_t.hierarchy;
8133 		break;
8134 
8135 	case FE_QPSK:
8136 	case FE_QAM:
8137 		assert (0);
8138 	}
8139 
8140 	xioctl (fe_fd, FE_SET_FRONTEND, &fe_param);
8141 
8142 	for (retry = 0;;) {
8143 		fe_status_t status;
8144 
8145 		xioctl (fe_fd, FE_READ_STATUS, &status);
8146 
8147 		if (status & FE_HAS_LOCK)
8148 			break;
8149 
8150 		if (++retry > 20) {
8151 			error_exit ("No signal detected.\n");
8152 		}
8153 
8154 		if (7 == (retry & 7)) {
8155 			log (2, "Waiting for a signal.\n");
8156 		}
8157 
8158 		usleep (250000);
8159 	}
8160 
8161 	log (2, "Signal detected.\n");
8162 
8163 	free (dev_name);
8164 
8165 	/* DVR. */
8166 
8167 	dev_name = xasprintf ("/dev/dvb/adapter%lu/dvr%lu",
8168 			      option_dvb_adapter_num,
8169 			      option_dvb_dvr_id);
8170 
8171 	dvr_fd = xopen_device (dev_name, O_RDONLY);
8172 
8173 	/* Not implemented? Let's try anyway. */
8174 	xioctl_may_fail (dvr_fd, DMX_SET_BUFFER_SIZE, (void *)(4 << 20));
8175 
8176 	free (dev_name);
8177 
8178 	/* Demultiplexer. */
8179 
8180 	dev_name = xasprintf ("/dev/dvb/adapter%lu/demux%lu",
8181 			      option_dvb_adapter_num,
8182 			      option_dvb_demux_id);
8183 
8184 	dmx_fd = xopen_device (dev_name, O_RDWR);
8185 
8186 	xioctl_may_fail (dmx_fd, DMX_SET_BUFFER_SIZE, (void *)(4 << 20));
8187 
8188 	CLEAR (filter);
8189 
8190 	/* We capture the entire transport multiplex so we can receive
8191 	   all stations on this transponder at once and properly handle
8192 	   transmission errors in the video ES demultiplexer. */
8193 	filter.pid = 0x2000;
8194 	filter.input = DMX_IN_FRONTEND;
8195 	filter.output = DMX_OUT_TS_TAP;
8196 	filter.pes_type = DMX_PES_OTHER;
8197 
8198 	xioctl (dmx_fd, DMX_SET_PES_FILTER, &filter);
8199 
8200 	free (dev_name);
8201 
8202 	/* Start capture thread. */
8203 
8204 	if (0 != pthread_create (&capture_thread_id,
8205 				 /* attr */ NULL,
8206 				 capture_thread,
8207 				 /* arg */ NULL)) {
8208 		errno_exit ("Cannot start capture thread");
8209 	}
8210 
8211 	log (2, "Opened dvb/adapter%lu, tuned to %.3f MHz and "
8212 	     "started capture thread.\n",
8213 	     option_dvb_adapter_num,
8214 	     station->frequency / 1e6);
8215 }
8216 
8217 static enum fe_type
device_type(void)8218 device_type			(void)
8219 {
8220 	struct dvb_frontend_info fe_info;
8221 	char *dev_name;
8222 	int fd;
8223 
8224 	dev_name = xasprintf ("/dev/dvb/adapter%lu/frontend%lu",
8225 			      option_dvb_adapter_num,
8226 			      option_dvb_frontend_id);
8227 
8228 	fd = xopen_device (dev_name, O_RDWR);
8229 
8230 	CLEAR (fe_info);
8231 
8232 	xioctl (fd, FE_GET_INFO, &fe_info);
8233 
8234 	close (fd);
8235 
8236 	switch (fe_info.type) {
8237 	case FE_ATSC:
8238 	case FE_OFDM:
8239 		break;
8240 
8241 	case FE_QPSK:
8242 	case FE_QAM:
8243 		error_exit ("'%s' is not an ATSC device.\n",
8244 			    dev_name);
8245 		break;
8246 	}
8247 
8248 	free (dev_name);
8249 
8250 	return fe_info.type;
8251 }
8252 
8253 
8254 static void
list_stations(void)8255 list_stations			(void)
8256 {
8257 	const struct station *st;
8258 	size_t max_len;
8259 
8260 	if (NULL == station_list) {
8261 		printf ("The channel config file is empty.\n");
8262 		return;
8263 	}
8264 
8265 	/* FIXME the encoding of station names is unknown,
8266 	   could be a multi-byte coding like UTF-8. */
8267 	max_len = 0;
8268 	for (st = station_list; NULL != st; st = st->next) {
8269 		size_t len;
8270 
8271 		len = strlen (st->name);
8272 		max_len = MAX (max_len, len);
8273 	}
8274 
8275 	for (st = station_list; NULL != st; st = st->next) {
8276 		printf ("%-*s  %3.3f MHz\n",
8277 			(int) max_len,
8278 			st->name,
8279 			st->frequency / 1e6);
8280 	}
8281 }
8282 
8283 static struct station *
find_station(const char * station_name)8284 find_station			(const char *		station_name)
8285 {
8286 	struct station *st;
8287 
8288 	for (st = station_list; NULL != st; st = st->next) {
8289 		if (0 == strcmp (station_name, st->name))
8290 			return st;
8291 	}
8292 
8293 	return NULL;
8294 }
8295 
8296 static char *
parse_station_name(const char ** sp,int delimiter)8297 parse_station_name		(const char **		sp,
8298 				 int			delimiter)
8299 {
8300 	const char *s;
8301 	const char *s_name;
8302 	char *station_name;
8303 	size_t len;
8304 
8305 	s = *sp;
8306 	while (isspace (*s))
8307 		++s;
8308 	s_name = s;
8309 	while (0 != *s && delimiter != *s)
8310 		++s;
8311 	*sp = s;
8312 	while (s > s_name && isspace (s[-1]))
8313 		--s;
8314 	len = s - s_name;
8315 	if (0 == len)
8316 		return NULL;
8317 
8318 	station_name = xmalloc (len + 1);
8319 
8320 	memcpy (station_name, s_name, len);
8321 	station_name[len] = 0;
8322 
8323 	return station_name;
8324 }
8325 
8326 struct key_value {
8327 	const char *		key;
8328 	int			value;
8329 };
8330 
8331 static vbi_bool
parse_enum(int * value,const char ** sp,const struct key_value * table)8332 parse_enum			(int *			value,
8333 				 const char **		sp,
8334 				 const struct key_value *table)
8335 {
8336 	const char *s;
8337 	unsigned int i;
8338 
8339 	s = *sp;
8340 
8341 	while (isspace (*s))
8342 		++s;
8343 
8344 	for (i = 0; NULL != table[i].key; ++i) {
8345 		size_t len = strlen (table[i].key);
8346 
8347 		if (0 == strncmp (s, table[i].key, len)) {
8348 			s += len;
8349 			break;
8350 		}
8351 	}
8352 
8353 	if (NULL == table[i].key)
8354 		return FALSE;
8355 
8356 	while (isspace (*s))
8357 		++s;
8358 
8359 	if (':' != *s++)
8360 		return FALSE;
8361 
8362 	*value = table[i].value;
8363 	*sp = s;
8364 
8365 	return TRUE;
8366 }
8367 
8368 static void
parse_tzap_channel_conf_line(const char * filename,unsigned int line_number,const char * buffer)8369 parse_tzap_channel_conf_line	(const char *		filename,
8370 				 unsigned int		line_number,
8371 				 const char *		buffer)
8372 {
8373 	static const struct key_value inversion [] = {
8374 		{ "INVERSION_OFF",	INVERSION_OFF },
8375 		{ "INVERSION_ON",	INVERSION_ON },
8376 		{ "INVERSION_AUTO",	INVERSION_AUTO },
8377 		{ NULL,			0 }
8378 	};
8379 	static const struct key_value bandwidth [] = {
8380 		{ "BANDWIDTH_6_MHZ",	BANDWIDTH_6_MHZ },
8381 		{ "BANDWIDTH_7_MHZ",	BANDWIDTH_7_MHZ },
8382 		{ "BANDWIDTH_8_MHZ",	BANDWIDTH_8_MHZ },
8383 		{ NULL,			0 }
8384 	};
8385 	static const struct key_value fec [] = {
8386 		{ "FEC_1_2",		FEC_1_2 },
8387 		{ "FEC_2_3",		FEC_2_3 },
8388 		{ "FEC_3_4",		FEC_3_4 },
8389 		{ "FEC_4_5",		FEC_4_5 },
8390 		{ "FEC_5_6",		FEC_5_6 },
8391 		{ "FEC_6_7",		FEC_6_7 },
8392 		{ "FEC_7_8",		FEC_7_8 },
8393 		{ "FEC_8_9",		FEC_8_9 },
8394 		{ "FEC_AUTO",		FEC_AUTO },
8395 		{ "FEC_NONE",		FEC_NONE },
8396 		{ NULL,			0 }
8397 	};
8398 	static const struct key_value constellation [] = {
8399 		{ "QPSK",		QPSK },
8400 		{ "QAM_16",		QAM_16 },
8401 		{ "QAM_32",		QAM_32 },
8402 		{ "QAM_64",		QAM_64 },
8403 		{ "QAM_128",		QAM_128 },
8404 		{ "QAM_256",		QAM_256 },
8405 		{ NULL,			0 }
8406 	};
8407 	static const struct key_value transmission_mode [] = {
8408 		{ "TRANSMISSION_MODE_2K", TRANSMISSION_MODE_2K },
8409 		{ "TRANSMISSION_MODE_8K", TRANSMISSION_MODE_8K },
8410 		{ NULL,			  0 }
8411 	};
8412 	static const struct key_value guard_interval [] = {
8413 		{"GUARD_INTERVAL_1_16",	GUARD_INTERVAL_1_16},
8414 		{"GUARD_INTERVAL_1_32",	GUARD_INTERVAL_1_32},
8415 		{"GUARD_INTERVAL_1_4",	GUARD_INTERVAL_1_4},
8416 		{"GUARD_INTERVAL_1_8",	GUARD_INTERVAL_1_8},
8417 		{ NULL,			0 }
8418 	};
8419 	static const struct key_value hierarchy [] = {
8420 		{ "HIERARCHY_1",	HIERARCHY_1 },
8421 		{ "HIERARCHY_2",	HIERARCHY_2 },
8422 		{ "HIERARCHY_4",	HIERARCHY_4 },
8423 		{ "HIERARCHY_NONE",	HIERARCHY_NONE },
8424 		{ NULL,			0 }
8425 	};
8426 	struct station *st;
8427 	struct station **stp;
8428 	const struct station *st2;
8429 	const char *detail;
8430 	const char *s;
8431 	char *s_end;
8432 	int value;
8433 
8434 	/* TZAP channel config file format:
8435 
8436 	   A number of lines with the fields:
8437 	   1. Station name (encoding?)
8438 	   2. Transponder frequency in Hz
8439 	   3. Inversion: INVERSION_(ON|OFF|AUTO)
8440 	   4. Bandwidth: BANDWIDTH_(6|7|8)_MHZ
8441 	   5. Code rate HP: FEC_(1_2|2_3|3_4|4_5|5_6|6_7|7_8|8_9|AUTO|NONE)
8442 	   6. Code rate LP: as above
8443 	   7. Constellation: QPSK, QAM_(16|32|64|128|256)
8444 	   8. Transmission mode: TRANSMISSION_MODE_(2K|8K)
8445 	   9. Guard interval: GUARD_INTERVAL_1_(4|8|16|32)
8446 	   10. Hierarchy information: HIERARCHY_(1|2|4|NONE)
8447 	   11. Video stream PID
8448 	   12. Audio stream PID
8449 	   13. ?
8450 
8451 	   The fields are separated by one colon. We skip whitespace
8452 	   at the beginning of a line, whitespace before and after
8453 	   colons, empty lines, and lines starting with a number
8454 	   sign. */
8455 
8456 	st = xmalloc (sizeof (*st));
8457 
8458 	CLEAR (*st);
8459 
8460 	s = buffer;
8461 
8462 	while (isspace (*s))
8463 		++s;
8464 	if (0 == *s || '#' == *s)
8465 		return;
8466 
8467 	detail = "station name";
8468 	st->name = parse_station_name (&s, /* delimiter */ ':');
8469 	if (NULL == st->name)
8470 		goto invalid;
8471 	if (':' != *s++)
8472 		goto invalid;
8473 
8474 	st2 = find_station (st->name);
8475 	if (NULL != st2) {
8476 		error_exit ("Duplicate station name '%s' "
8477 			    "in %s line %u.\n",
8478 			    st->name, filename, line_number);
8479 	}
8480 
8481 	st->type = FE_OFDM;
8482 
8483 	detail = "frequency";
8484 	/* NB. strtoul() skips leading whitespace. */
8485 	st->frequency = strtoul (s, &s_end, 0);
8486 	if (s_end == s || st->frequency < 1)
8487 		goto invalid;
8488 	s = s_end;
8489 	while (isspace (*s))
8490 		++s;
8491 	if (':' != *s++)
8492 		goto invalid;
8493 
8494 	detail = "inversion";
8495 	if (!parse_enum (&value, &s, inversion))
8496 		goto invalid;
8497 	st->u.dvb_t.inversion = value;
8498 
8499 	detail = "bandwidth";
8500 	if (!parse_enum (&value, &s, bandwidth))
8501 		goto invalid;
8502 	st->u.dvb_t.bandwidth = value;
8503 
8504 	detail = "code rate HP";
8505 	if (!parse_enum (&value, &s, fec))
8506 		goto invalid;
8507 	st->u.dvb_t.code_rate_HP = value;
8508 
8509 	detail = "code rate LP";
8510 	if (!parse_enum (&value, &s, fec))
8511 		goto invalid;
8512 	st->u.dvb_t.code_rate_LP = value;
8513 
8514 	detail = "constellation";
8515 	if (!parse_enum (&value, &s, constellation))
8516 		goto invalid;
8517 	st->u.dvb_t.constellation = value;
8518 
8519 	detail = "transmission_mode";
8520 	if (!parse_enum (&value, &s, transmission_mode))
8521 		goto invalid;
8522 	st->u.dvb_t.transm_mode = value;
8523 
8524 	detail = "guard_interval";
8525 	if (!parse_enum (&value, &s, guard_interval))
8526 		goto invalid;
8527 	st->u.dvb_t.guard_interval = value;
8528 
8529 	detail = "hierarchy";
8530 	if (!parse_enum (&value, &s, hierarchy))
8531 		goto invalid;
8532 	st->u.dvb_t.hierarchy = value;
8533 
8534 	detail = "video PID";
8535 	st->video_pid = strtoul (s, &s_end, 0);
8536 	if (s_end == s || (unsigned int) st->video_pid > 0x1FFE)
8537 		goto invalid;
8538 	s = s_end;
8539 	while (isspace (*s))
8540 		++s;
8541 	if (':' != *s++)
8542 		goto invalid;
8543 
8544 	detail = "audio PID";
8545 	st->audio_pid = strtoul (s, &s_end, 0);
8546 	if (s_end == s || (unsigned int) st->audio_pid > 0x1FFE)
8547 		goto invalid;
8548 	s = s_end;
8549 	while (isspace (*s))
8550 		++s;
8551 	if (':' != *s++)
8552 		goto invalid;
8553 	if (0 == st->video_pid) {
8554 		if (option_debug & DEBUG_CONFIG) {
8555 			fprintf (stderr, "Skipping radio station '%s'.\n",
8556 				 st->name);
8557 		}
8558 		free (st->name);
8559 		free (st);
8560 		return;
8561 	}
8562 
8563 	if (option_debug & DEBUG_CONFIG) {
8564 		fprintf (stderr, "%3u: station_name='%s' frequency=%lu "
8565 			 "inversion=%s bandwidth=%s code_rate=%s/%s "
8566 			 "constellation=%s transm_mode=%s "
8567 			 "guard_interval=%s hierarchy=%s "
8568 			 "video_pid=%u audio_pid=%u.\n",
8569 			 line_number,
8570 			 st->name,
8571 			 st->frequency,
8572 			 fe_spectral_inversion_name (st->u.dvb_t.inversion),
8573 			 fe_bandwidth_name (st->u.dvb_t.bandwidth),
8574 			 fe_code_rate_name (st->u.dvb_t.code_rate_HP),
8575 			 fe_code_rate_name (st->u.dvb_t.code_rate_LP),
8576 			 fe_modulation_name (st->u.dvb_t.constellation),
8577 			 fe_transmit_mode_name (st->u.dvb_t.transm_mode),
8578 			 fe_guard_interval_name (st->u.dvb_t.guard_interval),
8579 			 fe_hierarchy_name (st->u.dvb_t.hierarchy),
8580 			 st->video_pid,
8581 			 st->audio_pid);
8582 	}
8583 
8584 	/* Append to station list. */
8585 	for (stp = &station_list; NULL != *stp; stp = &(*stp)->next)
8586 		;
8587 	*stp = st;
8588 
8589 	return;
8590 
8591  invalid:
8592 	error_exit ("Invalid %s field in '%s' line %u.\n",
8593 		    detail, filename, line_number);
8594 }
8595 
8596 static void
parse_azap_channel_conf_line(const char * filename,unsigned int line_number,const char * buffer)8597 parse_azap_channel_conf_line	(const char *		filename,
8598 				 unsigned int		line_number,
8599 				 const char *		buffer)
8600 {
8601 	static const struct key_value modulations [] = {
8602 		{ "8VSB",	VSB_8 },
8603 		{ "16VSB",	VSB_16 },
8604 		{ "QAM_64",	QAM_64 },
8605 		{ "QAM_256",	QAM_256 },
8606 		{ NULL,		0 }
8607 	};
8608 	struct station *st;
8609 	struct station **stp;
8610 	const struct station *st2;
8611 	const char *detail;
8612 	const char *s;
8613 	char *s_end;
8614 	int value;
8615 
8616 	/* AZAP channel config file format:
8617 
8618 	   A number of lines with the fields:
8619 	   1. Station name (encoding?)
8620 	   2. Transponder frequency in Hz
8621 	   3. Modulation: 8VSB, 16VSB, QAM_64, QAM_256
8622 	   4. Video stream PID
8623 	   5. Audio stream PID (one or more?)
8624 	   6. Stream ID?
8625 
8626 	   The fields are separated by one colon. We skip whitespace
8627 	   at the beginning of a line, whitespace before and after
8628 	   colons, empty lines, and lines starting with a number
8629 	   sign. */
8630 
8631 	st = xmalloc (sizeof (*st));
8632 
8633 	CLEAR (*st);
8634 
8635 	s = buffer;
8636 
8637 	while (isspace (*s))
8638 		++s;
8639 	if (0 == *s || '#' == *s)
8640 		return;
8641 
8642 	detail = "station name";
8643 	st->name = parse_station_name (&s, /* delimiter */ ':');
8644 	if (NULL == st->name)
8645 		goto invalid;
8646 	if (':' != *s++)
8647 		goto invalid;
8648 
8649 	st2 = find_station (st->name);
8650 	if (NULL != st2) {
8651 		error_exit ("Duplicate station name '%s' "
8652 			    "in %s line %u.\n",
8653 			    st->name, filename, line_number);
8654 	}
8655 
8656 	st->type = FE_ATSC;
8657 
8658 	detail = "frequency";
8659 	/* NB. strtoul() skips leading whitespace. */
8660 	st->frequency = strtoul (s, &s_end, 0);
8661 	if (s_end == s || st->frequency < 1)
8662 		goto invalid;
8663 	s = s_end;
8664 	while (isspace (*s))
8665 		++s;
8666 	if (':' != *s++)
8667 		goto invalid;
8668 
8669 	detail = "modulation";
8670 	if (!parse_enum (&value, &s, modulations))
8671 		goto invalid;
8672 	st->u.atsc.modulation = value;
8673 
8674 	detail = "video PID";
8675 	st->video_pid = strtoul (s, &s_end, 0);
8676 	if (s_end == s || (unsigned int) st->video_pid > 0x1FFE)
8677 		goto invalid;
8678 	s = s_end;
8679 	while (isspace (*s))
8680 		++s;
8681 	if (':' != *s++)
8682 		goto invalid;
8683 
8684 	detail = "audio PID";
8685 	st->audio_pid = strtoul (s, &s_end, 0);
8686 	if (s_end == s || (unsigned int) st->audio_pid > 0x1FFE)
8687 		goto invalid;
8688 	s = s_end;
8689 	while (isspace (*s))
8690 		++s;
8691 	if (':' != *s++)
8692 		goto invalid;
8693 	if (0 == st->video_pid) {
8694 		if (option_debug & DEBUG_CONFIG) {
8695 			fprintf (stderr, "Skipping radio station '%s'.\n",
8696 				 st->name);
8697 		}
8698 		free (st->name);
8699 		free (st);
8700 		return;
8701 	}
8702 
8703 	if (option_debug & DEBUG_CONFIG) {
8704 		fprintf (stderr, "%3u: station_name='%s' frequency=%lu "
8705 			 "modulation=%s video_pid=%u audio_pid=%u.\n",
8706 			 line_number,
8707 			 st->name,
8708 			 st->frequency,
8709 			 fe_modulation_name (st->u.atsc.modulation),
8710 			 st->video_pid,
8711 			 st->audio_pid);
8712 	}
8713 
8714 	/* Append to station list. */
8715 	for (stp = &station_list; NULL != *stp; stp = &(*stp)->next)
8716 		;
8717 	*stp = st;
8718 
8719 	return;
8720 
8721  invalid:
8722 	error_exit ("Invalid %s field in '%s' line %u.\n",
8723 		    detail, filename, line_number);
8724 }
8725 
8726 static char *
get_channel_conf_name(enum fe_type type)8727 get_channel_conf_name		(enum fe_type		type)
8728 {
8729 	const char *home;
8730 	const char *s;
8731 
8732  	s = option_channel_conf_file_name;
8733 
8734 	if (NULL == s) {
8735 		switch (type) {
8736 		case FE_ATSC:
8737 			s = "~/.azap/channels.conf";
8738 			break;
8739 
8740 		case FE_OFDM:
8741 			s = "~/.tzap/channels.conf";
8742 			break;
8743 
8744 		case FE_QPSK:
8745 		case FE_QAM:
8746 			assert (0);
8747 			break;
8748 		}
8749 	}
8750 
8751 	if (0 == strncmp (s, "~/", 2)) {
8752 		home = getenv ("HOME");
8753 		if (NULL == home) {
8754 			error_exit ("Cannot open '%s' because the "
8755 				    "HOME environment variable "
8756 				    "is unset.\n",
8757 				    s);
8758 		}
8759 
8760 		++s;
8761 	} else {
8762 		home = "";
8763 	}
8764 
8765 	return xasprintf ("%s%s", home, s);
8766 }
8767 
8768 static void
read_channel_conf(void)8769 read_channel_conf		(void)
8770 {
8771 	char buffer[256];
8772 	char *channel_conf_name;
8773 	enum fe_type type;
8774 	unsigned int line_number;
8775 	FILE *fp;
8776 
8777 	if (NULL != station_list)
8778 		return;
8779 
8780 	type = option_dvb_type;
8781 	if ((enum fe_type) -1 == option_dvb_type)
8782 		type = device_type ();
8783 
8784 	channel_conf_name = get_channel_conf_name (type);
8785 
8786 	fp = fopen (channel_conf_name, "r");
8787 	if (NULL == fp) {
8788 		errno_exit ("Cannot open '%s'",
8789 			    channel_conf_name);
8790 	}
8791 
8792 	if (option_debug & DEBUG_CONFIG) {
8793 		fprintf (stderr, "Opened '%s' (%s):\n",
8794 			 channel_conf_name,
8795 			 fe_type_name (type));
8796 	}
8797 
8798 	line_number = 1;
8799 
8800 	while (NULL != fgets (buffer, sizeof (buffer), fp)) {
8801 		const char *s;
8802 
8803 		s = buffer;
8804 		while (isspace (*s))
8805 			++s;
8806 		if (0 == *s || '#' == *s)
8807 			continue;
8808 
8809 		switch (type) {
8810 		case FE_ATSC:
8811 			parse_azap_channel_conf_line (channel_conf_name,
8812 						      line_number,
8813 						      buffer);
8814 			break;
8815 
8816 		case FE_OFDM:
8817 			parse_tzap_channel_conf_line (channel_conf_name,
8818 						      line_number,
8819 						      buffer);
8820 			break;
8821 
8822 		case FE_QPSK:
8823 		case FE_QAM:
8824 			assert (0);
8825 		}
8826 
8827 		++line_number;
8828 	}
8829 
8830 	if (ferror (fp) || 0 != fclose (fp)) {
8831 		errno_exit ("Error while reading '%s'",
8832 			    channel_conf_name);
8833 	}
8834 
8835 	free (channel_conf_name);
8836 }
8837 
8838 static void
usage(FILE * fp)8839 usage				(FILE *			fp)
8840 {
8841 	fprintf (fp, "\
8842 " PROGRAM " " VERSION " -- ATSC Closed Caption and XDS decoder\n\
8843 Copyright (C) 2008 Michael H. Schimek <mschimek@users.sf.net>\n\
8844 Based on code by Mike Baker, Mark K. Kim and timecop@japan.co.jp.\n\
8845 This program is licensed under GPL 2 or later. NO WARRANTIES.\n\n\
8846 Usage: %s [options] [-n] station name\n\
8847 Options:\n\
8848 -? | -h | --help | --usage     Print this message, then terminate\n\
8849 -1 ... -4 | --cc1-file ... --cc4-file file name\n\
8850                                Append CC1 ... CC4 to this file\n\
8851 -5 ... -8 | --t1-file ... --t4-file file name\n\
8852                                Append T1 ... T4 to this file\n\
8853 -9 ... -0 | --s1-file ... --s2-file file name\n\
8854                                Append DTVCC service 1 ... 2 to this file\n\
8855 -a | --adapter-num number      DVB device adapter [%lu]\n\
8856 -b | --no-webtv                Do not print WebTV links\n\
8857 -c | --cc                      Print Closed Caption (includes WebTV)\n\
8858 -d | --demux-id number         DVB device demultiplexer [%lu]\n\
8859 -e | --channel-conf file name  Channel config. file [~/.azap/channels.conf]\n\
8860 -f | --filter type[,type]*     Select XDS info: all, call, desc, length,\n\
8861                                network, rating, time, timecode, timezone,\n\
8862                                title. Multiple -f options accumulate. [all]\n\
8863 -i | --frontend-id number      DVB device frontend [%lu]\n\
8864 -j | --format type             Print caption in 'plain' encoding, with\n\
8865                                'vt100' control codes or like the 'ntsc-cc'\n\
8866                                tool [ntsc-cc].\n\
8867 -l | --channel number          Select caption channel 1 ... 4 [nothing]\n\
8868 -m | --timestamps              Prepend timestamps to caption lines\n\
8869 -n | --station name            Station name. Usually the -n can be omitted\n\
8870 -q | --quiet		       Suppress all progress and error messages\n\
8871 -p | --plain                   Same as -j plain.\n\
8872 -r | --dvr-id number           DVB device dvr [%lu]\n\
8873 -s | --sentences               Decode caption by sentences\n\
8874 -v | --verbose                 Increase verbosity\n\
8875 -x | --xds                     Print XDS info\n\
8876 -C | --cc-file file name       Append all caption to this file [stdout]\n\
8877 -L | --list                    List all TV stations in the channel\n\
8878                                configuration file\n\
8879 -T | --ts                      Decode a DVB Transport Stream on stdin\n\
8880                                instead of opening a DVB device\n\
8881 -X | --xds-file file name      Append XDS info to this file [stdout]\n\
8882 \n\
8883 To record data from multiple stations sharing a transponder frequency\n\
8884 you can specify caption options and a station name repeatedly.\n\
8885 ",
8886 		 my_name,
8887 		 option_dvb_adapter_num,
8888 		 option_dvb_demux_id,
8889 		 option_dvb_frontend_id,
8890 		 option_dvb_dvr_id);
8891 }
8892 
8893 static const char
8894 short_options [] = ("-?1:2:3:4:5:6:7:8:9:0:"
8895 		    "a:bcd:e:f:hi:j:l:mn:pr:svx"
8896 		    "C:DELM:PTX:");
8897 
8898 #ifdef HAVE_GETOPT_LONG
8899 static const struct option
8900 long_options [] = {
8901 	{ "help",		no_argument,		NULL,	'?' },
8902 	/* From ntsc-cc.c. */
8903 	{ "cc1-file",		required_argument,	NULL,	'1' },
8904 	{ "cc2-file",		required_argument,	NULL,	'2' },
8905 	{ "cc3-file",		required_argument,	NULL,	'3' },
8906 	{ "cc4-file",		required_argument,	NULL,	'4' },
8907 	/* From ntsc-cc.c. */
8908 	{ "t1-file",		required_argument,	NULL,	'5' },
8909 	{ "t2-file",		required_argument,	NULL,	'6' },
8910 	{ "t3-file",		required_argument,	NULL,	'7' },
8911 	{ "t4-file",		required_argument,	NULL,	'8' },
8912 	{ "s1-file",		required_argument,	NULL,	'9' },
8913 	{ "s2-file",		required_argument,	NULL,	'0' },
8914 	{ "adapter-num",	required_argument,	NULL,	'a' },
8915 	/* From ntsc-cc.c. */
8916 	{ "no-webtv",		no_argument,		NULL,	'b' },
8917 	/* From ntsc-cc.c. */
8918 	{ "cc",			no_argument,		NULL,	'c' },
8919 	{ "demux-id",		required_argument,	NULL,	'd' },
8920 	{ "conf-file",		required_argument,	NULL,	'e' },
8921 	/* From ntsc-cc.c. */
8922 	{ "filter",		required_argument,	NULL,	'f' },
8923 	{ "help",		no_argument,		NULL,	'h' },
8924 	{ "usage",		no_argument,		NULL,	'h' },
8925 	{ "frontend-id",	required_argument,	NULL,	'i' },
8926 	{ "format",		required_argument,	NULL,	'j' },
8927 	{ "channel",		required_argument,	NULL,	'l' },
8928 	{ "timestamps",		no_argument,		NULL,	'm' },
8929 	{ "station",		required_argument,	NULL,	'n' },
8930 	/* From ntsc-cc.c. */
8931 	{ "plain",		no_argument,		NULL,	'p' },
8932 	/* From ntsc-cc.c. Actually the output was never limited to ASCII. */
8933 	{ "plain-ascii",	no_argument,		NULL,	'p' },
8934 	{ "quiet",		no_argument,		NULL,	'q' },
8935 	{ "dvr-id",		required_argument,	NULL,	'r' },
8936 	/* From ntsc-cc.c. */
8937 	{ "sentences",		no_argument,		NULL,	's' },
8938 	{ "verbose",		no_argument,		NULL,	'v' },
8939 	/* From ntsc-cc.c. */
8940 	{ "xds",		no_argument,		NULL,	'x' },
8941 	/* From ntsc-cc.c. */
8942 	{ "cc-file",		required_argument,	NULL,	'C' },
8943 	/* 'E' - video elementary stream? */
8944 	{ "list",		no_argument,		NULL,	'L' },
8945 	{ "minicut",		required_argument,	NULL,	'M' },
8946 	{ "pes",		no_argument,		NULL,	'P' },
8947 	{ "ts",			no_argument,		NULL,	'T' },
8948 	/* From ntsc-cc.c. */
8949 	{ "xds-file",		required_argument,	NULL,	'X' },
8950 
8951 	/* Test options, may change. */
8952 
8953 	{ "atsc",		no_argument,		NULL,	301 },
8954 	{ "dvb-t",		no_argument,		NULL,	302 },
8955 	{ "ts-all-tap",		required_argument,	NULL,	303 },
8956 	{ "ts-tap",		required_argument,	NULL,	304 },
8957 	{ "video-all-tap",	required_argument,	NULL,	305 },
8958 	{ "video-tap",		required_argument,	NULL,	306 },
8959 	{ "cc-data-tap",	required_argument,	NULL,	308 },
8960 	{ "debug",		required_argument,	NULL,	309 },
8961 	{ "mtest",		no_argument,		NULL,	310 },
8962 	{ "cc-data",		no_argument,		NULL,	311 },
8963 	{ "es",			no_argument,		NULL,	312 },
8964 	{ 0, 0, 0, 0 }
8965 };
8966 #else
8967 #  define getopt_long(ac, av, s, l, i) getopt(ac, av, s)
8968 #endif
8969 
8970 static int			option_index;
8971 
8972 static void
list_programs(void)8973 list_programs			(void)
8974 {
8975 	const unsigned int ll = 1; /* log level */
8976 	unsigned int i;
8977 
8978 	for (i = 0; i < n_programs; ++i) {
8979 		struct program *pr;
8980 		unsigned int j;
8981 
8982 		pr = &program_table[i];
8983 		log (ll, "Station %u: '%s'\n",
8984 		     station_num (pr),
8985 		     pr->option_station_name);
8986 		for (j = 0; j < 10; ++j) {
8987 			const char *stream_name [10] = {
8988 				"NTSC CC1", "NTSC CC2",
8989 				"NTSC CC3", "NTSC CC4",
8990 				"NTSC T1", "NTSC T2",
8991 				"NTSC T3", "NTSC T4",
8992 				"ATSC S1", "ATSC S2"
8993 			};
8994 			const char *file_name;
8995 
8996 			if (0 == (pr->cr.option_caption_mask & (1 << j)))
8997 				continue;
8998 
8999 			file_name = pr->cr.option_caption_file_name[j];
9000 			if (NULL != file_name) {
9001 				log (ll, "  %s -> '%s'\n",
9002 				     stream_name[j], file_name);
9003 			} else if (NULL != pr->option_minicut_dir_name) {
9004 				log (ll, "  %s -> '%s/"
9005 				     "YYYYMMDDHH0000/"
9006 				     "YYYYMMDDHHMM00%s.txt'\n",
9007 				     stream_name[j],
9008 				     pr->option_minicut_dir_name,
9009 				     cr_file_name_suffix[j]);
9010 			}
9011 		}
9012 		if (pr->cr.usexds) {
9013 			log (ll, "  XDS -> '%s'\n",
9014 			     pr->cr.option_xds_output_file_name);
9015 		}
9016 		if (NULL != pr->option_minicut_dir_name) {
9017 				log (ll, "  TS -> '%s/"
9018 				     "YYYYMMDDHH0000/"
9019 				     "YYYYMMDDHHMM00.ts'\n",
9020 				     pr->option_minicut_dir_name);
9021 		}
9022 		if (NULL != pr->vesd.video_es_tap_fp) {
9023 			const char *name;
9024 
9025 			name = pr->vesd.option_video_es_all_tap_file_name;
9026 			if (NULL == name)
9027 				name = pr->vesd.option_video_es_tap_file_name;
9028 			log (ll, "  V-ES -> '%s'\n",
9029 			     name);
9030 		}
9031 		if (NULL != pr->vr.aesp.audio_es_tap_fp) {
9032 			log (ll, "  A-ES -> '%s'\n",
9033 			     pr->vr.aesp.option_audio_es_tap_file_name);
9034 		}
9035 		if (NULL != pr->cr.ccd.cc_data_tap_fp) {
9036 			log (ll, "  cc_data -> '%s'\n",
9037 			     pr->cr.ccd.option_cc_data_tap_file_name);
9038 		}
9039 	}
9040 }
9041 
9042 static void
cr_open_xds_output_file(struct caption_recorder * cr)9043 cr_open_xds_output_file		(struct caption_recorder *cr)
9044 {
9045 	cr->xds_fp = open_output_file (cr->option_xds_output_file_name);
9046 }
9047 
9048 static void
cr_open_caption_output_files(struct caption_recorder * cr)9049 cr_open_caption_output_files	(struct caption_recorder *cr)
9050 {
9051 	unsigned int i;
9052 
9053 	for (i = 0; i < 10; ++i) {
9054 		const char *name;
9055 
9056 		name = cr->option_caption_file_name[i];
9057 		if (cr->option_caption_mask & (1 << i)
9058 		    && NULL != name) {
9059 			cr->caption_fp[i] = open_output_file (name);
9060 		}
9061 	}
9062 }
9063 
9064 static void
open_output_files(void)9065 open_output_files		(void)
9066 {
9067 	unsigned int i;
9068 
9069 	for (i = 0; i < n_programs; ++i) {
9070 		struct program *pr;
9071 
9072 		pr = &program_table[i];
9073 
9074 		if (pr->cr.usecc)
9075 			cr_open_caption_output_files (&pr->cr);
9076 
9077 		if (pr->cr.usexds)
9078 			cr_open_xds_output_file (&pr->cr);
9079 	}
9080 }
9081 
9082 static void
look_up_station_names(void)9083 look_up_station_names		(void)
9084 {
9085 	unsigned int i;
9086 
9087 	read_channel_conf ();
9088 
9089 	for (i = 0; i < n_programs; ++i) {
9090 		struct program *pr;
9091 		struct station *st;
9092 
9093 		pr = &program_table[i];
9094 
9095 		st = find_station (pr->option_station_name);
9096 		if (NULL == st) {
9097 			error_exit ("Station '%s' is unknown. List "
9098 				    "all stations with the -L option.\n",
9099 				    pr->option_station_name);
9100 		}
9101 
9102 		if (NULL == station) {
9103 			station = st;
9104 		} else if (!same_transponder (st, station)) {
9105 			error_exit ("To receive multiple programs the "
9106 				    "stations must share one "
9107 				    "transponder frequency.\n");
9108 		}
9109 
9110 		pr->tsd.pid[0] = st->video_pid;
9111 		pr->tsd.pid[1] = st->audio_pid;
9112 
9113 		assert (st->video_pid <= N_ELEMENTS (pid_map));
9114 		assert (st->audio_pid <= N_ELEMENTS (pid_map));
9115 
9116 		pid_map[st->video_pid].program = i;
9117 		pid_map[st->audio_pid].program = i;
9118 	}
9119 }
9120 
9121 static void
finish_program_setup(struct program * pr,vbi_bool have_cc_filter_option,vbi_bool have_xds_filter_option)9122 finish_program_setup		(struct program *	pr,
9123 				 vbi_bool		have_cc_filter_option,
9124 				 vbi_bool		have_xds_filter_option)
9125 {
9126 	if (NULL != pr->option_minicut_dir_name) {
9127 		pr->cr.usecc = TRUE;
9128 		if (0 == pr->cr.option_caption_mask)
9129 			pr->cr.option_caption_mask = 0x30F;
9130 	} else {
9131 		unsigned int i;
9132 
9133 		if (!(pr->cr.usecc | pr->cr.usexds)) {
9134 			error_exit ("Please give option -c or -x, "
9135 				    "or -h for help.\n");
9136 		}
9137 
9138 		if (pr->cr.usecc && !have_cc_filter_option)
9139 			pr->cr.option_caption_mask = 0x001;
9140 
9141 		for (i = 0; i < 10; ++i) {
9142 			if (0 != (pr->cr.option_caption_mask & (1 << i))
9143 			    && NULL == pr->cr.option_caption_file_name[i]) {
9144 				pr->cr.option_caption_file_name[i] = "-";
9145 			}
9146 		}
9147 	}
9148 
9149 	if (pr->cr.usexds && !have_xds_filter_option)
9150 		xds_filter_option (&pr->cr, "all");
9151 
9152 	if (NULL != pr->vesd.option_video_es_all_tap_file_name) {
9153 		pr->vesd.video_es_tap_fp = open_output_file
9154 			(pr->vesd.option_video_es_all_tap_file_name);
9155 	} else if (NULL != pr->vesd.option_video_es_tap_file_name) {
9156 		pr->vesd.video_es_tap_fp = open_output_file
9157 			(pr->vesd.option_video_es_tap_file_name);
9158 	}
9159 
9160 	if (NULL != pr->vr.aesp.option_audio_es_tap_file_name) {
9161 		pr->vr.aesp.audio_es_tap_fp = open_output_file
9162 			(pr->vr.aesp.option_audio_es_tap_file_name);
9163 	}
9164 
9165 	if (NULL != pr->cr.ccd.option_cc_data_tap_file_name) {
9166 		pr->cr.ccd.cc_data_tap_fp = open_output_file
9167 			(pr->cr.ccd.option_cc_data_tap_file_name);
9168 	}
9169 }
9170 
9171 static unsigned int
uint_option(const char * option_name,const char * optarg)9172 uint_option			(const char *		option_name,
9173 				 const char *		optarg)
9174 {
9175 	const char *s;
9176 	char *end;
9177 	unsigned long ul;
9178 
9179 	s = optarg;
9180 	while (isspace (*s))
9181 		++s;
9182 	if (!isdigit (*s))
9183 		goto failed;
9184 	ul = strtoul (optarg, &end, 0);
9185 	while (isspace (*end))
9186 		++end;
9187 	if (0 == *end && ul < UINT_MAX)
9188 		return ul;
9189 
9190  failed:
9191 	error_exit ("Invalid %s '%s'.\n", option_name, optarg);
9192 
9193 	return 0;
9194 }
9195 
9196 static void
format_option(struct caption_recorder * cr,const char * optarg)9197 format_option			(struct caption_recorder *cr,
9198 				 const char *		optarg)
9199 {
9200 	static const struct {
9201 		const char *		name;
9202 		enum caption_format	format;
9203 	} formats [] = {
9204 		{ "plain",		FORMAT_PLAIN },
9205 		{ "vt100",		FORMAT_VT100 },
9206 		{ "ntsc-cc",		FORMAT_NTSC_CC }
9207 	};
9208 	unsigned int i;
9209 
9210 	for (i = 0; i < N_ELEMENTS (formats); ++i) {
9211 		if (NULL != optarg
9212 		    && 0 == strcmp (optarg, formats[i].name)) {
9213 			cr->option_caption_format = formats[i].format;
9214 			break;
9215 		}
9216 	}
9217 
9218 	if (i >= N_ELEMENTS (formats)) {
9219 		error_exit ("Invalid caption format '%s'. "
9220 			    "Try 'plain', 'vt100' or 'ntsc-cc'.\n",
9221 			    optarg);
9222 	}
9223 
9224 	if (FORMAT_PLAIN == cr->option_caption_format) {
9225 		cr->xds_info_prefix = "% ";
9226 		cr->xds_info_suffix = "\n";
9227 	} else {
9228 		cr->xds_info_prefix = "\33[33m% ";
9229 		cr->xds_info_suffix = "\33[0m\n";
9230 	}
9231 }
9232 
9233 static void
debug_option(const char * optarg)9234 debug_option			(const char *		optarg)
9235 {
9236 	static const struct {
9237 		const char *	name;
9238 		unsigned int	flag;
9239 	} flags [] = {
9240 		{ "all",		-1 },
9241 		{ "ccdata",		DEBUG_CC_DATA },
9242 		{ "ccdec",		DEBUG_CC_DECODER },
9243 		{ "ccf1",		DEBUG_CC_F1 },
9244 		{ "ccf2",		DEBUG_CC_F2 },
9245 		{ "conf",		DEBUG_CONFIG },
9246 		{ "dtvccp",		DEBUG_DTVCC_PACKET },
9247 		{ "dtvccpc",		DEBUG_DTVCC_PUT_CHAR },
9248 		{ "dtvccse",		DEBUG_DTVCC_SE },
9249 		{ "dtvccsev",		DEBUG_DTVCC_STREAM_EVENT },
9250 		{ "vesdcc",		DEBUG_VESD_CC_DATA },
9251 		{ "vesdpe",		DEBUG_VESD_PIC_EXT },
9252 		{ "vesdph",		DEBUG_VESD_PIC_HDR },
9253  		{ "vesdpesp",		DEBUG_VESD_PES_PACKET },
9254  		{ "vesdsc",		DEBUG_VESD_START_CODE },
9255  		{ "vesdud",		DEBUG_VESD_USER_DATA },
9256 	};
9257 	const char *s;
9258 
9259 	if (NULL == optarg) {
9260 		option_debug = -1;
9261 		return;
9262 	} else if (0 == strcmp (optarg, "help")) {
9263 		unsigned int i;
9264 
9265 		printf ("Debugging switches:\n");
9266 
9267 		for (i = 0; i < N_ELEMENTS (flags); ++i) {
9268 			printf ("  %s\n", flags[i].name);
9269 		}
9270 
9271 		exit (EXIT_SUCCESS);
9272 	}
9273 
9274 	s = optarg;
9275 
9276 	while (isspace (*s))
9277 		++s;
9278 
9279 	while (0 != *s) {
9280 		unsigned int i;
9281 
9282 		for (i = 0; i < N_ELEMENTS (flags); ++i) {
9283 			const char *t;
9284 			const char *u;
9285 
9286 			t = s;
9287 			u = flags[i].name;
9288 			for (;;) {
9289 				if (0 == *t || ',' == *t || ' ' == *t) {
9290 					if (0 != *u)
9291 						break;
9292 					option_debug |= flags[i].flag;
9293 					s = t;
9294 					goto next_item;
9295 				} else if ('-' == *t || '_' == *t) {
9296 					++t;
9297 					continue;
9298 				} else if (*t++ != *u++) {
9299 					break;
9300 				}
9301 			}
9302 		}
9303 
9304 		error_exit ("Invalid debugging switch '%s'. "
9305 			    "Try --debug help.\n", optarg);
9306 
9307 	next_item:
9308 		while (',' == *s || isspace (*s))
9309 			++s;
9310 	}
9311 }
9312 
9313 static struct program *
add_program(void)9314 add_program			(void)
9315 {
9316 	struct program *pr;
9317 
9318 	if (n_programs >= N_ELEMENTS (program_table)) {
9319 		error_exit ("Sorry, too many programs.\n");
9320 	}
9321 
9322 	pr = &program_table[n_programs++];
9323 
9324 	init_program (pr);
9325 
9326 	return pr;
9327 }
9328 
9329 static void
parse_args(int argc,char ** argv)9330 parse_args			(int			argc,
9331 				 char **		argv)
9332 {
9333 	struct program *pr;
9334 	vbi_bool have_cc_filter_option;
9335 	vbi_bool have_xds_filter_option;
9336 	unsigned int n_program_options;
9337 
9338 	option_source = SOURCE_DVB_DEVICE;
9339 
9340 	option_dvb_type = -1; /* query device */
9341 
9342 	option_dvb_adapter_num = 0;
9343 	option_dvb_frontend_id = 0;
9344 	option_dvb_demux_id = 0;
9345 	option_dvb_dvr_id = 0;
9346 
9347 	option_verbosity = 1;
9348 
9349 	pr = add_program ();
9350 
9351 	format_option (&pr->cr, "ntsc-cc");
9352 
9353 	have_xds_filter_option = FALSE;
9354 	have_cc_filter_option = FALSE;
9355 	n_program_options = 0;
9356 
9357 	for (;;) {
9358 		int c;
9359 
9360 		c = getopt_long (argc, argv, short_options,
9361 				 long_options, &option_index);
9362 		if (-1 == c)
9363 			break;
9364 
9365 		switch (c) {
9366 			const char *name;
9367 			unsigned int i;
9368 			long ch;
9369 
9370 		case '?':
9371 		case 'h':
9372 			usage (stdout);
9373 			exit (EXIT_SUCCESS);
9374 
9375 		case '0' ... '9':
9376 			assert (NULL != optarg);
9377 			if ('0' == c)
9378 				i = 9;
9379 			else
9380 				i = c - '1';
9381 			pr->cr.option_caption_file_name[i] = optarg;
9382 			pr->cr.option_caption_mask |= 1 << i;
9383 			have_cc_filter_option = TRUE;
9384 			++n_program_options;
9385 			pr->cr.usecc = 1;
9386 			break;
9387 
9388 		case 'a':
9389 			assert (NULL != optarg);
9390 			option_dvb_adapter_num =
9391 				uint_option ("DVB adapter number",
9392 					     optarg);
9393 			break;
9394 
9395 		case 'b':
9396 			pr->cr.usewebtv = 0; /* sic, compatibility */
9397 			++n_program_options;
9398 			break;
9399 
9400 		case 'c':
9401 			pr->cr.usecc = 1;
9402 			++n_program_options;
9403 			break;
9404 
9405 		case 'd':
9406 			assert (NULL != optarg);
9407 			option_dvb_demux_id =
9408 				uint_option ("DVB demux device number",
9409 					     optarg);
9410 			break;
9411 
9412 		case 'e':
9413 			assert (NULL != optarg);
9414 			option_channel_conf_file_name = optarg;
9415 			break;
9416 
9417 		case 'f':
9418 			pr->cr.usexds = TRUE;
9419 			xds_filter_option (&pr->cr, optarg);
9420 			have_xds_filter_option = TRUE;
9421 			++n_program_options;
9422 			break;
9423 
9424 		case 'i':
9425 			assert (NULL != optarg);
9426 			option_dvb_frontend_id =
9427 				uint_option ("DVB frontend device number",
9428 					     optarg);
9429 			break;
9430 
9431 		case 'j':
9432 			assert (NULL != optarg);
9433 			format_option (&pr->cr, optarg);
9434 			++n_program_options;
9435 			break;
9436 
9437 		case 'l':
9438 			assert (NULL != optarg);
9439 			ch = strtol (optarg, NULL, 0);
9440 			if (ch < 1 || ch > 10) {
9441 				error_exit ("Invalid caption stream "
9442 					    "number %ld. The valid "
9443 					    "range is 1 ... 10.\n",
9444 					    ch);
9445 			}
9446 			pr->cr.option_caption_mask |= 1 << (ch - 1);
9447 			have_cc_filter_option = TRUE;
9448 			++n_program_options;
9449 			pr->cr.usecc = 1;
9450 			break;
9451 
9452 		case 'm':
9453 			pr->cr.option_caption_timestamps = TRUE;
9454 			++n_program_options;
9455 			break;
9456 
9457 		case '\1': /* not an option */
9458 			/* NB this is a GNU extension, hence the
9459 			   -n option. */
9460 
9461 		case 'n':
9462 			assert (NULL != optarg);
9463 			name = optarg;
9464 			if (NULL == pr->option_station_name) {
9465 				pr->option_station_name = name;
9466 				if (0 == n_program_options)
9467 					break;
9468 				name = NULL;
9469 			}
9470 			finish_program_setup (pr,
9471 					      have_cc_filter_option,
9472 					      have_xds_filter_option);
9473 			pr = add_program ();
9474 			pr->option_station_name = name;
9475 			have_xds_filter_option = FALSE;
9476 			have_cc_filter_option = FALSE;
9477 			n_program_options = 0;
9478 			break;
9479 
9480 		case 'p':
9481 			format_option (&pr->cr, "plain");
9482 			++n_program_options;
9483 			break;
9484 
9485 		case 'q':
9486 			option_verbosity = 0;
9487 			break;
9488 
9489 		case 'r':
9490 			assert (NULL != optarg);
9491 			option_dvb_dvr_id =
9492 				uint_option ("DVB DVR device number",
9493 					     optarg);
9494 			break;
9495 
9496 		case 's':
9497 			pr->cr.usesen = 1;
9498 			++n_program_options;
9499 			break;
9500 
9501 		case 'v':
9502 			++option_verbosity;
9503 			break;
9504 
9505 		case 'x':
9506 			pr->cr.usexds = 1;
9507 			++n_program_options;
9508 			break;
9509 
9510 		case 'C':
9511 			assert (NULL != optarg);
9512 			for (i = 0; i < 10; ++i) {
9513 				pr->cr.option_caption_file_name[i] =
9514 					optarg;
9515 			}
9516 			pr->cr.usecc = 1;
9517 			++n_program_options;
9518 			break;
9519 
9520 		case 'L':
9521 			read_channel_conf ();
9522 			list_stations ();
9523 			exit (EXIT_SUCCESS);
9524 
9525 		case 'M':
9526 			assert (NULL != optarg);
9527 			pr->option_minicut_dir_name = optarg;
9528 			++n_program_options;
9529 			break;
9530 
9531 		case 'P':
9532 			option_source = SOURCE_STDIN_PES;
9533 			break;
9534 
9535 		case 'T':
9536 			option_source = SOURCE_STDIN_TS;
9537 			break;
9538 
9539 		case 'X':
9540 			assert (NULL != optarg);
9541 			pr->cr.option_xds_output_file_name = optarg;
9542 			++n_program_options;
9543 			break;
9544 
9545 			/* Test options. */
9546 
9547 		case 301:
9548 			option_dvb_type = FE_ATSC;
9549 			break;
9550 
9551 		case 302:
9552 			option_dvb_type = FE_OFDM;
9553 			break;
9554 
9555 		case 303:
9556 			assert (NULL != optarg);
9557 			option_ts_all_tap_file_name = optarg;
9558 			break;
9559 
9560 		case 304:
9561 			assert (NULL != optarg);
9562 			option_ts_tap_file_name = optarg;
9563 			break;
9564 
9565 		case 305:
9566 			assert (NULL != optarg);
9567 			pr->vesd.option_video_es_all_tap_file_name = optarg;
9568 			++n_program_options;
9569 			break;
9570 
9571 		case 306:
9572 			assert (NULL != optarg);
9573 			pr->vesd.option_video_es_tap_file_name = optarg;
9574 			++n_program_options;
9575 			break;
9576 
9577 
9578 		case 307:
9579 			assert (NULL != optarg);
9580 			pr->vr.aesp.option_audio_es_tap_file_name = optarg;
9581 			++n_program_options;
9582 			break;
9583 
9584 		case 308:
9585 			assert (NULL != optarg);
9586 			pr->cr.ccd.option_cc_data_tap_file_name = optarg;
9587 			++n_program_options;
9588 			break;
9589 
9590 		case 309:
9591 			assert (NULL != optarg);
9592 			debug_option (optarg);
9593 			break;
9594 
9595 		case 310:
9596 			option_minicut_test = TRUE;
9597 			break;
9598 
9599 		case 311:
9600 			option_source = SOURCE_STDIN_CC_DATA;
9601 			break;
9602 
9603 		case 312:
9604 			option_source = SOURCE_STDIN_VIDEO_ES;
9605 			break;
9606 
9607 		default:
9608 			usage (stderr);
9609 			exit (EXIT_FAILURE);
9610 		}
9611 	}
9612 
9613 	if (pr->cr.usesen
9614 	    && (pr->cr.option_caption_timestamps
9615 		|| NULL != pr->option_minicut_dir_name)) {
9616 		error_exit ("Sorry, option -s does not "
9617 			    "combine with -m or -M.\n");
9618 	}
9619 
9620 	if (NULL == pr->option_station_name) {
9621 		if (0 == n_program_options) {
9622 			--n_programs;
9623 			if (SOURCE_DVB_DEVICE == option_source
9624 			    || SOURCE_STDIN_TS == option_source) {
9625 				if (0 == n_programs)
9626 					goto no_station;
9627 			}
9628 		} else {
9629 			if (SOURCE_DVB_DEVICE == option_source
9630 			    || SOURCE_STDIN_TS == option_source) {
9631 				if (optind == argc)
9632 					goto no_station;
9633 
9634 				pr->option_station_name = argv[optind];
9635 			}
9636 
9637 			finish_program_setup (pr,
9638 					      have_cc_filter_option,
9639 					      have_xds_filter_option);
9640 		}
9641 	} else {
9642 		finish_program_setup (pr,
9643 				      have_cc_filter_option,
9644 				      have_xds_filter_option);
9645 	}
9646 
9647 	if (SOURCE_DVB_DEVICE == option_source
9648 	    || SOURCE_STDIN_TS == option_source) {
9649 		look_up_station_names ();
9650 	} else {
9651 		if (n_programs > 1) {
9652 			goto too_many_stations;
9653 		} else if (NULL != program_table[0].option_station_name) {
9654 			log (1, "Ignoring station name.\n");
9655 		}
9656 	}
9657 
9658 	return;
9659 
9660  no_station:
9661 	error_exit ("Please give a station name. "
9662 		    "List all stations with the -L option.\n");
9663 
9664  too_many_stations:
9665 	error_exit ("Sorry, only one program can be decoded with "
9666 		    "the --cc-data, --es or\n"
9667 		    "--pes option.\n");
9668 }
9669 
9670 int
main(int argc,char ** argv)9671 main				(int			argc,
9672 				 char **		argv)
9673 {
9674 	my_name = argv[0];
9675 
9676 	setlocale (LC_ALL, "");
9677 
9678 	locale_codeset = vbi_locale_codeset (),
9679 
9680 	/* Don't swap out any code or data pages (if we have the
9681 	   privilege). If the capture thread is delayed we may lose
9682 	   packets. Errors ignored. */
9683 	mlockall (MCL_CURRENT | MCL_FUTURE);
9684 
9685 	memset (pid_map, -1, sizeof (pid_map));
9686 
9687 	parse_args (argc, argv);
9688 
9689 	init_demux_state ();
9690 
9691 	if (NULL != option_ts_all_tap_file_name) {
9692 		ts_tap_fp = open_output_file (option_ts_all_tap_file_name);
9693 	} else if (NULL != option_ts_tap_file_name) {
9694 		ts_tap_fp = open_output_file (option_ts_tap_file_name);
9695 	}
9696 
9697 	switch (option_source) {
9698 	case SOURCE_DVB_DEVICE:
9699 		open_device ();
9700 		open_output_files ();
9701 		if (n_programs > 1)
9702 			list_programs ();
9703 		demux_thread (/* arg */ NULL);
9704 		close_device ();
9705 		break;
9706 
9707 	case SOURCE_STDIN_TS:
9708 		open_output_files ();
9709 		if (n_programs > 1)
9710 			list_programs ();
9711 		ts_test_loop ("-");
9712 		break;
9713 
9714 	case SOURCE_STDIN_PES:
9715 		error_exit ("Sorry, the --pes option "
9716 			    "is not implemented yet.\n");
9717 		break;
9718 
9719 	case SOURCE_STDIN_VIDEO_ES:
9720 		/* For tests only. */
9721 		open_output_files ();
9722 		video_es_test_loop (&program_table[0], "-");
9723 		break;
9724 
9725 	case SOURCE_STDIN_CC_DATA:
9726 		/* For tests only. */
9727 		open_output_files ();
9728 		cc_data_test_loop (&program_table[0], "-");
9729 		break;
9730 	}
9731 
9732 	destroy_demux_state ();
9733 
9734 	exit (EXIT_SUCCESS);
9735 }
9736