summaryrefslogtreecommitdiff
path: root/src/dtvcc.h (plain)
blob: 83b0ef2871747ef8c89ebf8518c7b186d9ea38a6
1#ifndef _DTVCC_H_
2#define _DTVCC_H_
3
4#include <assert.h>
5#include <ctype.h>
6#include <dirent.h>
7#include <errno.h>
8#include <fcntl.h>
9#include <inttypes.h>
10#include <limits.h>
11#include <locale.h>
12#include <malloc.h>
13#include <math.h>
14#include <pthread.h>
15#include <signal.h>
16#include <stdarg.h>
17#include <stdio.h>
18#include <stdlib.h>
19#include <string.h>
20#include <sys/ioctl.h>
21#include <sys/mman.h>
22#include <sys/stat.h>
23#include <sys/statvfs.h>
24#include <sys/wait.h>
25#include <time.h>
26#include <unistd.h>
27#include "libzvbi.h"
28
29enum field_num {
30 FIELD_1 = 0,
31 FIELD_2,
32 MAX_FIELDS
33};
34
35enum cc_mode {
36 CC_MODE_UNKNOWN,
37 CC_MODE_ROLL_UP,
38 CC_MODE_POP_ON,
39 CC_MODE_PAINT_ON,
40 CC_MODE_TEXT
41};
42
43enum cc_effect_status {
44 CC_EFFECT_NONE,
45 CC_EFFECT_DISPLAY,
46 CC_EFFECT_HIDE
47};
48
49/* EIA 608-B Section 4.1. */
50#define VBI_CAPTION_CC1 1 /* primary synchronous caption service (F1) */
51#define VBI_CAPTION_CC2 2 /* special non-synchronous use captions (F1) */
52#define VBI_CAPTION_CC3 3 /* secondary synchronous caption service (F2) */
53#define VBI_CAPTION_CC4 4 /* special non-synchronous use captions (F2) */
54
55#define VBI_CAPTION_T1 5 /* first text service (F1) */
56#define VBI_CAPTION_T2 6 /* second text service (F1) */
57#define VBI_CAPTION_T3 7 /* third text service (F2) */
58#define VBI_CAPTION_T4 8 /* fourth text service (F2) */
59
60#define UNKNOWN_CC_CHANNEL 0
61#define MAX_CC_CHANNELS 8
62
63/* 47 CFR 15.119 (d) Screen format. */
64#define CC_FIRST_ROW 0
65#define CC_LAST_ROW 14
66#define CC_MAX_ROWS 15
67
68#define CC_FIRST_COLUMN 1
69#define CC_LAST_COLUMN 32
70#define CC_MAX_COLUMNS 32
71
72#define CC_ALL_ROWS_MASK ((1 << CC_MAX_ROWS) - 1)
73
74#define VBI_TRANSLUCENT VBI_SEMI_TRANSPARENT
75
76struct cc_timestamp {
77 /* System time when the event occured, zero if no event occured yet. */
78 struct timeval sys;
79
80 /* Presentation time stamp of the event. Only the 33 least
81 significant bits are valid. < 0 if no event occured yet. */
82 int64_t pts;
83};
84
85struct cc_channel {
86 /**
87 * [0] and [1] are the displayed and non-displayed buffer as
88 * defined in 47 CFR 15.119, and selected by displayed_buffer
89 * below. [2] is a snapshot of the displayed buffer at the
90 * last stream event.
91 *
92 * XXX Text channels don't need buffer[2] and buffer[3], we're
93 * wasting memory.
94 */
95 uint16_t buffer[3][CC_MAX_ROWS][1 + CC_MAX_COLUMNS];
96
97 /**
98 * For buffer[0 ... 2], if bit 1 << row is set this row
99 * contains displayable characters, spacing or non-spacing
100 * attributes. (Special character 0x1139 "transparent space"
101 * is not a displayable character.) This information is
102 * intended to speed up copying, erasing and formatting.
103 */
104 unsigned int dirty[3];
105
106 /** Index of displayed buffer, 0 or 1. */
107 unsigned int displayed_buffer;
108
109 /**
110 * Cursor position: FIRST_ROW ... LAST_ROW and
111 * FIRST_COLUMN ... LAST_COLUMN.
112 */
113 unsigned int curr_row;
114 unsigned int curr_column;
115
116 /**
117 * Text window height in CC_MODE_ROLL_UP. The first row of the
118 * window is curr_row - window_rows + 1, the last row is
119 * curr_row.
120 *
121 * Note: curr_row - window_rows + 1 may be < FIRST_ROW, this
122 * must be clipped before using window_rows:
123 *
124 * actual_rows = MIN (curr_row - FIRST_ROW + 1, window_rows);
125 *
126 * We won't do that at the RUx command because usually a PAC
127 * follows which may change curr_row.
128 */
129 unsigned int window_rows;
130
131 /* Most recently received PAC command. */
132 unsigned int last_pac;
133
134 /**
135 * This variable counts successive transmissions of the
136 * letters A to Z. It is reset to zero on reception of any
137 * letter a to z.
138 *
139 * Some stations do not transmit EIA 608-B extended characters
140 * and except for N with tilde the standard and special
141 * character sets contain only lower case accented
142 * characters. We force these characters to upper case if this
143 * variable indicates live caption, which is usually all upper
144 * case.
145 */
146 unsigned int uppercase_predictor;
147
148 /** Current caption mode or CC_MODE_UNKNOWN. */
149 enum cc_mode mode;
150
151 /**
152 * The time when we last received data for this
153 * channel. Intended to detect if this caption channel is
154 * active.
155 */
156 struct cc_timestamp timestamp;
157
158 /**
159 * The time when we received the first (but not necessarily
160 * leftmost) character in the current row. Unless the mode is
161 * CC_MODE_POP_ON the next stream event will carry this
162 * timestamp.
163 */
164 struct cc_timestamp timestamp_c0;
165};
166
167struct cc_decoder {
168 /**
169 * Decoder state. We decode all channels in parallel, this way
170 * clients can switch between channels without data loss, or
171 * capture multiple channels with a single decoder instance.
172 *
173 * Also 47 CFR 15.119 and EIA 608-C require us to remember the
174 * cursor position on each channel.
175 */
176 struct cc_channel channel[MAX_CC_CHANNELS];
177
178 /**
179 * Current channel, switched by caption control codes. Can be
180 * one of @c VBI_CAPTION_CC1 ... @c VBI_CAPTION_CC4 or @c
181 * VBI_CAPTION_T1 ... @c VBI_CAPTION_T4 or @c
182 * UNKNOWN_CC_CHANNEL if no channel number was received yet.
183 */
184 vbi_pgno curr_ch_num[MAX_FIELDS];
185
186 /**
187 * Caption control codes (two bytes) may repeat once for error
188 * correction. -1 if no repeated control code can be expected.
189 */
190 int expect_ctrl[MAX_FIELDS][2];
191
192 /** Receiving XDS data, as opposed to caption / ITV data. */
193 vbi_bool in_xds[MAX_FIELDS];
194
195 /**
196 * Pointer into the channel[] array if a display update event
197 * shall be sent at the end of this iteration, %c NULL
198 * otherwise. Purpose is to suppress an event for the first of
199 * two displayable characters in a caption byte pair.
200 */
201 struct cc_channel * event_pending;
202
203 /**
204 * Remembers past parity errors: One bit for each call of
205 * cc_feed(), most recent result in lsb. The idea is to
206 * disable the decoder if we detect too many errors.
207 */
208 unsigned int error_history;
209
210 /**
211 * The time when we last received data, including NUL bytes.
212 * Intended to detect if the station transmits any data on
213 * line 21 or 284 at all.
214 */
215 struct cc_timestamp timestamp;
216};
217
218/* CEA 708-C decoder. */
219
220enum justify {
221 JUSTIFY_LEFT = 0,
222 JUSTIFY_RIGHT,
223 JUSTIFY_CENTER,
224 JUSTIFY_FULL
225};
226
227enum direction {
228 DIR_LEFT_RIGHT = 0,
229 DIR_RIGHT_LEFT,
230 DIR_TOP_BOTTOM,
231 DIR_BOTTOM_TOP
232};
233
234enum display_effect {
235 DISPLAY_EFFECT_SNAP = 0,
236 DISPLAY_EFFECT_FADE,
237 DISPLAY_EFFECT_WIPE
238};
239
240enum opacity {
241 OPACITY_SOLID = 0,
242 OPACITY_FLASH,
243 OPACITY_TRANSLUCENT,
244 OPACITY_TRANSPARENT
245};
246
247enum edge {
248 EDGE_NONE = 0,
249 EDGE_RAISED,
250 EDGE_DEPRESSED,
251 EDGE_UNIFORM,
252 EDGE_SHADOW_LEFT,
253 EDGE_SHADOW_RIGHT
254};
255
256enum pen_size {
257 PEN_SIZE_SMALL = 0,
258 PEN_SIZE_STANDARD,
259 PEN_SIZE_LARGE
260};
261
262enum font_style {
263 FONT_STYLE_DEFAULT = 0,
264 FONT_STYLE_MONO_SERIF,
265 FONT_STYLE_PROP_SERIF,
266 FONT_STYLE_MONO_SANS,
267 FONT_STYLE_PROP_SANS,
268 FONT_STYLE_CASUAL,
269 FONT_STYLE_CURSIVE,
270 FONT_STYLE_SMALL_CAPS
271};
272
273enum text_tag {
274 TEXT_TAG_DIALOG = 0,
275 TEXT_TAG_SOURCE_ID,
276 TEXT_TAG_DEVICE,
277 TEXT_TAG_DIALOG_2,
278 TEXT_TAG_VOICEOVER,
279 TEXT_TAG_AUDIBLE_TRANSL,
280 TEXT_TAG_SUBTITLE_TRANSL,
281 TEXT_TAG_VOICE_DESCR,
282 TEXT_TAG_LYRICS,
283 TEXT_TAG_EFFECT_DESCR,
284 TEXT_TAG_SCORE_DESCR,
285 TEXT_TAG_EXPLETIVE,
286 TEXT_TAG_NOT_DISPLAYABLE = 15
287};
288
289enum offset {
290 OFFSET_SUBSCRIPT = 0,
291 OFFSET_NORMAL,
292 OFFSET_SUPERSCRIPT
293};
294
295/* RGB 2:2:2 (lsb = B). */
296typedef uint8_t dtvcc_color;
297
298/* Lsb = window 0, msb = window 7. */
299typedef uint8_t dtvcc_window_map;
300
301struct dtvcc_pen_style {
302 enum pen_size pen_size;
303 enum font_style font_style;
304 enum offset offset;
305 vbi_bool italics;
306 vbi_bool underline;
307
308 enum edge edge_type;
309
310 dtvcc_color fg_color;
311 enum opacity fg_opacity;
312
313 dtvcc_color bg_color;
314 enum opacity bg_opacity;
315
316 dtvcc_color edge_color;
317 vbi_bool fg_flash;
318 vbi_bool bg_flash;
319};
320
321struct dtvcc_pen {
322 enum text_tag text_tag;
323 struct dtvcc_pen_style style;
324};
325
326struct dtvcc_window_style {
327 enum justify justify;
328 enum direction print_direction;
329 enum direction scroll_direction;
330 vbi_bool wordwrap;
331
332 enum display_effect display_effect;
333 enum direction effect_direction;
334 unsigned int effect_speed; /* 1/10 sec */
335
336 dtvcc_color fill_color;
337 enum opacity fill_opacity;
338 vbi_bool window_flash;
339
340 enum edge border_type;
341 dtvcc_color border_color;
342};
343
344struct dtvcc_window {
345 /* EIA 708-C window state. */
346
347 uint16_t buffer[16][42];
348 struct dtvcc_pen_style pen[16][42];
349 int row_start[16];
350
351 vbi_bool visible;
352
353 /* 0 = highest ... 7 = lowest. */
354 unsigned int priority;
355
356 unsigned int anchor_point;
357 unsigned int anchor_horizontal;
358 unsigned int anchor_vertical;
359 vbi_bool anchor_relative;
360
361 unsigned int row_count;
362 unsigned int column_count;
363
364 vbi_bool row_lock;
365 vbi_bool column_lock;
366
367 unsigned int curr_row;
368 unsigned int curr_column;
369
370 struct dtvcc_pen curr_pen;
371
372 struct dtvcc_window_style style;
373
374 /* Used for fade and swipe */
375 struct timespec effect_timer;
376 /* 0~100 */
377 int effect_percent;
378 enum cc_effect_status effect_status;
379
380 /* Our stuff. */
381
382 /**
383 * If bit 1 << row is set we already sent a stream event for
384 * this row.
385 */
386 unsigned int streamed;
387
388 /**
389 * The time when we received the first (but not necessarily
390 * leftmost) character in the current row. Unless a
391 * DisplayWindow or ToggleWindow command completed the line
392 * the next stream event will carry this timestamp.
393 */
394 struct cc_timestamp timestamp_c0;
395};
396
397struct dtvcc_service {
398 /* Interpretation Layer. */
399 int id;
400
401 struct dtvcc_window window[8];
402 struct dtvcc_window old_window[8];
403
404 int old_win_cnt;
405 int update;
406
407 struct dtvcc_window * curr_window;
408
409 dtvcc_window_map created;
410
411 /* For debugging. */
412 unsigned int error_line;
413
414 /* Service Layer. */
415
416 uint8_t service_data[128];
417 unsigned int service_data_in;
418 /* For 0x8D 0x8E delay command
419 * if delay flag is set, decoder stop decoding
420 */
421 struct timespec delay_timer;
422
423
424 int delay;
425 int delay_cancel;
426
427 /** The time when we last received data for this service. */
428 struct cc_timestamp timestamp;
429};
430
431struct dtvcc_decoder {
432 struct dtvcc_service service[6];
433
434 /* Packet Layer. */
435
436 uint8_t packet[128];
437 unsigned int packet_size;
438
439 /* Next expected DTVCC packet sequence_number. Only the two
440 most significant bits are valid. < 0 if no sequence_number
441 has been received yet. */
442 int next_sequence_number;
443
444 /** The time when we last received data. */
445 struct cc_timestamp timestamp;
446
447 int flash_state;
448};
449
450/* ATSC A/53 Part 4:2007 Closed Caption Data decoder. */
451
452enum cc_type {
453 NTSC_F1 = 0,
454 NTSC_F2 = 1,
455 DTVCC_DATA = 2,
456 DTVCC_START = 3,
457};
458
459struct cc_data_decoder {
460 /* Test tap. */
461 const char * option_cc_data_tap_file_name;
462
463 FILE * cc_data_tap_fp;
464
465 /* For debugging. */
466 int64_t last_pts;
467};
468
469/* Caption recorder. */
470
471enum cc_attr {
472 VBI_UNDERLINE = (1 << 0),
473 VBI_ITALIC = (1 << 2),
474 VBI_FLASH = (1 << 3)
475};
476
477struct cc_pen {
478 uint8_t attr;
479
480 uint8_t fg_color;
481 uint8_t fg_opacity;
482
483 uint8_t bg_color;
484 uint8_t bg_opacity;
485
486 uint8_t edge_type;
487 uint8_t edge_color;
488 uint8_t edge_opacity;
489
490 uint8_t pen_size;
491 uint8_t font_style;
492
493 uint8_t reserved[6];
494};
495
496enum caption_format {
497 FORMAT_PLAIN,
498 FORMAT_VT100,
499 FORMAT_NTSC_CC
500};
501
502struct tvcc_decoder {
503 pthread_mutex_t mutex;
504 struct vbi_decoder *vbi;
505 struct cc_decoder cc;
506 struct dtvcc_decoder dtvcc;
507};
508unsigned int dtvcc_unicode (unsigned int c);
509
510extern void tvcc_init(struct tvcc_decoder *td);
511
512extern void tvcc_decode_data(struct tvcc_decoder *td, int64_t pts, const uint8_t *buf, unsigned int n_bytes);
513
514extern void tvcc_reset(struct tvcc_decoder *td);
515
516extern void tvcc_destroy(struct tvcc_decoder *td);
517
518extern void tvcc_fetch_page(struct tvcc_decoder *td, int pgno, int *cnt, struct vbi_page *sub_pages);
519
520static void dtvcc_init(struct dtvcc_decoder * dc);
521
522extern void dtvcc_decode_packet(struct dtvcc_decoder *dc, const struct timeval *tv, int64_t pts);
523
524extern void dtvcc_reset(struct dtvcc_decoder * dc);
525
526extern void cc_init(struct cc_decoder *cd);
527
528extern vbi_bool cc_feed(struct cc_decoder *cd, const uint8_t buffer[2], unsigned int line, const struct timeval * tv, int64_t pts);
529
530extern void cc_reset(struct cc_decoder *cd);
531
532extern void vbi_decode_caption(vbi_decoder *vbi, int line, const uint8_t *buf);
533
534extern int get_input_offset();
535
536extern void update_service_status(struct tvcc_decoder *td);
537static vbi_bool dtvcc_carriage_return (struct dtvcc_decoder *dc, struct dtvcc_service * ds);
538
539
540
541#endif
542
543