rx-player 4.0.0-beta.1 → 4.0.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (169) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/CONTRIBUTING.md +48 -168
  3. package/FILES.md +40 -92
  4. package/VERSION +1 -1
  5. package/dist/_esm5.processed/compat/browser_detection.d.ts +3 -1
  6. package/dist/_esm5.processed/compat/browser_detection.js +7 -2
  7. package/dist/_esm5.processed/compat/eme/load_session.js +1 -1
  8. package/dist/_esm5.processed/compat/has_issues_with_high_media_source_duration.d.ts +21 -0
  9. package/dist/_esm5.processed/compat/has_issues_with_high_media_source_duration.js +26 -0
  10. package/dist/_esm5.processed/config.d.ts +2 -0
  11. package/dist/_esm5.processed/core/adaptive/adaptive_representation_selector.js +5 -4
  12. package/dist/_esm5.processed/core/adaptive/buffer_based_chooser.d.ts +18 -1
  13. package/dist/_esm5.processed/core/adaptive/buffer_based_chooser.js +106 -25
  14. package/dist/_esm5.processed/core/adaptive/guess_based_chooser.js +6 -6
  15. package/dist/_esm5.processed/core/adaptive/network_analyzer.js +8 -5
  16. package/dist/_esm5.processed/core/adaptive/utils/representation_score_calculator.d.ts +19 -1
  17. package/dist/_esm5.processed/core/adaptive/utils/representation_score_calculator.js +1 -1
  18. package/dist/_esm5.processed/core/api/debug/render.js +1 -1
  19. package/dist/_esm5.processed/core/api/playback_observer.js +1 -0
  20. package/dist/_esm5.processed/core/api/public_api.d.ts +54 -1
  21. package/dist/_esm5.processed/core/api/public_api.js +232 -35
  22. package/dist/_esm5.processed/core/api/track_management/media_element_tracks_store.js +10 -1
  23. package/dist/_esm5.processed/core/api/track_management/track_dispatcher.d.ts +13 -1
  24. package/dist/_esm5.processed/core/api/track_management/track_dispatcher.js +30 -15
  25. package/dist/_esm5.processed/core/api/track_management/tracks_store.d.ts +3 -1
  26. package/dist/_esm5.processed/core/api/track_management/tracks_store.js +67 -152
  27. package/dist/_esm5.processed/core/api/utils.d.ts +10 -0
  28. package/dist/_esm5.processed/core/api/utils.js +20 -0
  29. package/dist/_esm5.processed/core/decrypt/session_events_listener.js +7 -1
  30. package/dist/_esm5.processed/core/decrypt/utils/clean_old_loaded_sessions.js +2 -0
  31. package/dist/_esm5.processed/core/decrypt/utils/loaded_sessions_store.js +5 -1
  32. package/dist/_esm5.processed/core/init/directfile_content_initializer.js +1 -1
  33. package/dist/_esm5.processed/core/init/media_source_content_initializer.js +47 -10
  34. package/dist/_esm5.processed/core/init/types.d.ts +9 -1
  35. package/dist/_esm5.processed/core/init/utils/content_time_boundaries_observer.d.ts +28 -1
  36. package/dist/_esm5.processed/core/init/utils/content_time_boundaries_observer.js +22 -9
  37. package/dist/_esm5.processed/core/init/utils/media_source_duration_updater.d.ts +58 -0
  38. package/dist/_esm5.processed/core/init/utils/{media_duration_updater.js → media_source_duration_updater.js} +84 -87
  39. package/dist/_esm5.processed/core/init/utils/rebuffering_controller.d.ts +36 -2
  40. package/dist/_esm5.processed/core/init/utils/rebuffering_controller.js +82 -2
  41. package/dist/_esm5.processed/core/segment_buffers/implementations/audio_video/audio_video_segment_buffer.d.ts +18 -7
  42. package/dist/_esm5.processed/core/segment_buffers/implementations/audio_video/audio_video_segment_buffer.js +31 -40
  43. package/dist/_esm5.processed/core/segment_buffers/implementations/text/html/html_text_segment_buffer.d.ts +8 -0
  44. package/dist/_esm5.processed/core/segment_buffers/implementations/text/html/html_text_segment_buffer.js +12 -0
  45. package/dist/_esm5.processed/core/segment_buffers/implementations/text/native/native_text_segment_buffer.d.ts +8 -0
  46. package/dist/_esm5.processed/core/segment_buffers/implementations/text/native/native_text_segment_buffer.js +12 -0
  47. package/dist/_esm5.processed/core/segment_buffers/implementations/types.d.ts +11 -4
  48. package/dist/_esm5.processed/core/segment_buffers/index.d.ts +2 -2
  49. package/dist/_esm5.processed/core/stream/adaptation/utils/create_representation_estimator.d.ts +47 -0
  50. package/dist/_esm5.processed/core/stream/adaptation/utils/create_representation_estimator.js +70 -0
  51. package/dist/_esm5.processed/core/stream/orchestrator/stream_orchestrator.js +15 -8
  52. package/dist/_esm5.processed/core/stream/period/period_stream.js +1 -1
  53. package/dist/_esm5.processed/core/stream/representation/representation_stream.js +22 -13
  54. package/dist/_esm5.processed/core/stream/representation/utils/append_segment_to_buffer.d.ts +4 -2
  55. package/dist/_esm5.processed/core/stream/representation/utils/append_segment_to_buffer.js +2 -2
  56. package/dist/_esm5.processed/core/stream/representation/utils/push_init_segment.d.ts +3 -2
  57. package/dist/_esm5.processed/core/stream/representation/utils/push_init_segment.js +8 -8
  58. package/dist/_esm5.processed/core/stream/representation/utils/push_media_segment.d.ts +2 -2
  59. package/dist/_esm5.processed/core/stream/representation/utils/push_media_segment.js +2 -3
  60. package/dist/_esm5.processed/default_config.d.ts +25 -0
  61. package/dist/_esm5.processed/default_config.js +27 -2
  62. package/dist/_esm5.processed/errors/index.d.ts +2 -2
  63. package/dist/_esm5.processed/errors/media_error.d.ts +23 -1
  64. package/dist/_esm5.processed/errors/media_error.js +18 -5
  65. package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/load_and_push_segment.d.ts +1 -1
  66. package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/load_and_push_segment.js +8 -7
  67. package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/video_thumbnail_loader.js +17 -9
  68. package/dist/_esm5.processed/experimental/tools/mediaCapabilitiesProber/index.js +0 -2
  69. package/dist/_esm5.processed/manifest/adaptation.d.ts +21 -2
  70. package/dist/_esm5.processed/manifest/adaptation.js +76 -1
  71. package/dist/_esm5.processed/manifest/manifest.js +1 -1
  72. package/dist/_esm5.processed/manifest/period.js +2 -2
  73. package/dist/_esm5.processed/manifest/representation.d.ts +33 -2
  74. package/dist/_esm5.processed/manifest/representation.js +21 -0
  75. package/dist/_esm5.processed/manifest/utils.js +1 -3
  76. package/dist/_esm5.processed/parsers/manifest/dash/js-parser/parse_from_document.d.ts +1 -1
  77. package/dist/_esm5.processed/parsers/manifest/dash/js-parser/parse_from_document.js +1 -1
  78. package/dist/_esm5.processed/parsers/manifest/dash/wasm-parser/ts/dash-wasm-parser.js +1 -0
  79. package/dist/_esm5.processed/public_types.d.ts +13 -3
  80. package/dist/_esm5.processed/tools/TextTrackRenderer/text_track_renderer.js +1 -1
  81. package/dist/_esm5.processed/transports/smooth/isobmff/create_boxes.d.ts +4 -6
  82. package/dist/_esm5.processed/transports/smooth/isobmff/create_boxes.js +4 -6
  83. package/dist/_esm5.processed/utils/is_null_or_undefined.d.ts +1 -1
  84. package/dist/_esm5.processed/utils/is_null_or_undefined.js +1 -1
  85. package/dist/mpd-parser.wasm +0 -0
  86. package/dist/rx-player.js +4709 -4218
  87. package/dist/rx-player.min.js +1 -1
  88. package/package.json +42 -36
  89. package/scripts/build/generate_build.js +1 -1
  90. package/scripts/fast_demo_build.js +4 -3
  91. package/scripts/generate_full_demo.js +1 -1
  92. package/sonar-project.properties +1 -1
  93. package/src/compat/browser_detection.ts +7 -1
  94. package/src/compat/eme/load_session.ts +1 -1
  95. package/src/compat/has_issues_with_high_media_source_duration.ts +27 -0
  96. package/src/core/adaptive/__tests__/buffer_based_chooser.test.ts +147 -48
  97. package/src/core/adaptive/adaptive_representation_selector.ts +7 -4
  98. package/src/core/adaptive/buffer_based_chooser.ts +144 -26
  99. package/src/core/adaptive/guess_based_chooser.ts +9 -8
  100. package/src/core/adaptive/network_analyzer.ts +9 -4
  101. package/src/core/adaptive/utils/representation_score_calculator.ts +22 -2
  102. package/src/core/api/debug/render.ts +1 -1
  103. package/src/core/api/playback_observer.ts +1 -0
  104. package/src/core/api/public_api.ts +277 -44
  105. package/src/core/api/track_management/media_element_tracks_store.ts +17 -8
  106. package/src/core/api/track_management/track_dispatcher.ts +37 -14
  107. package/src/core/api/track_management/tracks_store.ts +77 -167
  108. package/src/core/api/utils.ts +26 -0
  109. package/src/core/decrypt/session_events_listener.ts +6 -1
  110. package/src/core/decrypt/utils/clean_old_loaded_sessions.ts +2 -1
  111. package/src/core/decrypt/utils/loaded_sessions_store.ts +8 -1
  112. package/src/core/init/directfile_content_initializer.ts +1 -0
  113. package/src/core/init/media_source_content_initializer.ts +52 -9
  114. package/src/core/init/types.ts +9 -1
  115. package/src/core/init/utils/content_time_boundaries_observer.ts +46 -10
  116. package/src/core/init/utils/{media_duration_updater.ts → media_source_duration_updater.ts} +100 -112
  117. package/src/core/init/utils/rebuffering_controller.ts +114 -3
  118. package/src/core/segment_buffers/implementations/audio_video/audio_video_segment_buffer.ts +56 -55
  119. package/src/core/segment_buffers/implementations/text/html/html_text_segment_buffer.ts +16 -0
  120. package/src/core/segment_buffers/implementations/text/native/native_text_segment_buffer.ts +16 -0
  121. package/src/core/segment_buffers/implementations/types.ts +16 -4
  122. package/src/core/segment_buffers/index.ts +2 -0
  123. package/src/core/stream/adaptation/utils/create_representation_estimator.ts +114 -0
  124. package/src/core/stream/orchestrator/stream_orchestrator.ts +16 -8
  125. package/src/core/stream/period/period_stream.ts +2 -1
  126. package/src/core/stream/representation/representation_stream.ts +34 -22
  127. package/src/core/stream/representation/utils/append_segment_to_buffer.ts +8 -3
  128. package/src/core/stream/representation/utils/push_init_segment.ts +11 -6
  129. package/src/core/stream/representation/utils/push_media_segment.ts +3 -3
  130. package/src/default_config.ts +29 -2
  131. package/src/errors/__tests__/media_error.test.ts +6 -6
  132. package/src/errors/index.ts +4 -1
  133. package/src/errors/media_error.ts +67 -1
  134. package/src/experimental/tools/VideoThumbnailLoader/load_and_push_segment.ts +10 -7
  135. package/src/experimental/tools/VideoThumbnailLoader/video_thumbnail_loader.ts +17 -6
  136. package/src/experimental/tools/mediaCapabilitiesProber/index.ts +0 -4
  137. package/src/manifest/__tests__/manifest.test.ts +7 -7
  138. package/src/manifest/__tests__/period.test.ts +90 -45
  139. package/src/manifest/adaptation.ts +89 -1
  140. package/src/manifest/manifest.ts +1 -1
  141. package/src/manifest/period.ts +4 -2
  142. package/src/manifest/representation.ts +67 -1
  143. package/src/manifest/utils.ts +1 -3
  144. package/src/parsers/manifest/dash/js-parser/parse_from_document.ts +1 -1
  145. package/src/parsers/manifest/dash/wasm-parser/ts/dash-wasm-parser.ts +1 -0
  146. package/src/parsers/texttracks/ttml/parse_ttml.ts +1 -1
  147. package/src/public_types.ts +16 -1
  148. package/src/tools/TextTrackRenderer/text_track_renderer.ts +1 -1
  149. package/src/transports/smooth/isobmff/create_boxes.ts +4 -6
  150. package/src/typings/globals.d.ts +20 -20
  151. package/src/utils/is_null_or_undefined.ts +1 -1
  152. package/dist/_esm5.processed/core/init/utils/media_duration_updater.d.ts +0 -56
  153. package/scripts/doc-generator/construct_table_of_contents.js +0 -76
  154. package/scripts/doc-generator/convert_MD_to_HMTL.js +0 -26
  155. package/scripts/doc-generator/create_documentation.js +0 -331
  156. package/scripts/doc-generator/create_documentation_page.js +0 -209
  157. package/scripts/doc-generator/create_page.js +0 -210
  158. package/scripts/doc-generator/generate_header_html.js +0 -147
  159. package/scripts/doc-generator/generate_page_html.js +0 -115
  160. package/scripts/doc-generator/generate_page_list_html.js +0 -92
  161. package/scripts/doc-generator/generate_sidebar_html.js +0 -85
  162. package/scripts/doc-generator/get_search_data_for_content.js +0 -137
  163. package/scripts/doc-generator/index.js +0 -34
  164. package/scripts/doc-generator/parse_doc_configs.js +0 -327
  165. package/scripts/doc-generator/scripts/lunr.js +0 -10
  166. package/scripts/doc-generator/scripts/script.js +0 -451
  167. package/scripts/doc-generator/styles/code.css +0 -99
  168. package/scripts/doc-generator/styles/style.css +0 -835
  169. package/scripts/doc-generator/utils.js +0 -74
@@ -30,6 +30,14 @@ export default class TrackDispatcher extends EventEmitter<ITrackDispatcherEvent>
30
30
  private _lastEmitted;
31
31
  /** Interface allowing to clean-up resources when they are not needed anymore. */
32
32
  private _canceller;
33
+ /**
34
+ * Boolean set to `true` when a track-updating method is called and to `false`
35
+ * just before it performs the actual track change to allow checking for
36
+ * re-entrancy: if the token is already reset to `false` before the
37
+ * track change is officialized, then another track update has already been
38
+ * performed in the meantime.
39
+ */
40
+ private _updateToken;
33
41
  /**
34
42
  * Create a new `TrackDispatcher` by giving its Reference and an initial track
35
43
  * setting.
@@ -37,9 +45,12 @@ export default class TrackDispatcher extends EventEmitter<ITrackDispatcherEvent>
37
45
  * synchronously.
38
46
  * @param {Object} manifest
39
47
  * @param {Object} adaptationRef
48
+ */
49
+ constructor(manifest: Manifest, adaptationRef: ISharedReference<IAdaptationChoice | null | undefined>);
50
+ /**
40
51
  * @param {Object|null} initialTrackInfo
41
52
  */
42
- constructor(manifest: Manifest, adaptationRef: ISharedReference<IAdaptationChoice | null | undefined>, initialTrackInfo: ITrackSetting | null);
53
+ start(initialTrackInfo: ITrackSetting | null): void;
43
54
  /**
44
55
  * Update the wanted track on the Reference linked to this `TrackDispatcher`.
45
56
  * @param {Object|null} newTrackInfo
@@ -65,6 +76,7 @@ export interface ITrackDispatcherEvent {
65
76
  * none of them are currently "playable".
66
77
  */
67
78
  noPlayableLockedRepresentation: null;
79
+ noPlayableRepresentation: null;
68
80
  }
69
81
  /** Define a new Track preference given to the `TrackDispatcher`. */
70
82
  export interface ITrackSetting {
@@ -13,7 +13,6 @@ var __extends = (this && this.__extends) || (function () {
13
13
  d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
14
14
  };
15
15
  })();
16
- import { MediaError } from "../../../errors";
17
16
  import EventEmitter from "../../../utils/event_emitter";
18
17
  import createSharedReference from "../../../utils/reference";
19
18
  import TaskCanceller from "../../../utils/task_canceller";
@@ -31,36 +30,49 @@ var TrackDispatcher = /** @class */ (function (_super) {
31
30
  * synchronously.
32
31
  * @param {Object} manifest
33
32
  * @param {Object} adaptationRef
34
- * @param {Object|null} initialTrackInfo
35
33
  */
36
- function TrackDispatcher(manifest, adaptationRef, initialTrackInfo) {
34
+ function TrackDispatcher(manifest, adaptationRef) {
37
35
  var _this = _super.call(this) || this;
38
36
  _this._canceller = new TaskCanceller();
39
37
  _this._manifest = manifest;
40
38
  _this._adaptationRef = adaptationRef;
39
+ _this._updateToken = false;
40
+ return _this;
41
+ }
42
+ /**
43
+ * @param {Object|null} initialTrackInfo
44
+ */
45
+ TrackDispatcher.prototype.start = function (initialTrackInfo) {
46
+ this._updateToken = true;
41
47
  if (initialTrackInfo === null) {
42
- _this._lastEmitted = initialTrackInfo;
43
- adaptationRef.setValue(null);
44
- return _this;
48
+ this._lastEmitted = null;
49
+ this._updateToken = false;
50
+ this._adaptationRef.setValue(null);
51
+ return;
45
52
  }
46
- var reference = _this._constructLockedRepresentationsReference(initialTrackInfo);
47
- _this._lastEmitted = { adaptation: initialTrackInfo.adaptation,
53
+ var reference = this._constructLockedRepresentationsReference(initialTrackInfo);
54
+ if (!this._updateToken) {
55
+ return;
56
+ }
57
+ this._lastEmitted = { adaptation: initialTrackInfo.adaptation,
48
58
  switchingMode: initialTrackInfo.switchingMode,
49
59
  lockedRepresentations: null };
50
- adaptationRef.setValue({ adaptation: initialTrackInfo.adaptation,
60
+ this._updateToken = false;
61
+ this._adaptationRef.setValue({ adaptation: initialTrackInfo.adaptation,
51
62
  switchingMode: initialTrackInfo.switchingMode,
52
63
  representations: reference });
53
- return _this;
54
- }
64
+ };
55
65
  /**
56
66
  * Update the wanted track on the Reference linked to this `TrackDispatcher`.
57
67
  * @param {Object|null} newTrackInfo
58
68
  */
59
69
  TrackDispatcher.prototype.updateTrack = function (newTrackInfo) {
70
+ this._updateToken = true;
60
71
  if (newTrackInfo === null) {
61
72
  if (this._lastEmitted === null) {
62
73
  return;
63
74
  }
75
+ this._updateToken = false;
64
76
  this._canceller.cancel();
65
77
  // has no point but let's still create one for simplicity sake
66
78
  this._canceller = new TaskCanceller();
@@ -72,7 +84,11 @@ var TrackDispatcher = /** @class */ (function (_super) {
72
84
  this._canceller.cancel();
73
85
  this._canceller = new TaskCanceller();
74
86
  var reference = this._constructLockedRepresentationsReference(newTrackInfo);
87
+ if (!this._updateToken) {
88
+ return;
89
+ }
75
90
  this._lastEmitted = { adaptation: adaptation, switchingMode: switchingMode, lockedRepresentations: null };
91
+ this._updateToken = false;
76
92
  this._adaptationRef.setValue({ adaptation: adaptation, switchingMode: switchingMode, representations: reference });
77
93
  };
78
94
  /**
@@ -120,10 +136,9 @@ var TrackDispatcher = /** @class */ (function (_super) {
120
136
  }
121
137
  }
122
138
  if (playableRepresentations.length <= 0) {
123
- var adaptationType = trackInfo.adaptation.type;
124
- var noRepErr = new MediaError("NO_PLAYABLE_REPRESENTATION", "No Representation in the chosen " +
125
- adaptationType + " Adaptation can be played");
126
- throw noRepErr;
139
+ trackInfo.adaptation.isSupported = false;
140
+ self.trigger("noPlayableRepresentation", null);
141
+ return;
127
142
  }
128
143
  // Check if Locked Representations have changed
129
144
  var oldRef = reference.getValue();
@@ -14,7 +14,7 @@
14
14
  * limitations under the License.
15
15
  */
16
16
  import Manifest, { Adaptation, Period } from "../../../manifest";
17
- import { IAudioRepresentationsSwitchingMode, IAudioTrack, IAudioTrackSwitchingMode, ITrackUpdateEventPayload, IAvailableAudioTrack, IAvailableTextTrack, IAvailableVideoTrack, IBrokenRepresentationsLockContext, IPeriod, ITextTrack, IVideoRepresentationsSwitchingMode, IVideoTrack, IVideoTrackSwitchingMode } from "../../../public_types";
17
+ import { IAudioRepresentationsSwitchingMode, IAudioTrack, IAudioTrackSwitchingMode, ITrackUpdateEventPayload, IAvailableAudioTrack, IAvailableTextTrack, IAvailableVideoTrack, IBrokenRepresentationsLockContext, IPeriod, ITextTrack, IVideoRepresentationsSwitchingMode, IVideoTrack, IVideoTrackSwitchingMode, IPlayerError } from "../../../public_types";
18
18
  import EventEmitter from "../../../utils/event_emitter";
19
19
  import { ISharedReference } from "../../../utils/reference";
20
20
  import { IAdaptationChoice, IRepresentationsChoice } from "../../stream";
@@ -394,6 +394,8 @@ interface ITracksStoreEvents {
394
394
  newAvailablePeriods: IPeriod[];
395
395
  brokenRepresentationsLock: IBrokenRepresentationsLockContext;
396
396
  trackUpdate: ITrackUpdateEventPayload;
397
+ error: unknown;
398
+ warning: IPlayerError;
397
399
  }
398
400
  export interface IAudioRepresentationsLockSettings {
399
401
  representations: string[];
@@ -33,12 +33,14 @@ var __extends = (this && this.__extends) || (function () {
33
33
  * switching for an easier API management.
34
34
  */
35
35
  import config from "../../../config";
36
+ import { MediaError } from "../../../errors";
36
37
  import log from "../../../log";
37
38
  import arrayFind from "../../../utils/array_find";
38
39
  import assert from "../../../utils/assert";
39
40
  import EventEmitter from "../../../utils/event_emitter";
41
+ import isNullOrUndefined from "../../../utils/is_null_or_undefined";
42
+ import objectAssign from "../../../utils/object_assign";
40
43
  import createSharedReference from "../../../utils/reference";
41
- import takeFirstSet from "../../../utils/take_first_set";
42
44
  import TrackDispatcher from "./track_dispatcher";
43
45
  /**
44
46
  * Class helping with the management of the audio, video and text tracks and
@@ -115,7 +117,7 @@ var TracksStore = /** @class */ (function (_super) {
115
117
  var stillHere = textAdaptations
116
118
  .some(function (a) { return a.id === curWantedTextTrack_1.adaptation.id; });
117
119
  if (!stillHere) {
118
- log.warn("TracksStore: Chosen text Adaptation not available anymore");
120
+ log.warn("TS: Chosen text Adaptation not available anymore");
119
121
  var periodInfo = this_1._storedPeriodInfo[i];
120
122
  periodInfo.text.storedSettings = null;
121
123
  this_1.trigger("trackUpdate", { period: toExposedPeriod(newPeriod),
@@ -138,7 +140,7 @@ var TracksStore = /** @class */ (function (_super) {
138
140
  var stillHere = videoAdaptations
139
141
  .some(function (a) { return a.id === curWantedVideoTrack_1.adaptation.id; });
140
142
  if (!stillHere) {
141
- log.warn("TracksStore: Chosen video Adaptation not available anymore");
143
+ log.warn("TS: Chosen video Adaptation not available anymore");
142
144
  var periodItem = this_1._storedPeriodInfo[i];
143
145
  var storedSettings = void 0;
144
146
  if (videoAdaptations.length === 0) {
@@ -172,7 +174,7 @@ var TracksStore = /** @class */ (function (_super) {
172
174
  var stillHere = audioAdaptations
173
175
  .some(function (a) { return a.id === curWantedAudioTrack_1.adaptation.id; });
174
176
  if (!stillHere) {
175
- log.warn("TracksStore: Chosen audio Adaptation not available anymore");
177
+ log.warn("TS: Chosen audio Adaptation not available anymore");
176
178
  var periodItem = this_1._storedPeriodInfo[i];
177
179
  var storedSettings = audioAdaptations.length === 0 ?
178
180
  null :
@@ -262,20 +264,58 @@ var TracksStore = /** @class */ (function (_super) {
262
264
  end: period.end }]);
263
265
  }
264
266
  if (periodObj[bufferType].dispatcher !== null) {
265
- log.error("TracksStore: Subject already added for ".concat(bufferType, " ") +
267
+ log.error("TS: Subject already added for ".concat(bufferType, " ") +
266
268
  "and Period ".concat(period.start));
267
269
  return;
268
270
  }
269
271
  var trackSetting = periodObj[bufferType].storedSettings;
270
- var dispatcher = new TrackDispatcher(manifest, adaptationRef, trackSetting);
272
+ var dispatcher = new TrackDispatcher(manifest, adaptationRef);
271
273
  periodObj[bufferType].dispatcher = dispatcher;
274
+ dispatcher.addEventListener("noPlayableRepresentation", function () {
275
+ var _a, _b, _c;
276
+ var nextAdaptation = arrayFind(period.getAdaptationsForType(bufferType), function (a) {
277
+ var playableRepresentations = a.getPlayableRepresentations();
278
+ return playableRepresentations.length > 0;
279
+ });
280
+ if (nextAdaptation === undefined) {
281
+ var noRepErr = new MediaError("NO_PLAYABLE_REPRESENTATION", "No ".concat(bufferType, " Representation can be played"), { adaptation: undefined });
282
+ _this.trigger("error", noRepErr);
283
+ _this.dispose();
284
+ return;
285
+ }
286
+ var typeInfo = (_a = getPeriodItem(_this._storedPeriodInfo, period.id)) === null || _a === void 0 ? void 0 : _a[bufferType];
287
+ if (isNullOrUndefined(typeInfo)) {
288
+ return;
289
+ }
290
+ var switchingMode = bufferType === "audio" ?
291
+ _this._defaultAudioTrackSwitchingMode :
292
+ "reload";
293
+ var storedSettings = { adaptation: nextAdaptation, switchingMode: switchingMode, lockedRepresentations: createSharedReference(null) };
294
+ typeInfo.storedSettings = storedSettings;
295
+ _this.trigger("trackUpdate", { period: toExposedPeriod(period),
296
+ trackType: bufferType,
297
+ reason: "no-playable-representation" });
298
+ // The previous event trigger could have had side-effects, so we
299
+ // re-check if we're still mostly in the same state
300
+ if (_this._isDisposed) {
301
+ return; // Someone disposed the `TracksStore` on the previous side-effect
302
+ }
303
+ typeInfo = (_b = getPeriodItem(_this._storedPeriodInfo, period.id)) === null || _b === void 0 ? void 0 : _b[bufferType];
304
+ if (isNullOrUndefined(typeInfo) || typeInfo.storedSettings !== storedSettings) {
305
+ return;
306
+ }
307
+ (_c = typeInfo.dispatcher) === null || _c === void 0 ? void 0 : _c.updateTrack(storedSettings);
308
+ });
272
309
  dispatcher.addEventListener("noPlayableLockedRepresentation", function () {
310
+ // TODO check that it doesn't already lead to segment loading or MediaSource
311
+ // reloading
273
312
  trackSetting === null || trackSetting === void 0 ? void 0 : trackSetting.lockedRepresentations.setValue(null);
274
313
  _this.trigger("brokenRepresentationsLock", { period: { id: period.id,
275
314
  start: period.start,
276
315
  end: period.end },
277
316
  trackType: bufferType });
278
317
  });
318
+ dispatcher.start(trackSetting);
279
319
  };
280
320
  /**
281
321
  * Remove shared reference to choose an "audio", "video" or "text" Adaptation
@@ -286,13 +326,13 @@ var TracksStore = /** @class */ (function (_super) {
286
326
  TracksStore.prototype.removeTrackReference = function (bufferType, period) {
287
327
  var periodIndex = findPeriodIndex(this._storedPeriodInfo, period);
288
328
  if (periodIndex === undefined) {
289
- log.warn("TracksStore: ".concat(bufferType, " not found for period"), period.start);
329
+ log.warn("TS: ".concat(bufferType, " not found for period"), period.start);
290
330
  return;
291
331
  }
292
332
  var periodObj = this._storedPeriodInfo[periodIndex];
293
333
  var choiceItem = periodObj[bufferType];
294
334
  if ((choiceItem === null || choiceItem === void 0 ? void 0 : choiceItem.dispatcher) === null) {
295
- log.warn("TracksStore: TrackDispatcher already removed for ".concat(bufferType, " ") +
335
+ log.warn("TS: TrackDispatcher already removed for ".concat(bufferType, " ") +
296
336
  "and Period ".concat(period.start));
297
337
  return;
298
338
  }
@@ -564,7 +604,7 @@ var TracksStore = /** @class */ (function (_super) {
564
604
  TracksStore.prototype.getChosenAudioTrack = function (periodObj) {
565
605
  return periodObj.audio.storedSettings === null ?
566
606
  null :
567
- toAudioTrack(periodObj.audio.storedSettings.adaptation);
607
+ periodObj.audio.storedSettings.adaptation.toAudioTrack(true);
568
608
  };
569
609
  /**
570
610
  * Returns an object describing the chosen text track for the given text
@@ -579,7 +619,7 @@ var TracksStore = /** @class */ (function (_super) {
579
619
  TracksStore.prototype.getChosenTextTrack = function (periodObj) {
580
620
  return periodObj.text.storedSettings === null ?
581
621
  null :
582
- toTextTrack(periodObj.text.storedSettings.adaptation);
622
+ periodObj.text.storedSettings.adaptation.toTextTrack();
583
623
  };
584
624
  /**
585
625
  * Returns an object describing the chosen video track for the given video
@@ -595,7 +635,7 @@ var TracksStore = /** @class */ (function (_super) {
595
635
  if (periodObj.video.storedSettings === null) {
596
636
  return null;
597
637
  }
598
- return toVideoTrack(periodObj.video.storedSettings.adaptation);
638
+ return periodObj.video.storedSettings.adaptation.toVideoTrack(true);
599
639
  };
600
640
  /**
601
641
  * Returns all available audio tracks for a given Period, as an array of
@@ -613,21 +653,9 @@ var TracksStore = /** @class */ (function (_super) {
613
653
  null;
614
654
  return periodObj.period.getSupportedAdaptations("audio")
615
655
  .map(function (adaptation) {
616
- var formatted = {
617
- language: takeFirstSet(adaptation.language, ""),
618
- normalized: takeFirstSet(adaptation.normalizedLanguage, ""),
619
- audioDescription: adaptation.isAudioDescription === true,
620
- id: adaptation.id,
621
- active: currentId === null ? false :
622
- currentId === adaptation.id,
623
- representations: adaptation.getPlayableRepresentations()
624
- .map(parseAudioRepresentation),
625
- label: adaptation.label,
626
- };
627
- if (adaptation.isDub === true) {
628
- formatted.dub = true;
629
- }
630
- return formatted;
656
+ var active = currentId === null ? false :
657
+ currentId === adaptation.id;
658
+ return objectAssign(adaptation.toAudioTrack(true), { active: active });
631
659
  });
632
660
  };
633
661
  /**
@@ -646,19 +674,9 @@ var TracksStore = /** @class */ (function (_super) {
646
674
  null;
647
675
  return periodObj.period.getSupportedAdaptations("text")
648
676
  .map(function (adaptation) {
649
- var formatted = {
650
- language: takeFirstSet(adaptation.language, ""),
651
- normalized: takeFirstSet(adaptation.normalizedLanguage, ""),
652
- closedCaption: adaptation.isClosedCaption === true,
653
- id: adaptation.id,
654
- active: currentId === null ? false :
655
- currentId === adaptation.id,
656
- label: adaptation.label,
657
- };
658
- if (adaptation.isForcedSubtitles !== undefined) {
659
- formatted.forced = adaptation.isForcedSubtitles;
660
- }
661
- return formatted;
677
+ var active = currentId === null ? false :
678
+ currentId === adaptation.id;
679
+ return objectAssign(adaptation.toTextTrack(), { active: active });
662
680
  });
663
681
  };
664
682
  /**
@@ -677,35 +695,21 @@ var TracksStore = /** @class */ (function (_super) {
677
695
  storedSettings.adaptation.id;
678
696
  return periodObj.period.getSupportedAdaptations("video")
679
697
  .map(function (adaptation) {
680
- var trickModeTracks = adaptation.trickModeTracks !== undefined ?
681
- adaptation.trickModeTracks.map(function (trickModeAdaptation) {
698
+ var active = currentId === null ? false :
699
+ currentId === adaptation.id;
700
+ var track = adaptation.toVideoTrack(true);
701
+ var trickModeTracks = track.trickModeTracks !== undefined ?
702
+ track.trickModeTracks.map(function (trickModeAdaptation) {
682
703
  var isActive = currentId === null ? false :
683
704
  currentId === trickModeAdaptation.id;
684
- var representations = trickModeAdaptation.getPlayableRepresentations()
685
- .map(parseVideoRepresentation);
686
- var trickMode = { id: trickModeAdaptation.id, representations: representations, isTrickModeTrack: true,
687
- active: isActive };
688
- if (trickModeAdaptation.isSignInterpreted === true) {
689
- trickMode.signInterpreted = true;
690
- }
691
- return trickMode;
705
+ return objectAssign(trickModeAdaptation, { active: isActive });
692
706
  }) :
693
- undefined;
694
- var formatted = {
695
- id: adaptation.id,
696
- active: currentId === null ? false :
697
- currentId === adaptation.id,
698
- representations: adaptation.getPlayableRepresentations()
699
- .map(parseVideoRepresentation),
700
- label: adaptation.label,
701
- };
702
- if (adaptation.isSignInterpreted === true) {
703
- formatted.signInterpreted = true;
704
- }
707
+ [];
708
+ var availableTrack = objectAssign(track, { active: active });
705
709
  if (trickModeTracks !== undefined) {
706
- formatted.trickModeTracks = trickModeTracks;
710
+ availableTrack.trickModeTracks = trickModeTracks;
707
711
  }
708
- return formatted;
712
+ return availableTrack;
709
713
  });
710
714
  };
711
715
  TracksStore.prototype.getLockedAudioRepresentations = function (periodObj) {
@@ -888,15 +892,6 @@ function getPeriodItem(periods, periodId) {
888
892
  }
889
893
  }
890
894
  }
891
- /**
892
- * Parse video Representation into a IVideoRepresentation.
893
- * @param {Object} representation
894
- * @returns {Object}
895
- */
896
- function parseVideoRepresentation(_a) {
897
- var id = _a.id, bitrate = _a.bitrate, frameRate = _a.frameRate, width = _a.width, height = _a.height, codec = _a.codec, hdrInfo = _a.hdrInfo;
898
- return { id: id, bitrate: bitrate, frameRate: frameRate, width: width, height: height, codec: codec, hdrInfo: hdrInfo };
899
- }
900
895
  /**
901
896
  * A `ITMPeriodObject` should only be removed once all References linked to it
902
897
  * do not exist anymore, to keep the possibility of making track choices.
@@ -910,15 +905,6 @@ function isPeriodItemRemovable(periodObj) {
910
905
  ((_b = periodObj.audio) === null || _b === void 0 ? void 0 : _b.dispatcher) === null &&
911
906
  ((_c = periodObj.video) === null || _c === void 0 ? void 0 : _c.dispatcher) === null;
912
907
  }
913
- /**
914
- * Parse audio Representation into a ITMAudioRepresentation.
915
- * @param {Object} representation
916
- * @returns {Object}
917
- */
918
- function parseAudioRepresentation(_a) {
919
- var id = _a.id, bitrate = _a.bitrate, codec = _a.codec;
920
- return { id: id, bitrate: bitrate, codec: codec };
921
- }
922
908
  function getRightVideoTrack(adaptation, isTrickModeEnabled) {
923
909
  var _a;
924
910
  if (isTrickModeEnabled &&
@@ -982,77 +968,6 @@ function generatePeriodInfo(period, inManifest, isTrickModeTrackEnabled, default
982
968
  text: { storedSettings: textSettings,
983
969
  dispatcher: null } };
984
970
  }
985
- /**
986
- * Format Adaptation structure into the format awaited by the API.
987
- * @param {Object} a
988
- * @returns {Object}
989
- */
990
- function toTextTrack(a) {
991
- var _a, _b;
992
- var formatted = {
993
- language: (_a = a.language) !== null && _a !== void 0 ? _a : "",
994
- normalized: (_b = a.normalizedLanguage) !== null && _b !== void 0 ? _b : "",
995
- closedCaption: a.isClosedCaption === true,
996
- id: a.id,
997
- label: a.label,
998
- };
999
- if (a.isForcedSubtitles !== undefined) {
1000
- formatted.forced = a.isForcedSubtitles;
1001
- }
1002
- return formatted;
1003
- }
1004
- /**
1005
- * Format Adaptation structure into the format awaited by the API.
1006
- * @param {Object} a
1007
- * @returns {Object}
1008
- */
1009
- function toVideoTrack(a) {
1010
- var trickModeTracks = a.trickModeTracks !== undefined ?
1011
- a.trickModeTracks.map(function (trickModeAdaptation) {
1012
- var representations = trickModeAdaptation.getPlayableRepresentations()
1013
- .map(parseVideoRepresentation);
1014
- var trickMode = { id: trickModeAdaptation.id, representations: representations, isTrickModeTrack: true };
1015
- if (trickModeAdaptation.isSignInterpreted === true) {
1016
- trickMode.signInterpreted = true;
1017
- }
1018
- return trickMode;
1019
- }) :
1020
- undefined;
1021
- var videoTrack = {
1022
- id: a.id,
1023
- representations: a.getPlayableRepresentations().map(parseVideoRepresentation),
1024
- label: a.label,
1025
- };
1026
- if (a.isSignInterpreted === true) {
1027
- videoTrack.signInterpreted = true;
1028
- }
1029
- if (a.isTrickModeTrack === true) {
1030
- videoTrack.isTrickModeTrack = true;
1031
- }
1032
- if (trickModeTracks !== undefined) {
1033
- videoTrack.trickModeTracks = trickModeTracks;
1034
- }
1035
- return videoTrack;
1036
- }
1037
- /**
1038
- * Convert an audio Adaptation into an audio track.
1039
- * @param {object|null} adaptation - Audio adaptation
1040
- * @returns {object|null} - corresponding audio track object.
1041
- */
1042
- function toAudioTrack(adaptation) {
1043
- var audioTrack = {
1044
- language: takeFirstSet(adaptation.language, ""),
1045
- normalized: takeFirstSet(adaptation.normalizedLanguage, ""),
1046
- audioDescription: adaptation.isAudioDescription === true,
1047
- id: adaptation.id,
1048
- representations: adaptation.representations.map(parseAudioRepresentation),
1049
- label: adaptation.label,
1050
- };
1051
- if (adaptation.isDub === true) {
1052
- audioTrack.dub = true;
1053
- }
1054
- return audioTrack;
1055
- }
1056
971
  function toExposedPeriod(p) {
1057
972
  return { start: p.start, end: p.end, id: p.id };
1058
973
  }
@@ -30,6 +30,16 @@ import { IPlaybackObservation, IReadOnlyPlaybackObserver } from "./playback_obse
30
30
  * remove all listeners this function has registered.
31
31
  */
32
32
  export declare function emitSeekEvents(mediaElement: HTMLMediaElement | null, playbackObserver: IReadOnlyPlaybackObserver<IPlaybackObservation>, onSeeking: () => void, onSeeked: () => void, cancelSignal: CancellationSignal): void;
33
+ /**
34
+ * @param {HTMLMediaElement} mediaElement
35
+ * @param {function} onPlay - Callback called when a play operation has started
36
+ * on `mediaElement`.
37
+ * @param {function} onPause - Callback called when a pause operation has
38
+ * started on `mediaElement`.
39
+ * @param {Object} cancelSignal - When triggered, stop calling callbacks and
40
+ * remove all listeners this function has registered.
41
+ */
42
+ export declare function emitPlayPauseEvents(mediaElement: HTMLMediaElement | null, onPlay: () => void, onPause: () => void, cancelSignal: CancellationSignal): void;
33
43
  /** Player state dictionnary. */
34
44
  export declare const enum PLAYER_STATES {
35
45
  STOPPED = "STOPPED",
@@ -49,6 +49,26 @@ export function emitSeekEvents(mediaElement, playbackObserver, onSeeking, onSeek
49
49
  }
50
50
  }, { includeLastObservation: true, clearSignal: cancelSignal });
51
51
  }
52
+ /**
53
+ * @param {HTMLMediaElement} mediaElement
54
+ * @param {function} onPlay - Callback called when a play operation has started
55
+ * on `mediaElement`.
56
+ * @param {function} onPause - Callback called when a pause operation has
57
+ * started on `mediaElement`.
58
+ * @param {Object} cancelSignal - When triggered, stop calling callbacks and
59
+ * remove all listeners this function has registered.
60
+ */
61
+ export function emitPlayPauseEvents(mediaElement, onPlay, onPause, cancelSignal) {
62
+ if (cancelSignal.isCancelled() || mediaElement === null) {
63
+ return;
64
+ }
65
+ mediaElement.addEventListener("play", onPlay);
66
+ mediaElement.addEventListener("pause", onPause);
67
+ cancelSignal.register(function () {
68
+ mediaElement.removeEventListener("play", onPlay);
69
+ mediaElement.removeEventListener("pause", onPause);
70
+ });
71
+ }
52
72
  export function constructPlayerStateReference(initializer, mediaElement, playbackObserver, cancelSignal) {
53
73
  var playerStateRef = createSharedReference("LOADING" /* PLAYER_STATES.LOADING */, cancelSignal);
54
74
  initializer.addEventListener("loaded", function () {
@@ -133,7 +133,13 @@ export default function SessionEventsListener(session, keySystemOptions, keySyst
133
133
  log.info("DRM: No license given, skipping session.update");
134
134
  }
135
135
  else {
136
- return updateSessionWithMessage(session, licenseObject);
136
+ try {
137
+ return updateSessionWithMessage(session, licenseObject);
138
+ }
139
+ catch (err) {
140
+ manualCanceller.cancel();
141
+ callbacks.onError(err);
142
+ }
137
143
  }
138
144
  })
139
145
  .catch(function (err) {
@@ -49,6 +49,7 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
49
49
  if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
50
50
  }
51
51
  };
52
+ import log from "../../../log";
52
53
  /**
53
54
  * Close sessions from the loadedSessionsStore to allow at maximum `limit`
54
55
  * stored MediaKeySessions in it.
@@ -67,6 +68,7 @@ export default function cleanOldLoadedSessions(loadedSessionsStore, limit) {
67
68
  if (limit < 0 || limit >= loadedSessionsStore.getLength()) {
68
69
  return [2 /*return*/];
69
70
  }
71
+ log.info("DRM: LSS cache limit exceeded", limit, loadedSessionsStore.getLength());
70
72
  proms = [];
71
73
  entries = loadedSessionsStore.getAll().slice();
72
74
  toDelete = entries.length - limit;
@@ -92,6 +92,7 @@ var LoadedSessionsStore = /** @class */ (function () {
92
92
  LoadedSessionsStore.prototype.createSession = function (initData, sessionType) {
93
93
  var _this = this;
94
94
  var keySessionRecord = new KeySessionRecord(initData);
95
+ log.debug("DRM-LSS: calling `createSession`", sessionType);
95
96
  var mediaKeySession = this._mediaKeys.createSession(sessionType);
96
97
  var entry = { mediaKeySession: mediaKeySession, sessionType: sessionType, keySessionRecord: keySessionRecord, isGeneratingRequest: false,
97
98
  isLoadingPersistentSession: false,
@@ -99,6 +100,7 @@ var LoadedSessionsStore = /** @class */ (function () {
99
100
  if (!isNullOrUndefined(mediaKeySession.closed)) {
100
101
  mediaKeySession.closed
101
102
  .then(function () {
103
+ log.info("DRM-LSS: session was closed, removing it.", mediaKeySession.sessionId);
102
104
  var index = _this.getIndex(keySessionRecord);
103
105
  if (index >= 0 &&
104
106
  _this._storage[index].mediaKeySession === mediaKeySession) {
@@ -110,8 +112,8 @@ var LoadedSessionsStore = /** @class */ (function () {
110
112
  log.warn("DRM-LSS: MediaKeySession.closed rejected: ".concat(e));
111
113
  });
112
114
  }
113
- log.debug("DRM-LSS: Add MediaKeySession", entry.sessionType);
114
115
  this._storage.push(__assign({}, entry));
116
+ log.debug("DRM-LSS: MediaKeySession added", entry.sessionType, this._storage.length);
115
117
  return entry;
116
118
  };
117
119
  /**
@@ -132,6 +134,7 @@ var LoadedSessionsStore = /** @class */ (function () {
132
134
  if (stored.keySessionRecord.isCompatibleWith(initializationData)) {
133
135
  this._storage.splice(i, 1);
134
136
  this._storage.push(stored);
137
+ log.debug("DRM-LSS: Reusing session:", stored.mediaKeySession.sessionId, stored.sessionType);
135
138
  return __assign({}, stored);
136
139
  }
137
140
  }
@@ -365,6 +368,7 @@ var LoadedSessionsStore = /** @class */ (function () {
365
368
  for (var i = this._storage.length - 1; i >= 0; i--) {
366
369
  var stored = this._storage[i];
367
370
  if (stored.mediaKeySession === mediaKeySession) {
371
+ log.debug("DRM-LSS: Removing session without closing it", mediaKeySession.sessionId);
368
372
  this._storage.splice(i, 1);
369
373
  return true;
370
374
  }
@@ -73,7 +73,7 @@ var DirectFileContentInitializer = /** @class */ (function (_super) {
73
73
  * Class trying to avoid various stalling situations, emitting "stalled"
74
74
  * events when it cannot, as well as "unstalled" events when it get out of one.
75
75
  */
76
- var rebufferingController = new RebufferingController(playbackObserver, null, speed);
76
+ var rebufferingController = new RebufferingController(playbackObserver, null, null, speed);
77
77
  rebufferingController.addEventListener("stalled", function (evt) {
78
78
  return _this.trigger("stalled", evt);
79
79
  });