Source: lib/cea/cea608_data_channel.js

  1. /*! @license
  2. * Shaka Player
  3. * Copyright 2016 Google LLC
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. goog.provide('shaka.cea.Cea608DataChannel');
  7. goog.require('shaka.cea.Cea608Memory');
  8. goog.require('shaka.cea.CeaUtils');
  9. goog.require('shaka.log');
  10. goog.requireType('shaka.cea.ICaptionDecoder');
  11. /**
  12. * 608 closed captions channel.
  13. */
  14. shaka.cea.Cea608DataChannel = class {
  15. /**
  16. * @param {!number} fieldNum Field number.
  17. * @param {!number} channelNum Channel number.
  18. */
  19. constructor(fieldNum, channelNum) {
  20. /**
  21. * Current Caption Type.
  22. * @public {!shaka.cea.Cea608DataChannel.CaptionType}
  23. */
  24. this.type_ = shaka.cea.Cea608DataChannel.CaptionType.NONE;
  25. /**
  26. * Text buffer for CEA-608 "text mode". Although, we don't emit text mode.
  27. * So, this buffer serves as a no-op placeholder, just in case we receive
  28. * captions that toggle text mode.
  29. * @private @const {!shaka.cea.Cea608Memory}
  30. */
  31. this.text_ =
  32. new shaka.cea.Cea608Memory(fieldNum, channelNum);
  33. /**
  34. * Displayed memory.
  35. * @private {!shaka.cea.Cea608Memory}
  36. */
  37. this.displayedMemory_ =
  38. new shaka.cea.Cea608Memory(fieldNum, channelNum);
  39. /**
  40. * Non-displayed memory.
  41. * @private {!shaka.cea.Cea608Memory}
  42. */
  43. this.nonDisplayedMemory_ =
  44. new shaka.cea.Cea608Memory(fieldNum, channelNum);
  45. /**
  46. * Points to current buffer.
  47. * @private {!shaka.cea.Cea608Memory}
  48. */
  49. this.curbuf_ = this.displayedMemory_;
  50. /**
  51. * End time of the previous caption, serves as start time of next caption.
  52. * @private {!number}
  53. */
  54. this.prevEndTime_ = 0;
  55. /**
  56. * Last control pair, 16 bits representing byte 1 and byte 2
  57. * @private {?number}
  58. */
  59. this.lastcp_ = null;
  60. }
  61. /**
  62. * Resets channel state.
  63. */
  64. reset() {
  65. this.type_ = shaka.cea.Cea608DataChannel.CaptionType.PAINTON;
  66. this.curbuf_ = this.displayedMemory_;
  67. this.lastcp_ = null;
  68. this.displayedMemory_.reset();
  69. this.nonDisplayedMemory_.reset();
  70. this.text_.reset();
  71. }
  72. /**
  73. * Gets the row index from a Preamble Address Code byte pair.
  74. * @param {!number} b1 Byte 1.
  75. * @param {!number} b2 Byte 2.
  76. * @return {!number} Row index.
  77. * @private
  78. */
  79. pacToRow_(b1, b2) {
  80. const ccrowtab = [
  81. 11, 11, // 0x00 or 0x01
  82. 1, 2, // 0x02 -> 0x03
  83. 3, 4, // 0x04 -> 0x05
  84. 12, 13, // 0x06 -> 0x07
  85. 14, 15, // 0x08 -> 0x09
  86. 5, 6, // 0x0A -> 0x0B
  87. 7, 8, // 0x0C -> 0x0D
  88. 9, 10, // 0x0E -> 0x0F
  89. ];
  90. return ccrowtab[((b1 & 0x07) << 1) | ((b2 >> 5) & 0x01)];
  91. }
  92. /**
  93. * PAC - Preamble Address Code.
  94. * b1 is of the form |P|0|0|1|C|0|ROW|
  95. * b2 is of the form |P|1|N|ATTRIBUTE|U|
  96. * @param {!number} b1 Byte 1.
  97. * @param {!number} b2 Byte 2.
  98. * @private
  99. */
  100. controlPac_(b1, b2) {
  101. const row = this.pacToRow_(b1, b2);
  102. // Get attribute bits (4 bits)
  103. const attr = (b2 & 0x1E) >> 1;
  104. // Set up the defaults.
  105. let textColor = shaka.cea.CeaUtils.DEFAULT_TXT_COLOR;
  106. let italics = false;
  107. // Attributes < 7 are colors, = 7 is white w/ italics, and >7 are indents
  108. if (attr < 7) {
  109. textColor = shaka.cea.Cea608DataChannel.TEXT_COLORS[attr];
  110. } else if (attr === 7) {
  111. italics = true; // color stays white
  112. }
  113. // PACs toggle underline on the last bit of b2.
  114. const underline = (b2 & 0x01) === 0x01;
  115. if (this.type_ === shaka.cea.Cea608DataChannel.CaptionType.TEXT) {
  116. // Don't execute the PAC if in text mode.
  117. return;
  118. }
  119. // Execute the PAC.
  120. const buf = this.curbuf_;
  121. // Move entire scroll window to a new base in rollup mode.
  122. if (this.type_ === shaka.cea.Cea608DataChannel.CaptionType.ROLLUP &&
  123. row !== buf.getRow()) {
  124. const oldTopRow = 1 + buf.getRow() - buf.getScrollSize();
  125. const newTopRow = 1 + row - buf.getScrollSize();
  126. // Shift up the scroll window.
  127. buf.moveRows(newTopRow, oldTopRow, buf.getScrollSize());
  128. // Clear everything outside of the new scroll window.
  129. buf.resetRows(0, newTopRow - 1);
  130. buf.resetRows(row + 1,
  131. shaka.cea.Cea608Memory.CC_ROWS - row);
  132. }
  133. buf.setRow(row);
  134. this.curbuf_.setUnderline(underline);
  135. this.curbuf_.setItalics(italics);
  136. this.curbuf_.setTextColor(textColor);
  137. // Clear the background color, since new row (PAC) should reset ALL styles.
  138. this.curbuf_.setBackgroundColor(shaka.cea.CeaUtils.DEFAULT_BG_COLOR);
  139. }
  140. /**
  141. * Mid-Row control code handler.
  142. * @param {!number} b2 Byte #2.
  143. * @private
  144. */
  145. controlMidrow_(b2) {
  146. // Clear all pre-existing midrow style attributes.
  147. this.curbuf_.setUnderline(false);
  148. this.curbuf_.setItalics(false);
  149. this.curbuf_.setTextColor(shaka.cea.CeaUtils.DEFAULT_TXT_COLOR);
  150. // Mid-row attrs use a space.
  151. this.curbuf_.addChar(
  152. shaka.cea.Cea608Memory.CharSet.BASIC_NORTH_AMERICAN, ' '.charCodeAt(0));
  153. let textColor = shaka.cea.CeaUtils.DEFAULT_TXT_COLOR;
  154. let italics = false;
  155. // Midrow codes set underline on last (LSB) bit.
  156. const underline = (b2 & 0x01) === 0x01;
  157. // b2 has the form |P|0|1|0|STYLE|U|
  158. textColor = shaka.cea.Cea608DataChannel.TEXT_COLORS[(b2 & 0xe) >> 1];
  159. if (textColor === 'white_italics') {
  160. textColor = 'white';
  161. italics = true;
  162. }
  163. this.curbuf_.setUnderline(underline);
  164. this.curbuf_.setItalics(italics);
  165. this.curbuf_.setTextColor(textColor);
  166. }
  167. /**
  168. * Background attribute control code handler.
  169. * @param {!number} b1 Byte #1
  170. * @param {!number} b2 Byte #2.
  171. * @private
  172. */
  173. controlBackgroundAttribute_(b1, b2) {
  174. let backgroundColor = shaka.cea.CeaUtils.DEFAULT_BG_COLOR;
  175. if ((b1 & 0x07) === 0x0) {
  176. // If background provided, last 3 bits of b1 are |0|0|0|. Color is in b2.
  177. backgroundColor = shaka.cea.Cea608DataChannel.BG_COLORS[(b2 & 0xe) >> 1];
  178. }
  179. this.curbuf_.setBackgroundColor(backgroundColor);
  180. }
  181. /**
  182. * The Cea608DataChannel control methods implement all CC control operations.
  183. * @param {!shaka.cea.Cea608DataChannel.Cea608Packet} ccPacket
  184. * @return {?shaka.cea.ICaptionDecoder.ClosedCaption}
  185. * @private
  186. */
  187. controlMiscellaneous_(ccPacket) {
  188. const MiscCmd = shaka.cea.Cea608DataChannel.MiscCmd_;
  189. const b2 = ccPacket.ccData2;
  190. const pts = ccPacket.pts;
  191. let parsedClosedCaption = null;
  192. switch (b2) {
  193. case MiscCmd.RCL:
  194. this.controlRcl_();
  195. break;
  196. case MiscCmd.BS:
  197. this.controlBs_();
  198. break;
  199. // unused (alarm off and alarm on)
  200. case MiscCmd.AOD:
  201. case MiscCmd.AON:
  202. break;
  203. case MiscCmd.DER:
  204. // Delete to End of Row. Not implemented since position not supported.
  205. break;
  206. case MiscCmd.RU2:
  207. parsedClosedCaption = this.controlRu_(2, pts);
  208. break;
  209. case MiscCmd.RU3:
  210. parsedClosedCaption = this.controlRu_(3, pts);
  211. break;
  212. case MiscCmd.RU4:
  213. parsedClosedCaption = this.controlRu_(4, pts);
  214. break;
  215. case MiscCmd.FON:
  216. this.controlFon_();
  217. break;
  218. case MiscCmd.RDC:
  219. this.controlRdc_(pts);
  220. break;
  221. case MiscCmd.TR:
  222. this.controlTr_();
  223. break;
  224. case MiscCmd.RTD:
  225. this.controlRtd_();
  226. break;
  227. case MiscCmd.EDM:
  228. parsedClosedCaption = this.controlEdm_(pts);
  229. break;
  230. case MiscCmd.CR:
  231. parsedClosedCaption = this.controlCr_(pts);
  232. break;
  233. case MiscCmd.ENM:
  234. this.controlEnm_();
  235. break;
  236. case MiscCmd.EOC:
  237. parsedClosedCaption = this.controlEoc_(pts);
  238. break;
  239. }
  240. return parsedClosedCaption;
  241. }
  242. /**
  243. * Handles CR - Carriage Return (Start new row).
  244. * CR only affects scroll windows (Rollup and Text modes).
  245. * Any currently buffered line needs to be emitted, along
  246. * with a window scroll action.
  247. * @param {!number} pts in seconds.
  248. * @return {?shaka.cea.ICaptionDecoder.ClosedCaption}
  249. * @private
  250. */
  251. controlCr_(pts) {
  252. const buf = this.curbuf_;
  253. // Only rollup and text mode is affected, but we don't emit text mode.
  254. if (this.type_ !== shaka.cea.Cea608DataChannel.CaptionType.ROLLUP) {
  255. return null;
  256. }
  257. // Force out the scroll window since the top row will cleared.
  258. const parsedClosedCaption = buf.forceEmit(this.prevEndTime_, pts);
  259. // Calculate the top of the scroll window.
  260. const toprow = (buf.getRow() - buf.getScrollSize()) + 1;
  261. // Shift up the window one row higher.
  262. buf.moveRows(toprow - 1, toprow, buf.getScrollSize());
  263. // Clear out anything that's outside of our current scroll window.
  264. buf.resetRows(0, toprow - 1);
  265. buf.resetRows(buf.getRow(), shaka.cea.Cea608Memory.CC_ROWS - buf.getRow());
  266. // Update the end time so the next caption emits starting at this time.
  267. this.prevEndTime_ = pts;
  268. return parsedClosedCaption;
  269. }
  270. /**
  271. * Handles RU2, RU3, RU4 - Roll-Up, N rows.
  272. * If in TEXT, POPON or PAINTON, any displayed captions are erased.
  273. * This means must force emit entire display buffer.
  274. * @param {!number} scrollSize New scroll window size.
  275. * @param {!number} pts
  276. * @return {?shaka.cea.ICaptionDecoder.ClosedCaption}
  277. * @private
  278. */
  279. controlRu_(scrollSize, pts) {
  280. this.curbuf_ = this.displayedMemory_; // Point to displayed memory
  281. const buf = this.curbuf_;
  282. let parsedClosedCaption = null;
  283. // For any type except rollup and text mode, it should be emitted,
  284. // and memories cleared.
  285. if (this.type_ !== shaka.cea.Cea608DataChannel.CaptionType.ROLLUP &&
  286. this.type_ !== shaka.cea.Cea608DataChannel.CaptionType.TEXT) {
  287. parsedClosedCaption = buf.forceEmit(this.prevEndTime_, pts);
  288. // Clear both memories.
  289. this.displayedMemory_.eraseBuffer();
  290. this.nonDisplayedMemory_.eraseBuffer();
  291. // Rollup base row defaults to the last row (15).
  292. buf.setRow(shaka.cea.Cea608Memory.CC_ROWS);
  293. }
  294. this.type_ = shaka.cea.Cea608DataChannel.CaptionType.ROLLUP;
  295. // Set the new rollup window size.
  296. buf.setScrollSize(scrollSize);
  297. return parsedClosedCaption;
  298. }
  299. /**
  300. * Handles flash on.
  301. * @private
  302. */
  303. controlFon_() {
  304. this.curbuf_.addChar(
  305. shaka.cea.Cea608Memory.CharSet.BASIC_NORTH_AMERICAN,
  306. ' '.charCodeAt(0));
  307. }
  308. /**
  309. * Handles EDM - Erase Displayed Mem
  310. * Mode check:
  311. * EDM affects all captioning modes (but not Text mode);
  312. * @param {!number} pts
  313. * @return {?shaka.cea.ICaptionDecoder.ClosedCaption}
  314. * @private
  315. */
  316. controlEdm_(pts) {
  317. const buf = this.displayedMemory_;
  318. let parsedClosedCaption = null;
  319. if (this.type_ !== shaka.cea.Cea608DataChannel.CaptionType.TEXT) {
  320. // Clearing displayed memory means we now know how long
  321. // its contents were displayed, so force it out.
  322. parsedClosedCaption = buf.forceEmit(this.prevEndTime_, pts);
  323. }
  324. buf.resetAllRows();
  325. return parsedClosedCaption;
  326. }
  327. /**
  328. * Handles RDC - Resume Direct Captions. Initiates Paint-On captioning mode.
  329. * RDC does not affect current display, so nothing needs to be forced out yet.
  330. * @param {!number} pts in seconds
  331. * @private
  332. */
  333. controlRdc_(pts) {
  334. this.type_ = shaka.cea.Cea608DataChannel.CaptionType.PAINTON;
  335. // Point to displayed memory.
  336. this.curbuf_ = this.displayedMemory_;
  337. // No scroll window now.
  338. this.curbuf_.setScrollSize(0);
  339. // The next paint-on caption needs this time as the start time.
  340. this.prevEndTime_ = pts;
  341. }
  342. /**
  343. * Handles ENM - Erase Nondisplayed Mem
  344. * @private
  345. */
  346. controlEnm_() {
  347. this.nonDisplayedMemory_.resetAllRows();
  348. }
  349. /**
  350. * Handles EOC - End Of Caption (flip mem)
  351. * This forces Pop-On mode, and swaps the displayed and nondisplayed memories.
  352. * @private
  353. * @param {!number} pts
  354. * @return {?shaka.cea.ICaptionDecoder.ClosedCaption}
  355. */
  356. controlEoc_(pts) {
  357. let parsedClosedCaption = null;
  358. if (this.type_ !== shaka.cea.Cea608DataChannel.CaptionType.TEXT) {
  359. parsedClosedCaption =
  360. this.displayedMemory_.forceEmit(this.prevEndTime_, pts);
  361. }
  362. // Swap memories
  363. const buf = this.nonDisplayedMemory_;
  364. this.nonDisplayedMemory_ = this.displayedMemory_; // Swap buffers
  365. this.displayedMemory_ = buf;
  366. // Enter Pop-On mode.
  367. this.controlRcl_();
  368. // The caption ended, and so the previous end time should be updated.
  369. this.prevEndTime_ = pts;
  370. return parsedClosedCaption;
  371. }
  372. /**
  373. * Handles RCL - Resume Caption Loading
  374. * Initiates Pop-On style captioning. No need to force anything out upon
  375. * entering Pop-On mode because it does not affect the current display.
  376. * @private
  377. */
  378. controlRcl_() {
  379. this.type_ = shaka.cea.Cea608DataChannel.CaptionType.POPON;
  380. this.curbuf_ = this.nonDisplayedMemory_;
  381. // No scroll window now
  382. this.curbuf_.setScrollSize(0);
  383. }
  384. /**
  385. * Handles BS - BackSpace.
  386. * @private
  387. */
  388. controlBs_() {
  389. this.curbuf_.eraseChar();
  390. }
  391. /**
  392. * Handles TR - Text Restart.
  393. * Clears text buffer and resumes Text Mode.
  394. * @private
  395. */
  396. controlTr_() {
  397. this.text_.reset();
  398. this.controlRtd_(); // Put into text mode.
  399. }
  400. /**
  401. * Handles RTD - Resume Text Display.
  402. * Resumes text mode. No need to force anything out, because Text Mode doesn't
  403. * affect current display. Also, this decoder does not emit Text Mode anyway.
  404. * @private
  405. */
  406. controlRtd_() {
  407. shaka.log.warnOnce('Cea608DataChannel',
  408. 'CEA-608 text mode entered, but is unsupported');
  409. this.curbuf_ = this.text_;
  410. this.type_ = shaka.cea.Cea608DataChannel.CaptionType.TEXT;
  411. }
  412. /**
  413. * Handles a Basic North American byte pair.
  414. * @param {!number} b1 Byte 1.
  415. * @param {!number} b2 Byte 2.
  416. */
  417. handleBasicNorthAmericanChar(b1, b2) {
  418. this.curbuf_.addChar(
  419. shaka.cea.Cea608Memory.CharSet.BASIC_NORTH_AMERICAN, b1);
  420. this.curbuf_.addChar(
  421. shaka.cea.Cea608Memory.CharSet.BASIC_NORTH_AMERICAN, b2);
  422. }
  423. /**
  424. * Handles an Extended Western European byte pair.
  425. * @param {!number} b1 Byte 1.
  426. * @param {!number} b2 Byte 2.
  427. * @private
  428. */
  429. handleExtendedWesternEuropeanChar_(b1, b2) {
  430. // Get the char set from the LSB, which is the char set toggle bit.
  431. const charSet = b1 & 0x01 ?
  432. shaka.cea.Cea608Memory.CharSet.PORTUGUESE_GERMAN:
  433. shaka.cea.Cea608Memory.CharSet.SPANISH_FRENCH;
  434. this.curbuf_.addChar(charSet, b2);
  435. }
  436. /**
  437. * Decodes control code.
  438. * Three types of control codes:
  439. * Preamble Address Codes, Mid-Row Codes, and Miscellaneous Control Codes.
  440. * @param {!shaka.cea.Cea608DataChannel.Cea608Packet} ccPacket
  441. * @return {?shaka.cea.ICaptionDecoder.ClosedCaption}
  442. */
  443. handleControlCode(ccPacket) {
  444. const b1 = ccPacket.ccData1;
  445. const b2 = ccPacket.ccData2;
  446. // FCC wants control codes transmitted twice, and that will often be
  447. // seen in broadcast captures. If the very next frame has a duplicate
  448. // control code, that duplicate is ignored. Note that this only applies
  449. // to the very next frame, and only for one match.
  450. if (this.lastcp_ === ((b1 << 8) | b2)) {
  451. this.lastcp_ = null;
  452. return null;
  453. }
  454. // Remember valid control code for checking in next frame!
  455. this.lastcp_ = (b1 << 8) | b2;
  456. if (this.isPAC_(b1, b2)) {
  457. this.controlPac_(b1, b2);
  458. } else if (this.isMidrowStyleChange_(b1, b2)) {
  459. this.controlMidrow_(b2);
  460. } else if (this.isBackgroundAttribute_(b1, b2)) {
  461. this.controlBackgroundAttribute_(b1, b2);
  462. } else if (this.isSpecialNorthAmericanChar_(b1, b2)) {
  463. this.curbuf_.addChar(
  464. shaka.cea.Cea608Memory.CharSet.SPECIAL_NORTH_AMERICAN, b2);
  465. } else if (this.isExtendedWesternEuropeanChar_(b1, b2)) {
  466. this.handleExtendedWesternEuropeanChar_(b1, b2);
  467. } else if (this.isMiscellaneous_(b1, b2)) {
  468. return this.controlMiscellaneous_(ccPacket);
  469. }
  470. return null;
  471. }
  472. /**
  473. * Checks if this is a Miscellaneous control code.
  474. * @param {!number} b1 Byte 1.
  475. * @param {!number} b2 Byte 2.
  476. * @return {!boolean}
  477. * @private
  478. */
  479. isMiscellaneous_(b1, b2) {
  480. // For Miscellaneous Control Codes, the bytes take the following form:
  481. // b1 -> |0|0|0|1|C|1|0|F|
  482. // b2 -> |0|0|1|0|X|X|X|X|
  483. return ((b1 & 0xf6) === 0x14) && ((b2 & 0xf0) === 0x20);
  484. }
  485. /**
  486. * Checks if this is a PAC control code.
  487. * @param {!number} b1 Byte 1.
  488. * @param {!number} b2 Byte 2.
  489. * @return {!boolean}
  490. * @private
  491. */
  492. isPAC_(b1, b2) {
  493. // For Preamble Address Codes, the bytes take the following form:
  494. // b1 -> |0|0|0|1|X|X|X|X|
  495. // b2 -> |0|1|X|X|X|X|X|X|
  496. return ((b1 & 0xf0) === 0x10) && ((b2 & 0xc0) === 0x40);
  497. }
  498. /**
  499. * Checks if this is a Midrow style change control code.
  500. * @param {!number} b1 Byte 1.
  501. * @param {!number} b2 Byte 2.
  502. * @return {!boolean}
  503. * @private
  504. */
  505. isMidrowStyleChange_(b1, b2) {
  506. // For Midrow Control Codes, the bytes take the following form:
  507. // b1 -> |0|0|0|1|C|0|0|1|
  508. // b2 -> |0|0|1|0|X|X|X|X|
  509. return ((b1 & 0xf7) === 0x11) && ((b2 & 0xf0) === 0x20);
  510. }
  511. /**
  512. * Checks if this is a background attribute control code.
  513. * @param {!number} b1 Byte 1.
  514. * @param {!number} b2 Byte 2.
  515. * @return {!boolean}
  516. * @private
  517. */
  518. isBackgroundAttribute_(b1, b2) {
  519. // For Background Attribute Codes, the bytes take the following form:
  520. // Bg provided: b1 -> |0|0|0|1|C|0|0|0| b2 -> |0|0|1|0|COLOR|T|
  521. // No Bg: b1 -> |0|0|0|1|C|1|1|1| b2 -> |0|0|1|0|1|1|0|1|
  522. return (((b1 & 0xf7) === 0x10) && ((b2 & 0xf0) === 0x20)) ||
  523. (((b1 & 0xf7) === 0x17) && ((b2 & 0xff) === 0x2D));
  524. }
  525. /**
  526. * Checks if the character is in the Special North American char. set.
  527. * @param {!number} b1 Byte 1.
  528. * @param {!number} b2 Byte 2.
  529. * @return {!boolean}
  530. * @private
  531. */
  532. isSpecialNorthAmericanChar_(b1, b2) {
  533. // The bytes take the following form:
  534. // b1 -> |0|0|0|1|C|0|0|1|
  535. // b2 -> |0|0|1|1| CHAR |
  536. return ((b1 & 0xf7) === 0x11) && ((b2 & 0xf0) === 0x30);
  537. }
  538. /**
  539. * Checks if the character is in the Extended Western European char. set.
  540. * @param {!number} b1 Byte 1.
  541. * @param {!number} b2 Byte 2.
  542. * @return {!boolean}
  543. * @private
  544. */
  545. isExtendedWesternEuropeanChar_(b1, b2) {
  546. // The bytes take the following form:
  547. // b1 -> |0|0|0|1|C|0|1|S|
  548. // b2 -> |0|0|1|CHARACTER|
  549. return ((b1 & 0xf6) === 0x12) && ((b2 & 0xe0) === 0x20);
  550. }
  551. /**
  552. * Checks if the data contains a control code.
  553. * @param {!number} b1 Byte 1.
  554. * @return {!boolean}
  555. */
  556. static isControlCode(b1) {
  557. // For control codes, the first byte takes the following form:
  558. // b1 -> |P|0|0|1|X|X|X|X|
  559. return (b1 & 0x70) === 0x10;
  560. }
  561. };
  562. /**
  563. * Command codes.
  564. * @enum {!number}
  565. * @private
  566. */
  567. shaka.cea.Cea608DataChannel.MiscCmd_ = {
  568. // "RCL - Resume Caption Loading"
  569. RCL: 0x20,
  570. // "BS - BackSpace"
  571. BS: 0x21,
  572. // "AOD - Unused (alarm off)"
  573. AOD: 0x22,
  574. // "AON - Unused (alarm on)"
  575. AON: 0x23,
  576. // "DER - Delete to End of Row"
  577. DER: 0x24,
  578. // "RU2 - Roll-Up, 2 rows"
  579. RU2: 0x25,
  580. // "RU3 - Roll-Up, 3 rows"
  581. RU3: 0x26,
  582. // "RU4 - Roll-Up, 4 rows"
  583. RU4: 0x27,
  584. // "FON - Flash On"
  585. FON: 0x28,
  586. // "RDC - Resume Direct Captions"
  587. RDC: 0x29,
  588. // "TR - Text Restart"
  589. TR: 0x2a,
  590. // "RTD - Resume Text Display"
  591. RTD: 0x2b,
  592. // "EDM - Erase Displayed Mem"
  593. EDM: 0x2c,
  594. // "CR - Carriage return"
  595. CR: 0x2d,
  596. // "ENM - Erase Nondisplayed Mem"
  597. ENM: 0x2e,
  598. // "EOC - End Of Caption (flip mem)"
  599. EOC: 0x2f,
  600. };
  601. /**
  602. * Caption type.
  603. * @private @const @enum {!number}
  604. */
  605. shaka.cea.Cea608DataChannel.CaptionType = {
  606. NONE: 0,
  607. POPON: 1,
  608. PAINTON: 2,
  609. ROLLUP: 3,
  610. TEXT: 4,
  611. };
  612. /**
  613. * @const {!Array<!string>}
  614. */
  615. shaka.cea.Cea608DataChannel.BG_COLORS = [
  616. 'black',
  617. 'green',
  618. 'blue',
  619. 'cyan',
  620. 'red',
  621. 'yellow',
  622. 'magenta',
  623. 'black',
  624. ];
  625. /**
  626. * @const {!Array<!string>}
  627. */
  628. shaka.cea.Cea608DataChannel.TEXT_COLORS = [
  629. 'white',
  630. 'green',
  631. 'blue',
  632. 'cyan',
  633. 'red',
  634. 'yellow',
  635. 'magenta',
  636. 'white_italics',
  637. ];
  638. /**
  639. * Style associated with a cue.
  640. * @typedef {{
  641. * textColor: ?string,
  642. * backgroundColor: ?string,
  643. * italics: ?boolean,
  644. * underline: ?boolean
  645. * }}
  646. */
  647. shaka.cea.Cea608DataChannel.Style;
  648. /**
  649. * CEA closed captions packet.
  650. * @typedef {{
  651. * pts: !number,
  652. * type: !number,
  653. * ccData1: !number,
  654. * ccData2: !number,
  655. * order: !number
  656. * }}
  657. *
  658. * @property {!number} pts
  659. * Presentation timestamp (in second) at which this packet was received.
  660. * @property {!number} type
  661. * Type of the packet. Either 0 or 1, representing the CEA-608 field.
  662. * @property {!number} ccData1 CEA-608 byte 1.
  663. * @property {!number} ccData2 CEA-608 byte 2.
  664. * @property {(!number)} order
  665. * A number indicating the order this packet was received in a sequence
  666. * of packets. Used to break ties in a stable sorting algorithm
  667. */
  668. shaka.cea.Cea608DataChannel.Cea608Packet;