UNPKG

shaka-player

Version:
323 lines (284 loc) 8.15 kB
/*! @license * Shaka Player * Copyright 2016 Google LLC * SPDX-License-Identifier: Apache-2.0 */ goog.provide('shaka.cea.Cea608Memory'); goog.require('shaka.cea.CeaUtils'); goog.require('shaka.text.Cue'); /** * CEA-608 captions memory/buffer. */ shaka.cea.Cea608Memory = class { /** * @param {number} fieldNum Field number. * @param {number} channelNum Channel number. */ constructor(fieldNum, channelNum) { /** * Buffer for storing decoded characters. * @private @const {!Array<!Array<!shaka.cea.CeaUtils.StyledChar>>} */ this.rows_ = []; /** * Current row. * @private {number} */ this.row_ = 1; /** * Number of rows in the scroll window. Used for rollup mode. * @private {number} */ this.scrollRows_ = 0; /** * Field number. * @private {number} */ this.fieldNum_ = fieldNum; /** * Channel number. * @private {number} */ this.channelNum_ = channelNum; /** * @private {boolean} */ this.underline_ = false; /** * @private {boolean} */ this.italics_ = false; /** * @private {string} */ this.textColor_ = shaka.cea.CeaUtils.DEFAULT_TXT_COLOR; /** * @private {string} */ this.backgroundColor_ = shaka.cea.CeaUtils.DEFAULT_BG_COLOR; this.reset(); } /** * Emits a closed caption based on the state of the buffer. * @param {number} startTime Start time of the cue. * @param {number} endTime End time of the cue. * @return {?shaka.extern.ICaptionDecoder.ClosedCaption} */ forceEmit(startTime, endTime) { const stream = `CC${(this.fieldNum_<< 1) | this.channelNum_ +1}`; const topLevelCue = new shaka.text.Cue( startTime, endTime, /* payload= */ ''); topLevelCue.lineInterpretation = shaka.text.Cue.lineInterpretation.PERCENTAGE; const maxRows = shaka.cea.Cea608Memory.CC_ROWS + 1; topLevelCue.line = this.row_ / maxRows * 100; return shaka.cea.CeaUtils.getParsedCaption( topLevelCue, stream, this.rows_, startTime, endTime); } /** * Resets the memory buffer. */ reset() { this.resetAllRows(); this.row_ = 1; } /** * @return {number} */ getRow() { return this.row_; } /** * @param {number} row */ setRow(row) { this.row_ = row; } /** * @return {number} */ getScrollSize() { return this.scrollRows_; } /** * @param {number} scrollRows */ setScrollSize(scrollRows) { this.scrollRows_ = scrollRows; } /** * Adds a character to the buffer. * @param {!shaka.cea.Cea608Memory.CharSet} set Character set. * @param {number} b CC byte to add. */ addChar(set, b) { // Valid chars are in the range [0x20, 0x7f] if (b < 0x20 || b > 0x7f) { return; } let char = ''; switch (set) { case shaka.cea.Cea608Memory.CharSet.BASIC_NORTH_AMERICAN: if (shaka.cea.Cea608Memory.CharSet.BasicNorthAmericanChars.has(b)) { char = shaka.cea.Cea608Memory.CharSet.BasicNorthAmericanChars.get(b); } else { // Regular ASCII char = String.fromCharCode(b); } break; case shaka.cea.Cea608Memory.CharSet.SPECIAL_NORTH_AMERICAN: char = shaka.cea.Cea608Memory.CharSet.SpecialNorthAmericanChars.get(b); break; case shaka.cea.Cea608Memory.CharSet.SPANISH_FRENCH: // Extended charset does a BS over preceding char, 6.4.2 EIA-608-B. this.eraseChar(); char = shaka.cea.Cea608Memory.CharSet.ExtendedSpanishFrench.get(b); break; case shaka.cea.Cea608Memory.CharSet.PORTUGUESE_GERMAN: this.eraseChar(); char = shaka.cea.Cea608Memory.CharSet.ExtendedPortugueseGerman.get(b); break; } if (char) { const styledChar = new shaka.cea.CeaUtils.StyledChar( char, this.underline_, this.italics_, this.backgroundColor_, this.textColor_); this.rows_[this.row_].push(styledChar); } } /** * Erases a character from the buffer. */ eraseChar() { this.rows_[this.row_].pop(); } /** * Moves rows of characters. * @param {number} dst Destination row index. * @param {number} src Source row index. * @param {number} count Count of rows to move. */ moveRows(dst, src, count) { if (src < 0 || dst < 0) { return; } if (dst >= src) { for (let i = count-1; i >= 0; i--) { this.rows_[dst + i] = this.rows_[src + i].map((e) => e); } } else { for (let i = 0; i < count; i++) { this.rows_[dst + i] = this.rows_[src + i].map((e) => e); } } } /** * Resets rows of characters. * @param {number} idx Starting index. * @param {number} count Count of rows to reset. */ resetRows(idx, count) { for (let i = 0; i <= count; i++) { this.rows_[idx + i] = []; } } /** * Resets the entire memory buffer. */ resetAllRows() { this.resetRows(0, shaka.cea.Cea608Memory.CC_ROWS); } /** * Erases entire memory buffer. * Doesn't change scroll state or number of rows. */ eraseBuffer() { this.row_ = (this.scrollRows_ > 0) ? this.scrollRows_ : 0; this.resetAllRows(); } /** * @param {boolean} underline */ setUnderline(underline) { this.underline_ = underline; } /** * @param {boolean} italics */ setItalics(italics) { this.italics_ = italics; } /** * @param {string} color */ setTextColor(color) { this.textColor_ = color; } /** * @param {string} color */ setBackgroundColor(color) { this.backgroundColor_ = color; } }; /** * Maximum number of rows in the buffer. * @const {number} */ shaka.cea.Cea608Memory.CC_ROWS = 15; /** * Characters sets. * @const @enum {number} */ shaka.cea.Cea608Memory.CharSet = { BASIC_NORTH_AMERICAN: 0, SPECIAL_NORTH_AMERICAN: 1, SPANISH_FRENCH: 2, PORTUGUESE_GERMAN: 3, }; /** * Basic North American char set deviates from ASCII with these exceptions. * @private @const {!Map<number, string>} */ shaka.cea.Cea608Memory.CharSet.BasicNorthAmericanChars = new Map([ [0x27, '’'], [0x2a, 'á'], [0x5c, 'é'], [0x5c, 'é'], [0x5e, 'í'], [0x5f, 'ó'], [0x60, 'ú'], [0x7b, 'ç'], [0x7c, '÷'], [0x7d, 'Ñ'], [0x7e, 'ñ'], [0x7f, '█'], ]); /** * Special North American char set. * Note: Transparent Space is currently implemented as a regular space. * @private @const {!Map<number, string>} */ shaka.cea.Cea608Memory.CharSet.SpecialNorthAmericanChars = new Map([ [0x30, '®'], [0x31, '°'], [0x32, '½'], [0x33, '¿'], [0x34, '™'], [0x35, '¢'], [0x36, '£'], [0x37, '♪'], [0x38, 'à'], [0x39, '⠀'], [0x3a, 'è'], [0x3b, 'â'], [0x3c, 'ê'], [0x3d, 'î'], [0x3e, 'ô'], [0x3f, 'û'], ]); /** * Extended Spanish/Misc/French char set. * @private @const {!Map<number, string>} */ shaka.cea.Cea608Memory.CharSet.ExtendedSpanishFrench = new Map([ [0x20, 'Á'], [0x21, 'É'], [0x22, 'Ó'], [0x23, 'Ú'], [0x24, 'Ü'], [0x25, 'ü'], [0x26, '‘'], [0x27, '¡'], [0x28, '*'], [0x29, '\''], [0x2a, '─'], [0x2b, '©'], [0x2c, '℠'], [0x2d, '·'], [0x2e, '“'], [0x2f, '”'], [0x30, 'À'], [0x31, 'Â'], [0x32, 'Ç'], [0x33, 'È'], [0x34, 'Ê'], [0x35, 'Ë'], [0x36, 'ë'], [0x37, 'Î'], [0x38, 'Ï'], [0x39, 'ï'], [0x3a, 'Ô'], [0x3b, 'Ù'], [0x3c, 'ù'], [0x3d, 'Û'], [0x3e, '«'], [0x3f, '»'], ]); /** * Extended Portuguese/German/Danish char set. * @private @const {!Map<number, string>} */ shaka.cea.Cea608Memory.CharSet.ExtendedPortugueseGerman = new Map([ [0x20, 'Ã'], [0x21, 'ã'], [0x22, 'Í'], [0x23, 'Ì'], [0x24, 'ì'], [0x25, 'Ò'], [0x26, 'ò'], [0x27, 'Õ'], [0x28, 'õ'], [0x29, '{'], [0x2a, '}'], [0x2b, '\\'], [0x2c, '^'], [0x2d, '_'], [0x2e, '|'], [0x2f, '~'], [0x30, 'Ä'], [0x31, 'ä'], [0x32, 'Ö'], [0x33, 'ö'], [0x34, 'ß'], [0x35, '¥'], [0x36, '¤'], [0x37, '│'], [0x38, 'Å'], [0x39, 'å'], [0x3a, 'Ø'], [0x3b, 'ø'], [0x3c, '┌'], [0x3d, '┐'], [0x3e, '└'], [0x3f, '┘'], ]);