Source: lib/media/closed_caption_parser.js

  1. /*! @license
  2. * Shaka Player
  3. * Copyright 2016 Google LLC
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. goog.provide('shaka.media.ClosedCaptionParser');
  7. goog.provide('shaka.media.IClosedCaptionParser');
  8. goog.require('shaka.cea.DummyCaptionDecoder');
  9. goog.require('shaka.cea.DummyCeaParser');
  10. goog.require('shaka.util.BufferUtils');
  11. /**
  12. * The IClosedCaptionParser defines the interface to provide all operations for
  13. * parsing the closed captions embedded in Dash videos streams.
  14. * TODO: Remove this interface and move method definitions
  15. * directly to ClosedCaptonParser.
  16. * @interface
  17. * @export
  18. */
  19. shaka.media.IClosedCaptionParser = class {
  20. /**
  21. * Initialize the caption parser. This should be called only once.
  22. * @param {BufferSource} initSegment
  23. */
  24. init(initSegment) {}
  25. /**
  26. * Parses embedded CEA closed captions and interacts with the underlying
  27. * CaptionStream, and calls the callback function when there are closed
  28. * captions.
  29. *
  30. * @param {BufferSource} mediaFragment
  31. * @return {!Array<!shaka.extern.ICaptionDecoder.ClosedCaption>}
  32. * An array of parsed closed captions.
  33. */
  34. parseFrom(mediaFragment) {}
  35. /**
  36. * Resets the CaptionStream.
  37. */
  38. reset() {}
  39. };
  40. /**
  41. * Closed Caption Parser provides all operations for parsing the closed captions
  42. * embedded in Dash videos streams.
  43. *
  44. * @implements {shaka.media.IClosedCaptionParser}
  45. * @final
  46. * @export
  47. */
  48. shaka.media.ClosedCaptionParser = class {
  49. /**
  50. * @param {string} mimeType
  51. */
  52. constructor(mimeType) {
  53. /** @private {!shaka.extern.ICeaParser} */
  54. this.ceaParser_ = new shaka.cea.DummyCeaParser();
  55. const parserFactory =
  56. shaka.media.ClosedCaptionParser.findParser(mimeType.toLowerCase());
  57. if (parserFactory) {
  58. this.ceaParser_ = parserFactory();
  59. }
  60. /**
  61. * Decoder for decoding CEA-X08 data from closed caption packets.
  62. * @private {!shaka.extern.ICaptionDecoder}
  63. */
  64. this.ceaDecoder_ = new shaka.cea.DummyCaptionDecoder();
  65. const decoderFactory = shaka.media.ClosedCaptionParser.findDecoder();
  66. if (decoderFactory) {
  67. this.ceaDecoder_ = decoderFactory();
  68. }
  69. }
  70. /**
  71. * @override
  72. */
  73. init(initSegment) {
  74. this.ceaParser_.init(initSegment);
  75. }
  76. /**
  77. * @override
  78. */
  79. parseFrom(mediaFragment) {
  80. // Parse the fragment.
  81. const captionPackets = this.ceaParser_.parse(mediaFragment);
  82. // Extract the caption packets for decoding.
  83. for (const captionPacket of captionPackets) {
  84. const uint8ArrayData =
  85. shaka.util.BufferUtils.toUint8(captionPacket.packet);
  86. if (uint8ArrayData.length > 0) {
  87. this.ceaDecoder_.extract(uint8ArrayData, captionPacket.pts);
  88. }
  89. }
  90. // Decode and return the parsed captions.
  91. return this.ceaDecoder_.decode();
  92. }
  93. /**
  94. * @override
  95. */
  96. reset() {
  97. this.ceaDecoder_.clear();
  98. }
  99. /**
  100. * @param {string} mimeType
  101. * @param {!shaka.extern.CeaParserPlugin} plugin
  102. * @export
  103. */
  104. static registerParser(mimeType, plugin) {
  105. shaka.media.ClosedCaptionParser.parserMap_[mimeType] = plugin;
  106. }
  107. /**
  108. * @param {string} mimeType
  109. * @export
  110. */
  111. static unregisterParser(mimeType) {
  112. delete shaka.media.ClosedCaptionParser.parserMap_[mimeType];
  113. }
  114. /**
  115. * @param {string} mimeType
  116. * @return {?shaka.extern.CeaParserPlugin}
  117. * @export
  118. */
  119. static findParser(mimeType) {
  120. return shaka.media.ClosedCaptionParser.parserMap_[mimeType];
  121. }
  122. /**
  123. * @param {!shaka.extern.CaptionDecoderPlugin} plugin
  124. * @export
  125. */
  126. static registerDecoder(plugin) {
  127. shaka.media.ClosedCaptionParser.decoderFactory_ = plugin;
  128. }
  129. /**
  130. * @export
  131. */
  132. static unregisterDecoder() {
  133. shaka.media.ClosedCaptionParser.decoderFactory_ = null;
  134. }
  135. /**
  136. * @return {?shaka.extern.CaptionDecoderPlugin}
  137. * @export
  138. */
  139. static findDecoder() {
  140. return shaka.media.ClosedCaptionParser.decoderFactory_;
  141. }
  142. };
  143. /** @private {!Object<string, shaka.extern.CeaParserPlugin>} */
  144. shaka.media.ClosedCaptionParser.parserMap_ = {};
  145. /** @private {?shaka.extern.CaptionDecoderPlugin} */
  146. shaka.media.ClosedCaptionParser.decoderFactory_ = null;