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.
- package/CHANGELOG.md +40 -0
- package/CONTRIBUTING.md +48 -168
- package/FILES.md +40 -92
- package/VERSION +1 -1
- package/dist/_esm5.processed/compat/browser_detection.d.ts +3 -1
- package/dist/_esm5.processed/compat/browser_detection.js +7 -2
- package/dist/_esm5.processed/compat/eme/load_session.js +1 -1
- package/dist/_esm5.processed/compat/has_issues_with_high_media_source_duration.d.ts +21 -0
- package/dist/_esm5.processed/compat/has_issues_with_high_media_source_duration.js +26 -0
- package/dist/_esm5.processed/config.d.ts +2 -0
- package/dist/_esm5.processed/core/adaptive/adaptive_representation_selector.js +5 -4
- package/dist/_esm5.processed/core/adaptive/buffer_based_chooser.d.ts +18 -1
- package/dist/_esm5.processed/core/adaptive/buffer_based_chooser.js +106 -25
- package/dist/_esm5.processed/core/adaptive/guess_based_chooser.js +6 -6
- package/dist/_esm5.processed/core/adaptive/network_analyzer.js +8 -5
- package/dist/_esm5.processed/core/adaptive/utils/representation_score_calculator.d.ts +19 -1
- package/dist/_esm5.processed/core/adaptive/utils/representation_score_calculator.js +1 -1
- package/dist/_esm5.processed/core/api/debug/render.js +1 -1
- package/dist/_esm5.processed/core/api/playback_observer.js +1 -0
- package/dist/_esm5.processed/core/api/public_api.d.ts +54 -1
- package/dist/_esm5.processed/core/api/public_api.js +232 -35
- package/dist/_esm5.processed/core/api/track_management/media_element_tracks_store.js +10 -1
- package/dist/_esm5.processed/core/api/track_management/track_dispatcher.d.ts +13 -1
- package/dist/_esm5.processed/core/api/track_management/track_dispatcher.js +30 -15
- package/dist/_esm5.processed/core/api/track_management/tracks_store.d.ts +3 -1
- package/dist/_esm5.processed/core/api/track_management/tracks_store.js +67 -152
- package/dist/_esm5.processed/core/api/utils.d.ts +10 -0
- package/dist/_esm5.processed/core/api/utils.js +20 -0
- package/dist/_esm5.processed/core/decrypt/session_events_listener.js +7 -1
- package/dist/_esm5.processed/core/decrypt/utils/clean_old_loaded_sessions.js +2 -0
- package/dist/_esm5.processed/core/decrypt/utils/loaded_sessions_store.js +5 -1
- package/dist/_esm5.processed/core/init/directfile_content_initializer.js +1 -1
- package/dist/_esm5.processed/core/init/media_source_content_initializer.js +47 -10
- package/dist/_esm5.processed/core/init/types.d.ts +9 -1
- package/dist/_esm5.processed/core/init/utils/content_time_boundaries_observer.d.ts +28 -1
- package/dist/_esm5.processed/core/init/utils/content_time_boundaries_observer.js +22 -9
- package/dist/_esm5.processed/core/init/utils/media_source_duration_updater.d.ts +58 -0
- package/dist/_esm5.processed/core/init/utils/{media_duration_updater.js → media_source_duration_updater.js} +84 -87
- package/dist/_esm5.processed/core/init/utils/rebuffering_controller.d.ts +36 -2
- package/dist/_esm5.processed/core/init/utils/rebuffering_controller.js +82 -2
- package/dist/_esm5.processed/core/segment_buffers/implementations/audio_video/audio_video_segment_buffer.d.ts +18 -7
- package/dist/_esm5.processed/core/segment_buffers/implementations/audio_video/audio_video_segment_buffer.js +31 -40
- package/dist/_esm5.processed/core/segment_buffers/implementations/text/html/html_text_segment_buffer.d.ts +8 -0
- package/dist/_esm5.processed/core/segment_buffers/implementations/text/html/html_text_segment_buffer.js +12 -0
- package/dist/_esm5.processed/core/segment_buffers/implementations/text/native/native_text_segment_buffer.d.ts +8 -0
- package/dist/_esm5.processed/core/segment_buffers/implementations/text/native/native_text_segment_buffer.js +12 -0
- package/dist/_esm5.processed/core/segment_buffers/implementations/types.d.ts +11 -4
- package/dist/_esm5.processed/core/segment_buffers/index.d.ts +2 -2
- package/dist/_esm5.processed/core/stream/adaptation/utils/create_representation_estimator.d.ts +47 -0
- package/dist/_esm5.processed/core/stream/adaptation/utils/create_representation_estimator.js +70 -0
- package/dist/_esm5.processed/core/stream/orchestrator/stream_orchestrator.js +15 -8
- package/dist/_esm5.processed/core/stream/period/period_stream.js +1 -1
- package/dist/_esm5.processed/core/stream/representation/representation_stream.js +22 -13
- package/dist/_esm5.processed/core/stream/representation/utils/append_segment_to_buffer.d.ts +4 -2
- package/dist/_esm5.processed/core/stream/representation/utils/append_segment_to_buffer.js +2 -2
- package/dist/_esm5.processed/core/stream/representation/utils/push_init_segment.d.ts +3 -2
- package/dist/_esm5.processed/core/stream/representation/utils/push_init_segment.js +8 -8
- package/dist/_esm5.processed/core/stream/representation/utils/push_media_segment.d.ts +2 -2
- package/dist/_esm5.processed/core/stream/representation/utils/push_media_segment.js +2 -3
- package/dist/_esm5.processed/default_config.d.ts +25 -0
- package/dist/_esm5.processed/default_config.js +27 -2
- package/dist/_esm5.processed/errors/index.d.ts +2 -2
- package/dist/_esm5.processed/errors/media_error.d.ts +23 -1
- package/dist/_esm5.processed/errors/media_error.js +18 -5
- package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/load_and_push_segment.d.ts +1 -1
- package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/load_and_push_segment.js +8 -7
- package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/video_thumbnail_loader.js +17 -9
- package/dist/_esm5.processed/experimental/tools/mediaCapabilitiesProber/index.js +0 -2
- package/dist/_esm5.processed/manifest/adaptation.d.ts +21 -2
- package/dist/_esm5.processed/manifest/adaptation.js +76 -1
- package/dist/_esm5.processed/manifest/manifest.js +1 -1
- package/dist/_esm5.processed/manifest/period.js +2 -2
- package/dist/_esm5.processed/manifest/representation.d.ts +33 -2
- package/dist/_esm5.processed/manifest/representation.js +21 -0
- package/dist/_esm5.processed/manifest/utils.js +1 -3
- package/dist/_esm5.processed/parsers/manifest/dash/js-parser/parse_from_document.d.ts +1 -1
- package/dist/_esm5.processed/parsers/manifest/dash/js-parser/parse_from_document.js +1 -1
- package/dist/_esm5.processed/parsers/manifest/dash/wasm-parser/ts/dash-wasm-parser.js +1 -0
- package/dist/_esm5.processed/public_types.d.ts +13 -3
- package/dist/_esm5.processed/tools/TextTrackRenderer/text_track_renderer.js +1 -1
- package/dist/_esm5.processed/transports/smooth/isobmff/create_boxes.d.ts +4 -6
- package/dist/_esm5.processed/transports/smooth/isobmff/create_boxes.js +4 -6
- package/dist/_esm5.processed/utils/is_null_or_undefined.d.ts +1 -1
- package/dist/_esm5.processed/utils/is_null_or_undefined.js +1 -1
- package/dist/mpd-parser.wasm +0 -0
- package/dist/rx-player.js +4709 -4218
- package/dist/rx-player.min.js +1 -1
- package/package.json +42 -36
- package/scripts/build/generate_build.js +1 -1
- package/scripts/fast_demo_build.js +4 -3
- package/scripts/generate_full_demo.js +1 -1
- package/sonar-project.properties +1 -1
- package/src/compat/browser_detection.ts +7 -1
- package/src/compat/eme/load_session.ts +1 -1
- package/src/compat/has_issues_with_high_media_source_duration.ts +27 -0
- package/src/core/adaptive/__tests__/buffer_based_chooser.test.ts +147 -48
- package/src/core/adaptive/adaptive_representation_selector.ts +7 -4
- package/src/core/adaptive/buffer_based_chooser.ts +144 -26
- package/src/core/adaptive/guess_based_chooser.ts +9 -8
- package/src/core/adaptive/network_analyzer.ts +9 -4
- package/src/core/adaptive/utils/representation_score_calculator.ts +22 -2
- package/src/core/api/debug/render.ts +1 -1
- package/src/core/api/playback_observer.ts +1 -0
- package/src/core/api/public_api.ts +277 -44
- package/src/core/api/track_management/media_element_tracks_store.ts +17 -8
- package/src/core/api/track_management/track_dispatcher.ts +37 -14
- package/src/core/api/track_management/tracks_store.ts +77 -167
- package/src/core/api/utils.ts +26 -0
- package/src/core/decrypt/session_events_listener.ts +6 -1
- package/src/core/decrypt/utils/clean_old_loaded_sessions.ts +2 -1
- package/src/core/decrypt/utils/loaded_sessions_store.ts +8 -1
- package/src/core/init/directfile_content_initializer.ts +1 -0
- package/src/core/init/media_source_content_initializer.ts +52 -9
- package/src/core/init/types.ts +9 -1
- package/src/core/init/utils/content_time_boundaries_observer.ts +46 -10
- package/src/core/init/utils/{media_duration_updater.ts → media_source_duration_updater.ts} +100 -112
- package/src/core/init/utils/rebuffering_controller.ts +114 -3
- package/src/core/segment_buffers/implementations/audio_video/audio_video_segment_buffer.ts +56 -55
- package/src/core/segment_buffers/implementations/text/html/html_text_segment_buffer.ts +16 -0
- package/src/core/segment_buffers/implementations/text/native/native_text_segment_buffer.ts +16 -0
- package/src/core/segment_buffers/implementations/types.ts +16 -4
- package/src/core/segment_buffers/index.ts +2 -0
- package/src/core/stream/adaptation/utils/create_representation_estimator.ts +114 -0
- package/src/core/stream/orchestrator/stream_orchestrator.ts +16 -8
- package/src/core/stream/period/period_stream.ts +2 -1
- package/src/core/stream/representation/representation_stream.ts +34 -22
- package/src/core/stream/representation/utils/append_segment_to_buffer.ts +8 -3
- package/src/core/stream/representation/utils/push_init_segment.ts +11 -6
- package/src/core/stream/representation/utils/push_media_segment.ts +3 -3
- package/src/default_config.ts +29 -2
- package/src/errors/__tests__/media_error.test.ts +6 -6
- package/src/errors/index.ts +4 -1
- package/src/errors/media_error.ts +67 -1
- package/src/experimental/tools/VideoThumbnailLoader/load_and_push_segment.ts +10 -7
- package/src/experimental/tools/VideoThumbnailLoader/video_thumbnail_loader.ts +17 -6
- package/src/experimental/tools/mediaCapabilitiesProber/index.ts +0 -4
- package/src/manifest/__tests__/manifest.test.ts +7 -7
- package/src/manifest/__tests__/period.test.ts +90 -45
- package/src/manifest/adaptation.ts +89 -1
- package/src/manifest/manifest.ts +1 -1
- package/src/manifest/period.ts +4 -2
- package/src/manifest/representation.ts +67 -1
- package/src/manifest/utils.ts +1 -3
- package/src/parsers/manifest/dash/js-parser/parse_from_document.ts +1 -1
- package/src/parsers/manifest/dash/wasm-parser/ts/dash-wasm-parser.ts +1 -0
- package/src/parsers/texttracks/ttml/parse_ttml.ts +1 -1
- package/src/public_types.ts +16 -1
- package/src/tools/TextTrackRenderer/text_track_renderer.ts +1 -1
- package/src/transports/smooth/isobmff/create_boxes.ts +4 -6
- package/src/typings/globals.d.ts +20 -20
- package/src/utils/is_null_or_undefined.ts +1 -1
- package/dist/_esm5.processed/core/init/utils/media_duration_updater.d.ts +0 -56
- package/scripts/doc-generator/construct_table_of_contents.js +0 -76
- package/scripts/doc-generator/convert_MD_to_HMTL.js +0 -26
- package/scripts/doc-generator/create_documentation.js +0 -331
- package/scripts/doc-generator/create_documentation_page.js +0 -209
- package/scripts/doc-generator/create_page.js +0 -210
- package/scripts/doc-generator/generate_header_html.js +0 -147
- package/scripts/doc-generator/generate_page_html.js +0 -115
- package/scripts/doc-generator/generate_page_list_html.js +0 -92
- package/scripts/doc-generator/generate_sidebar_html.js +0 -85
- package/scripts/doc-generator/get_search_data_for_content.js +0 -137
- package/scripts/doc-generator/index.js +0 -34
- package/scripts/doc-generator/parse_doc_configs.js +0 -327
- package/scripts/doc-generator/scripts/lunr.js +0 -10
- package/scripts/doc-generator/scripts/script.js +0 -451
- package/scripts/doc-generator/styles/code.css +0 -99
- package/scripts/doc-generator/styles/style.css +0 -835
- 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
|
-
|
|
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> = {
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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 = {
|
|
86
|
+
const data = { initSegmentUniqueId,
|
|
87
87
|
chunk: chunkData,
|
|
88
88
|
timestampOffset: chunkOffset,
|
|
89
89
|
appendWindow: safeAppendWindow,
|
package/src/default_config.ts
CHANGED
|
@@ -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.
|
|
416
|
-
LOW_LATENCY: 0.
|
|
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("
|
|
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("
|
|
26
|
+
expect(mediaError.code).toBe("MEDIA_TIME_BEFORE_MANIFEST");
|
|
27
27
|
expect(mediaError.fatal).toBe(false);
|
|
28
|
-
expect(mediaError.message).toBe("MediaError (
|
|
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("
|
|
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("
|
|
38
|
+
expect(mediaError.code).toBe("MEDIA_TIME_AFTER_MANIFEST");
|
|
39
39
|
expect(mediaError.fatal).toBe(true);
|
|
40
|
-
expect(mediaError.message).toBe("MediaError (
|
|
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", () => {
|
package/src/errors/index.ts
CHANGED
|
@@ -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
|
|
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(
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
55
|
+
isInitSegment = false;
|
|
52
56
|
data = parsed.chunkData;
|
|
53
57
|
timestampOffset = parsed.chunkOffset;
|
|
54
58
|
}
|
|
55
59
|
const pushOperation = segmentBuffer.pushChunk({
|
|
56
|
-
data: {
|
|
57
|
-
|
|
58
|
-
|
|
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
|
|
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
|
-
|
|
189
|
+
lastRepInfoCleaner.signal
|
|
186
190
|
).then(async (segmentBuffer) => {
|
|
187
|
-
|
|
188
|
-
|
|
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
|
-
|
|
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 {
|
|
@@ -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).
|
|
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).
|
|
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).
|
|
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).
|
|
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).
|
|
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).
|
|
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).
|
|
422
|
+
expect(fakeIdGenerator).toHaveBeenCalled();
|
|
423
423
|
expect(fakeGenerateNewId).toHaveBeenCalledTimes(1);
|
|
424
424
|
expect(fakeLogger.info).not.toHaveBeenCalled();
|
|
425
425
|
expect(fakeLogger.warn).not.toHaveBeenCalled();
|