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