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
@@ -20,6 +20,7 @@ import Manifest, {
20
20
  Period,
21
21
  Representation,
22
22
  } from "../../../../manifest";
23
+ import objectAssign from "../../../../utils/object_assign";
23
24
  import { CancellationSignal } from "../../../../utils/task_canceller";
24
25
  import { IReadOnlyPlaybackObserver } from "../../../api";
25
26
  import {
@@ -42,6 +43,7 @@ export default async function pushInitSegment<T>(
42
43
  {
43
44
  playbackObserver,
44
45
  content,
46
+ initSegmentUniqueId,
45
47
  segment,
46
48
  segmentData,
47
49
  segmentBuffer,
@@ -53,27 +55,30 @@ export default async function pushInitSegment<T>(
53
55
  manifest : Manifest;
54
56
  period : Period;
55
57
  representation : Representation; };
56
- segmentData : T | null;
58
+ initSegmentUniqueId : string;
59
+ segmentData : T;
57
60
  segment : ISegment;
58
61
  segmentBuffer : SegmentBuffer;
59
62
  },
60
63
  cancelSignal : CancellationSignal
61
64
  ) : Promise< IStreamEventAddedSegmentPayload<T> | null > {
62
- if (segmentData === null) {
63
- return null;
64
- }
65
65
  if (cancelSignal.cancellationError !== null) {
66
66
  throw cancelSignal.cancellationError;
67
67
  }
68
68
  const codec = content.representation.getMimeTypeString();
69
- const data : IPushedChunkData<T> = { initSegment: segmentData,
69
+ const data : IPushedChunkData<T> = { initSegmentUniqueId,
70
70
  chunk: null,
71
71
  timestampOffset: 0,
72
72
  appendWindow: [ undefined, undefined ],
73
73
  codec };
74
+ const inventoryInfos = objectAssign({ segment,
75
+ chunkSize: undefined,
76
+ start: 0,
77
+ end: 0 },
78
+ content);
74
79
  await appendSegmentToBuffer(playbackObserver,
75
80
  segmentBuffer,
76
- { data, inventoryInfos: null },
81
+ { data, inventoryInfos },
77
82
  cancelSignal);
78
83
  const buffered = segmentBuffer.getBufferedRanges();
79
84
  return { content, segment, buffered, segmentData };
@@ -41,7 +41,7 @@ import appendSegmentToBuffer from "./append_segment_to_buffer";
41
41
  export default async function pushMediaSegment<T>(
42
42
  { playbackObserver,
43
43
  content,
44
- initSegmentData,
44
+ initSegmentUniqueId,
45
45
  parsedSegment,
46
46
  segment,
47
47
  segmentBuffer } :
@@ -52,7 +52,7 @@ export default async function pushMediaSegment<T>(
52
52
  manifest : Manifest;
53
53
  period : Period;
54
54
  representation : Representation; };
55
- initSegmentData : T | null;
55
+ initSegmentUniqueId : string | null;
56
56
  parsedSegment : ISegmentParserParsedMediaChunk<T>;
57
57
  segment : ISegment;
58
58
  segmentBuffer : SegmentBuffer; },
@@ -83,7 +83,7 @@ export default async function pushMediaSegment<T>(
83
83
  undefined,
84
84
  ];
85
85
 
86
- const data = { initSegment: initSegmentData,
86
+ const data = { initSegmentUniqueId,
87
87
  chunk: chunkData,
88
88
  timestampOffset: chunkOffset,
89
89
  appendWindow: safeAppendWindow,
@@ -374,6 +374,33 @@ const DEFAULT_CONFIG = {
374
374
  */
375
375
  SAMPLING_INTERVAL_NO_MEDIASOURCE: 500,
376
376
 
377
+ /**
378
+ * Amount of buffer to have ahead of the current position before we may
379
+ * consider buffer-based adaptive estimates, in seconds.
380
+ *
381
+ * For example setting it to `10` means that we need to have ten seconds of
382
+ * buffer ahead of the current position before relying on buffer-based
383
+ * adaptive estimates.
384
+ *
385
+ * To avoid getting in-and-out of the buffer-based logic all the time, it
386
+ * should be set higher than `ABR_EXIT_BUFFER_BASED_ALGO`.
387
+ */
388
+ ABR_ENTER_BUFFER_BASED_ALGO: 10,
389
+
390
+ /**
391
+ * Below this amount of buffer ahead of the current position, in seconds, we
392
+ * will stop using buffer-based estimate in our adaptive logic to select a
393
+ * quality.
394
+ *
395
+ * For example setting it to `5` means that if we have less than 5 seconds of
396
+ * buffer ahead of the current position, we should stop relying on
397
+ * buffer-based estimates to choose a quality.
398
+ *
399
+ * To avoid getting in-and-out of the buffer-based logic all the time, it
400
+ * should be set lower than `ABR_ENTER_BUFFER_BASED_ALGO`.
401
+ */
402
+ ABR_EXIT_BUFFER_BASED_ALGO: 5,
403
+
377
404
  /**
378
405
  * Minimum number of bytes sampled before we trust the estimate.
379
406
  * If we have not sampled much data, our estimate may not be accurate
@@ -412,8 +439,8 @@ const DEFAULT_CONFIG = {
412
439
  * @type {Object}
413
440
  */
414
441
  ABR_REGULAR_FACTOR: {
415
- DEFAULT: 0.8,
416
- LOW_LATENCY: 0.8,
442
+ DEFAULT: 0.72,
443
+ LOW_LATENCY: 0.72,
417
444
  },
418
445
 
419
446
  /**
@@ -19,25 +19,25 @@ import MediaError from "../media_error";
19
19
  describe("errors - MediaError", () => {
20
20
  it("should format a MediaError", () => {
21
21
  const reason = "test";
22
- const mediaError = new MediaError("BUFFER_FULL_ERROR", reason);
22
+ const mediaError = new MediaError("MEDIA_TIME_BEFORE_MANIFEST", reason);
23
23
  expect(mediaError).toBeInstanceOf(Error);
24
24
  expect(mediaError.name).toBe("MediaError");
25
25
  expect(mediaError.type).toBe("MEDIA_ERROR");
26
- expect(mediaError.code).toBe("BUFFER_FULL_ERROR");
26
+ expect(mediaError.code).toBe("MEDIA_TIME_BEFORE_MANIFEST");
27
27
  expect(mediaError.fatal).toBe(false);
28
- expect(mediaError.message).toBe("MediaError (BUFFER_FULL_ERROR) test");
28
+ expect(mediaError.message).toBe("MediaError (MEDIA_TIME_BEFORE_MANIFEST) test");
29
29
  });
30
30
 
31
31
  it("should be able to set it as fatal", () => {
32
32
  const reason = "test";
33
- const mediaError = new MediaError("BUFFER_APPEND_ERROR", reason);
33
+ const mediaError = new MediaError("MEDIA_TIME_AFTER_MANIFEST", reason);
34
34
  mediaError.fatal = true;
35
35
  expect(mediaError).toBeInstanceOf(Error);
36
36
  expect(mediaError.name).toBe("MediaError");
37
37
  expect(mediaError.type).toBe("MEDIA_ERROR");
38
- expect(mediaError.code).toBe("BUFFER_APPEND_ERROR");
38
+ expect(mediaError.code).toBe("MEDIA_TIME_AFTER_MANIFEST");
39
39
  expect(mediaError.fatal).toBe(true);
40
- expect(mediaError.message).toBe("MediaError (BUFFER_APPEND_ERROR) test");
40
+ expect(mediaError.message).toBe("MediaError (MEDIA_TIME_AFTER_MANIFEST) test");
41
41
  });
42
42
 
43
43
  it("should filter in a valid error code", () => {
@@ -26,7 +26,9 @@ import {
26
26
  } from "./error_codes";
27
27
  import formatError from "./format_error";
28
28
  import isKnownError from "./is_known_error";
29
- import MediaError from "./media_error";
29
+ import MediaError, {
30
+ IMediaErrorTrackContext,
31
+ } from "./media_error";
30
32
  import NetworkError from "./network_error";
31
33
  import OtherError from "./other_error";
32
34
  import RequestError from "./request_error";
@@ -39,6 +41,7 @@ export {
39
41
  ErrorTypes,
40
42
  IErrorCode,
41
43
  IErrorType,
44
+ IMediaErrorTrackContext,
42
45
  formatError,
43
46
  MediaError as MediaError,
44
47
  NetworkError,
@@ -14,12 +14,42 @@
14
14
  * limitations under the License.
15
15
  */
16
16
 
17
+ import { Adaptation } from "../manifest";
18
+ import {
19
+ IAudioTrack,
20
+ ITextTrack,
21
+ IVideoTrack,
22
+ } from "../public_types";
17
23
  import {
18
24
  ErrorTypes,
19
25
  IMediaErrorCode,
20
26
  } from "./error_codes";
21
27
  import errorMessage from "./error_message";
22
28
 
29
+ interface IAudioTrackMediaErrorContext {
30
+ type : "audio";
31
+ track : IAudioTrack;
32
+ }
33
+
34
+ interface IVideoTrackMediaErrorContext {
35
+ type : "video";
36
+ track : IVideoTrack;
37
+ }
38
+
39
+ interface ITextTrackMediaErrorContext {
40
+ type : "text";
41
+ track : ITextTrack;
42
+ }
43
+
44
+ export type IMediaErrorTrackContext = IAudioTrackMediaErrorContext |
45
+ IVideoTrackMediaErrorContext |
46
+ ITextTrackMediaErrorContext;
47
+
48
+ type ICodeWithAdaptationType = "BUFFER_APPEND_ERROR" |
49
+ "BUFFER_FULL_ERROR" |
50
+ "NO_PLAYABLE_REPRESENTATION" |
51
+ "MANIFEST_INCOMPATIBLE_CODECS_ERROR";
52
+
23
53
  /**
24
54
  * Error linked to the media Playback.
25
55
  *
@@ -31,13 +61,32 @@ export default class MediaError extends Error {
31
61
  public readonly type : "MEDIA_ERROR";
32
62
  public readonly message : string;
33
63
  public readonly code : IMediaErrorCode;
64
+ public readonly trackInfo : IMediaErrorTrackContext | undefined;
34
65
  public fatal : boolean;
35
66
 
36
67
  /**
37
68
  * @param {string} code
38
69
  * @param {string} reason
70
+ * @param {Object|undefined} [context]
39
71
  */
40
- constructor(code : IMediaErrorCode, reason : string) {
72
+ constructor(
73
+ code : ICodeWithAdaptationType,
74
+ reason : string,
75
+ context: {
76
+ adaptation : Adaptation | undefined;
77
+ }
78
+ );
79
+ constructor(
80
+ code : Exclude<IMediaErrorCode, ICodeWithAdaptationType>,
81
+ reason : string,
82
+ );
83
+ constructor(
84
+ code : IMediaErrorCode,
85
+ reason : string,
86
+ context? : {
87
+ adaptation? : Adaptation | undefined;
88
+ } | undefined
89
+ ) {
41
90
  super();
42
91
  // @see https://stackoverflow.com/questions/41102060/typescript-extending-error-class
43
92
  Object.setPrototypeOf(this, MediaError.prototype);
@@ -48,5 +97,22 @@ export default class MediaError extends Error {
48
97
  this.code = code;
49
98
  this.message = errorMessage(this.name, this.code, reason);
50
99
  this.fatal = false;
100
+ const adaptation = context?.adaptation;
101
+ if (adaptation !== undefined) {
102
+ switch (adaptation.type) {
103
+ case "audio":
104
+ this.trackInfo = { type: "audio",
105
+ track: adaptation.toAudioTrack(false) };
106
+ break;
107
+ case "video":
108
+ this.trackInfo = { type: "video",
109
+ track: adaptation.toVideoTrack(false) };
110
+ break;
111
+ case "text":
112
+ this.trackInfo = { type: "text",
113
+ track: adaptation.toTextTrack() };
114
+ break;
115
+ }
116
+ }
51
117
  }
52
118
  }
@@ -33,30 +33,33 @@ export default function loadAndPushSegment(
33
33
  segmentInfo : ISegmentLoaderContent,
34
34
  segmentBuffer: AudioVideoSegmentBuffer,
35
35
  segmentFetcher: ISegmentFetcher<ArrayBuffer | Uint8Array>,
36
+ initSegmentUniqueId : string | null,
36
37
  cancelSignal: CancellationSignal
37
38
  ): Promise<unknown> {
38
39
  const pushOperations : Array<Promise<unknown>> = [];
39
40
  return segmentFetcher(segmentInfo, {
40
41
  onChunk(parseChunk) {
41
42
  const parsed = parseChunk(undefined);
42
- let isIsInitSegment : boolean;
43
+ let isInitSegment : boolean;
43
44
  let data : BufferSource | null;
44
45
  let timestampOffset : number;
45
46
  const codec = segmentInfo.representation.getMimeTypeString();
46
47
  if (parsed.segmentType === "init") {
47
- isIsInitSegment = true;
48
+ isInitSegment = true;
48
49
  data = parsed.initializationData;
49
50
  timestampOffset = 0;
51
+ if (initSegmentUniqueId !== null) {
52
+ segmentBuffer.declareInitSegment(initSegmentUniqueId, data);
53
+ }
50
54
  } else {
51
- isIsInitSegment = false;
55
+ isInitSegment = false;
52
56
  data = parsed.chunkData;
53
57
  timestampOffset = parsed.chunkOffset;
54
58
  }
55
59
  const pushOperation = segmentBuffer.pushChunk({
56
- data: { initSegment: isIsInitSegment ? data :
57
- null,
58
- chunk: isIsInitSegment ? null :
59
- data,
60
+ data: { initSegmentUniqueId,
61
+ chunk: isInitSegment ? null :
62
+ data,
60
63
  appendWindow: [segmentInfo.period.start, segmentInfo.period.end],
61
64
  timestampOffset,
62
65
  codec },
@@ -167,7 +167,7 @@ export default class VideoThumbnailLoader {
167
167
 
168
168
  let lastRepInfo : IVideoThumbnailLoaderRepresentationInfo;
169
169
  if (this._lastRepresentationInfo === null) {
170
- const cleaner = new TaskCanceller();
170
+ const lastRepInfoCleaner = new TaskCanceller();
171
171
  const segmentFetcher = createSegmentFetcher(
172
172
  "video",
173
173
  loader.video,
@@ -179,13 +179,17 @@ export default class VideoThumbnailLoader {
179
179
  maxRetry: 0,
180
180
  requestTimeout: config.getCurrent().DEFAULT_REQUEST_TIMEOUT }
181
181
  ) as ISegmentFetcher<ArrayBuffer | Uint8Array>;
182
+ const initSegment = content.representation.index.getInitSegment();
183
+ const initSegmentUniqueId = initSegment !== null ?
184
+ content.representation.uniqueId :
185
+ null;
182
186
  const segmentBufferProm = prepareSourceBuffer(
183
187
  this._videoElement,
184
188
  content.representation.getMimeTypeString(),
185
- cleaner.signal
189
+ lastRepInfoCleaner.signal
186
190
  ).then(async (segmentBuffer) => {
187
- const initSegment = content.representation.index.getInitSegment();
188
- if (initSegment === null) {
191
+ if (initSegment === null || initSegmentUniqueId === null) {
192
+ lastRepInfo.initSegmentUniqueId = null;
189
193
  return segmentBuffer;
190
194
  }
191
195
  const segmentInfo = objectAssign({ segment: initSegment },
@@ -193,13 +197,18 @@ export default class VideoThumbnailLoader {
193
197
  await loadAndPushSegment(segmentInfo,
194
198
  segmentBuffer,
195
199
  lastRepInfo.segmentFetcher,
196
- cleaner.signal);
200
+ initSegmentUniqueId,
201
+ lastRepInfoCleaner.signal);
202
+ lastRepInfoCleaner.signal.register(() => {
203
+ segmentBuffer.freeInitSegment(initSegmentUniqueId);
204
+ });
197
205
  return segmentBuffer;
198
206
  });
199
207
  lastRepInfo = {
200
- cleaner,
208
+ cleaner: lastRepInfoCleaner,
201
209
  segmentBuffer: segmentBufferProm,
202
210
  content,
211
+ initSegmentUniqueId,
203
212
  segmentFetcher,
204
213
  pendingRequests: [],
205
214
  };
@@ -251,6 +260,7 @@ export default class VideoThumbnailLoader {
251
260
  const prom = loadAndPushSegment(segmentInfo,
252
261
  segmentBuffer,
253
262
  lastRepInfo.segmentFetcher,
263
+ lastRepInfo.initSegmentUniqueId,
254
264
  requestCanceller.signal)
255
265
  .then(unlinkSignal, (err) => {
256
266
  unlinkSignal();
@@ -390,6 +400,7 @@ interface IVideoThumbnailLoaderRepresentationInfo {
390
400
  * `pendingRequests`.
391
401
  */
392
402
  pendingRequests : IPendingRequestInfo[];
403
+ initSegmentUniqueId : string | null;
393
404
  }
394
405
 
395
406
  interface IPendingRequestInfo {
@@ -15,8 +15,4 @@
15
15
  */
16
16
 
17
17
  import MediaCapabilitiesProber from "./api";
18
- import log from "./log";
19
-
20
- log.setLevel("WARNING");
21
-
22
18
  export default MediaCapabilitiesProber;
@@ -72,7 +72,7 @@ describe("Manifest - Manifest", () => {
72
72
  expect(manifest.suggestedPresentationDelay).toEqual(undefined);
73
73
  expect(manifest.uris).toEqual([]);
74
74
 
75
- expect(fakeIdGenerator).toHaveBeenCalledTimes(1);
75
+ expect(fakeIdGenerator).toHaveBeenCalled();
76
76
  expect(fakeGenerateNewId).toHaveBeenCalledTimes(1);
77
77
  expect(fakeLogger.info).not.toHaveBeenCalled();
78
78
  expect(fakeLogger.warn).not.toHaveBeenCalled();
@@ -114,7 +114,7 @@ describe("Manifest - Manifest", () => {
114
114
  contentWarnings: [] } ]);
115
115
  expect(manifest.adaptations).toEqual({});
116
116
 
117
- expect(fakeIdGenerator).toHaveBeenCalledTimes(1);
117
+ expect(fakeIdGenerator).toHaveBeenCalled();
118
118
  expect(fakeGenerateNewId).toHaveBeenCalledTimes(1);
119
119
  expect(fakeLogger.info).not.toHaveBeenCalled();
120
120
  expect(fakeLogger.warn).not.toHaveBeenCalled();
@@ -152,7 +152,7 @@ describe("Manifest - Manifest", () => {
152
152
  expect(fakePeriod).toHaveBeenCalledTimes(2);
153
153
  expect(fakePeriod).toHaveBeenCalledWith(period1, representationFilter);
154
154
  expect(fakePeriod).toHaveBeenCalledWith(period2, representationFilter);
155
- expect(fakeIdGenerator).toHaveBeenCalledTimes(1);
155
+ expect(fakeIdGenerator).toHaveBeenCalled();
156
156
  expect(fakeGenerateNewId).toHaveBeenCalledTimes(1);
157
157
  expect(fakeLogger.info).not.toHaveBeenCalled();
158
158
  expect(fakeLogger.warn).not.toHaveBeenCalled();
@@ -194,7 +194,7 @@ describe("Manifest - Manifest", () => {
194
194
  ]);
195
195
  expect(manifest.adaptations).toBe(adapP1);
196
196
 
197
- expect(fakeIdGenerator).toHaveBeenCalledTimes(1);
197
+ expect(fakeIdGenerator).toHaveBeenCalled();
198
198
  expect(fakeGenerateNewId).toHaveBeenCalledTimes(1);
199
199
  expect(fakeLogger.info).not.toHaveBeenCalled();
200
200
  expect(fakeLogger.warn).not.toHaveBeenCalled();
@@ -234,7 +234,7 @@ describe("Manifest - Manifest", () => {
234
234
  expect(manifest.contentWarnings).toContainEqual(new Error("0"));
235
235
  expect(manifest.contentWarnings).toContainEqual(new Error("1"));
236
236
 
237
- expect(fakeIdGenerator).toHaveBeenCalledTimes(1);
237
+ expect(fakeIdGenerator).toHaveBeenCalled();
238
238
  expect(fakeGenerateNewId).toHaveBeenCalledTimes(1);
239
239
  expect(fakeLogger.info).not.toHaveBeenCalled();
240
240
  expect(fakeLogger.warn).not.toHaveBeenCalled();
@@ -285,7 +285,7 @@ describe("Manifest - Manifest", () => {
285
285
  ]);
286
286
  expect(manifest.suggestedPresentationDelay).toEqual(99);
287
287
  expect(manifest.uris).toEqual(["url1", "url2"]);
288
- expect(fakeIdGenerator).toHaveBeenCalledTimes(1);
288
+ expect(fakeIdGenerator).toHaveBeenCalled();
289
289
  expect(fakeGenerateNewId).toHaveBeenCalledTimes(1);
290
290
  expect(fakeLogger.info).not.toHaveBeenCalled();
291
291
  expect(fakeLogger.warn).not.toHaveBeenCalled();
@@ -419,7 +419,7 @@ describe("Manifest - Manifest", () => {
419
419
  .toHaveBeenCalledWith(manifest.periods, newManifest.periods);
420
420
  expect(mockTrigger).toHaveBeenCalledTimes(1);
421
421
  expect(mockTrigger).toHaveBeenCalledWith("manifestUpdate", fakeReplacePeriodsRes);
422
- expect(fakeIdGenerator).toHaveBeenCalledTimes(1);
422
+ expect(fakeIdGenerator).toHaveBeenCalled();
423
423
  expect(fakeGenerateNewId).toHaveBeenCalledTimes(1);
424
424
  expect(fakeLogger.info).not.toHaveBeenCalled();
425
425
  expect(fakeLogger.warn).not.toHaveBeenCalled();