rx-player 3.30.0-dev.2023020100 → 3.30.0-dev.2023030200

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 (183) hide show
  1. package/.eslintrc.js +8 -0
  2. package/CHANGELOG.md +5 -1
  3. package/VERSION +1 -1
  4. package/dist/_esm5.processed/compat/browser_detection.d.ts +23 -12
  5. package/dist/_esm5.processed/compat/browser_detection.js +80 -38
  6. package/dist/_esm5.processed/compat/can_reuse_media_keys.js +2 -2
  7. package/dist/_esm5.processed/compat/eme/close_session.js +2 -2
  8. package/dist/_esm5.processed/compat/event_listeners.js +1 -1
  9. package/dist/_esm5.processed/config.d.ts +2 -0
  10. package/dist/_esm5.processed/core/adaptive/adaptive_representation_selector.js +4 -2
  11. package/dist/_esm5.processed/core/api/debug/buffer_graph.d.ts +28 -0
  12. package/dist/_esm5.processed/core/api/debug/buffer_graph.js +175 -0
  13. package/dist/_esm5.processed/core/api/debug/buffer_size_graph.d.ts +10 -0
  14. package/dist/_esm5.processed/core/api/debug/buffer_size_graph.js +104 -0
  15. package/dist/_esm5.processed/core/api/debug/constants.d.ts +2 -0
  16. package/dist/_esm5.processed/core/api/debug/constants.js +2 -0
  17. package/dist/_esm5.processed/core/api/debug/index.d.ts +2 -0
  18. package/dist/_esm5.processed/core/api/debug/index.js +2 -0
  19. package/dist/_esm5.processed/core/api/debug/modules/general_info.d.ts +3 -0
  20. package/dist/_esm5.processed/core/api/debug/modules/general_info.js +199 -0
  21. package/dist/_esm5.processed/core/api/debug/modules/segment_buffer_content.d.ts +4 -0
  22. package/dist/_esm5.processed/core/api/debug/modules/segment_buffer_content.js +121 -0
  23. package/dist/_esm5.processed/core/api/debug/modules/segment_buffer_size.d.ts +3 -0
  24. package/dist/_esm5.processed/core/api/debug/modules/segment_buffer_size.js +35 -0
  25. package/dist/_esm5.processed/core/api/debug/render.d.ts +3 -0
  26. package/dist/_esm5.processed/core/api/debug/render.js +32 -0
  27. package/dist/_esm5.processed/core/api/debug/utils.d.ts +39 -0
  28. package/dist/_esm5.processed/core/api/debug/utils.js +57 -0
  29. package/dist/_esm5.processed/core/api/playback_observer.js +3 -2
  30. package/dist/_esm5.processed/core/api/public_api.d.ts +3 -0
  31. package/dist/_esm5.processed/core/api/public_api.js +25 -14
  32. package/dist/_esm5.processed/core/api/utils.js +3 -3
  33. package/dist/_esm5.processed/core/decrypt/__tests__/__global__/utils.d.ts +32 -13
  34. package/dist/_esm5.processed/core/decrypt/__tests__/__global__/utils.js +28 -7
  35. package/dist/_esm5.processed/core/decrypt/attach_media_keys.js +1 -1
  36. package/dist/_esm5.processed/core/decrypt/content_decryptor.js +1 -1
  37. package/dist/_esm5.processed/core/decrypt/find_key_system.js +33 -24
  38. package/dist/_esm5.processed/core/decrypt/session_events_listener.js +54 -50
  39. package/dist/_esm5.processed/core/decrypt/utils/check_key_statuses.js +4 -0
  40. package/dist/_esm5.processed/core/fetchers/cdn_prioritizer.d.ts +17 -8
  41. package/dist/_esm5.processed/core/fetchers/cdn_prioritizer.js +10 -6
  42. package/dist/_esm5.processed/core/fetchers/manifest/manifest_fetcher.js +5 -4
  43. package/dist/_esm5.processed/core/fetchers/segment/segment_fetcher.d.ts +22 -5
  44. package/dist/_esm5.processed/core/fetchers/segment/segment_fetcher.js +37 -21
  45. package/dist/_esm5.processed/core/fetchers/segment/task_prioritizer.js +21 -23
  46. package/dist/_esm5.processed/core/fetchers/utils/schedule_request.js +17 -7
  47. package/dist/_esm5.processed/core/init/directfile_content_initializer.js +1 -1
  48. package/dist/_esm5.processed/core/init/media_source_content_initializer.js +27 -31
  49. package/dist/_esm5.processed/core/init/utils/content_time_boundaries_observer.js +2 -2
  50. package/dist/_esm5.processed/core/init/utils/create_media_source.js +3 -12
  51. package/dist/_esm5.processed/core/init/utils/end_of_stream.js +6 -3
  52. package/dist/_esm5.processed/core/init/utils/get_loaded_reference.js +2 -1
  53. package/dist/_esm5.processed/core/init/utils/initial_seek_and_play.js +9 -5
  54. package/dist/_esm5.processed/core/init/utils/initialize_content_decryption.js +2 -1
  55. package/dist/_esm5.processed/core/init/utils/media_duration_updater.js +23 -19
  56. package/dist/_esm5.processed/core/init/utils/rebuffering_controller.js +1 -1
  57. package/dist/_esm5.processed/core/init/utils/stream_events_emitter/stream_events_emitter.js +6 -4
  58. package/dist/_esm5.processed/core/init/utils/throw_on_media_error.js +1 -1
  59. package/dist/_esm5.processed/core/segment_buffers/implementations/audio_video/audio_video_segment_buffer.js +7 -10
  60. package/dist/_esm5.processed/core/segment_buffers/implementations/text/html/html_text_segment_buffer.js +4 -2
  61. package/dist/_esm5.processed/core/segment_buffers/segment_buffers_store.js +13 -9
  62. package/dist/_esm5.processed/core/stream/adaptation/adaptation_stream.js +25 -16
  63. package/dist/_esm5.processed/core/stream/orchestrator/stream_orchestrator.js +26 -12
  64. package/dist/_esm5.processed/core/stream/period/period_stream.js +11 -10
  65. package/dist/_esm5.processed/core/stream/representation/representation_stream.js +15 -15
  66. package/dist/_esm5.processed/core/stream/representation/utils/append_segment_to_buffer.js +1 -1
  67. package/dist/_esm5.processed/core/stream/representation/utils/downloading_queue.js +16 -6
  68. package/dist/_esm5.processed/default_config.d.ts +16 -0
  69. package/dist/_esm5.processed/default_config.js +19 -0
  70. package/dist/_esm5.processed/experimental/features/debug_element.d.ts +8 -0
  71. package/dist/_esm5.processed/experimental/features/debug_element.js +10 -0
  72. package/dist/_esm5.processed/experimental/features/index.d.ts +1 -0
  73. package/dist/_esm5.processed/experimental/features/index.js +1 -0
  74. package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/prepare_source_buffer.js +7 -4
  75. package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/video_thumbnail_loader.js +8 -4
  76. package/dist/_esm5.processed/features/features_object.js +1 -0
  77. package/dist/_esm5.processed/features/initialize_features.js +13 -10
  78. package/dist/_esm5.processed/features/types.d.ts +3 -0
  79. package/dist/_esm5.processed/manifest/adaptation.js +4 -0
  80. package/dist/_esm5.processed/manifest/manifest.js +2 -0
  81. package/dist/_esm5.processed/manifest/representation.js +11 -4
  82. package/dist/_esm5.processed/parsers/manifest/dash/common/parse_adaptation_sets.js +105 -137
  83. package/dist/_esm5.processed/parsers/manifest/dash/common/parse_representations.js +25 -5
  84. package/dist/_esm5.processed/public_types.d.ts +1 -0
  85. package/dist/_esm5.processed/transports/dash/add_segment_integrity_checks_to_loader.js +15 -11
  86. package/dist/_esm5.processed/transports/dash/low_latency_segment_loader.js +2 -2
  87. package/dist/_esm5.processed/transports/dash/manifest_parser.js +1 -1
  88. package/dist/_esm5.processed/transports/dash/segment_loader.js +4 -4
  89. package/dist/_esm5.processed/transports/local/segment_loader.js +13 -26
  90. package/dist/_esm5.processed/transports/smooth/segment_loader.js +4 -4
  91. package/dist/_esm5.processed/transports/utils/call_custom_manifest_loader.js +3 -3
  92. package/dist/_esm5.processed/utils/cancellable_sleep.js +4 -10
  93. package/dist/_esm5.processed/utils/create_cancellable_promise.d.ts +26 -0
  94. package/dist/_esm5.processed/utils/create_cancellable_promise.js +52 -0
  95. package/dist/_esm5.processed/utils/reference.js +6 -0
  96. package/dist/_esm5.processed/utils/request/xhr.js +1 -1
  97. package/dist/_esm5.processed/utils/task_canceller.d.ts +34 -15
  98. package/dist/_esm5.processed/utils/task_canceller.js +55 -22
  99. package/dist/rx-player.js +880 -677
  100. package/dist/rx-player.min.js +1 -1
  101. package/jest.config.js +1 -0
  102. package/package.json +19 -18
  103. package/scripts/build/constants.d.ts +1 -0
  104. package/scripts/report_build_sizes +4 -0
  105. package/sonar-project.properties +1 -1
  106. package/src/compat/browser_detection.ts +99 -52
  107. package/src/compat/can_reuse_media_keys.ts +5 -2
  108. package/src/compat/eme/close_session.ts +2 -2
  109. package/src/compat/event_listeners.ts +1 -1
  110. package/src/core/adaptive/adaptive_representation_selector.ts +4 -2
  111. package/src/core/api/debug/buffer_graph.ts +247 -0
  112. package/src/core/api/debug/buffer_size_graph.ts +130 -0
  113. package/src/core/api/debug/constants.ts +2 -0
  114. package/src/core/api/debug/index.ts +3 -0
  115. package/src/core/api/debug/modules/general_info.ts +204 -0
  116. package/src/core/api/debug/modules/segment_buffer_content.ts +155 -0
  117. package/src/core/api/debug/modules/segment_buffer_size.ts +48 -0
  118. package/src/core/api/debug/render.ts +40 -0
  119. package/src/core/api/debug/utils.ts +103 -0
  120. package/src/core/api/playback_observer.ts +4 -2
  121. package/src/core/api/public_api.ts +28 -14
  122. package/src/core/api/utils.ts +3 -3
  123. package/src/core/decrypt/__tests__/__global__/utils.ts +61 -40
  124. package/src/core/decrypt/attach_media_keys.ts +1 -1
  125. package/src/core/decrypt/content_decryptor.ts +1 -1
  126. package/src/core/decrypt/find_key_system.ts +36 -35
  127. package/src/core/decrypt/session_events_listener.ts +57 -56
  128. package/src/core/decrypt/utils/check_key_statuses.ts +6 -0
  129. package/src/core/fetchers/cdn_prioritizer.ts +18 -9
  130. package/src/core/fetchers/manifest/manifest_fetcher.ts +5 -4
  131. package/src/core/fetchers/segment/segment_fetcher.ts +36 -14
  132. package/src/core/fetchers/segment/task_prioritizer.ts +25 -30
  133. package/src/core/fetchers/utils/schedule_request.ts +18 -7
  134. package/src/core/init/directfile_content_initializer.ts +1 -1
  135. package/src/core/init/media_source_content_initializer.ts +37 -41
  136. package/src/core/init/utils/content_time_boundaries_observer.ts +2 -2
  137. package/src/core/init/utils/create_media_source.ts +4 -16
  138. package/src/core/init/utils/end_of_stream.ts +6 -3
  139. package/src/core/init/utils/get_loaded_reference.ts +2 -1
  140. package/src/core/init/utils/initial_seek_and_play.ts +9 -5
  141. package/src/core/init/utils/initialize_content_decryption.ts +2 -1
  142. package/src/core/init/utils/media_duration_updater.ts +25 -20
  143. package/src/core/init/utils/rebuffering_controller.ts +1 -1
  144. package/src/core/init/utils/stream_events_emitter/stream_events_emitter.ts +6 -4
  145. package/src/core/init/utils/throw_on_media_error.ts +1 -1
  146. package/src/core/segment_buffers/implementations/audio_video/audio_video_segment_buffer.ts +7 -11
  147. package/src/core/segment_buffers/implementations/text/html/html_text_segment_buffer.ts +4 -2
  148. package/src/core/segment_buffers/segment_buffers_store.ts +16 -13
  149. package/src/core/stream/adaptation/adaptation_stream.ts +28 -19
  150. package/src/core/stream/orchestrator/stream_orchestrator.ts +26 -12
  151. package/src/core/stream/period/period_stream.ts +11 -10
  152. package/src/core/stream/representation/representation_stream.ts +15 -15
  153. package/src/core/stream/representation/utils/append_segment_to_buffer.ts +1 -1
  154. package/src/core/stream/representation/utils/downloading_queue.ts +16 -4
  155. package/src/default_config.ts +30 -9
  156. package/src/experimental/features/__tests__/debug_element.test.ts +26 -0
  157. package/src/experimental/features/debug_element.ts +13 -0
  158. package/src/experimental/features/index.ts +1 -0
  159. package/src/experimental/tools/VideoThumbnailLoader/prepare_source_buffer.ts +7 -4
  160. package/src/experimental/tools/VideoThumbnailLoader/video_thumbnail_loader.ts +8 -4
  161. package/src/features/__tests__/initialize_features.test.ts +11 -0
  162. package/src/features/features_object.ts +1 -0
  163. package/src/features/initialize_features.ts +15 -10
  164. package/src/features/types.ts +9 -0
  165. package/src/manifest/adaptation.ts +7 -0
  166. package/src/manifest/manifest.ts +4 -0
  167. package/src/manifest/representation.ts +10 -4
  168. package/src/parsers/manifest/dash/common/parse_adaptation_sets.ts +116 -151
  169. package/src/parsers/manifest/dash/common/parse_representations.ts +21 -4
  170. package/src/public_types.ts +1 -0
  171. package/src/transports/dash/add_segment_integrity_checks_to_loader.ts +31 -22
  172. package/src/transports/dash/low_latency_segment_loader.ts +2 -2
  173. package/src/transports/dash/manifest_parser.ts +1 -1
  174. package/src/transports/dash/segment_loader.ts +4 -4
  175. package/src/transports/local/segment_loader.ts +14 -30
  176. package/src/transports/smooth/segment_loader.ts +4 -4
  177. package/src/transports/utils/call_custom_manifest_loader.ts +3 -3
  178. package/src/typings/globals.d.ts +2 -0
  179. package/src/utils/cancellable_sleep.ts +5 -14
  180. package/src/utils/create_cancellable_promise.ts +69 -0
  181. package/src/utils/reference.ts +6 -0
  182. package/src/utils/request/xhr.ts +1 -1
  183. package/src/utils/task_canceller.ts +63 -34
@@ -271,15 +271,6 @@ export default function parseAdaptationSets(
271
271
 
272
272
  const parsedAdaptationsIDs : string[] = [];
273
273
 
274
- /**
275
- * Index of the last parsed Video AdaptationSet with a Role set as "main" in
276
- * `parsedAdaptations.video`.
277
- * `-1` if not yet encountered.
278
- * Used as we merge all main video AdaptationSet due to a comprehension of the
279
- * DASH-IF IOP.
280
- */
281
- let lastMainVideoAdapIdx = -1;
282
-
283
274
  for (let adaptationIdx = 0; adaptationIdx < adaptationsIR.length; adaptationIdx++) {
284
275
  const adaptation = adaptationsIR[adaptationIdx];
285
276
  const adaptationChildren = adaptation.children;
@@ -316,7 +307,6 @@ export default function parseAdaptationSets(
316
307
 
317
308
  const priority = adaptation.attributes.selectionPriority ?? 1;
318
309
  const originalID = adaptation.attributes.id;
319
- let newID : string;
320
310
  const adaptationSetSwitchingIDs = getAdaptationSetSwitchingIDs(adaptation);
321
311
  const parentSegmentTemplates = [];
322
312
  if (context.segmentTemplate !== undefined) {
@@ -356,161 +346,136 @@ export default function parseAdaptationSets(
356
346
 
357
347
  const isTrickModeTrack = trickModeAttachedAdaptationIds !== undefined;
358
348
 
359
- if (type === "video" &&
360
- isMainAdaptation &&
361
- lastMainVideoAdapIdx >= 0 &&
362
- parsedAdaptations.video.length > lastMainVideoAdapIdx &&
363
- !isTrickModeTrack)
349
+ const { accessibilities } = adaptationChildren;
350
+
351
+ let isDub : boolean|undefined;
352
+ if (roles !== undefined &&
353
+ roles.some((role) => role.value === "dub"))
364
354
  {
365
- const videoMainAdaptation = parsedAdaptations.video[lastMainVideoAdapIdx][0];
366
- reprCtxt.unsafelyBaseOnPreviousAdaptation = context
367
- .unsafelyBaseOnPreviousPeriod?.getAdaptation(videoMainAdaptation.id) ?? null;
368
- const representations = parseRepresentations(representationsIR,
369
- adaptation,
370
- reprCtxt);
371
- videoMainAdaptation.representations.push(...representations);
372
- newID = videoMainAdaptation.id;
373
- } else {
374
- const { accessibilities } = adaptationChildren;
355
+ isDub = true;
356
+ }
375
357
 
376
- let isDub : boolean|undefined;
377
- if (roles !== undefined &&
378
- roles.some((role) => role.value === "dub"))
379
- {
380
- isDub = true;
381
- }
358
+ let isClosedCaption;
359
+ if (type !== "text") {
360
+ isClosedCaption = false;
361
+ } else {
362
+ isClosedCaption = isCaptionning(accessibilities, roles);
363
+ }
382
364
 
383
- let isClosedCaption;
384
- if (type !== "text") {
385
- isClosedCaption = false;
386
- } else {
387
- isClosedCaption = isCaptionning(accessibilities, roles);
388
- }
365
+ let isForcedSubtitle;
366
+ if (type === "text" &&
367
+ roles !== undefined &&
368
+ roles.some((role) => role.value === "forced-subtitle" ||
369
+ role.value === "forced_subtitle"))
370
+ {
371
+ isForcedSubtitle = true;
372
+ }
389
373
 
390
- let isForcedSubtitle;
391
- if (type === "text" &&
392
- roles !== undefined &&
393
- roles.some((role) => role.value === "forced-subtitle" ||
394
- role.value === "forced_subtitle"))
395
- {
396
- isForcedSubtitle = true;
397
- }
374
+ let isAudioDescription;
375
+ if (type !== "audio") {
376
+ isAudioDescription = false;
377
+ } else if (accessibilities !== undefined) {
378
+ isAudioDescription = accessibilities.some(isVisuallyImpaired);
379
+ }
398
380
 
399
- let isAudioDescription;
400
- if (type !== "audio") {
401
- isAudioDescription = false;
402
- } else if (accessibilities !== undefined) {
403
- isAudioDescription = accessibilities.some(isVisuallyImpaired);
404
- }
381
+ let isSignInterpreted;
382
+ if (type !== "video") {
383
+ isSignInterpreted = false;
384
+ } else if (accessibilities !== undefined) {
385
+ isSignInterpreted = accessibilities.some(hasSignLanguageInterpretation);
386
+ }
405
387
 
406
- let isSignInterpreted;
407
- if (type !== "video") {
408
- isSignInterpreted = false;
409
- } else if (accessibilities !== undefined) {
410
- isSignInterpreted = accessibilities.some(hasSignLanguageInterpretation);
411
- }
388
+ let adaptationID = getAdaptationID(adaptation,
389
+ { isAudioDescription,
390
+ isForcedSubtitle,
391
+ isClosedCaption,
392
+ isSignInterpreted,
393
+ isTrickModeTrack,
394
+ type });
395
+
396
+ // Avoid duplicate IDs
397
+ while (arrayIncludes(parsedAdaptationsIDs, adaptationID)) {
398
+ adaptationID += "-dup";
399
+ }
412
400
 
413
- let adaptationID = getAdaptationID(adaptation,
414
- { isAudioDescription,
415
- isForcedSubtitle,
416
- isClosedCaption,
417
- isSignInterpreted,
418
- isTrickModeTrack,
419
- type });
420
-
421
- // Avoid duplicate IDs
422
- while (arrayIncludes(parsedAdaptationsIDs, adaptationID)) {
423
- adaptationID += "-dup";
424
- }
401
+ const newID = adaptationID;
402
+ parsedAdaptationsIDs.push(adaptationID);
403
+
404
+ reprCtxt.unsafelyBaseOnPreviousAdaptation = context
405
+ .unsafelyBaseOnPreviousPeriod?.getAdaptation(adaptationID) ?? null;
406
+
407
+ const representations = parseRepresentations(representationsIR,
408
+ adaptation,
409
+ reprCtxt);
410
+ const parsedAdaptationSet : IParsedAdaptation =
411
+ { id: adaptationID,
412
+ representations,
413
+ type,
414
+ isTrickModeTrack };
415
+ if (adaptation.attributes.language != null) {
416
+ parsedAdaptationSet.language = adaptation.attributes.language;
417
+ }
418
+ if (isClosedCaption != null) {
419
+ parsedAdaptationSet.closedCaption = isClosedCaption;
420
+ }
421
+ if (isAudioDescription != null) {
422
+ parsedAdaptationSet.audioDescription = isAudioDescription;
423
+ }
424
+ if (isDub === true) {
425
+ parsedAdaptationSet.isDub = true;
426
+ }
427
+ if (isForcedSubtitle !== undefined) {
428
+ parsedAdaptationSet.forcedSubtitles = isForcedSubtitle;
429
+ }
430
+ if (isSignInterpreted === true) {
431
+ parsedAdaptationSet.isSignInterpreted = true;
432
+ }
425
433
 
426
- newID = adaptationID;
427
- parsedAdaptationsIDs.push(adaptationID);
428
-
429
- reprCtxt.unsafelyBaseOnPreviousAdaptation = context
430
- .unsafelyBaseOnPreviousPeriod?.getAdaptation(adaptationID) ?? null;
431
-
432
- const representations = parseRepresentations(representationsIR,
433
- adaptation,
434
- reprCtxt);
435
- const parsedAdaptationSet : IParsedAdaptation =
436
- { id: adaptationID,
437
- representations,
438
- type,
439
- isTrickModeTrack };
440
- if (adaptation.attributes.language != null) {
441
- parsedAdaptationSet.language = adaptation.attributes.language;
442
- }
443
- if (isClosedCaption != null) {
444
- parsedAdaptationSet.closedCaption = isClosedCaption;
445
- }
446
- if (isAudioDescription != null) {
447
- parsedAdaptationSet.audioDescription = isAudioDescription;
448
- }
449
- if (isDub === true) {
450
- parsedAdaptationSet.isDub = true;
451
- }
452
- if (isForcedSubtitle !== undefined) {
453
- parsedAdaptationSet.forcedSubtitles = isForcedSubtitle;
454
- }
455
- if (isSignInterpreted === true) {
456
- parsedAdaptationSet.isSignInterpreted = true;
457
- }
434
+ if (label !== undefined) {
435
+ parsedAdaptationSet.label = label;
436
+ }
458
437
 
459
- if (label !== undefined) {
460
- parsedAdaptationSet.label = label;
461
- }
438
+ if (trickModeAttachedAdaptationIds !== undefined) {
439
+ trickModeAdaptations.push({ adaptation: parsedAdaptationSet,
440
+ trickModeAttachedAdaptationIds });
441
+ } else {
462
442
 
463
- if (trickModeAttachedAdaptationIds !== undefined) {
464
- trickModeAdaptations.push({ adaptation: parsedAdaptationSet,
465
- trickModeAttachedAdaptationIds });
466
- } else {
467
-
468
- // look if we have to merge this into another Adaptation
469
- let mergedIntoIdx = -1;
470
- for (const id of adaptationSetSwitchingIDs) {
471
- const switchingInfos = adaptationSwitchingInfos[id];
472
- if (switchingInfos !== undefined &&
473
- switchingInfos.newID !== newID &&
474
- arrayIncludes(switchingInfos.adaptationSetSwitchingIDs, originalID))
443
+ // look if we have to merge this into another Adaptation
444
+ let mergedIntoIdx = -1;
445
+ for (const id of adaptationSetSwitchingIDs) {
446
+ const switchingInfos = adaptationSwitchingInfos[id];
447
+ if (switchingInfos !== undefined &&
448
+ switchingInfos.newID !== newID &&
449
+ arrayIncludes(switchingInfos.adaptationSetSwitchingIDs, originalID))
450
+ {
451
+ mergedIntoIdx = arrayFindIndex(parsedAdaptations[type],
452
+ (a) => a[0].id === id);
453
+ const mergedInto = parsedAdaptations[type][mergedIntoIdx];
454
+ if (mergedInto !== undefined &&
455
+ mergedInto[0].audioDescription ===
456
+ parsedAdaptationSet.audioDescription &&
457
+ mergedInto[0].closedCaption ===
458
+ parsedAdaptationSet.closedCaption &&
459
+ mergedInto[0].language === parsedAdaptationSet.language)
475
460
  {
476
- mergedIntoIdx = arrayFindIndex(parsedAdaptations[type],
477
- (a) => a[0].id === id);
478
- const mergedInto = parsedAdaptations[type][mergedIntoIdx];
479
- if (mergedInto !== undefined &&
480
- mergedInto[0].audioDescription ===
481
- parsedAdaptationSet.audioDescription &&
482
- mergedInto[0].closedCaption ===
483
- parsedAdaptationSet.closedCaption &&
484
- mergedInto[0].language === parsedAdaptationSet.language)
485
- {
486
- log.info("DASH Parser: merging \"switchable\" AdaptationSets",
487
- originalID, id);
488
- mergedInto[0].representations.push(...parsedAdaptationSet.representations);
489
- if (type === "video" &&
490
- isMainAdaptation &&
491
- !mergedInto[1].isMainAdaptation)
492
- {
493
- lastMainVideoAdapIdx = Math.max(lastMainVideoAdapIdx, mergedIntoIdx);
494
- }
495
- mergedInto[1] = {
496
- priority: Math.max(priority, mergedInto[1].priority),
497
- isMainAdaptation: isMainAdaptation ||
498
- mergedInto[1].isMainAdaptation,
499
- indexInMpd: Math.min(adaptationIdx, mergedInto[1].indexInMpd),
500
- };
501
- }
461
+ log.info("DASH Parser: merging \"switchable\" AdaptationSets",
462
+ originalID, id);
463
+ mergedInto[0].representations.push(...parsedAdaptationSet.representations);
464
+ mergedInto[1] = {
465
+ priority: Math.max(priority, mergedInto[1].priority),
466
+ isMainAdaptation: isMainAdaptation ||
467
+ mergedInto[1].isMainAdaptation,
468
+ indexInMpd: Math.min(adaptationIdx, mergedInto[1].indexInMpd),
469
+ };
502
470
  }
503
471
  }
472
+ }
504
473
 
505
- if (mergedIntoIdx < 0) {
506
- parsedAdaptations[type].push([ parsedAdaptationSet,
507
- { priority,
508
- isMainAdaptation,
509
- indexInMpd: adaptationIdx }]);
510
- if (type === "video" && isMainAdaptation) {
511
- lastMainVideoAdapIdx = parsedAdaptations.video.length - 1;
512
- }
513
- }
474
+ if (mergedIntoIdx < 0) {
475
+ parsedAdaptations[type].push([ parsedAdaptationSet,
476
+ { priority,
477
+ isMainAdaptation,
478
+ indexInMpd: adaptationIdx }]);
514
479
  }
515
480
  }
516
481
 
@@ -66,16 +66,17 @@ function combineInbandEventStreams(
66
66
  */
67
67
  function getHDRInformation(
68
68
  { adaptationProfiles,
69
+ essentialProperties,
70
+ supplementalProperties,
69
71
  manifestProfiles,
70
72
  codecs,
71
73
  }: { adaptationProfiles?: string | undefined;
74
+ essentialProperties? : IScheme[] | undefined;
75
+ supplementalProperties? : IScheme[] | undefined;
72
76
  manifestProfiles?: string | undefined;
73
77
  codecs?: string | undefined; }
74
78
  ): undefined | IHDRInformation {
75
79
  const profiles = (adaptationProfiles ?? "") + (manifestProfiles ?? "");
76
- if (codecs === undefined) {
77
- return undefined;
78
- }
79
80
  if (
80
81
  profiles.indexOf(
81
82
  "http://dashif.org/guidelines/dash-if-uhd#hevc-hdr-pq10") !== -1
@@ -87,7 +88,20 @@ function getHDRInformation(
87
88
  colorSpace: "rec2020" };
88
89
  }
89
90
  }
90
- if (/^vp(08|09|10)/.exec(codecs)) {
91
+ const transferCharacteristicScheme = arrayFind(
92
+ [...(essentialProperties ?? []), ...(supplementalProperties ?? [])],
93
+ (p) => p.schemeIdUri === "urn:mpeg:mpegB:cicp:TransferCharacteristics");
94
+ if (transferCharacteristicScheme !== undefined) {
95
+ switch (transferCharacteristicScheme.value) {
96
+ case "15":
97
+ return undefined; // SDR
98
+ case "16":
99
+ return { eotf: "pq" };
100
+ case "18":
101
+ return { eotf: "hlg" };
102
+ }
103
+ }
104
+ if (codecs !== undefined && /^vp(08|09|10)/.exec(codecs)) {
91
105
  return getWEBMHDRInformation(codecs);
92
106
  }
93
107
  }
@@ -273,6 +287,9 @@ export default function parseRepresentations(
273
287
 
274
288
  parsedRepresentation.hdrInfo =
275
289
  getHDRInformation({ adaptationProfiles: adaptation.attributes.profiles,
290
+ supplementalProperties: adaptation.children
291
+ .supplementalProperties,
292
+ essentialProperties: adaptation.children.essentialProperties,
276
293
  manifestProfiles: context.manifestProfiles,
277
294
  codecs });
278
295
 
@@ -244,6 +244,7 @@ export interface IAdaptation {
244
244
  normalizedLanguage? : string | undefined;
245
245
  isAudioDescription? : boolean | undefined;
246
246
  isClosedCaption? : boolean | undefined;
247
+ isSignInterpreted? : boolean | undefined;
247
248
  isTrickModeTrack? : boolean | undefined;
248
249
  representations : IRepresentation[];
249
250
 
@@ -31,11 +31,9 @@ export default function addSegmentIntegrityChecks<T>(
31
31
  ) : ISegmentLoader<T> {
32
32
  return (url, content, loaderOptions, initialCancelSignal, callbacks) => {
33
33
  return new Promise((resolve, reject) => {
34
- const requestCanceller = new TaskCanceller({ cancelOn: initialCancelSignal });
35
-
36
- // Reject the `CancellationError` when `requestCanceller`'s signal emits
37
- // `stopRejectingOnCancel` here is a function allowing to stop this mechanism
38
- const stopRejectingOnCancel = requestCanceller.signal.register(reject);
34
+ const requestCanceller = new TaskCanceller();
35
+ const unlinkCanceller = requestCanceller.linkToSignal(initialCancelSignal);
36
+ requestCanceller.signal.register(reject);
39
37
 
40
38
  segmentLoader(url, content, loaderOptions, requestCanceller.signal, {
41
39
  ...callbacks,
@@ -45,31 +43,42 @@ export default function addSegmentIntegrityChecks<T>(
45
43
  callbacks.onNewChunk(data);
46
44
  } catch (err) {
47
45
  // Do not reject with a `CancellationError` after cancelling the request
48
- stopRejectingOnCancel();
46
+ cleanUpCancellers();
47
+
49
48
  // Cancel the request
50
49
  requestCanceller.cancel();
50
+
51
51
  // Reject with thrown error
52
52
  reject(err);
53
53
  }
54
54
  },
55
- }).then((info) => {
56
- if (requestCanceller.isUsed) {
57
- return;
58
- }
59
- stopRejectingOnCancel();
60
- if (info.resultType === "segment-loaded") {
61
- try {
62
- trowOnIntegrityError(info.resultData.responseData);
63
- } catch (err) {
55
+ })
56
+ .then(
57
+ (info) => {
58
+ cleanUpCancellers();
59
+ if (requestCanceller.isUsed()) {
60
+ return;
61
+ }
62
+ if (info.resultType === "segment-loaded") {
63
+ try {
64
+ trowOnIntegrityError(info.resultData.responseData);
65
+ } catch (err) {
66
+ reject(err);
67
+ return;
68
+ }
69
+ }
70
+ resolve(info);
71
+ },
72
+ (err : unknown) => {
73
+ cleanUpCancellers();
64
74
  reject(err);
65
- return;
66
75
  }
67
- }
68
- resolve(info);
69
- }, (error : unknown) => {
70
- stopRejectingOnCancel();
71
- reject(error);
72
- });
76
+ );
77
+
78
+ function cleanUpCancellers() {
79
+ requestCanceller.signal.deregister(reject);
80
+ unlinkCanceller();
81
+ }
73
82
  });
74
83
 
75
84
  /**
@@ -65,14 +65,14 @@ export default function lowLatencySegmentLoader(
65
65
  partialChunk = res[1];
66
66
  for (let i = 0; i < completeChunks.length; i++) {
67
67
  callbacks.onNewChunk(completeChunks[i]);
68
- if (cancelSignal.isCancelled) {
68
+ if (cancelSignal.isCancelled()) {
69
69
  return;
70
70
  }
71
71
  }
72
72
  callbacks.onProgress({ duration: info.duration,
73
73
  size: info.size,
74
74
  totalSize: info.totalSize });
75
- if (cancelSignal.isCancelled) {
75
+ if (cancelSignal.isCancelled()) {
76
76
  return;
77
77
  }
78
78
  }
@@ -139,7 +139,7 @@ export default function generateManifestParser(
139
139
  if (parserResponse.value.warnings.length > 0) {
140
140
  onWarnings(parserResponse.value.warnings);
141
141
  }
142
- if (cancelSignal.isCancelled) {
142
+ if (cancelSignal.isCancelled()) {
143
143
  return Promise.reject(cancelSignal.cancellationError);
144
144
  }
145
145
  const manifest = new Manifest(parserResponse.value.parsed, options);
@@ -156,7 +156,7 @@ export default function generateSegmentLoader(
156
156
  size? : number | undefined;
157
157
  duration? : number | undefined; }
158
158
  ) => {
159
- if (hasFinished || cancelSignal.isCancelled) {
159
+ if (hasFinished || cancelSignal.isCancelled()) {
160
160
  return;
161
161
  }
162
162
  hasFinished = true;
@@ -172,7 +172,7 @@ export default function generateSegmentLoader(
172
172
  * @param {*} err - The corresponding error encountered
173
173
  */
174
174
  const reject = (err : unknown) : void => {
175
- if (hasFinished || cancelSignal.isCancelled) {
175
+ if (hasFinished || cancelSignal.isCancelled()) {
176
176
  return;
177
177
  }
178
178
  hasFinished = true;
@@ -198,7 +198,7 @@ export default function generateSegmentLoader(
198
198
  size : number;
199
199
  totalSize? : number | undefined; }
200
200
  ) => {
201
- if (hasFinished || cancelSignal.isCancelled) {
201
+ if (hasFinished || cancelSignal.isCancelled()) {
202
202
  return;
203
203
  }
204
204
  callbacks.onProgress({ duration: _args.duration,
@@ -211,7 +211,7 @@ export default function generateSegmentLoader(
211
211
  * the "regular" implementation
212
212
  */
213
213
  const fallback = () => {
214
- if (hasFinished || cancelSignal.isCancelled) {
214
+ if (hasFinished || cancelSignal.isCancelled()) {
215
215
  return;
216
216
  }
217
217
  hasFinished = true;
@@ -20,11 +20,9 @@ import {
20
20
  ILocalManifestInitSegmentLoader,
21
21
  ILocalManifestSegmentLoader,
22
22
  } from "../../parsers/manifest/local";
23
+ import createCancellablePromise from "../../utils/create_cancellable_promise";
23
24
  import isNullOrUndefined from "../../utils/is_null_or_undefined";
24
- import {
25
- CancellationError,
26
- CancellationSignal,
27
- } from "../../utils/task_canceller";
25
+ import { CancellationSignal } from "../../utils/task_canceller";
28
26
  import {
29
27
  ISegmentContext,
30
28
  ISegmentLoaderCallbacks,
@@ -41,7 +39,7 @@ function loadInitSegment(
41
39
  customSegmentLoader : ILocalManifestInitSegmentLoader,
42
40
  cancelSignal : CancellationSignal
43
41
  ) : Promise<ISegmentLoaderResultSegmentLoaded<ArrayBuffer | null>> {
44
- return new Promise((res, rej) => {
42
+ return createCancellablePromise(cancelSignal, (res, rej) => {
45
43
  /** `true` when the custom segmentLoader should not be active anymore. */
46
44
  let hasFinished = false;
47
45
 
@@ -54,11 +52,10 @@ function loadInitSegment(
54
52
  size? : number;
55
53
  duration? : number;
56
54
  }) => {
57
- if (hasFinished || cancelSignal.isCancelled) {
55
+ if (hasFinished || cancelSignal.isCancelled()) {
58
56
  return;
59
57
  }
60
58
  hasFinished = true;
61
- cancelSignal.deregister(abortLoader);
62
59
  res({ resultType: "segment-loaded",
63
60
  resultData: { responseData: _args.data,
64
61
  size: _args.size,
@@ -70,22 +67,17 @@ function loadInitSegment(
70
67
  * @param {*} err - The corresponding error encountered
71
68
  */
72
69
  const reject = (err? : Error) => {
73
- if (hasFinished || cancelSignal.isCancelled) {
70
+ if (hasFinished || cancelSignal.isCancelled()) {
74
71
  return;
75
72
  }
76
73
  hasFinished = true;
77
- cancelSignal.deregister(abortLoader);
78
74
  rej(err);
79
75
  };
80
76
 
81
77
  const abort = customSegmentLoader({ resolve, reject });
82
78
 
83
- cancelSignal.register(abortLoader);
84
- /**
85
- * The logic to run when this loader is cancelled while pending.
86
- * @param {Error} err
87
- */
88
- function abortLoader(err : CancellationError) {
79
+ /** The logic to run when this loader is cancelled while pending. */
80
+ return () => {
89
81
  if (hasFinished) {
90
82
  return;
91
83
  }
@@ -93,8 +85,7 @@ function loadInitSegment(
93
85
  if (typeof abort === "function") {
94
86
  abort();
95
87
  }
96
- rej(err);
97
- }
88
+ };
98
89
  });
99
90
  }
100
91
 
@@ -109,7 +100,7 @@ function loadSegment(
109
100
  customSegmentLoader : ILocalManifestSegmentLoader,
110
101
  cancelSignal : CancellationSignal
111
102
  ) : Promise< ISegmentLoaderResultSegmentLoaded<ArrayBuffer | null>> {
112
- return new Promise((res, rej) => {
103
+ return createCancellablePromise(cancelSignal, (res, rej) => {
113
104
  /** `true` when the custom segmentLoader should not be active anymore. */
114
105
  let hasFinished = false;
115
106
 
@@ -122,11 +113,10 @@ function loadSegment(
122
113
  size? : number;
123
114
  duration? : number;
124
115
  }) => {
125
- if (hasFinished || cancelSignal.isCancelled) {
116
+ if (hasFinished || cancelSignal.isCancelled()) {
126
117
  return;
127
118
  }
128
119
  hasFinished = true;
129
- cancelSignal.deregister(abortLoader);
130
120
  res({ resultType: "segment-loaded",
131
121
  resultData: { responseData: _args.data,
132
122
  size: _args.size,
@@ -138,11 +128,10 @@ function loadSegment(
138
128
  * @param {*} err - The corresponding error encountered
139
129
  */
140
130
  const reject = (err? : Error) => {
141
- if (hasFinished || cancelSignal.isCancelled) {
131
+ if (hasFinished || cancelSignal.isCancelled()) {
142
132
  return;
143
133
  }
144
134
  hasFinished = true;
145
- cancelSignal.deregister(abortLoader);
146
135
 
147
136
  // Format error and send it
148
137
  const castedErr = err as (null | undefined | { message? : string;
@@ -161,12 +150,8 @@ function loadSegment(
161
150
 
162
151
  const abort = customSegmentLoader(segment, { resolve, reject });
163
152
 
164
- cancelSignal.register(abortLoader);
165
- /**
166
- * The logic to run when this loader is cancelled while pending.
167
- * @param {Error} err
168
- */
169
- function abortLoader(err : CancellationError) {
153
+ /** The logic to run when this loader is cancelled while pending. */
154
+ return () => {
170
155
  if (hasFinished) {
171
156
  return;
172
157
  }
@@ -174,8 +159,7 @@ function loadSegment(
174
159
  if (typeof abort === "function") {
175
160
  abort();
176
161
  }
177
- rej(err);
178
- }
162
+ };
179
163
  });
180
164
  }
181
165
 
@@ -185,7 +185,7 @@ const generateSegmentLoader = ({
185
185
  size? : number | undefined;
186
186
  duration? : number | undefined;
187
187
  }) => {
188
- if (hasFinished || cancelSignal.isCancelled) {
188
+ if (hasFinished || cancelSignal.isCancelled()) {
189
189
  return;
190
190
  }
191
191
  hasFinished = true;
@@ -213,7 +213,7 @@ const generateSegmentLoader = ({
213
213
  * @param {*} err - The corresponding error encountered
214
214
  */
215
215
  const reject = (err : unknown) => {
216
- if (hasFinished || cancelSignal.isCancelled) {
216
+ if (hasFinished || cancelSignal.isCancelled()) {
217
217
  return;
218
218
  }
219
219
  hasFinished = true;
@@ -239,7 +239,7 @@ const generateSegmentLoader = ({
239
239
  size : number;
240
240
  totalSize? : number | undefined; }
241
241
  ) => {
242
- if (hasFinished || cancelSignal.isCancelled) {
242
+ if (hasFinished || cancelSignal.isCancelled()) {
243
243
  return;
244
244
  }
245
245
  callbacks.onProgress({ duration: _args.duration,
@@ -248,7 +248,7 @@ const generateSegmentLoader = ({
248
248
  };
249
249
 
250
250
  const fallback = () => {
251
- if (hasFinished || cancelSignal.isCancelled) {
251
+ if (hasFinished || cancelSignal.isCancelled()) {
252
252
  return;
253
253
  }
254
254
  hasFinished = true;