From d50e3b94c0e7981ecc4b76358c3f10c2df10fb8b Mon Sep 17 00:00:00 2001 From: enen92 <92enen@gmail.com> Date: Sun, 29 Nov 2020 21:56:31 +0000 Subject: [CC] Fix basic american and special american charsets for EIA-608 CC decoder --- .../DVDCodecs/Overlay/contrib/cc_decoder.c | 148 +++++++++++++++------ .../DVDCodecs/Overlay/contrib/cc_decoder.h | 1 + 2 files changed, 112 insertions(+), 37 deletions(-) diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Overlay/contrib/cc_decoder.c b/xbmc/cores/VideoPlayer/DVDCodecs/Overlay/contrib/cc_decoder.c index 0a0043f434..05e660ea1b 100644 --- a/xbmc/cores/VideoPlayer/DVDCodecs/Overlay/contrib/cc_decoder.c +++ b/xbmc/cores/VideoPlayer/DVDCodecs/Overlay/contrib/cc_decoder.c @@ -1,4 +1,6 @@ /* + * Copyright (C) 2008-2020 Team Kodi + * * Copyright (C) 2000-2008 the xine project * * Copyright (C) Christian Vogler @@ -33,19 +35,8 @@ enum { WHITE, GREEN, BLUE, CYAN, RED, YELLOW, MAGENTA, BLACK }; /* --------------------- misc. EIA 608 definitions -------------------*/ -#define TRANSP_SPACE 0x19 /* code for transparent space, essentially - arbitrary */ - /* mapping from PAC row code to actual CC row */ static int rowdata[] = {10, -1, 0, 1, 2, 3, 11, 12, 13, 14, 4, 5, 6, 7, 8, 9}; -/* FIXME: do real TM */ -/* must be mapped as a music note in the captioning font */ - -static unsigned char specialchar[] = {0xAE,0xB0,0xBD,0xBF,0x54,0xA2,0xA3,0xB6,0xA0, - TRANSP_SPACE,0xA8,0xA2,0xAA,0xAE,0xB4,0xBB}; - -/* character translation table - EIA 608 codes are not all the same as ASCII */ -static unsigned char chartbl[128]; /* CC codes use odd parity for error detection, since they originally were */ /* transmitted via noisy video signals */ @@ -53,6 +44,94 @@ static int parity_table[256]; static cc_buffer_t* active_ccbuffer(cc_decoder_t* dec); +/* --------------------- EIA 608 charsets -----------------------------*/ +// for all charsets, CC codes are essentially identical to ASCII apart for a few exceptions +// see https://en.wikipedia.org/wiki/EIA-608#Characters for reference + +// @todo add support to CCSET_EXTENDED_SPANISH_FRENCH_MISC +// and CCSET_EXTENDED_PORTUGUESE_GERMAN_DANISH +enum cc_charset +{ + CCSET_BASIC_AMERICAN = 0, + CCSET_SPECIAL_AMERICAN, +}; + +char* get_char_override(uint8_t charset, uint8_t c) +{ + if (charset == CCSET_BASIC_AMERICAN) + { + switch (c) + { + case 0x27: + return u8"\u2019"; + case 0x2a: + return u8"\u00e1"; + case 0x5c: + return u8"\u00e9"; + case 0x5e: + return u8"\u00ed"; + case 0x5f: + return u8"\u00f3"; + case 0x60: + return u8"\u00fa"; + case 0x7b: + return u8"\u00e7"; + case 0x7c: + return u8"\u00f7"; + case 0x7d: + return u8"\u00d1"; + case 0x7e: + return u8"\u00f1"; + case 0x7f: + return u8"\u2588"; + default: + break; + } + } + else if (charset == CCSET_SPECIAL_AMERICAN) + { + switch (c) + { + case 0x30: + return u8"\u00ae"; + case 0x31: + return u8"\u00b0"; + case 0x32: + return u8"\u00bd"; + case 0x33: + return u8"\u00bf"; + case 0x34: + return u8"\u2122"; + case 0x35: + return u8"\u00a2"; + case 0x36: + return u8"\u00a3"; + case 0x37: + return u8"\u266a"; + case 0x38: + return u8"\u00e0"; + case 0x39: + return u8"\u00A0"; + case 0x3a: + return u8"\u00e8"; + case 0x3b: + return u8"\u00e2"; + case 0x3c: + return u8"\u00ea"; + case 0x3d: + return u8"\u00ee"; + case 0x3e: + return u8"\u00f4"; + case 0x3f: + return u8"\u00fb"; + default: + break; + } + } + // regular ascii char + return NULL; +} + /*---------------- general utility functions ---------------------*/ static int parity(uint8_t byte) @@ -87,26 +166,7 @@ static int good_parity(uint16_t data) return ret; } -static void build_char_table(void) -{ - int i; - /* first the normal ASCII codes */ - for (i = 0; i < 128; i++) - chartbl[i] = (char) i; - /* now the special codes */ - chartbl[0x2a] = 0xA1; - chartbl[0x5c] = 0xA9; - chartbl[0x5e] = 0xAD; - chartbl[0x5f] = 0xB3; - chartbl[0x60] = 0xAA; - chartbl[0x7b] = 0xA7; - chartbl[0x7c] = 0xb7; - chartbl[0x7d] = 0x91; - chartbl[0x7e] = 0xB1; - chartbl[0x7f] = 0xA4; /* FIXME: this should be a solid block */ -} - -static void ccbuf_add_char(cc_buffer_t *buf, uint8_t c) +static void ccbuf_add_char(cc_buffer_t* buf, uint8_t c, uint8_t charset) { cc_row_t *rowbuf = &buf->rows[buf->rowpos]; int pos = rowbuf->pos; @@ -127,6 +187,7 @@ static void ccbuf_add_char(cc_buffer_t *buf, uint8_t c) } rowbuf->cells[pos].c = c; + rowbuf->cells[pos].charset = charset; rowbuf->cells[pos].midrow_attr = rowbuf->attr_chg; rowbuf->pos++; @@ -166,7 +227,7 @@ static void ccbuf_apply_attribute(cc_buffer_t *buf, cc_attribute_t *attr) rowbuf->attr_chg = 1; rowbuf->cells[pos].attributes = *attr; /* A midrow attribute always counts as a space */ - ccbuf_add_char(buf, chartbl[(unsigned int) ' ']); + ccbuf_add_char(buf, (unsigned int)' ', CCSET_BASIC_AMERICAN); } @@ -250,7 +311,21 @@ void ccmem_tobuf(cc_decoder_t *dec) if (buf->rows[i].cells[l].c != ' ') break; for (j = f; j <= l; j++) - dec->text[dec->textlen++] = buf->rows[i].cells[j].c; + { + char* chbytes = get_char_override(buf->rows[i].cells[j].charset, buf->rows[i].cells[j].c); + if (chbytes != NULL) + { + for (; *chbytes != '\0'; chbytes++) + { + dec->text[dec->textlen++] = *chbytes; + } + } + else + { + // ascii char + dec->text[dec->textlen++] = (unsigned char)buf->rows[i].cells[j].c; + } + } dec->text[dec->textlen++] = '\n'; } } @@ -312,10 +387,10 @@ static void cc_decode_standard_char(cc_decoder_t *dec, uint8_t c1, uint8_t c2) { cc_buffer_t *buf = active_ccbuffer(dec); /* c1 always is a valid character */ - ccbuf_add_char(buf, chartbl[c1]); + ccbuf_add_char(buf, c1, CCSET_BASIC_AMERICAN); /* c2 might not be a printable character, even if c1 was */ if (c2 & 0x60) - ccbuf_add_char(buf, chartbl[c2]); + ccbuf_add_char(buf, c2, CCSET_BASIC_AMERICAN); } @@ -365,7 +440,7 @@ static void cc_decode_special_char(cc_decoder_t *dec, int channel, cc_set_channel(dec, channel); buf = active_ccbuffer(dec); - ccbuf_add_char(buf, specialchar[c2 & 0xf]); + ccbuf_add_char(buf, c2, CCSET_SPECIAL_AMERICAN); } static void cc_decode_midrow_attr(cc_decoder_t *dec, int channel, @@ -618,7 +693,6 @@ void cc_decoder_close(cc_decoder_t *dec) void cc_decoder_init(void) { build_parity_table(); - build_char_table(); } #ifdef __cplusplus diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Overlay/contrib/cc_decoder.h b/xbmc/cores/VideoPlayer/DVDCodecs/Overlay/contrib/cc_decoder.h index f0893e6140..d9fc266007 100644 --- a/xbmc/cores/VideoPlayer/DVDCodecs/Overlay/contrib/cc_decoder.h +++ b/xbmc/cores/VideoPlayer/DVDCodecs/Overlay/contrib/cc_decoder.h @@ -37,6 +37,7 @@ typedef struct cc_char_cell_s uint8_t c; /* character code, not the same as ASCII */ cc_attribute_t attributes; /* attributes of this character, if changed */ /* here */ + uint8_t charset; /* charset type */ int midrow_attr; /* true if this cell changes an attribute */ } cc_char_cell_t; -- cgit v1.2.3