2
* libzvbi - EIA 608-B Closed Caption decoder
4
* Copyright (C) 2008 Michael H. Schimek
6
* This library is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU Library General Public
8
* License as published by the Free Software Foundation; either
9
* version 2 of the License, or (at your option) any later version.
11
* This library is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
* Library General Public License for more details.
16
* You should have received a copy of the GNU Library General Public
17
* License along with this library; if not, write to the
18
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19
* Boston, MA 02110-1301 USA.
22
/* $Id: cc608_decoder.c,v 1.2 2009/12/14 23:43:23 mschimek Exp $ */
24
/* This code is experimental and not yet part of the library.
35
#include "event-priv.h"
36
#include "cc608_decoder.h"
38
#ifndef CC608_DECODER_LOG_INPUT
39
# define CC608_DECODER_LOG_INPUT 0
48
#define UNKNOWN_CHANNEL 0
49
#define MAX_CHANNELS 8
51
/* 47 CFR 15.119 (d) Screen format. */
57
#define ALL_ROWS_MASK ((1 << MAX_ROWS) - 1)
59
/* Note these are visible columns. We also buffer a zeroth column
60
which is implied by 47 CFR 15.119 and EIA 608-B to set the default
61
or PAC attributes for column one, and visible as a solid space if
62
padding for legibility is enabled. We do not reserve a 33rd column
63
for padding since format_row() can just append a space to the
65
#define FIRST_COLUMN 1
66
#define LAST_COLUMN 32
67
#define MAX_COLUMNS 32
70
/* System time when the event occured, zero if no event
74
/* ISO 13818-1 Presentation Time Stamp of the event. Unit is
75
1/90000 second. Only the 33 least significant bits are
76
valid. < 0 if no event occured yet. */
82
* [0] and [1] are the displayed and non-displayed buffer as
83
* defined in 47 CFR 15.119, and selected by @a
84
* displayed_buffer below. [2] is a snapshot of the displayed
85
* buffer at the last stream event.
87
* XXX Text channels don't need buffer[2] and buffer[3], we're
90
uint16_t buffer[3][MAX_ROWS][1 + MAX_COLUMNS];
93
* For buffer[0 ... 2], if bit 1 << row is set this row
94
* contains displayable characters, spacing or non-spacing
95
* attributes. (Special character 0x1139 "transparent space"
96
* is not a displayable character.) This information is
97
* intended to speed up copying, erasing and formatting.
99
unsigned int dirty[3];
101
/** Index of the displayed buffer, 0 or 1. */
102
unsigned int displayed_buffer;
105
* Cursor position: FIRST_ROW ... LAST_ROW and
106
* FIRST_COLUMN ... LAST_COLUMN.
108
unsigned int curr_row;
109
unsigned int curr_column;
112
* Text window height in VBI_CC608_MODE_ROLL_UP. The top row
113
* of the window is curr_row - window_rows + 1, the bottom row
116
* Note: curr_row - window_rows + 1 may be < FIRST_ROW, this
117
* must be clipped before using window_rows:
119
* actual_rows = MIN (curr_row - FIRST_ROW + 1, window_rows);
121
* We won't do that at the RUx command because usually a PAC
122
* command follows which may change curr_row.
124
unsigned int window_rows;
126
/* Most recently received PAC command. */
127
unsigned int last_pac;
130
* This variable counts successive transmissions of the
131
* letters A to Z. It is reset to zero upon reception of any
134
* Some stations do not transmit EIA 608-B extended characters
135
* and except for N with tilde the standard and special
136
* character sets contain only lower case accented
137
* characters. We force these characters to upper case if this
138
* variable indicates live caption, where the text is usually
141
unsigned int uppercase_predictor;
143
/** Current caption mode or VBI_CC608_MODE_UNKNOWN. */
144
_vbi_cc608_mode mode;
147
* The time when we last received data for this
148
* channel. Intended to detect if this caption channel is
151
struct timestamp timestamp;
154
* The time when we received the first (but not necessarily
155
* leftmost) character in the current row. Unless the mode is
156
* VBI_CC608_MODE_POP_ON the next stream event will carry this
159
struct timestamp timestamp_c0;
162
struct _vbi_cc608_decoder {
164
* Decoder state. We decode all channels in parallel, this way
165
* clients can switch between channels without data loss or
166
* capture multiple channels with a single decoder instance.
168
* Also 47 CFR 15.119 and EIA 608-C require us to remember the
169
* cursor position on each channel.
171
struct channel channel[MAX_CHANNELS];
174
* Current channel, switched by caption control codes. Can be
175
* one of @c VBI_CAPTION_CC1 (1) ... @c VBI_CAPTION_CC4 (4) or
176
* @c VBI_CAPTION_T1 (5) ... @c VBI_CAPTION_T4 (8) or @c
177
* UNKNOWN_CHANNEL (0) if no channel number was received yet.
179
vbi_pgno curr_ch_num[MAX_FIELDS];
182
* Caption control codes (two bytes) may repeat once for error
183
* correction. -1 if no repeated control code can be expected.
185
int expect_ctrl[MAX_FIELDS][2];
188
* Receiving XDS data, as opposed to caption / ITV data.
189
* There's no XDS data on the first field, we just use an
190
* array for convenience.
192
vbi_bool in_xds[MAX_FIELDS];
195
* Pointer into the channel[] array if a display update event
196
* shall be sent at the end of this iteration, @c NULL
197
* otherwise. Purpose is to suppress an event for the first of
198
* two displayable characters in a caption byte pair.
200
struct channel * event_pending;
203
* Remembers past parity errors: One bit for each call of
204
* vbi_cc608_decoder_feed(), most recent result in lsb. The
205
* idea is to disable the decoder if we detect too many
208
unsigned int error_history;
211
* The time when we last received data, including NUL bytes.
212
* Intended to detect if the station transmits any data on
215
struct timestamp timestamp;
217
_vbi_event_handler_list handlers;
220
/* 47 CFR 15.119 Mid-Row Codes, Preamble Address Codes.
221
EIA 608-B Table 3. */
222
static const vbi_color
224
VBI_WHITE, VBI_GREEN, VBI_BLUE, VBI_CYAN,
225
VBI_RED, VBI_YELLOW, VBI_MAGENTA,
227
/* Note Mid-Row Codes interpret this value as "Italics"; PACs
228
as "White Italics"; Background Attributes as "Black". */
232
/* 47 CFR 15.119 Preamble Address Codes. */
235
/* 0 */ 10, /* 0x1040 */
236
/* 1 */ -1, /* no function */
237
/* 2 */ 0, 1, 2, 3, /* 0x1140 ... 0x1260 */
238
/* 6 */ 11, 12, 13, 14, /* 0x1340 ... 0x1460 */
239
/* 10 */ 4, 5, 6, 7, 8, 9 /* 0x1540 ... 0x1760 */
244
_vbi_cc608_dump (FILE * fp,
248
const vbi_bool to_upper = FALSE;
249
const int repl_char = '?';
250
uint16_t ucs2_str[2];
257
fprintf (fp, "%02X%02X %02X%c%02X%c",
258
c1 & 0xFF, c2 & 0xFF,
259
c1 & 0x7F, vbi_unpar8 (c1) < 0 ? '*' : ' ',
260
c2 & 0x7F, vbi_unpar8 (c2) < 0 ? '*' : ' ');
262
/* Note we ignore wrong parity. */
267
fputs (" null\n", fp);
269
} else if (c1 < 0x10) {
271
fputs (" XDS packet end\n", fp);
273
fputs (" XDS packet start/continue\n", fp);
275
} else if (c1 >= 0x20) {
279
ucs2_str[i++] = vbi_caption_unicode (c1, to_upper);
281
ucs2_str[i++] = vbi_caption_unicode (c2, to_upper);
283
vbi_fputs_iconv_ucs2 (fp, vbi_locale_codeset (),
284
ucs2_str, i, repl_char);
285
fprintf (fp, "'%s\n",
286
(c2 > 0 && c2 < 0x20) ? " invalid" : "");
290
/* Some common bits. */
291
c = (c1 >> 3) & 1; /* channel */
292
f = c1 & 1; /* field */
293
u = c2 & 1; /* underline */
296
fputs (" invalid\n", fp);
298
} else if (c2 >= 0x40) {
303
/* Preamble Address Codes -- 001 crrr 1ri xxxu */
305
rrrr = (c1 & 7) * 2 + ((c2 & 0x20) > 0);
308
row = pac_row_map [rrrr];
310
fprintf (fp, " PAC ch=%u row=%d column=%u u=%u\n",
313
fprintf (fp, " PAC ch=%u row=%d color=%u u=%u\n",
320
/* Control codes -- 001 caaa 01x bbbu */
325
static const char mnemo [16 * 4] =
326
"BWO\0BWS\0BGO\0BGS\0"
327
"BBO\0BBS\0BCO\0BCS\0"
328
"BRO\0BRS\0BYO\0BYS\0"
329
"BMO\0BMS\0BAO\0BAS";
331
/* Backgr. Attr. Codes -- 001 c000 010 xxxt */
333
fprintf (fp, " %s ch=%u\n",
334
mnemo + (c2 & 0xF) * 4, c);
343
/* Mid-Row Codes -- 001 c001 010 xxxu */
346
fprintf (fp, " mid-row ch=%u color=%u u=%u\n",
349
/* Special Characters -- 001 c001 011 xxxx */
351
fprintf (fp, " special character ch=%u '", c);
352
ucs2_str[0] = vbi_caption_unicode
353
(0x1100 | c2, to_upper);
354
vbi_fputs_iconv_ucs2 (fp, vbi_locale_codeset (),
355
ucs2_str, 1, repl_char);
360
case 2: /* first group */
361
case 3: /* second group */
362
/* Extended Character Set -- 001 c01x 01x xxxx */
364
fprintf (fp, " extended character ch=%u '", c);
365
ucs2_str[0] = vbi_caption_unicode (c1 * 256 + c2, to_upper);
366
vbi_fputs_iconv_ucs2 (fp, vbi_locale_codeset (),
367
ucs2_str, 1, repl_char);
374
static const char mnemo [16 * 4] =
375
"RCL\0BS \0AOF\0AON\0"
376
"DER\0RU2\0RU3\0RU4\0"
377
"FON\0RDC\0TR \0RTD\0"
378
"EDM\0CR \0ENM\0EOC";
380
/* Misc. Control Codes -- 001 c10f 010 xxxx */
382
fprintf (fp, " %s ch=%u f=%u\n",
383
mnemo + (c2 & 0xF) * 4, c, f);
388
case 6: /* reserved */
396
fprintf (fp, " TO%u ch=%u\n", c2 - 0x20, c);
400
fprintf (fp, " BT ch=%u\n", c);
404
fprintf (fp, " FA ch=%u\n", c);
408
fprintf (fp, " FAU ch=%u\n", c);
417
fprintf (fp, " unknown\n");
422
VBI_UNDERLINE = (1 << 0),
423
VBI_ITALIC = (1 << 2),
428
vbi_char_copy_attr (struct vbi_char * cp1,
429
const struct vbi_char *cp2,
432
if (attr & VBI_UNDERLINE)
433
cp1->underline = cp2->underline;
434
if (attr & VBI_ITALIC)
435
cp1->italic = cp2->italic;
436
if (attr & VBI_FLASH)
437
cp1->flash = cp2->flash;
441
vbi_char_clear_attr (struct vbi_char * cp,
444
if (attr & VBI_UNDERLINE)
446
if (attr & VBI_ITALIC)
448
if (attr & VBI_FLASH)
453
vbi_char_set_attr (struct vbi_char * cp,
456
if (attr & VBI_UNDERLINE)
458
if (attr & VBI_ITALIC)
460
if (attr & VBI_FLASH)
464
_vbi_inline unsigned int
465
vbi_char_has_attr (const struct vbi_char *cp,
468
attr &= (VBI_UNDERLINE | VBI_ITALIC | VBI_FLASH);
470
if (0 == cp->underline)
471
attr &= ~VBI_UNDERLINE;
480
_vbi_inline unsigned int
481
vbi_char_xor_attr (const struct vbi_char *cp1,
482
const struct vbi_char *cp2,
485
attr &= (VBI_UNDERLINE | VBI_ITALIC | VBI_FLASH);
487
if (0 == (cp1->underline ^ cp2->underline))
488
attr &= ~VBI_UNDERLINE;
489
if (0 == (cp1->italic ^ cp2->italic))
491
if (0 == (cp1->flash ^ cp2->flash))
498
timestamp_reset (struct timestamp * ts)
505
timestamp_is_set (const struct timestamp *ts)
507
return (ts->pts >= 0 || ts->sys > 0.0);
511
channel_num (const _vbi_cc608_decoder *cd,
512
const struct channel * ch)
514
return (ch - cd->channel) + 1;
517
/* This implementation of character attributes is based on 47 CFR
518
15.119 (h) and the following sections of EIA 608-B:
520
EIA 608-B Annex C.7 "Preamble Address Codes and Tab Offsets
521
(Regulatory/Preferred)": "In general, Preamble Address Codes (PACs)
522
have no immediate effect on the display. A major exception is the
523
receipt of a PAC during roll-up captioning. In that case, if the
524
base row designated in the PAC is not the same as the current base
525
row, the display shall be moved immediately to the new base
526
row. [...] An indenting PAC carries the attributes of white,
527
non-italicized, and it sets underlining on or off. Tab Offset
528
commands do not change these attributes. If an indenting PAC with
529
underline ON is received followed by a Tab Offset and by text, the
530
text shall be underlined (except as noted below). When a
531
displayable character is received, it is deposited at the current
532
cursor position. If there is already a displayable character in the
533
column immediately to the left, the new character assumes the
534
attributes of that character. The new character may be arriving as
535
the result of an indenting PAC (with or without a Tab Offset), and
536
that PAC may designate other attributes, but the new character is
537
forced to assume the attributes of the character immediately to its
538
left, and the PAC's attributes are ignored. If, when a displayable
539
character is received, it overwrites an existing PAC or mid-row
540
code, and there are already characters to the right of the new
541
character, these existing characters shall assume the same
542
attributes as the new character. This adoption can result in a
543
whole caption row suddenly changing color, underline, italics,
544
and/or flash attributes."
546
EIA 608-B Annex C.14 "Special Cases Regarding Attributes
547
(Normative)": "In most cases, Preamble Address Codes shall set
548
attributes for the caption elements they address. It is
549
theoretically possible for a service provider to use an indenting
550
PAC to start a row at Column 5 or greater, and then to use
551
Backspace to move the cursor to the left of the PAC into an area to
552
which no attributes have been assigned. It is also possible for a
553
roll-up row, having been created by a Carriage Return, to receive
554
characters with no PAC used to set attributes. In these cases, and
555
in any other case where no explicit attributes have been assigned,
556
the display shall be white, non-underlined, non-italicized, and
557
non-flashing. In case new displayable characters are received
558
immediately after a Delete to End of Row (DER), the display
559
attributes of the first deleted character shall remain in effect if
560
there is a displayable character to the left of the cursor;
561
otherwise, the most recently received PAC shall set the display
564
47 CFR 15.119 (n) clarifies that Special Character "transparent
565
space" is not a "displayable character". */
569
* @param to_upper Convert the lower case Latin characters in the
570
* standard character set to upper case.
571
* @param padding Add spaces around words for improved legibility
572
* as defined in 47 CFR 15.119. If @c TRUE the resulting page will
573
* be 34 columns wide, otherwise 32 columns. The height is always 15
575
* @param alpha Add an offset to the vbi_color of characters: +0 for
576
* opaque, +8 for translucent, +16 for transparent characters. Intended
577
* for formatting with an alpha color map.
580
format_row (struct vbi_char * cp,
581
unsigned int max_columns,
582
const struct channel * ch,
590
struct vbi_char ac_ts;
594
/* 47 CFR 15.119 (h)(1). EIA 608-B Section 6.4. */
596
ac.opacity = VBI_OPAQUE;
597
ac.foreground = VBI_WHITE;
598
ac.background = VBI_BLACK;
601
ac_ts.unicode = 0x20;
602
ac_ts.opacity = VBI_TRANSPARENT_SPACE;
604
ac_ts.foreground += 16;
605
ac_ts.background += 16;
608
end = cp + MAX_COLUMNS;
612
assert (end <= cp + max_columns);
615
if (0 == (ch->dirty[buffer] & (1 << row))) {
626
for (i = FIRST_COLUMN - 1; i <= LAST_COLUMN; ++i) {
631
c = ch->buffer[buffer][row][i];
634
&& VBI_TRANSPARENT_SPACE != cp[-1].opacity
635
&& 0x20 != cp[-1].unicode) {
636
/* Append a space with the same colors
637
and opacity (opaque or transp.
638
backgr.) as the text to the left of
641
/* We don't underline spaces, see
643
vbi_char_clear_attr (cp - 1, -1);
646
cp[-1].opacity = VBI_TRANSPARENT_SPACE;
649
16 + (ac.foreground & 7);
651
16 + (ac.background & 7);
656
} else if (c < 0x1020) {
658
&& VBI_TRANSPARENT_SPACE == cp[-1].opacity) {
659
/* Prepend a space with the same
660
colors and opacity (opaque or
661
transp. backgr.) as the text to the
664
/* We don't underline spaces, see
666
vbi_char_clear_attr (cp - 1, -1);
669
if ((c >= 'a' && c <= 'z')
670
|| 0x7E == c /* n with tilde */) {
671
/* We do not force these characters to
672
upper case because the standard
673
character set includes upper case
674
versions of these characters and
675
lower case was probably
676
deliberately transmitted. */
677
ac.unicode = vbi_caption_unicode
678
(c, /* to_upper */ FALSE);
680
ac.unicode = vbi_caption_unicode
683
} else if (c < 0x1040) {
686
/* Backgr. Attr. Codes -- 001 c000 010 xxxt */
687
/* EIA 608-B Section 6.2. */
689
/* This is a set-at spacing attribute. */
691
color = (c >> 1) & 7;
692
ac.background = color_map[color];
697
ac.opacity = VBI_SEMI_TRANSPARENT;
699
ac.opacity = VBI_OPAQUE;
701
} else if (c < 0x1120) {
702
/* Preamble Address Codes -- 001 crrr 1ri xxxu */
704
/* PAC is a non-spacing attribute and only
705
stored in the buffer at the addressed
706
column minus one if it replaces a
707
transparent space (EIA 608-B Annex C.7,
708
C.14). There's always a transparent space
709
to the left of the first column but we show
710
this zeroth column only if padding is
713
&& VBI_TRANSPARENT_SPACE != cp[-1].opacity
714
&& 0x20 != cp[-1].unicode) {
717
vbi_char_clear_attr (cp - 1, -1);
720
cp[-1].opacity = VBI_TRANSPARENT_SPACE;
723
16 + (ac.foreground & 7);
725
16 + (ac.background & 7);
729
vbi_char_clear_attr (&ac, VBI_UNDERLINE | VBI_ITALIC);
731
vbi_char_set_attr (&ac, VBI_UNDERLINE);
733
ac.foreground = VBI_WHITE;
737
color = (c >> 1) & 7;
739
ac.foreground = VBI_WHITE;
740
vbi_char_set_attr (&ac, VBI_ITALIC);
742
ac.foreground = color_map[color];
747
} else if (c < 0x1130) {
750
/* Mid-Row Codes -- 001 c001 010 xxxu */
751
/* 47 CFR 15.119 Mid-Row Codes table,
752
(h)(1)(ii), (h)(1)(iii). */
754
/* 47 CFR 15.119 (h)(1)(i), EIA 608-B Section
755
6.2: Mid-Row codes, FON, BT, FA and FAU are
756
set-at spacing attributes. */
758
vbi_char_clear_attr (&ac, -1);
760
vbi_char_set_attr (&ac, VBI_UNDERLINE);
761
color = (c >> 1) & 7;
763
vbi_char_set_attr (&ac, VBI_ITALIC);
765
ac.foreground = color_map[color];
767
} else if (c < 0x1220) {
768
/* Special Characters -- 001 c001 011 xxxx */
769
/* 47 CFR 15.119 Character Set Table. */
772
&& VBI_TRANSPARENT_SPACE == cp[-1].opacity) {
774
vbi_char_clear_attr (cp - 1, -1);
777
assert (0x1139 /* transparent space */ != c);
778
ac.unicode = vbi_caption_unicode (c, to_upper);
779
} else if (c < 0x1428) {
780
/* Extended Character Set -- 001 c01x 01x xxxx */
781
/* EIA 608-B Section 6.4.2 */
784
&& VBI_TRANSPARENT_SPACE == cp[-1].opacity) {
786
vbi_char_clear_attr (cp - 1, -1);
789
/* We do not force these characters to upper
790
case because the extended character set
791
includes upper case versions of all letters
792
and lower case was probably deliberately
794
ac.unicode = vbi_caption_unicode
795
(c, /* to_upper */ FALSE);
797
if (0x2500 == (ac.unicode & 0xFFE0)) {
798
/* Box drawing characters probably
799
shouldn't have these attributes. */
801
vbi_char_clear_attr (cp - 1,
806
} else if (c < 0x172D) {
807
/* FON Flash On -- 001 c10f 010 1000 */
808
/* 47 CFR 15.119 (h)(1)(iii). */
810
vbi_char_set_attr (&ac, VBI_FLASH);
811
} else if (c < 0x172E) {
812
/* BT Background Transparent -- 001 c111 010 1101 */
813
/* EIA 608-B Section 6.4. */
815
ac.opacity = VBI_TRANSPARENT_FULL;
817
ac.background = 16 + (ac.background & 7);
819
} else if (c <= 0x172F) {
820
/* FA Foreground Black -- 001 c111 010 111u */
821
/* EIA 608-B Section 6.4. */
823
vbi_char_clear_attr (&ac, -1);
825
vbi_char_set_attr (&ac, VBI_UNDERLINE);
826
ac.foreground = VBI_BLACK;
831
/* 47 CFR 15.119 and EIA 608-B are silent about
832
underlined spaces, but considering the example in
833
47 CFR (h)(1)(iv) which would produce something
834
ugly like "__text" I suppose we should not
835
underline them. For good measure we also clear the
836
invisible italic and flash attribute. */
837
if (0x20 == ac.unicode)
838
vbi_char_clear_attr (cp - 1, -1);
843
vbi_char_clear_attr (&ac, -1);
845
if (VBI_TRANSPARENT_SPACE != cp[-1].opacity
846
&& 0x20 != cp[-1].unicode) {
849
ac.opacity = VBI_TRANSPARENT_SPACE;
850
ac.foreground = 16 + (ac.foreground & 7);
851
ac.background = 16 + (ac.background & 7);
860
# define VBI_RGBA(r, g, b) \
861
((((r) & 0xFF) << 0) | (((g) & 0xFF) << 8) \
862
| (((b) & 0xFF) << 16) | (0xFF << 24))
866
* @param cd Caption decoder allocated with vbi_cc608_decoder_new().
867
* @param pg The display state will be stored here.
868
* @param channel Caption channel @c VBI_CHANNEL_CC1 ...
869
* @c VBI_CHANNEL_CC4 or @c VBI_CHANNEL_T1 ... @c VBI_CHANNEL_T4.
870
* @param padding Add spaces around words for improved legibility
871
* as defined in 47 CFR 15.119. If @c TRUE the resulting page will
872
* be 34 columns wide, otherwise 32 columns. The height is always 15
875
* This function stores the current display state of the given caption
876
* channel in the @a pg structure. (There is no channel switch
877
* function; all channels are decoded simultaneously.)
879
* All fields of @a pg will be initialized but the @a vbi, @a nuid, @a
880
* dirty, @a nav_link, @a nav_index, and @a font fields will not
881
* contain useful information.
884
* @c FALSE on failure: The channel number is out of bounds.
887
_vbi_cc608_decoder_get_page (_vbi_cc608_decoder * cd,
892
static const vbi_rgba default_color_map [3 * 8] = {
893
0xFF000000, 0xFF0000FF, 0xFF00FF00, 0xFF00FFFF,
894
0xFFFF0000, 0xFFFF00FF, 0xFFFFFF00, 0xFFFFFFFF,
896
0x80000000, 0x800000FF, 0x8000FF00, 0x8000FFFF,
897
0x80FF0000, 0x80FF00FF, 0x80FFFF00, 0x80FFFFFF,
899
0x00000000, 0x000000FF, 0x0000FF00, 0x0000FFFF,
900
0x00FF0000, 0x00FF00FF, 0x00FFFF00, 0x00FFFFFF,
910
if (channel < VBI_CAPTION_CC1 || channel > VBI_CAPTION_T4)
913
ch = &cd->channel[channel - VBI_CAPTION_CC1];
922
pg->columns = MAX_COLUMNS + 2;
924
pg->columns = MAX_COLUMNS;
926
assert (N_ELEMENTS (pg->text) >= MAX_ROWS * (MAX_COLUMNS + 2));
928
pg->dirty.y1 = LAST_ROW;
930
pg->screen_opacity = VBI_TRANSPARENT_SPACE;
932
assert (sizeof (pg->color_map) >= sizeof (default_color_map));
933
memcpy (pg->color_map, default_color_map,
934
sizeof (default_color_map));
938
to_upper = (ch->uppercase_predictor > 3);
940
for (row = 0; row < MAX_ROWS; ++row) {
941
format_row (cp, pg->columns,
942
ch, ch->displayed_buffer,
943
row, to_upper, padding,
953
display_event (_vbi_cc608_decoder * cd,
955
_vbi_cc608_event_flags flags)
958
struct _vbi_event_cc608_page cc608;
962
ev.type = _VBI_EVENT_CC608;
963
ev.ev._cc608 = &cc608;
964
cc608.channel = channel_num (cd, ch);
965
cc608.mode = ch->mode;
968
_vbi_event_handler_list_send (&cd->handlers, &ev);
971
/* This decoder is mainly designed to overlay caption onto live video,
972
but to create transcripts we also offer an event every time a line
973
of caption is complete. The event occurs when certain control codes
976
In POP_ON mode we send the event upon reception of EOC, which swaps
977
the displayed and non-displayed memory.
979
In ROLL_UP and TEXT mode captioners are not expected to display new
980
text by erasing and overwriting a row with PAC, TOx, BS and DER so
981
we do not send an event on reception of these codes. In ROLL_UP
982
mode CR, EDM, EOC, RCL and RDC complete a line: CR moves the cursor
983
to a new row, EDM erases the displayed memory. The remaining codes
984
switch to POP_ON or PAINT_ON mode. In TEXT mode CR and TR are our
985
line completion indicators. CR works as above and TR erases the
986
displayed memory. EDM, EOC, RDC, RCL and RUx have no effect on Text
987
channels according to EIA 608.
989
In PAINT_ON mode RDC never erases the displayed memory and CR has
990
no function. Instead captioners can freely position the cursor and
991
erase or overwrite (parts of) rows with PAC, TOx, BS and DER, or
992
erase all rows with EDM. We send an event on PAC, EDM, EOC, RCL and
993
RUx, provided the characters (including spacing attributes) in the
994
current row changed since the last event: PAC is the only control
995
code which can move the cursor to the left and/or to a new row, and
996
likely to introduce a new line. EOC, RCL and RUx switch to POP_ON
1000
stream_event (_vbi_cc608_decoder * cd,
1001
struct channel * ch,
1002
unsigned int first_row,
1003
unsigned int last_row)
1006
struct _vbi_event_cc608_stream cc608_stream;
1012
ev.type = _VBI_EVENT_CC608_STREAM;
1013
ev.ev._cc608_stream = &cc608_stream;
1014
cc608_stream.capture_time = ch->timestamp_c0.sys;
1015
cc608_stream.pts = ch->timestamp_c0.pts;
1016
cc608_stream.channel = channel_num (cd, ch);
1017
cc608_stream.mode = ch->mode;
1019
to_upper = (ch->uppercase_predictor > 3);
1021
for (row = first_row; row <= last_row; ++row) {
1024
format_row (cc608_stream.text,
1025
N_ELEMENTS (cc608_stream.text),
1026
ch, ch->displayed_buffer,
1028
/* padding */ FALSE,
1031
for (end = N_ELEMENTS (cc608_stream.text);
1033
if (VBI_TRANSPARENT_SPACE
1034
!= cc608_stream.text[end - 1].opacity)
1041
_vbi_event_handler_list_send (&cd->handlers, &ev);
1044
timestamp_reset (&ch->timestamp_c0);
1048
put_char (_vbi_cc608_decoder * cd,
1049
struct channel * ch,
1051
vbi_bool displayable,
1055
unsigned int curr_buffer;
1057
unsigned int column;
1059
/* 47 CFR Section 15.119 (f)(1), (f)(2), (f)(3). */
1060
curr_buffer = ch->displayed_buffer
1061
^ (_VBI_CC608_MODE_POP_ON == ch->mode);
1064
column = ch->curr_column;
1066
if (unlikely (backspace)) {
1067
/* 47 CFR 15.119 (f)(1)(vi), (f)(2)(ii),
1068
(f)(3)(i). EIA 608-B Section 6.4.2, 7.4. */
1069
if (column > FIRST_COLUMN)
1072
/* 47 CFR 15.119 (f)(1)(v), (f)(1)(vi), (f)(2)(ii),
1073
(f)(3)(i). EIA 608-B Section 7.4. */
1074
if (column < LAST_COLUMN)
1075
ch->curr_column = column + 1;
1078
text = &ch->buffer[curr_buffer][row][0];
1081
/* Send a display update event when the displayed buffer of
1082
the current channel changed, but no more than once for each
1083
pair of Closed Caption bytes. */
1084
/* XXX This may not be a visible change, but such cases are
1085
rare and we'd probably need a function almost as complex as
1086
format_row() to find out. */
1087
if (_VBI_CC608_MODE_POP_ON != ch->mode) {
1088
cd->event_pending = ch;
1091
if (likely (displayable)) {
1092
/* EIA 608-B Annex C.7, C.14. */
1093
if (FIRST_COLUMN == column
1094
|| 0 == text[column - 1]) {
1095
/* Note last_pac may be 0 as well. */
1096
text[column - 1] = ch->last_pac;
1099
if (c >= 'a' && c <= 'z') {
1100
ch->uppercase_predictor = 0;
1101
} else if (c >= 'A' && c <= 'Z') {
1104
up = ch->uppercase_predictor + 1;
1106
ch->uppercase_predictor = up;
1108
} else if (unlikely (0 == c)) {
1111
/* This is special character "transparent space". */
1113
for (i = FIRST_COLUMN; i <= LAST_COLUMN; ++i)
1114
c |= ch->buffer[curr_buffer][row][i];
1116
ch->dirty[curr_buffer] &= ~((0 == c) << row);
1120
/* This is a spacing attribute. */
1122
/* EIA 608-B Annex C.7, C.14. */
1123
if (FIRST_COLUMN == column
1124
|| 0 == text[column - 1]) {
1125
/* Note last_pac may be 0 as well. */
1126
text[column - 1] = ch->last_pac;
1130
assert (sizeof (ch->dirty[0]) * 8 - 1 >= MAX_ROWS);
1131
ch->dirty[curr_buffer] |= 1 << row;
1133
if (!timestamp_is_set (&ch->timestamp_c0)) {
1134
ch->timestamp_c0 = cd->timestamp;
1139
ext_control_code (_vbi_cc608_decoder * cd,
1140
struct channel * ch,
1143
unsigned int column;
1146
case 0x21: /* TO1 */
1147
case 0x22: /* TO2 */
1148
case 0x23: /* TO3 Tab Offset -- 001 c111 010 00xx */
1149
/* 47 CFR 15.119 (e)(1)(ii). EIA 608-B Section 7.4,
1151
column = ch->curr_column + (c2 & 3);
1152
ch->curr_column = MIN (column,
1153
(unsigned int) LAST_COLUMN);
1156
case 0x24: /* Select standard character set in normal size */
1157
case 0x25: /* Select standard character set in double size */
1158
case 0x26: /* Select first private character set */
1159
case 0x27: /* Select second private character set */
1160
case 0x28: /* Select character set GB 2312-80 (Chinese) */
1161
case 0x29: /* Select character set KSC 5601-1987 (Korean) */
1162
case 0x2A: /* Select first registered character set. */
1163
/* EIA 608-B Section 6.3 Closed Group Extensions. */
1166
case 0x2D: /* BT Background Transparent -- 001 c111 010 1101 */
1167
case 0x2E: /* FA Foreground Black -- 001 c111 010 1110 */
1168
case 0x2F: /* FAU Foregr. Black Underl. -- 001 c111 010 1111 */
1169
/* EIA 608-B Section 6.2. */
1170
put_char (cd, ch, 0x1700 | c2,
1171
/* displayable */ FALSE,
1172
/* backspace */ TRUE);
1176
/* 47 CFR Section 15.119 (j): Ignore. */
1181
/* Send a stream event if the current row has changed since the last
1182
stream event. This is necessary in paint-on mode where CR has no
1183
function and captioners can freely position the cursor to erase or
1184
overwrite (parts of) rows. */
1186
stream_event_if_changed (_vbi_cc608_decoder * cd,
1187
struct channel * ch)
1189
unsigned int curr_buffer;
1193
curr_buffer = ch->displayed_buffer;
1196
if (0 == (ch->dirty[curr_buffer] & (1 << row)))
1199
for (i = FIRST_COLUMN; i <= LAST_COLUMN; ++i) {
1203
c1 = ch->buffer[curr_buffer][row][i];
1206
c1 = 0; /* PAC -- non-spacing */
1207
} else if (c1 < 0x1130 || c1 >= 0x1428) {
1208
/* MR, FON, BT, FA, FAU -- spacing */
1213
c2 = ch->buffer[2][row][i];
1217
} else if (c2 < 0x1130 || c2 >= 0x1428) {
1223
stream_event (cd, ch, row, row);
1225
memcpy (ch->buffer[2][row],
1226
ch->buffer[curr_buffer][row],
1227
sizeof (ch->buffer[0][0]));
1229
ch->dirty[2] = ch->dirty[curr_buffer];
1237
end_of_caption (_vbi_cc608_decoder * cd,
1238
struct channel * ch)
1240
unsigned int curr_buffer;
1243
/* EOC End Of Caption -- 001 c10f 010 1111 */
1245
curr_buffer = ch->displayed_buffer;
1248
case _VBI_CC608_MODE_UNKNOWN:
1249
case _VBI_CC608_MODE_POP_ON:
1252
case _VBI_CC608_MODE_ROLL_UP:
1254
if (0 != (ch->dirty[curr_buffer] & (1 << row)))
1255
stream_event (cd, ch, row, row);
1258
case _VBI_CC608_MODE_PAINT_ON:
1259
stream_event_if_changed (cd, ch);
1262
case _VBI_CC608_MODE_TEXT:
1263
/* Not reached. (ch is a caption channel.) */
1267
ch->displayed_buffer = curr_buffer ^= 1;
1269
/* 47 CFR Section 15.119 (f)(2). */
1270
ch->mode = _VBI_CC608_MODE_POP_ON;
1272
if (0 != ch->dirty[curr_buffer]) {
1273
ch->timestamp_c0 = cd->timestamp;
1275
stream_event (cd, ch,
1279
display_event (cd, ch, /* flags */ 0);
1284
carriage_return (_vbi_cc608_decoder * cd,
1285
struct channel * ch)
1287
unsigned int curr_buffer;
1289
unsigned int window_rows;
1290
unsigned int first_row;
1292
/* CR Carriage Return -- 001 c10f 010 1101 */
1294
curr_buffer = ch->displayed_buffer;
1298
case _VBI_CC608_MODE_UNKNOWN:
1301
case _VBI_CC608_MODE_ROLL_UP:
1302
/* 47 CFR Section 15.119 (f)(1)(iii). */
1303
ch->curr_column = FIRST_COLUMN;
1305
/* 47 CFR 15.119 (f)(1): "The cursor always remains on
1311
/* No event if the buffer contains only
1312
TRANSPARENT_SPACEs. */
1313
if (0 == ch->dirty[curr_buffer])
1316
window_rows = MIN (row + 1 - FIRST_ROW,
1320
case _VBI_CC608_MODE_POP_ON:
1321
case _VBI_CC608_MODE_PAINT_ON:
1322
/* 47 CFR 15.119 (f)(2)(i), (f)(3)(i): No effect. */
1325
case _VBI_CC608_MODE_TEXT:
1326
/* 47 CFR Section 15.119 (f)(1)(iii). */
1327
ch->curr_column = FIRST_COLUMN;
1332
/* EIA 608-B Section 7.4: "When Text Mode has
1333
initially been selected and the specified Text
1334
memory is empty, the cursor starts at the topmost
1335
row, Column 1, and moves down to Column 1 on the
1336
next row each time a Carriage Return is received
1337
until the last available row is reached. A variety
1338
of methods may be used to accomplish the scrolling,
1339
provided that the text is legible while moving. For
1340
example, as soon as all of the available rows of
1341
text are on the screen, Text Mode switches to the
1342
standard roll-up type of presentation." */
1344
if (LAST_ROW != row) {
1345
if (0 != (ch->dirty[curr_buffer] & (1 << row))) {
1346
stream_event (cd, ch, row, row);
1349
ch->curr_row = row + 1;
1354
/* No event if the buffer contains all
1355
TRANSPARENT_SPACEs. */
1356
if (0 == ch->dirty[curr_buffer])
1359
window_rows = MAX_ROWS;
1364
/* 47 CFR Section 15.119 (f)(1)(iii). */
1366
if (0 != (ch->dirty[curr_buffer] & (1 << row))) {
1367
stream_event (cd, ch, row, row);
1370
first_row = row + 1 - window_rows;
1371
memmove (ch->buffer[curr_buffer][first_row],
1372
ch->buffer[curr_buffer][first_row + 1],
1373
(window_rows - 1) * sizeof (ch->buffer[0][0]));
1375
ch->dirty[curr_buffer] >>= 1;
1377
memset (ch->buffer[curr_buffer][row], 0,
1378
sizeof (ch->buffer[0][0]));
1380
/* See the description of VBI_CC608_START_ROLLING and
1381
test/caption for the expected effect. */
1382
display_event (cd, ch, _VBI_CC608_START_ROLLING);
1386
erase_memory (_vbi_cc608_decoder * cd,
1387
struct channel * ch,
1388
unsigned int buffer)
1390
if (0 != ch->dirty[buffer]) {
1391
CLEAR (ch->buffer[buffer]);
1393
ch->dirty[buffer] = 0;
1395
if (buffer == ch->displayed_buffer)
1396
display_event (cd, ch, /* flags */ 0);
1401
erase_displayed_memory (_vbi_cc608_decoder * cd,
1402
struct channel * ch)
1406
/* EDM Erase Displayed Memory -- 001 c10f 010 1100 */
1409
case _VBI_CC608_MODE_UNKNOWN:
1410
/* We have not received EOC, RCL, RDC or RUx yet, but
1414
case _VBI_CC608_MODE_ROLL_UP:
1416
if (0 != (ch->dirty[ch->displayed_buffer] & (1 << row)))
1417
stream_event (cd, ch, row, row);
1420
case _VBI_CC608_MODE_PAINT_ON:
1421
stream_event_if_changed (cd, ch);
1424
case _VBI_CC608_MODE_POP_ON:
1425
/* Nothing to do. */
1428
case _VBI_CC608_MODE_TEXT:
1429
/* Not reached. (ch is a caption channel.) */
1433
/* May send a display event. */
1434
erase_memory (cd, ch, ch->displayed_buffer);
1438
text_restart (_vbi_cc608_decoder * cd,
1439
struct channel * ch)
1441
unsigned int curr_buffer;
1444
/* TR Text Restart -- 001 c10f 010 1010 */
1446
curr_buffer = ch->displayed_buffer;
1449
/* ch->mode is invariably VBI_CC608_MODE_TEXT. */
1451
if (0 != (ch->dirty[curr_buffer] & (1 << row))) {
1452
stream_event (cd, ch, row, row);
1455
/* EIA 608-B Section 7.4. */
1456
/* May send a display event. */
1457
erase_memory (cd, ch, ch->displayed_buffer);
1459
/* EIA 608-B Section 7.4. */
1460
ch->curr_row = FIRST_ROW;
1461
ch->curr_column = FIRST_COLUMN;
1465
resume_direct_captioning (_vbi_cc608_decoder * cd,
1466
struct channel * ch)
1468
unsigned int curr_buffer;
1471
/* RDC Resume Direct Captioning -- 001 c10f 010 1001 */
1473
/* 47 CFR 15.119 (f)(1)(x), (f)(2)(vi) and EIA 608-B Annex
1474
B.7: Does not erase memory, does not move the cursor when
1475
resuming after a Text transmission.
1477
XXX If ch->mode is unknown, roll-up or pop-on, what is
1478
expected if no PAC is received between RDC and the text? */
1480
curr_buffer = ch->displayed_buffer;
1484
case _VBI_CC608_MODE_ROLL_UP:
1485
if (0 != (ch->dirty[curr_buffer] & (1 << row)))
1486
stream_event (cd, ch, row, row);
1490
case _VBI_CC608_MODE_UNKNOWN:
1491
case _VBI_CC608_MODE_POP_ON:
1492
/* No change since last stream_event(). */
1493
memcpy (ch->buffer[2], ch->buffer[curr_buffer],
1494
sizeof (ch->buffer[2]));
1497
case _VBI_CC608_MODE_PAINT_ON:
1498
/* Mode continues. */
1501
case _VBI_CC608_MODE_TEXT:
1502
/* Not reached. (ch is a caption channel.) */
1506
ch->mode = _VBI_CC608_MODE_PAINT_ON;
1510
resize_window (_vbi_cc608_decoder * cd,
1511
struct channel * ch,
1512
unsigned int new_rows)
1514
unsigned int curr_buffer;
1515
unsigned int max_rows;
1516
unsigned int old_rows;
1519
curr_buffer = ch->displayed_buffer;
1522
if (0 == ch->dirty[curr_buffer])
1525
row1 = ch->curr_row + 1;
1526
max_rows = row1 - FIRST_ROW;
1527
old_rows = MIN (ch->window_rows, max_rows);
1528
new_rows = MIN (new_rows, max_rows);
1530
/* Nothing to do unless the window shrinks. */
1531
if (0 == new_rows || new_rows >= old_rows)
1534
memset (&ch->buffer[curr_buffer][row1 - old_rows][0], 0,
1535
(old_rows - new_rows)
1536
* sizeof (ch->buffer[0][0]));
1538
ch->dirty[curr_buffer] &= -1 << (row1 - new_rows);
1540
display_event (cd, ch, /* flags */ 0);
1544
roll_up_caption (_vbi_cc608_decoder * cd,
1545
struct channel * ch,
1548
unsigned int window_rows;
1550
/* Roll-Up Captions -- 001 c10f 010 01xx */
1552
window_rows = (c2 & 7) - 3; /* 2, 3, 4 */
1555
case _VBI_CC608_MODE_ROLL_UP:
1556
/* 47 CFR 15.119 (f)(1)(iv). */
1557
/* May send a display event. */
1558
resize_window (cd, ch, window_rows);
1562
case _VBI_CC608_MODE_UNKNOWN:
1563
ch->mode = _VBI_CC608_MODE_ROLL_UP;
1564
ch->window_rows = window_rows;
1566
/* 47 CFR 15.119 (f)(1)(ix): No cursor movements,
1567
no memory erasing. */
1571
case _VBI_CC608_MODE_PAINT_ON:
1572
stream_event_if_changed (cd, ch);
1576
case _VBI_CC608_MODE_POP_ON:
1577
ch->mode = _VBI_CC608_MODE_ROLL_UP;
1578
ch->window_rows = window_rows;
1580
/* 47 CFR 15.119 (f)(1)(ii). */
1581
ch->curr_row = LAST_ROW;
1582
ch->curr_column = FIRST_COLUMN;
1584
/* 47 CFR 15.119 (f)(1)(x). */
1585
/* May send a display event. */
1586
erase_memory (cd, ch, ch->displayed_buffer);
1587
erase_memory (cd, ch, ch->displayed_buffer ^ 1);
1591
case _VBI_CC608_MODE_TEXT:
1592
/* Not reached. (ch is a caption channel.) */
1598
delete_to_end_of_row (_vbi_cc608_decoder * cd,
1599
struct channel * ch)
1601
unsigned int curr_buffer;
1604
/* DER Delete To End Of Row -- 001 c10f 010 0100 */
1606
/* 47 CFR 15.119 (f)(1)(vii), (f)(2)(iii), (f)(3)(ii) and EIA
1607
608-B Section 7.4: In all caption modes and Text mode
1608
"[the] Delete to End of Row command will erase from memory
1609
any characters or control codes starting at the current
1610
cursor location and in all columns to its right on the same
1613
curr_buffer = ch->displayed_buffer
1614
^ (_VBI_CC608_MODE_POP_ON == ch->mode);
1618
/* No event if the row contains only TRANSPARENT_SPACEs. */
1619
if (0 != (ch->dirty[curr_buffer] & (1 << row))) {
1620
unsigned int column;
1624
column = ch->curr_column;
1626
memset (&ch->buffer[curr_buffer][row][column], 0,
1627
(LAST_COLUMN - column + 1)
1628
* sizeof (ch->buffer[0][0][0]));
1631
for (i = FIRST_COLUMN; i < column; ++i)
1632
c |= ch->buffer[curr_buffer][row][i];
1634
ch->dirty[curr_buffer] &= ~((0 == c) << row);
1636
display_event (cd, ch, /* flags */ 0);
1641
backspace (_vbi_cc608_decoder * cd,
1642
struct channel * ch)
1644
unsigned int curr_buffer;
1646
unsigned int column;
1648
/* BS Backspace -- 001 c10f 010 0001 */
1650
/* 47 CFR Section 15.119 (f)(1)(vi), (f)(2)(ii), (f)(3)(i) and
1651
EIA 608-B Section 7.4. */
1652
column = ch->curr_column;
1653
if (column <= FIRST_COLUMN)
1656
ch->curr_column = --column;
1658
curr_buffer = ch->displayed_buffer
1659
^ (_VBI_CC608_MODE_POP_ON == ch->mode);
1663
/* No event if there's no visible effect. */
1664
if (0 != ch->buffer[curr_buffer][row][column]) {
1668
/* 47 CFR 15.119 (f), (f)(1)(vi), (f)(2)(ii) and EIA
1669
608-B Section 7.4. */
1670
ch->buffer[curr_buffer][row][column] = 0;
1673
for (i = FIRST_COLUMN; i <= LAST_COLUMN; ++i)
1674
c |= ch->buffer[curr_buffer][row][i];
1676
ch->dirty[curr_buffer] &= ~((0 == c) << row);
1678
display_event (cd, ch, /* flags */ 0);
1683
resume_caption_loading (_vbi_cc608_decoder * cd,
1684
struct channel * ch)
1688
/* RCL Resume Caption Loading -- 001 c10f 010 0000 */
1691
case _VBI_CC608_MODE_UNKNOWN:
1692
case _VBI_CC608_MODE_POP_ON:
1695
case _VBI_CC608_MODE_ROLL_UP:
1697
if (0 != (ch->dirty[ch->displayed_buffer] & (1 << row)))
1698
stream_event (cd, ch, row, row);
1701
case _VBI_CC608_MODE_PAINT_ON:
1702
stream_event_if_changed (cd, ch);
1705
case _VBI_CC608_MODE_TEXT:
1706
/* Not reached. (ch is a caption channel.) */
1710
/* 47 CFR 15.119 (f)(1)(x): Does not erase memory.
1711
(f)(2)(iv): Cursor position remains unchanged. */
1713
ch->mode = _VBI_CC608_MODE_POP_ON;
1716
/* Note curr_ch is invalid if UNKNOWN_CHANNEL == cd->cc.curr_ch_num. */
1717
static struct channel *
1718
switch_channel (_vbi_cc608_decoder * cd,
1719
struct channel * curr_ch,
1720
vbi_pgno new_ch_num,
1723
struct channel *new_ch;
1725
if (UNKNOWN_CHANNEL != cd->curr_ch_num[f]
1726
&& _VBI_CC608_MODE_UNKNOWN != curr_ch->mode) {
1727
/* XXX Force a display update if we do not send events
1728
on every display change. */
1731
cd->curr_ch_num[f] = new_ch_num;
1732
new_ch = &cd->channel[new_ch_num - VBI_CAPTION_CC1];
1737
/* Note ch is invalid if UNKNOWN_CHANNEL == cd->cc.curr_ch_num[f]. */
1739
misc_control_code (_vbi_cc608_decoder * cd,
1740
struct channel * ch,
1742
unsigned int ch_num0,
1745
unsigned int new_ch_num;
1747
/* Misc Control Codes -- 001 c10f 010 xxxx */
1749
/* c = channel (0 -> CC1/CC3/T1/T3, 1 -> CC2/CC4/T2/T4)
1750
-- 47 CFR Section 15.119, EIA 608-B Section 7.7.
1751
f = field (0 -> F1, 1 -> F2)
1752
-- EIA 608-B Section 8.4, 8.5. */
1754
/* XXX The f flag is intended to detect accidential field
1755
swapping and we should use it for that purpose. */
1758
case 0: /* RCL Resume Caption Loading -- 001 c10f 010 0000 */
1759
/* 47 CFR 15.119 (f)(2) and EIA 608-B Section 7.7. */
1760
new_ch_num = VBI_CAPTION_CC1 + (ch_num0 & 3);
1761
ch = switch_channel (cd, ch, new_ch_num, f);
1762
resume_caption_loading (cd, ch);
1765
case 1: /* BS Backspace -- 001 c10f 010 0001 */
1766
if (UNKNOWN_CHANNEL == cd->curr_ch_num[f]
1767
|| _VBI_CC608_MODE_UNKNOWN == ch->mode)
1772
case 2: /* reserved (formerly AOF Alarm Off) */
1773
case 3: /* reserved (formerly AON Alarm On) */
1776
case 4: /* DER Delete To End Of Row -- 001 c10f 010 0100 */
1777
if (UNKNOWN_CHANNEL == cd->curr_ch_num[f]
1778
|| _VBI_CC608_MODE_UNKNOWN == ch->mode)
1780
delete_to_end_of_row (cd, ch);
1785
case 7: /* RU4 Roll-Up Captions -- 001 c10f 010 01xx */
1786
/* 47 CFR 15.119 (f)(1) and EIA 608-B Section 7.7. */
1787
new_ch_num = VBI_CAPTION_CC1 + (ch_num0 & 3);
1788
ch = switch_channel (cd, ch, new_ch_num, f);
1789
roll_up_caption (cd, ch, c2);
1792
case 8: /* FON Flash On -- 001 c10f 010 1000 */
1793
if (UNKNOWN_CHANNEL == cd->curr_ch_num[f]
1794
|| _VBI_CC608_MODE_UNKNOWN == ch->mode)
1797
/* 47 CFR 15.119 (h)(1)(i): Spacing attribute. */
1798
put_char (cd, ch, 0x1428,
1799
/* displayable */ FALSE,
1800
/* backspace */ FALSE);
1803
case 9: /* RDC Resume Direct Captioning -- 001 c10f 010 1001 */
1804
/* 47 CFR 15.119 (f)(3) and EIA 608-B Section 7.7. */
1805
new_ch_num = VBI_CAPTION_CC1 + (ch_num0 & 3);
1806
ch = switch_channel (cd, ch, new_ch_num, f);
1807
resume_direct_captioning (cd, ch);
1810
case 10: /* TR Text Restart -- 001 c10f 010 1010 */
1811
/* EIA 608-B Section 7.4. */
1812
new_ch_num = VBI_CAPTION_T1 + (ch_num0 & 3);
1813
ch = switch_channel (cd, ch, new_ch_num, f);
1814
text_restart (cd, ch);
1817
case 11: /* RTD Resume Text Display -- 001 c10f 010 1011 */
1818
/* EIA 608-B Section 7.4. */
1819
new_ch_num = VBI_CAPTION_T1 + (ch_num0 & 3);
1820
ch = switch_channel (cd, ch, new_ch_num, f);
1821
/* ch->mode is invariably VBI_CC608_MODE_TEXT. */
1824
case 12: /* EDM Erase Displayed Memory -- 001 c10f 010 1100 */
1825
/* 47 CFR 15.119 (f). EIA 608-B Section 7.7 and Annex
1826
B.7: "[The] command shall be acted upon as
1827
appropriate for caption processing without
1828
terminating the Text Mode data stream." */
1830
/* We need not check cd->curr_ch_num because bit 2 is
1831
implied, bit 1 is the known field number and bit 0
1832
is coded in the control code. */
1833
ch = &cd->channel[ch_num0 & 3];
1835
erase_displayed_memory (cd, ch);
1839
case 13: /* CR Carriage Return -- 001 c10f 010 1101 */
1840
if (UNKNOWN_CHANNEL == cd->curr_ch_num[f])
1842
carriage_return (cd, ch);
1845
case 14: /* ENM Erase Non-Displayed Memory -- 001 c10f 010 1110 */
1846
/* 47 CFR 15.119 (f)(2)(v). EIA 608-B Section 7.7 and
1847
Annex B.7: "[The] command shall be acted upon as
1848
appropriate for caption processing without
1849
terminating the Text Mode data stream." */
1852
ch = &cd->channel[ch_num0 & 3];
1854
erase_memory (cd, ch, ch->displayed_buffer ^ 1);
1858
case 15: /* EOC End Of Caption -- 001 c10f 010 1111 */
1859
/* 47 CFR 15.119 (f), (f)(2), (f)(3)(iv) and EIA 608-B
1860
Section 7.7, Annex C.11. */
1861
new_ch_num = VBI_CAPTION_CC1 + (ch_num0 & 3);
1862
ch = switch_channel (cd, ch, new_ch_num, f);
1863
end_of_caption (cd, ch);
1869
move_window (_vbi_cc608_decoder * cd,
1870
struct channel * ch,
1871
unsigned int new_base_row)
1874
unsigned int curr_buffer;
1875
unsigned int bytes_per_row;
1876
unsigned int old_max_rows;
1877
unsigned int new_max_rows;
1878
unsigned int copy_bytes;
1879
unsigned int erase_begin;
1880
unsigned int erase_end;
1882
curr_buffer = ch->displayed_buffer;
1884
/* Shortcut and no event if we do not move the window or the
1885
buffer contains only TRANSPARENT_SPACEs. */
1886
if (new_base_row == ch->curr_row
1887
|| 0 == ch->dirty[curr_buffer])
1890
base = (void *) &ch->buffer[curr_buffer][FIRST_ROW][0];
1891
bytes_per_row = sizeof (ch->buffer[0][0]);
1893
old_max_rows = ch->curr_row + 1 - FIRST_ROW;
1894
new_max_rows = new_base_row + 1 - FIRST_ROW;
1895
copy_bytes = MIN (MIN (old_max_rows, new_max_rows),
1896
ch->window_rows) * bytes_per_row;
1898
if (new_base_row < ch->curr_row) {
1899
erase_begin = (new_base_row + 1) * bytes_per_row;
1900
erase_end = (ch->curr_row + 1) * bytes_per_row;
1902
memmove (base + erase_begin - copy_bytes,
1903
base + erase_end - copy_bytes, copy_bytes);
1905
ch->dirty[curr_buffer] >>= ch->curr_row - new_base_row;
1907
erase_begin = (ch->curr_row + 1) * bytes_per_row
1909
erase_end = (new_base_row + 1) * bytes_per_row
1912
memmove (base + erase_end,
1913
base + erase_begin, copy_bytes);
1915
ch->dirty[curr_buffer] <<= new_base_row - ch->curr_row;
1916
ch->dirty[curr_buffer] &= ALL_ROWS_MASK;
1919
memset (base + erase_begin, 0, erase_end - erase_begin);
1921
display_event (cd, ch, /* flags */ 0);
1925
preamble_address_code (_vbi_cc608_decoder * cd,
1926
struct channel * ch,
1932
/* PAC Preamble Address Codes -- 001 crrr 1ri xxxu */
1934
row = pac_row_map[(c1 & 7) * 2 + ((c2 >> 5) & 1)];
1939
case _VBI_CC608_MODE_UNKNOWN:
1942
case _VBI_CC608_MODE_ROLL_UP:
1943
/* EIA 608-B Annex C.4. */
1944
if (ch->window_rows > row + 1)
1945
row = ch->window_rows - 1;
1947
/* 47 CFR Section 15.119 (f)(1)(ii). */
1948
/* May send a display event. */
1949
move_window (cd, ch, row);
1955
case _VBI_CC608_MODE_PAINT_ON:
1956
stream_event_if_changed (cd, ch);
1960
case _VBI_CC608_MODE_POP_ON:
1961
/* XXX 47 CFR 15.119 (f)(2)(i), (f)(3)(i): In Pop-on
1962
and paint-on mode "Preamble Address Codes can be
1963
used to move the cursor around the screen in random
1964
order to place captions on Rows 1 to 15." We do not
1965
have a limit on the number of displayable rows, but
1966
as EIA 608-B Annex C.6 points out, if more than
1967
four rows must be displayed they were probably
1968
received in error and we should respond
1971
/* 47 CFR Section 15.119 (d)(1)(i) and EIA 608-B Annex
1977
case _VBI_CC608_MODE_TEXT:
1978
/* 47 CFR 15.119 (e)(1) and EIA 608-B Section 7.4:
1979
Does not change the cursor row. */
1984
/* 47 CFR 15.119 (e)(1)(i) and EIA 608-B Table 71. */
1985
ch->curr_column = FIRST_COLUMN + (c2 & 0x0E) * 2;
1988
/* PAC is a non-spacing attribute for the next character, see
1990
ch->last_pac = 0x1000 | c2;
1994
control_code (_vbi_cc608_decoder * cd,
2000
unsigned int ch_num0;
2002
if (CC608_DECODER_LOG_INPUT) {
2003
fprintf (stdout, "%s:%u: %s c1=%02x c2=%02x f=%d\n",
2004
__FILE__, __LINE__, __FUNCTION__,
2008
/* b2: Caption / text,
2010
b0 (lsb): primary / secondary channel. */
2011
ch_num0 = (((cd->curr_ch_num[f] - VBI_CAPTION_CC1) & 4)
2015
/* Note ch is invalid if UNKNOWN_CHANNEL ==
2016
cd->curr_ch_num[f]. */
2017
ch = &cd->channel[ch_num0];
2020
/* Preamble Address Codes -- 001 crrr 1ri xxxu */
2021
if (UNKNOWN_CHANNEL != cd->curr_ch_num[f])
2022
preamble_address_code (cd, ch, c1, c2);
2028
if (UNKNOWN_CHANNEL == cd->curr_ch_num[f]
2029
|| _VBI_CC608_MODE_UNKNOWN == ch->mode)
2033
/* Backgr. Attr. Codes -- 001 c000 010 xxxt */
2034
/* EIA 608-B Section 6.2. */
2035
put_char (cd, ch, 0x1000 | c2,
2036
/* displayable */ FALSE,
2037
/* backspace */ TRUE);
2045
if (UNKNOWN_CHANNEL == cd->curr_ch_num[f]
2046
|| _VBI_CC608_MODE_UNKNOWN == ch->mode)
2050
/* Mid-Row Codes -- 001 c001 010 xxxu */
2051
/* 47 CFR 15.119 (h)(1)(i): Spacing attribute. */
2052
put_char (cd, ch, 0x1100 | c2,
2053
/* displayable */ FALSE,
2054
/* backspace */ FALSE);
2056
/* Special Characters -- 001 c001 011 xxxx */
2058
/* Transparent space. */
2059
put_char (cd, ch, 0,
2060
/* displayable */ FALSE,
2061
/* backspace */ FALSE);
2063
put_char (cd, ch, 0x1100 | c2,
2064
/* displayable */ TRUE,
2065
/* backspace */ FALSE);
2072
case 3: /* Extended Character Set -- 001 c01x 01x xxxx */
2073
if (UNKNOWN_CHANNEL == cd->curr_ch_num[f]
2074
|| _VBI_CC608_MODE_UNKNOWN == ch->mode)
2077
/* EIA 608-B Section 6.4.2. */
2078
put_char (cd, ch, (c1 * 256 + c2) & 0x777F,
2079
/* displayable */ TRUE,
2080
/* backspace */ TRUE);
2086
/* Misc. Control Codes -- 001 c10f 010 xxxx */
2087
misc_control_code (cd, ch, c2, ch_num0, f);
2094
case 6: /* reserved */
2097
case 7: /* Extended control codes -- 001 c111 01x xxxx */
2098
if (UNKNOWN_CHANNEL == cd->curr_ch_num[f]
2099
|| _VBI_CC608_MODE_UNKNOWN == ch->mode)
2102
ext_control_code (cd, ch, c2);
2109
characters (_vbi_cc608_decoder * cd,
2110
struct channel * ch,
2113
if (CC608_DECODER_LOG_INPUT) {
2114
fprintf (stdout, "%s:%u: %s c=0x%02x='%c'\n",
2115
__FILE__, __LINE__, __FUNCTION__,
2116
c, _vbi_to_ascii (c));
2120
if (_VBI_CC608_MODE_UNKNOWN == ch->mode)
2123
/* XXX After x NUL characters (presumably a caption
2124
pause), force a display update if we do not send
2125
events on every display change. */
2131
/* Parity error or invalid data. */
2133
if (c < 0 && _VBI_CC608_MODE_UNKNOWN != ch->mode) {
2134
/* 47 CFR Section 15.119 (j)(1). */
2135
put_char (cd, ch, 0x7F,
2136
/* displayable */ TRUE,
2137
/* backspace */ FALSE);
2143
if (_VBI_CC608_MODE_UNKNOWN != ch->mode) {
2144
put_char (cd, ch, c,
2145
/* displayable */ TRUE,
2146
/* backspace */ FALSE);
2153
* @param cd Caption decoder allocated with _vbi_cc608_decoder_new().
2154
* @param buffer A caption byte pair with parity bits.
2155
* @param line ITU-R line number this data originated from,
2156
* usually 21 or 284.
2157
* @param capture_time System time in seconds when the sliced data was
2159
* @param pts ISO 13818-1 Presentation Time Stamp of the sliced
2160
* data. @a pts counts 1/90000 seconds from an arbitrary point in the
2161
* video stream. Only the 33 least significant bits have to be valid.
2162
* If @a pts is negative the function converts @a capture_time to a
2165
* This function decodes two bytes of Closed Caption data and updates
2166
* the decoder state. It may send one VBI_EVENT_CC608 and one or more
2167
* VBI_EVENT_CC608_STREAM.
2170
* @c FALSE if the caption byte pair contained errors.
2173
_vbi_cc608_decoder_feed (_vbi_cc608_decoder * cd,
2174
const uint8_t buffer[2],
2176
double capture_time,
2181
vbi_bool all_successful;
2183
assert (NULL != cd);
2186
fprintf (stdout, "%s:%u: %s "
2187
"buffer={ 0x%02x 0x%02x '%c%c' } "
2188
"line=%3d capture_time=%f "
2189
"pts=%" PRId64 "\n",
2190
__FILE__, __LINE__, __FUNCTION__,
2193
_vbi_to_ascii (buffer[0]),
2194
_vbi_to_ascii (buffer[1]),
2195
line, capture_time, pts);
2202
case 22: /* PAL/SECAM? */
2205
case 284: /* NTSC */
2213
cd->timestamp.sys = capture_time;
2216
pts = (int64_t)(capture_time * 90000);
2218
/* Modulo 1 << 33 guaranteed in VBI_EVENT_CC608_STREAM dox. */
2219
cd->timestamp.pts = pts & (((int64_t) 1 << 33) - 1);
2221
/* XXX deferred reset here */
2223
if (0 && FIELD_1 == f) {
2224
_vbi_cc608_dump (stderr, buffer[0], buffer[1]);
2227
c1 = vbi_unpar8 (buffer[0]);
2228
c2 = vbi_unpar8 (buffer[1]);
2230
all_successful = TRUE;
2232
/* See 47 CFR 15.119 (2)(i)(4). EIA 608-B Section 8.3: Caption
2233
control codes on field 2 may repeat as on field 1. Section
2234
8.6.2: XDS control codes shall not repeat. */
2236
if (unlikely (c1 < 0)) {
2238
} else if (c1 == cd->expect_ctrl[f][0]
2239
&& c2 == cd->expect_ctrl[f][1]) {
2240
/* Already acted upon. */
2241
cd->expect_ctrl[f][0] = -1;
2245
if (c1 >= 0x10 && c1 < 0x20) {
2246
/* Caption control code. */
2248
/* There's no XDS on field 1, we just
2249
use an array to save a branch. */
2250
cd->in_xds[f] = FALSE;
2252
/* 47 CFR Section 15.119 (i)(1), (i)(2). */
2254
/* Parity error or invalid control code.
2255
Let's hope this code will repeat. */
2259
control_code (cd, c1, c2, f);
2261
if (cd->event_pending) {
2262
display_event (cd, cd->event_pending,
2264
cd->event_pending = NULL;
2267
cd->expect_ctrl[f][0] = c1;
2268
cd->expect_ctrl[f][1] = c2;
2270
cd->expect_ctrl[f][0] = -1;
2274
/* 47 CFR Section 15.119 (i)(1): "If the
2275
non-printing character in the pair is
2276
in the range 00h to 0Fh, that character
2277
alone will be ignored and the second
2278
character will be treated normally." */
2280
} else if (0x0F == c1) {
2281
/* XDS packet terminator. */
2282
cd->in_xds[FIELD_2] = FALSE;
2284
} else if (c1 >= 0x01) {
2285
/* XDS packet start or continuation.
2286
EIA 608-B Section 7.7, 8.5: Also
2287
interrupts a Text mode
2289
cd->in_xds[FIELD_2] = TRUE;
2298
ch_num = cd->curr_ch_num[f];
2299
if (UNKNOWN_CHANNEL == ch_num)
2302
ch_num = ((ch_num - VBI_CAPTION_CC1) & 5) + f * 2;
2303
ch = &cd->channel[ch_num];
2305
all_successful &= characters (cd, ch, c1);
2306
all_successful &= characters (cd, ch, c2);
2308
if (cd->event_pending) {
2309
display_event (cd, cd->event_pending,
2311
cd->event_pending = NULL;
2317
cd->error_history = cd->error_history * 2 + all_successful;
2319
return all_successful;
2322
cd->expect_ctrl[f][0] = -1;
2324
/* XXX Some networks stupidly transmit 0x0000 instead of
2325
0x8080 as filler. Perhaps we shouldn't take that as a
2326
serious parity error. */
2327
cd->error_history *= 2;
2333
* @param cd Caption decoder allocated with _vbi_cc608_decoder_new().
2334
* @param sliced Sliced VBI data.
2335
* @param n_lines Number of lines in the @a sliced array.
2336
* @param capture_time System time in seconds when the sliced data was
2338
* @param pts ISO 13818-1 Presentation Time Stamp of all elements
2339
* in the sliced data array. @a pts counts 1/90000 seconds from an
2340
* arbitrary point in the video stream. Only the 33 least significant
2341
* bits have to be valid. If @a pts is negative the function
2342
* converts @a capture_time to a PTS.
2344
* This function works like _vbi_cc608_decoder_feed() but operates
2345
* on sliced VBI data and filters out @c VBI_SLICED_CAPTION_525.
2348
_vbi_cc608_decoder_feed_frame (_vbi_cc608_decoder * cd,
2349
const vbi_sliced * sliced,
2350
unsigned int n_lines,
2351
double capture_time,
2354
const vbi_sliced *end;
2356
assert (NULL != cd);
2357
assert (NULL != sliced);
2359
for (end = sliced + n_lines; sliced < end; ++sliced) {
2360
if (sliced->id & VBI_SLICED_CAPTION_525) {
2361
if (!_vbi_cc608_decoder_feed (cd,
2374
* @param cd Caption decoder allocated with _vbi_cc608_decoder_new().
2375
* @param callback Function to be called on events.
2376
* @param user_data User pointer passed through to the @a callback
2379
* Removes an event handler from the caption decoder, if a handler with
2380
* this @a callback and @a user_data has been registered.
2383
_vbi_cc608_decoder_remove_event_handler
2384
(_vbi_cc608_decoder * cd,
2385
vbi_event_handler callback,
2388
_vbi_event_handler_list_remove_by_callback (&cd->handlers,
2394
* @param cd Caption decoder allocated with _vbi_cc608_decoder_new().
2395
* @param event_mask Set of events the handler is waiting for,
2396
* VBI_EVENT_CC608 or VBI_EVENT_CC608_STREAM.
2397
* @param callback Function to be called on events by
2398
* _vbi_cc608_decoder_feed().
2399
* @param user_data User pointer passed through to the @a callback
2402
* Adds a new event handler to the caption decoder. When the @a
2403
* callback with this @a user_data is already registered the function
2404
* changes the set of events the callback function will receive in the
2407
* Any number of handlers can be added, also different handlers for the
2408
* same event, which will be called in registration order.
2411
* @c FALSE on failure (out of memory).
2414
_vbi_cc608_decoder_add_event_handler
2415
(_vbi_cc608_decoder * cd,
2416
unsigned int event_mask,
2417
vbi_event_handler callback,
2420
event_mask &= (_VBI_EVENT_CC608 |
2421
_VBI_EVENT_CC608_STREAM);
2423
if (0 == event_mask) {
2424
_vbi_event_handler_list_remove_by_callback (&cd->handlers,
2430
if (NULL != _vbi_event_handler_list_add (&cd->handlers,
2441
* @param cd Caption decoder allocated with _vbi_cc608_decoder_new().
2443
* Resets the caption decoder, useful for example after a channel
2447
_vbi_cc608_decoder_reset (_vbi_cc608_decoder * cd)
2449
unsigned int ch_num;
2451
assert (NULL != cd);
2453
if (CC608_DECODER_LOG_INPUT) {
2454
fprintf (stderr, "%s:%u: %s\n",
2455
__FILE__, __LINE__, __FUNCTION__);
2459
for (ch_num = 0; ch_num < MAX_CHANNELS; ++ch_num) {
2462
ch = &cd->channel[ch_num];
2465
ch->mode = _VBI_CC608_MODE_UNKNOWN;
2467
/* Plausible for roll-up mode. We don't
2468
display text while the caption mode is
2469
unknown and may choose more suitable
2470
defaults when we receive a mode changing
2472
ch->curr_row = LAST_ROW;
2473
ch->curr_column = FIRST_COLUMN;
2474
ch->window_rows = 4;
2476
ch->mode = _VBI_CC608_MODE_TEXT; /* invariable */
2478
/* EIA 608-B Section 7.4: "When Text Mode has
2479
initially been selected and the specified
2480
Text memory is empty, the cursor starts at
2481
the topmost row, Column 1." */
2482
ch->curr_row = FIRST_ROW;
2483
ch->curr_column = FIRST_COLUMN;
2484
ch->window_rows = 0; /* n/a */
2487
ch->displayed_buffer = 0;
2494
timestamp_reset (&ch->timestamp);
2495
timestamp_reset (&ch->timestamp_c0);
2498
cd->curr_ch_num[0] = UNKNOWN_CHANNEL;
2499
cd->curr_ch_num[1] = UNKNOWN_CHANNEL;
2501
memset (cd->expect_ctrl, -1, sizeof (cd->expect_ctrl));
2505
cd->event_pending = NULL;
2509
_vbi_cc608_decoder_destroy (_vbi_cc608_decoder * cd)
2511
assert (NULL != cd);
2513
_vbi_event_handler_list_destroy (&cd->handlers);
2519
_vbi_cc608_decoder_init (_vbi_cc608_decoder * cd)
2521
assert (NULL != cd);
2525
_vbi_event_handler_list_init (&cd->handlers);
2527
_vbi_cc608_decoder_reset (cd);
2529
timestamp_reset (&cd->timestamp);
2533
* @param cd Caption decoder allocated with _vbi_cc608_decoder_new(),
2536
* Frees all resources associated with @a cd.
2539
_vbi_cc608_decoder_delete (_vbi_cc608_decoder * cd)
2544
_vbi_cc608_decoder_destroy (cd);
2550
* Allocates a new EIA 608-B Closed Caption decoder.
2552
* To enter caption data call the _vbi_cc608_decoder_feed()
2553
* function. Decoded data is available through VBI_EVENT_CC608_STREAM
2554
* and the _vbi_cc608_decoder_get_page() function.
2556
* To be notified when new data is available call
2557
* _vbi_cc608_decoder_add_event_handler().
2560
* Pointer to a newly allocated caption decoder which must be freed
2561
* with _vbi_cc608_decoder_delete() when no longer needed. @c NULL
2562
* on failure (out of memory).
2564
_vbi_cc608_decoder *
2565
_vbi_cc608_decoder_new (void)
2567
_vbi_cc608_decoder *cd;
2569
cd = vbi_malloc (sizeof (*cd));
2572
_vbi_cc608_decoder_init (cd);