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
@@ -84,9 +84,15 @@ export default function RepresentationStream(_a, callbacks, parentCancelSignal)
84
84
  /** Saved initialization segment state for this representation. */
85
85
  var initSegmentState = {
86
86
  segment: representation.index.getInitSegment(),
87
- segmentData: null,
87
+ uniqueId: null,
88
88
  isLoaded: false,
89
89
  };
90
+ globalCanceller.signal.register(function () {
91
+ // Free initialization segment if one has been declared
92
+ if (initSegmentState.uniqueId !== null) {
93
+ segmentBuffer.freeInitSegment(initSegmentState.uniqueId);
94
+ }
95
+ });
90
96
  /** Emit the last scheduled downloading queue for segments. */
91
97
  var lastSegmentQueue = createSharedReference({
92
98
  initSegment: null,
@@ -95,7 +101,6 @@ export default function RepresentationStream(_a, callbacks, parentCancelSignal)
95
101
  /** If `true`, the current Representation has a linked initialization segment. */
96
102
  var hasInitSegment = initSegmentState.segment !== null;
97
103
  if (!hasInitSegment) {
98
- initSegmentState.segmentData = null;
99
104
  initSegmentState.isLoaded = true;
100
105
  }
101
106
  /**
@@ -303,16 +308,20 @@ export default function RepresentationStream(_a, callbacks, parentCancelSignal)
303
308
  evt.segmentList !== undefined) {
304
309
  representation.index.initialize(evt.segmentList);
305
310
  }
306
- initSegmentState.segmentData = evt.initializationData;
307
311
  initSegmentState.isLoaded = true;
308
- pushInitSegment({ playbackObserver: playbackObserver, content: content, segment: evt.segment,
309
- segmentData: evt.initializationData, segmentBuffer: segmentBuffer }, globalCanceller.signal)
310
- .then(function (result) {
311
- if (result !== null) {
312
- callbacks.addedSegment(result);
313
- }
314
- })
315
- .catch(onFatalBufferError);
312
+ if (evt.initializationData !== null) {
313
+ var initSegmentUniqueId = representation.uniqueId;
314
+ initSegmentState.uniqueId = initSegmentUniqueId;
315
+ segmentBuffer.declareInitSegment(initSegmentUniqueId, evt.initializationData);
316
+ pushInitSegment({ playbackObserver: playbackObserver, content: content, initSegmentUniqueId: initSegmentUniqueId, segment: evt.segment,
317
+ segmentData: evt.initializationData, segmentBuffer: segmentBuffer }, globalCanceller.signal)
318
+ .then(function (result) {
319
+ if (result !== null) {
320
+ callbacks.addedSegment(result);
321
+ }
322
+ })
323
+ .catch(onFatalBufferError);
324
+ }
316
325
  // Sometimes the segment list is only known once the initialization segment
317
326
  // is parsed. Thus we immediately re-check if there's new segments to load.
318
327
  checkStatus();
@@ -335,8 +344,8 @@ export default function RepresentationStream(_a, callbacks, parentCancelSignal)
335
344
  return; // previous callback has stopped everything by side-effect
336
345
  }
337
346
  }
338
- var initSegmentData = initSegmentState.segmentData;
339
- pushMediaSegment({ playbackObserver: playbackObserver, content: content, initSegmentData: initSegmentData, parsedSegment: evt,
347
+ var initSegmentUniqueId = initSegmentState.uniqueId;
348
+ pushMediaSegment({ playbackObserver: playbackObserver, content: content, initSegmentUniqueId: initSegmentUniqueId, parsedSegment: evt,
340
349
  segment: evt.segment, segmentBuffer: segmentBuffer }, globalCanceller.signal)
341
350
  .then(function (result) {
342
351
  if (result !== null) {
@@ -15,7 +15,7 @@
15
15
  */
16
16
  import { CancellationSignal } from "../../../../utils/task_canceller";
17
17
  import { IReadOnlyPlaybackObserver } from "../../../api";
18
- import { IPushChunkInfos, SegmentBuffer } from "../../../segment_buffers";
18
+ import { IInsertedChunkInfos, IPushChunkInfos, SegmentBuffer } from "../../../segment_buffers";
19
19
  import { IRepresentationStreamPlaybackObservation } from "../types";
20
20
  /**
21
21
  * Append a segment to the given segmentBuffer.
@@ -27,4 +27,6 @@ import { IRepresentationStreamPlaybackObservation } from "../types";
27
27
  * @param {Object} cancellationSignal
28
28
  * @returns {Promise}
29
29
  */
30
- export default function appendSegmentToBuffer<T>(playbackObserver: IReadOnlyPlaybackObserver<IRepresentationStreamPlaybackObservation>, segmentBuffer: SegmentBuffer, dataInfos: IPushChunkInfos<T>, cancellationSignal: CancellationSignal): Promise<void>;
30
+ export default function appendSegmentToBuffer<T>(playbackObserver: IReadOnlyPlaybackObserver<IRepresentationStreamPlaybackObservation>, segmentBuffer: SegmentBuffer, dataInfos: IPushChunkInfos<T> & {
31
+ inventoryInfos: IInsertedChunkInfos;
32
+ }, cancellationSignal: CancellationSignal): Promise<void>;
@@ -87,7 +87,7 @@ export default function appendSegmentToBuffer(playbackObserver, segmentBuffer, d
87
87
  reason = appendError_1 instanceof Error ?
88
88
  appendError_1.toString() :
89
89
  "An unknown error happened when pushing content";
90
- throw new MediaError("BUFFER_APPEND_ERROR", reason);
90
+ throw new MediaError("BUFFER_APPEND_ERROR", reason, { adaptation: dataInfos.inventoryInfos.adaptation });
91
91
  }
92
92
  position = playbackObserver.getReference().getValue().position;
93
93
  currentPos = (_a = position.pending) !== null && _a !== void 0 ? _a : position.last;
@@ -105,7 +105,7 @@ export default function appendSegmentToBuffer(playbackObserver, segmentBuffer, d
105
105
  err2_1 = _b.sent();
106
106
  reason = err2_1 instanceof Error ? err2_1.toString() :
107
107
  "Could not clean the buffer";
108
- throw new MediaError("BUFFER_FULL_ERROR", reason);
108
+ throw new MediaError("BUFFER_FULL_ERROR", reason, { adaptation: dataInfos.inventoryInfos.adaptation });
109
109
  case 7: return [3 /*break*/, 8];
110
110
  case 8: return [2 /*return*/];
111
111
  }
@@ -24,7 +24,7 @@ import { IRepresentationStreamPlaybackObservation, IStreamEventAddedSegmentPaylo
24
24
  * @param {Object} cancelSignal
25
25
  * @returns {Promise}
26
26
  */
27
- export default function pushInitSegment<T>({ playbackObserver, content, segment, segmentData, segmentBuffer, }: {
27
+ export default function pushInitSegment<T>({ playbackObserver, content, initSegmentUniqueId, segment, segmentData, segmentBuffer, }: {
28
28
  playbackObserver: IReadOnlyPlaybackObserver<IRepresentationStreamPlaybackObservation>;
29
29
  content: {
30
30
  adaptation: Adaptation;
@@ -32,7 +32,8 @@ export default function pushInitSegment<T>({ playbackObserver, content, segment,
32
32
  period: Period;
33
33
  representation: Representation;
34
34
  };
35
- segmentData: T | null;
35
+ initSegmentUniqueId: string;
36
+ segmentData: T;
36
37
  segment: ISegment;
37
38
  segmentBuffer: SegmentBuffer;
38
39
  }, cancelSignal: CancellationSignal): Promise<IStreamEventAddedSegmentPayload<T> | null>;
@@ -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 objectAssign from "../../../../utils/object_assign";
52
53
  import appendSegmentToBuffer from "./append_segment_to_buffer";
53
54
  /**
54
55
  * Push the initialization segment to the SegmentBuffer.
@@ -57,24 +58,23 @@ import appendSegmentToBuffer from "./append_segment_to_buffer";
57
58
  * @returns {Promise}
58
59
  */
59
60
  export default function pushInitSegment(_a, cancelSignal) {
60
- var playbackObserver = _a.playbackObserver, content = _a.content, segment = _a.segment, segmentData = _a.segmentData, segmentBuffer = _a.segmentBuffer;
61
+ var playbackObserver = _a.playbackObserver, content = _a.content, initSegmentUniqueId = _a.initSegmentUniqueId, segment = _a.segment, segmentData = _a.segmentData, segmentBuffer = _a.segmentBuffer;
61
62
  return __awaiter(this, void 0, void 0, function () {
62
- var codec, data, buffered;
63
+ var codec, data, inventoryInfos, buffered;
63
64
  return __generator(this, function (_b) {
64
65
  switch (_b.label) {
65
66
  case 0:
66
- if (segmentData === null) {
67
- return [2 /*return*/, null];
68
- }
69
67
  if (cancelSignal.cancellationError !== null) {
70
68
  throw cancelSignal.cancellationError;
71
69
  }
72
70
  codec = content.representation.getMimeTypeString();
73
- data = { initSegment: segmentData,
74
- chunk: null,
71
+ data = { initSegmentUniqueId: initSegmentUniqueId, chunk: null,
75
72
  timestampOffset: 0,
76
73
  appendWindow: [undefined, undefined], codec: codec };
77
- return [4 /*yield*/, appendSegmentToBuffer(playbackObserver, segmentBuffer, { data: data, inventoryInfos: null }, cancelSignal)];
74
+ inventoryInfos = objectAssign({ segment: segment, chunkSize: undefined,
75
+ start: 0,
76
+ end: 0 }, content);
77
+ return [4 /*yield*/, appendSegmentToBuffer(playbackObserver, segmentBuffer, { data: data, inventoryInfos: inventoryInfos }, cancelSignal)];
78
78
  case 1:
79
79
  _b.sent();
80
80
  buffered = segmentBuffer.getBufferedRanges();
@@ -25,7 +25,7 @@ import { IRepresentationStreamPlaybackObservation, IStreamEventAddedSegmentPaylo
25
25
  * @param {Object} cancelSignal
26
26
  * @returns {Promise}
27
27
  */
28
- export default function pushMediaSegment<T>({ playbackObserver, content, initSegmentData, parsedSegment, segment, segmentBuffer }: {
28
+ export default function pushMediaSegment<T>({ playbackObserver, content, initSegmentUniqueId, parsedSegment, segment, segmentBuffer }: {
29
29
  playbackObserver: IReadOnlyPlaybackObserver<IRepresentationStreamPlaybackObservation>;
30
30
  content: {
31
31
  adaptation: Adaptation;
@@ -33,7 +33,7 @@ export default function pushMediaSegment<T>({ playbackObserver, content, initSeg
33
33
  period: Period;
34
34
  representation: Representation;
35
35
  };
36
- initSegmentData: T | null;
36
+ initSegmentUniqueId: string | null;
37
37
  parsedSegment: ISegmentParserParsedMediaChunk<T>;
38
38
  segment: ISegment;
39
39
  segmentBuffer: SegmentBuffer;
@@ -60,7 +60,7 @@ import appendSegmentToBuffer from "./append_segment_to_buffer";
60
60
  */
61
61
  export default function pushMediaSegment(_a, cancelSignal) {
62
62
  var _b, _c;
63
- var playbackObserver = _a.playbackObserver, content = _a.content, initSegmentData = _a.initSegmentData, parsedSegment = _a.parsedSegment, segment = _a.segment, segmentBuffer = _a.segmentBuffer;
63
+ var playbackObserver = _a.playbackObserver, content = _a.content, initSegmentUniqueId = _a.initSegmentUniqueId, parsedSegment = _a.parsedSegment, segment = _a.segment, segmentBuffer = _a.segmentBuffer;
64
64
  return __awaiter(this, void 0, void 0, function () {
65
65
  var chunkData, chunkInfos, chunkOffset, chunkSize, appendWindow, codec, APPEND_WINDOW_SECURITIES, safeAppendWindow, data, estimatedStart, estimatedDuration, estimatedEnd, inventoryInfos, buffered;
66
66
  return __generator(this, function (_d) {
@@ -83,8 +83,7 @@ export default function pushMediaSegment(_a, cancelSignal) {
83
83
  appendWindow[1] + APPEND_WINDOW_SECURITIES.END :
84
84
  undefined,
85
85
  ];
86
- data = { initSegment: initSegmentData,
87
- chunk: chunkData,
86
+ data = { initSegmentUniqueId: initSegmentUniqueId, chunk: chunkData,
88
87
  timestampOffset: chunkOffset,
89
88
  appendWindow: safeAppendWindow, codec: codec };
90
89
  estimatedStart = (_b = chunkInfos === null || chunkInfos === void 0 ? void 0 : chunkInfos.time) !== null && _b !== void 0 ? _b : segment.time;
@@ -334,6 +334,31 @@ declare const DEFAULT_CONFIG: {
334
334
  * @type {Number}
335
335
  */
336
336
  SAMPLING_INTERVAL_NO_MEDIASOURCE: number;
337
+ /**
338
+ * Amount of buffer to have ahead of the current position before we may
339
+ * consider buffer-based adaptive estimates, in seconds.
340
+ *
341
+ * For example setting it to `10` means that we need to have ten seconds of
342
+ * buffer ahead of the current position before relying on buffer-based
343
+ * adaptive estimates.
344
+ *
345
+ * To avoid getting in-and-out of the buffer-based logic all the time, it
346
+ * should be set higher than `ABR_EXIT_BUFFER_BASED_ALGO`.
347
+ */
348
+ ABR_ENTER_BUFFER_BASED_ALGO: number;
349
+ /**
350
+ * Below this amount of buffer ahead of the current position, in seconds, we
351
+ * will stop using buffer-based estimate in our adaptive logic to select a
352
+ * quality.
353
+ *
354
+ * For example setting it to `5` means that if we have less than 5 seconds of
355
+ * buffer ahead of the current position, we should stop relying on
356
+ * buffer-based estimates to choose a quality.
357
+ *
358
+ * To avoid getting in-and-out of the buffer-based logic all the time, it
359
+ * should be set lower than `ABR_ENTER_BUFFER_BASED_ALGO`.
360
+ */
361
+ ABR_EXIT_BUFFER_BASED_ALGO: number;
337
362
  /**
338
363
  * Minimum number of bytes sampled before we trust the estimate.
339
364
  * If we have not sampled much data, our estimate may not be accurate
@@ -340,6 +340,31 @@ var DEFAULT_CONFIG = {
340
340
  * @type {Number}
341
341
  */
342
342
  SAMPLING_INTERVAL_NO_MEDIASOURCE: 500,
343
+ /**
344
+ * Amount of buffer to have ahead of the current position before we may
345
+ * consider buffer-based adaptive estimates, in seconds.
346
+ *
347
+ * For example setting it to `10` means that we need to have ten seconds of
348
+ * buffer ahead of the current position before relying on buffer-based
349
+ * adaptive estimates.
350
+ *
351
+ * To avoid getting in-and-out of the buffer-based logic all the time, it
352
+ * should be set higher than `ABR_EXIT_BUFFER_BASED_ALGO`.
353
+ */
354
+ ABR_ENTER_BUFFER_BASED_ALGO: 10,
355
+ /**
356
+ * Below this amount of buffer ahead of the current position, in seconds, we
357
+ * will stop using buffer-based estimate in our adaptive logic to select a
358
+ * quality.
359
+ *
360
+ * For example setting it to `5` means that if we have less than 5 seconds of
361
+ * buffer ahead of the current position, we should stop relying on
362
+ * buffer-based estimates to choose a quality.
363
+ *
364
+ * To avoid getting in-and-out of the buffer-based logic all the time, it
365
+ * should be set lower than `ABR_ENTER_BUFFER_BASED_ALGO`.
366
+ */
367
+ ABR_EXIT_BUFFER_BASED_ALGO: 5,
343
368
  /**
344
369
  * Minimum number of bytes sampled before we trust the estimate.
345
370
  * If we have not sampled much data, our estimate may not be accurate
@@ -375,8 +400,8 @@ var DEFAULT_CONFIG = {
375
400
  * @type {Object}
376
401
  */
377
402
  ABR_REGULAR_FACTOR: {
378
- DEFAULT: 0.8,
379
- LOW_LATENCY: 0.8,
403
+ DEFAULT: 0.72,
404
+ LOW_LATENCY: 0.72,
380
405
  },
381
406
  /**
382
407
  * If a media buffer has less than ABR_STARVATION_GAP in seconds ahead of the
@@ -19,8 +19,8 @@ import EncryptedMediaError from "./encrypted_media_error";
19
19
  import { ErrorCodes, ErrorTypes, IErrorCode, IErrorType, NetworkErrorTypes } from "./error_codes";
20
20
  import formatError from "./format_error";
21
21
  import isKnownError from "./is_known_error";
22
- import MediaError from "./media_error";
22
+ import MediaError, { IMediaErrorTrackContext } from "./media_error";
23
23
  import NetworkError from "./network_error";
24
24
  import OtherError from "./other_error";
25
25
  import RequestError from "./request_error";
26
- export { AssertionError, CustomLoaderError, EncryptedMediaError, ErrorCodes, ErrorTypes, IErrorCode, IErrorType, formatError, MediaError as MediaError, NetworkError, OtherError, RequestError, NetworkErrorTypes, isKnownError, };
26
+ export { AssertionError, CustomLoaderError, EncryptedMediaError, ErrorCodes, ErrorTypes, IErrorCode, IErrorType, IMediaErrorTrackContext, formatError, MediaError as MediaError, NetworkError, OtherError, RequestError, NetworkErrorTypes, isKnownError, };
@@ -13,7 +13,23 @@
13
13
  * See the License for the specific language governing permissions and
14
14
  * limitations under the License.
15
15
  */
16
+ import { Adaptation } from "../manifest";
17
+ import { IAudioTrack, ITextTrack, IVideoTrack } from "../public_types";
16
18
  import { IMediaErrorCode } from "./error_codes";
19
+ interface IAudioTrackMediaErrorContext {
20
+ type: "audio";
21
+ track: IAudioTrack;
22
+ }
23
+ interface IVideoTrackMediaErrorContext {
24
+ type: "video";
25
+ track: IVideoTrack;
26
+ }
27
+ interface ITextTrackMediaErrorContext {
28
+ type: "text";
29
+ track: ITextTrack;
30
+ }
31
+ export type IMediaErrorTrackContext = IAudioTrackMediaErrorContext | IVideoTrackMediaErrorContext | ITextTrackMediaErrorContext;
32
+ type ICodeWithAdaptationType = "BUFFER_APPEND_ERROR" | "BUFFER_FULL_ERROR" | "NO_PLAYABLE_REPRESENTATION" | "MANIFEST_INCOMPATIBLE_CODECS_ERROR";
17
33
  /**
18
34
  * Error linked to the media Playback.
19
35
  *
@@ -25,10 +41,16 @@ export default class MediaError extends Error {
25
41
  readonly type: "MEDIA_ERROR";
26
42
  readonly message: string;
27
43
  readonly code: IMediaErrorCode;
44
+ readonly trackInfo: IMediaErrorTrackContext | undefined;
28
45
  fatal: boolean;
29
46
  /**
30
47
  * @param {string} code
31
48
  * @param {string} reason
49
+ * @param {Object|undefined} [context]
32
50
  */
33
- constructor(code: IMediaErrorCode, reason: string);
51
+ constructor(code: ICodeWithAdaptationType, reason: string, context: {
52
+ adaptation: Adaptation | undefined;
53
+ });
54
+ constructor(code: Exclude<IMediaErrorCode, ICodeWithAdaptationType>, reason: string);
34
55
  }
56
+ export {};
@@ -38,11 +38,7 @@ import errorMessage from "./error_message";
38
38
  */
39
39
  var MediaError = /** @class */ (function (_super) {
40
40
  __extends(MediaError, _super);
41
- /**
42
- * @param {string} code
43
- * @param {string} reason
44
- */
45
- function MediaError(code, reason) {
41
+ function MediaError(code, reason, context) {
46
42
  var _this = _super.call(this) || this;
47
43
  // @see https://stackoverflow.com/questions/41102060/typescript-extending-error-class
48
44
  Object.setPrototypeOf(_this, MediaError.prototype);
@@ -51,6 +47,23 @@ var MediaError = /** @class */ (function (_super) {
51
47
  _this.code = code;
52
48
  _this.message = errorMessage(_this.name, _this.code, reason);
53
49
  _this.fatal = false;
50
+ var adaptation = context === null || context === void 0 ? void 0 : context.adaptation;
51
+ if (adaptation !== undefined) {
52
+ switch (adaptation.type) {
53
+ case "audio":
54
+ _this.trackInfo = { type: "audio",
55
+ track: adaptation.toAudioTrack(false) };
56
+ break;
57
+ case "video":
58
+ _this.trackInfo = { type: "video",
59
+ track: adaptation.toVideoTrack(false) };
60
+ break;
61
+ case "text":
62
+ _this.trackInfo = { type: "text",
63
+ track: adaptation.toTextTrack() };
64
+ break;
65
+ }
66
+ }
54
67
  return _this;
55
68
  }
56
69
  return MediaError;
@@ -23,4 +23,4 @@ import { CancellationSignal } from "../../../utils/task_canceller";
23
23
  * @param {Object} cancelSignal
24
24
  * @returns {Promise}
25
25
  */
26
- export default function loadAndPushSegment(segmentInfo: ISegmentLoaderContent, segmentBuffer: AudioVideoSegmentBuffer, segmentFetcher: ISegmentFetcher<ArrayBuffer | Uint8Array>, cancelSignal: CancellationSignal): Promise<unknown>;
26
+ export default function loadAndPushSegment(segmentInfo: ISegmentLoaderContent, segmentBuffer: AudioVideoSegmentBuffer, segmentFetcher: ISegmentFetcher<ArrayBuffer | Uint8Array>, initSegmentUniqueId: string | null, cancelSignal: CancellationSignal): Promise<unknown>;
@@ -21,29 +21,30 @@ import log from "../../../log";
21
21
  * @param {Object} cancelSignal
22
22
  * @returns {Promise}
23
23
  */
24
- export default function loadAndPushSegment(segmentInfo, segmentBuffer, segmentFetcher, cancelSignal) {
24
+ export default function loadAndPushSegment(segmentInfo, segmentBuffer, segmentFetcher, initSegmentUniqueId, cancelSignal) {
25
25
  var pushOperations = [];
26
26
  return segmentFetcher(segmentInfo, {
27
27
  onChunk: function (parseChunk) {
28
28
  var parsed = parseChunk(undefined);
29
- var isIsInitSegment;
29
+ var isInitSegment;
30
30
  var data;
31
31
  var timestampOffset;
32
32
  var codec = segmentInfo.representation.getMimeTypeString();
33
33
  if (parsed.segmentType === "init") {
34
- isIsInitSegment = true;
34
+ isInitSegment = true;
35
35
  data = parsed.initializationData;
36
36
  timestampOffset = 0;
37
+ if (initSegmentUniqueId !== null) {
38
+ segmentBuffer.declareInitSegment(initSegmentUniqueId, data);
39
+ }
37
40
  }
38
41
  else {
39
- isIsInitSegment = false;
42
+ isInitSegment = false;
40
43
  data = parsed.chunkData;
41
44
  timestampOffset = parsed.chunkOffset;
42
45
  }
43
46
  var pushOperation = segmentBuffer.pushChunk({
44
- data: { initSegment: isIsInitSegment ? data :
45
- null,
46
- chunk: isIsInitSegment ? null :
47
+ data: { initSegmentUniqueId: initSegmentUniqueId, chunk: isInitSegment ? null :
47
48
  data,
48
49
  appendWindow: [segmentInfo.period.start, segmentInfo.period.end], timestampOffset: timestampOffset, codec: codec },
49
50
  inventoryInfos: null,
@@ -161,34 +161,42 @@ var VideoThumbnailLoader = /** @class */ (function () {
161
161
  }
162
162
  var lastRepInfo;
163
163
  if (this._lastRepresentationInfo === null) {
164
- var cleaner_1 = new TaskCanceller();
164
+ var lastRepInfoCleaner_1 = new TaskCanceller();
165
165
  var segmentFetcher = createSegmentFetcher("video", loader.video, null,
166
166
  // We don't care about the SegmentFetcher's lifecycle events
167
167
  {}, { baseDelay: 0,
168
168
  maxDelay: 0,
169
169
  maxRetry: 0,
170
170
  requestTimeout: config.getCurrent().DEFAULT_REQUEST_TIMEOUT });
171
- var segmentBufferProm = prepareSourceBuffer(this._videoElement, content.representation.getMimeTypeString(), cleaner_1.signal).then(function (segmentBuffer) { return __awaiter(_this, void 0, void 0, function () {
172
- var initSegment, segmentInfo;
171
+ var initSegment_1 = content.representation.index.getInitSegment();
172
+ var initSegmentUniqueId_1 = initSegment_1 !== null ?
173
+ content.representation.uniqueId :
174
+ null;
175
+ var segmentBufferProm = prepareSourceBuffer(this._videoElement, content.representation.getMimeTypeString(), lastRepInfoCleaner_1.signal).then(function (segmentBuffer) { return __awaiter(_this, void 0, void 0, function () {
176
+ var segmentInfo;
173
177
  return __generator(this, function (_a) {
174
178
  switch (_a.label) {
175
179
  case 0:
176
- initSegment = content.representation.index.getInitSegment();
177
- if (initSegment === null) {
180
+ if (initSegment_1 === null || initSegmentUniqueId_1 === null) {
181
+ lastRepInfo.initSegmentUniqueId = null;
178
182
  return [2 /*return*/, segmentBuffer];
179
183
  }
180
- segmentInfo = objectAssign({ segment: initSegment }, content);
181
- return [4 /*yield*/, loadAndPushSegment(segmentInfo, segmentBuffer, lastRepInfo.segmentFetcher, cleaner_1.signal)];
184
+ segmentInfo = objectAssign({ segment: initSegment_1 }, content);
185
+ return [4 /*yield*/, loadAndPushSegment(segmentInfo, segmentBuffer, lastRepInfo.segmentFetcher, initSegmentUniqueId_1, lastRepInfoCleaner_1.signal)];
182
186
  case 1:
183
187
  _a.sent();
188
+ lastRepInfoCleaner_1.signal.register(function () {
189
+ segmentBuffer.freeInitSegment(initSegmentUniqueId_1);
190
+ });
184
191
  return [2 /*return*/, segmentBuffer];
185
192
  }
186
193
  });
187
194
  }); });
188
195
  lastRepInfo = {
189
- cleaner: cleaner_1,
196
+ cleaner: lastRepInfoCleaner_1,
190
197
  segmentBuffer: segmentBufferProm,
191
198
  content: content,
199
+ initSegmentUniqueId: initSegmentUniqueId_1,
192
200
  segmentFetcher: segmentFetcher,
193
201
  pendingRequests: [],
194
202
  };
@@ -233,7 +241,7 @@ var VideoThumbnailLoader = /** @class */ (function () {
233
241
  var unlinkSignal_1 = requestCanceller
234
242
  .linkToSignal(lastRepInfo.cleaner.signal);
235
243
  var segmentInfo = objectAssign({ segment: segment }, content);
236
- var prom = loadAndPushSegment(segmentInfo, segmentBuffer, lastRepInfo.segmentFetcher, requestCanceller.signal)
244
+ var prom = loadAndPushSegment(segmentInfo, segmentBuffer, lastRepInfo.segmentFetcher, lastRepInfo.initSegmentUniqueId, requestCanceller.signal)
237
245
  .then(unlinkSignal_1, function (err) {
238
246
  unlinkSignal_1();
239
247
  throw err;
@@ -14,6 +14,4 @@
14
14
  * limitations under the License.
15
15
  */
16
16
  import MediaCapabilitiesProber from "./api";
17
- import log from "./log";
18
- log.setLevel("WARNING");
19
17
  export default MediaCapabilitiesProber;
@@ -14,13 +14,13 @@
14
14
  * limitations under the License.
15
15
  */
16
16
  import { IParsedAdaptation } from "../parsers/manifest";
17
- import { ITrackType, IRepresentationFilter } from "../public_types";
17
+ import { IAudioTrack, ITrackType, IRepresentationFilter, ITextTrack, IVideoTrack } from "../public_types";
18
18
  import Representation from "./representation";
19
19
  /** List in an array every possible value for the Adaptation's `type` property. */
20
20
  export declare const SUPPORTED_ADAPTATIONS_TYPE: ITrackType[];
21
21
  /**
22
22
  * Normalized Adaptation structure.
23
- * An Adaptation describes a single `Track`. For example a specific audio
23
+ * An `Adaptation` describes a single `Track`. For example a specific audio
24
24
  * track (in a given language) or a specific video track.
25
25
  * It istelf can be represented in different qualities, which we call here
26
26
  * `Representation`.
@@ -91,4 +91,23 @@ export default class Adaptation {
91
91
  * @returns {Object|undefined}
92
92
  */
93
93
  getRepresentation(wantedId: number | string): Representation | undefined;
94
+ /**
95
+ * Format an `Adaptation`, generally of type `"audio"`, as an `IAudioTrack`.
96
+ * @param {boolean} filterPlayable - If `true` only "playable" Representation
97
+ * will be returned.
98
+ * @returns {Object}
99
+ */
100
+ toAudioTrack(filterPlayable: boolean): IAudioTrack;
101
+ /**
102
+ * Format an `Adaptation`, generally of type `"audio"`, as an `IAudioTrack`.
103
+ * @returns {Object}
104
+ */
105
+ toTextTrack(): ITextTrack;
106
+ /**
107
+ * Format an `Adaptation`, generally of type `"video"`, as an `IAudioTrack`.
108
+ * @param {boolean} filterPlayable - If `true` only "playable" Representation
109
+ * will be returned.
110
+ * @returns {Object}
111
+ */
112
+ toVideoTrack(filterPlayable: boolean): IVideoTrack;
94
113
  }
@@ -22,7 +22,7 @@ import Representation from "./representation";
22
22
  export var SUPPORTED_ADAPTATIONS_TYPE = ["audio", "video", "text"];
23
23
  /**
24
24
  * Normalized Adaptation structure.
25
- * An Adaptation describes a single `Track`. For example a specific audio
25
+ * An `Adaptation` describes a single `Track`. For example a specific audio
26
26
  * track (in a given language) or a specific video track.
27
27
  * It istelf can be represented in different qualities, which we call here
28
28
  * `Representation`.
@@ -139,6 +139,81 @@ var Adaptation = /** @class */ (function () {
139
139
  return wantedId === id;
140
140
  });
141
141
  };
142
+ /**
143
+ * Format an `Adaptation`, generally of type `"audio"`, as an `IAudioTrack`.
144
+ * @param {boolean} filterPlayable - If `true` only "playable" Representation
145
+ * will be returned.
146
+ * @returns {Object}
147
+ */
148
+ Adaptation.prototype.toAudioTrack = function (filterPlayable) {
149
+ var _a, _b;
150
+ var formatted = {
151
+ language: (_a = this.language) !== null && _a !== void 0 ? _a : "",
152
+ normalized: (_b = this.normalizedLanguage) !== null && _b !== void 0 ? _b : "",
153
+ audioDescription: this.isAudioDescription === true,
154
+ id: this.id,
155
+ representations: (filterPlayable ?
156
+ this.getPlayableRepresentations() :
157
+ this.representations).map(function (r) { return r.toAudioRepresentation(); }),
158
+ label: this.label,
159
+ };
160
+ if (this.isDub === true) {
161
+ formatted.dub = true;
162
+ }
163
+ return formatted;
164
+ };
165
+ /**
166
+ * Format an `Adaptation`, generally of type `"audio"`, as an `IAudioTrack`.
167
+ * @returns {Object}
168
+ */
169
+ Adaptation.prototype.toTextTrack = function () {
170
+ var _a, _b;
171
+ return {
172
+ language: (_a = this.language) !== null && _a !== void 0 ? _a : "",
173
+ normalized: (_b = this.normalizedLanguage) !== null && _b !== void 0 ? _b : "",
174
+ closedCaption: this.isClosedCaption === true,
175
+ id: this.id,
176
+ label: this.label,
177
+ forced: this.isForcedSubtitles,
178
+ };
179
+ };
180
+ /**
181
+ * Format an `Adaptation`, generally of type `"video"`, as an `IAudioTrack`.
182
+ * @param {boolean} filterPlayable - If `true` only "playable" Representation
183
+ * will be returned.
184
+ * @returns {Object}
185
+ */
186
+ Adaptation.prototype.toVideoTrack = function (filterPlayable) {
187
+ var trickModeTracks = this.trickModeTracks !== undefined ?
188
+ this.trickModeTracks.map(function (trickModeAdaptation) {
189
+ var representations = (filterPlayable ?
190
+ trickModeAdaptation.getPlayableRepresentations() :
191
+ trickModeAdaptation.representations).map(function (r) { return r.toVideoRepresentation(); });
192
+ var trickMode = { id: trickModeAdaptation.id, representations: representations, isTrickModeTrack: true };
193
+ if (trickModeAdaptation.isSignInterpreted === true) {
194
+ trickMode.signInterpreted = true;
195
+ }
196
+ return trickMode;
197
+ }) :
198
+ undefined;
199
+ var videoTrack = {
200
+ id: this.id,
201
+ representations: (filterPlayable ?
202
+ this.getPlayableRepresentations() :
203
+ this.representations).map(function (r) { return r.toVideoRepresentation(); }),
204
+ label: this.label,
205
+ };
206
+ if (this.isSignInterpreted === true) {
207
+ videoTrack.signInterpreted = true;
208
+ }
209
+ if (this.isTrickModeTrack === true) {
210
+ videoTrack.isTrickModeTrack = true;
211
+ }
212
+ if (trickModeTracks !== undefined) {
213
+ videoTrack.trickModeTracks = trickModeTracks;
214
+ }
215
+ return videoTrack;
216
+ };
142
217
  return Adaptation;
143
218
  }());
144
219
  export default Adaptation;
@@ -373,8 +373,8 @@ function updateDeciperability(manifest, isDecipherable) {
373
373
  var result = isDecipherable(representation);
374
374
  if (result !== representation.decipherable) {
375
375
  updates.push({ manifest: manifest, period: period, adaptation: adaptation, representation: representation });
376
- log.debug("Decipherability changed for \"".concat(representation.id, "\""), "(".concat(representation.bitrate, ")"), String(representation.decipherable));
377
376
  representation.decipherable = result;
377
+ log.debug("Decipherability changed for \"".concat(representation.id, "\""), "(".concat(representation.bitrate, ")"), String(representation.decipherable));
378
378
  }
379
379
  }
380
380
  }