Source: lib/lcevc/lcevc_dec.js

  1. /*! @license
  2. * Shaka Player
  3. * Copyright 2016 Google LLC
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. goog.provide('shaka.lcevc.Dec');
  7. goog.require('shaka.log');
  8. goog.require('shaka.Deprecate');
  9. goog.require('shaka.util.IReleasable');
  10. goog.require('shaka.util.ManifestParserUtils');
  11. /**
  12. * @summary
  13. * lcevcDec - (MPEG-5 Part 2 LCEVC - Decoder) provides
  14. * all the operations related to the enhancement and rendering
  15. * of LCEVC enabled streams and on to a canvas.
  16. * @implements {shaka.util.IReleasable}
  17. * @export
  18. */
  19. shaka.lcevc.Dec = class {
  20. /**
  21. * @param {HTMLVideoElement} media The video element that will be attached to
  22. * LCEVC Decoder for input.
  23. * @param {HTMLCanvasElement} canvas The canvas element that will be attached
  24. * to LCEVC Decoder to render the enhanced frames.
  25. * @param {shaka.extern.LcevcConfiguration} lcevcConfig LCEVC configuration
  26. * object to initialize the LCEVC Decoder.
  27. * @param {boolean} isDualTrack
  28. */
  29. constructor(media, canvas, lcevcConfig, isDualTrack) {
  30. /**
  31. * LCEVC Decoder library based on availability, to check if either
  32. * lcevc_dil or lcevc_dec is present.
  33. * @private {LCEVCmodule}
  34. */
  35. this.lcevcLib_;
  36. /** @private {?LCEVCdec.LCEVCdec} */
  37. this.dec_ = null;
  38. /** @private {HTMLVideoElement} */
  39. this.media_ = media;
  40. /** @private {HTMLCanvasElement} */
  41. this.canvas_ = canvas;
  42. /** @private {shaka.extern.LcevcConfiguration} */
  43. this.decConfig_ = lcevcConfig;
  44. /** @private {boolean} */
  45. this.isDualTrack_ = isDualTrack;
  46. /** @private {boolean} */
  47. this.toBeDeprecated_ = false;
  48. this.create_();
  49. }
  50. /**
  51. * Append data to the LCEVC Dec.
  52. * @param {BufferSource} data
  53. * @param {number} timestampOffset
  54. * @param {shaka.extern.Stream} stream
  55. */
  56. appendBuffer(data, timestampOffset, stream) {
  57. const ContentType = shaka.util.ManifestParserUtils.ContentType;
  58. // LCEVC only supports VIDEO.
  59. if (stream.type !== ContentType.VIDEO ||
  60. (this.isDualTrack_ && !stream.baseOriginalId)) {
  61. return;
  62. }
  63. if (this.dec_) {
  64. // Timestamp offset describes how much offset should be applied to the
  65. // LCEVC enhancement to match the decoded video frame, as such it needs
  66. // to be negated.
  67. this.dec_.appendBuffer(data, 'video', stream.id, -timestampOffset,
  68. !this.isDualTrack_);
  69. }
  70. }
  71. /**
  72. * Hide the canvas specifically in the case of a DRM Content
  73. */
  74. hideCanvas() {
  75. if (this.dec_) {
  76. this.canvas_.classList.add('shaka-hidden');
  77. }
  78. }
  79. /**
  80. * Create LCEVC Decoder.
  81. * @private
  82. */
  83. create_() {
  84. if (this.isSupported_() && !this.dec_) {
  85. if (this.lcevcLib_.SupportObject.webGLSupport(this.canvas_)) {
  86. // Make sure the canvas is not hidden from a previous playback session.
  87. this.canvas_.classList.remove('shaka-hidden');
  88. // Initiate LCEVC Dec Library based on the type of module available.
  89. if (this.toBeDeprecated_) {
  90. this.dec_ = new this.lcevcLib_.LcevcDil(
  91. this.media_,
  92. this.canvas_,
  93. this.decConfig_);
  94. } else {
  95. this.dec_ = new this.lcevcLib_.LCEVCdec(
  96. this.media_,
  97. this.canvas_,
  98. this.decConfig_);
  99. }
  100. }
  101. }
  102. }
  103. /**
  104. * Close LCEVC Decoder.
  105. * @override
  106. * @export
  107. */
  108. release() {
  109. if (this.dec_) {
  110. this.dec_.close();
  111. this.dec_ = null;
  112. }
  113. }
  114. /**
  115. * Check if the LCEVC Decoder lib is present and is supported by the browser.
  116. * @return {boolean}
  117. * @private
  118. */
  119. isSupported_() {
  120. if (typeof libDPIModule === 'undefined') {
  121. shaka.log.alwaysWarn(
  122. 'Could not find LCEVC Library dependencies on this page');
  123. }
  124. // This is a check to make the LCEVC Dec Integration is backwards compatible
  125. // with previous Integration. This logic checks for both implementations
  126. // and uses the one available.
  127. if (typeof LCEVCdec !== 'undefined') {
  128. this.lcevcLib_ = LCEVCdec;
  129. } else {
  130. if (typeof LcevcDil !== 'undefined') {
  131. this.lcevcLib_ = LcevcDil;
  132. this.toBeDeprecated_ = true;
  133. shaka.Deprecate.deprecateFeature(5,
  134. 'LcevcDil',
  135. 'lcevc_dil.js is deprecated, please use lcevc_dec.js instead');
  136. } else {
  137. shaka.log.alwaysWarn('Could not find LCEVC Library on this page');
  138. return false;
  139. }
  140. }
  141. // Making Sure if there is a valid LCEVC Dec Library exists.
  142. if (typeof this.lcevcLib_.SupportObject === 'undefined') {
  143. shaka.log.alwaysWarn('Could not find LCEVC Library on this page');
  144. return false;
  145. } else {
  146. if (!this.lcevcLib_.SupportObject.SupportStatus) {
  147. shaka.log.alwaysWarn(this.lcevcLib_.SupportObject.SupportError);
  148. }
  149. }
  150. return typeof this.lcevcLib_ !== 'undefined' &&
  151. typeof libDPIModule !== 'undefined' &&
  152. this.canvas_ instanceof HTMLCanvasElement &&
  153. this.lcevcLib_.SupportObject.SupportStatus;
  154. }
  155. /**
  156. * Update current active variant
  157. * @param {shaka.extern.Variant} variant
  158. * @param {?string} manifestType
  159. */
  160. updateVariant(variant, manifestType) {
  161. let stream = variant.video;
  162. if (!stream) {
  163. return;
  164. }
  165. if (stream.dependencyStream) {
  166. stream = stream.dependencyStream;
  167. }
  168. let containerFormat = shaka.lcevc.Dec.ContainerFormat.MPEG2_TS;
  169. let streamingFormat = shaka.lcevc.Dec.StreamingFormat.OTHER;
  170. switch (stream.mimeType) {
  171. case 'video/webm': {
  172. containerFormat = shaka.lcevc.Dec.ContainerFormat.WEBM;
  173. break;
  174. }
  175. case 'video/mp4': {
  176. containerFormat = shaka.lcevc.Dec.ContainerFormat.MP4;
  177. break;
  178. }
  179. }
  180. switch (manifestType) {
  181. case 'DASH': {
  182. streamingFormat = shaka.lcevc.Dec.StreamingFormat.DASH;
  183. break;
  184. }
  185. case 'HLS': {
  186. streamingFormat = shaka.lcevc.Dec.StreamingFormat.HLS;
  187. break;
  188. }
  189. }
  190. if (this.dec_) {
  191. this.dec_.setLevelSwitching(stream.id, true);
  192. this.dec_.setContainerFormat(containerFormat);
  193. // This functionality is only available on the LCEVC Dec Library.
  194. if (!this.toBeDeprecated_) {
  195. this.dec_.setStreamingFormat(streamingFormat);
  196. }
  197. }
  198. }
  199. /**
  200. * Checks if a dual track content enhancement stream is supported.
  201. *
  202. * @param {shaka.extern.Stream} stream
  203. * @return {boolean}
  204. */
  205. static isStreamSupported(stream) {
  206. if (!stream || typeof LCEVCdec === 'undefined') {
  207. return false;
  208. }
  209. return stream.codecs == 'lvc1';
  210. }
  211. };
  212. /**
  213. * Container Formats.
  214. * @const @enum {number}
  215. */
  216. shaka.lcevc.Dec.ContainerFormat = {
  217. MPEG2_TS: 0,
  218. WEBM: 1,
  219. MP4: 2,
  220. };
  221. /**
  222. * Streaming Formats.
  223. * @const @enum {number}
  224. */
  225. shaka.lcevc.Dec.StreamingFormat = {
  226. HLS: 0,
  227. DASH: 1,
  228. OTHER: -1,
  229. };