rx-player 3.28.0 → 3.28.1-dev.2022083000
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/.github/workflows/checks.yml +20 -18
- package/CHANGELOG.md +11 -0
- package/VERSION +1 -1
- package/dist/_esm5.processed/compat/eme/load_session.d.ts +5 -6
- package/dist/_esm5.processed/compat/eme/load_session.js +5 -6
- package/dist/_esm5.processed/core/api/public_api.js +2 -2
- package/dist/_esm5.processed/core/decrypt/create_session.js +33 -4
- package/dist/_esm5.processed/core/decrypt/utils/loaded_sessions_store.d.ts +14 -0
- package/dist/_esm5.processed/core/decrypt/utils/loaded_sessions_store.js +25 -0
- package/dist/_esm5.processed/core/fetchers/segment/segment_fetcher.d.ts +1 -1
- package/dist/_esm5.processed/core/fetchers/segment/segment_fetcher.js +1 -1
- package/dist/_esm5.processed/core/init/content_time_boundaries_observer.js +110 -38
- package/dist/_esm5.processed/core/stream/representation/check_for_discontinuity.js +21 -9
- package/dist/_esm5.processed/core/stream/representation/get_buffer_status.js +21 -29
- package/dist/_esm5.processed/errors/encrypted_media_error.d.ts +1 -2
- package/dist/_esm5.processed/errors/encrypted_media_error.js +0 -1
- package/dist/_esm5.processed/errors/error_codes.d.ts +6 -1
- package/dist/_esm5.processed/errors/media_error.d.ts +1 -2
- package/dist/_esm5.processed/errors/media_error.js +0 -1
- package/dist/_esm5.processed/errors/network_error.d.ts +1 -2
- package/dist/_esm5.processed/errors/network_error.js +0 -1
- package/dist/_esm5.processed/errors/other_error.d.ts +1 -2
- package/dist/_esm5.processed/errors/other_error.js +0 -1
- package/dist/_esm5.processed/manifest/manifest.d.ts +1 -1
- package/dist/_esm5.processed/manifest/manifest.js +1 -1
- package/dist/_esm5.processed/manifest/representation_index/static.d.ts +21 -6
- package/dist/_esm5.processed/manifest/representation_index/static.js +26 -8
- package/dist/_esm5.processed/manifest/representation_index/types.d.ts +55 -44
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/base.d.ts +21 -8
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/base.js +25 -10
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/list.d.ts +26 -12
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/list.js +26 -13
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/template.d.ts +23 -7
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/template.js +65 -22
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/timeline/timeline_representation_index.d.ts +20 -3
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/timeline/timeline_representation_index.js +57 -7
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/{is_period_fulfilled.d.ts → utils.d.ts} +3 -6
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/{is_period_fulfilled.js → utils.js} +4 -8
- package/dist/_esm5.processed/parsers/manifest/dash/common/parse_periods.js +1 -1
- package/dist/_esm5.processed/parsers/manifest/local/parse_local_manifest.js +5 -8
- package/dist/_esm5.processed/parsers/manifest/local/representation_index.d.ts +21 -8
- package/dist/_esm5.processed/parsers/manifest/local/representation_index.js +49 -14
- package/dist/_esm5.processed/parsers/manifest/local/types.d.ts +16 -0
- package/dist/_esm5.processed/parsers/manifest/metaplaylist/representation_index.d.ts +20 -6
- package/dist/_esm5.processed/parsers/manifest/metaplaylist/representation_index.js +28 -10
- package/dist/_esm5.processed/parsers/manifest/smooth/create_parser.js +4 -4
- package/dist/_esm5.processed/parsers/manifest/smooth/representation_index.d.ts +21 -12
- package/dist/_esm5.processed/parsers/manifest/smooth/representation_index.js +39 -14
- package/dist/_esm5.processed/parsers/manifest/utils/get_first_time_from_adaptation.js +1 -1
- package/dist/_esm5.processed/parsers/manifest/utils/get_last_time_from_adaptation.js +1 -1
- package/dist/_esm5.processed/transports/metaplaylist/pipelines.js +0 -2
- package/dist/_esm5.processed/transports/smooth/segment_loader.js +1 -1
- package/dist/_esm5.processed/transports/types.d.ts +1 -1
- package/dist/_esm5.processed/utils/deep_merge.d.ts +1 -1
- package/dist/_esm5.processed/utils/deep_merge.js +6 -5
- package/dist/_esm5.processed/utils/task_canceller.d.ts +0 -3
- package/dist/_esm5.processed/utils/task_canceller.js +0 -3
- package/dist/mpd-parser.wasm +0 -0
- package/dist/rx-player.js +1382 -1058
- package/dist/rx-player.min.js +1 -1
- package/jest.config.js +5 -0
- package/package.json +31 -30
- package/sonar-project.properties +1 -1
- package/src/compat/eme/load_session.ts +5 -6
- package/src/core/api/public_api.ts +2 -2
- package/src/core/decrypt/create_session.ts +28 -2
- package/src/core/decrypt/utils/loaded_sessions_store.ts +29 -0
- package/src/core/fetchers/segment/segment_fetcher.ts +1 -1
- package/src/core/init/content_time_boundaries_observer.ts +116 -42
- package/src/core/stream/representation/check_for_discontinuity.ts +28 -10
- package/src/core/stream/representation/get_buffer_status.ts +27 -34
- package/src/errors/encrypted_media_error.ts +1 -2
- package/src/errors/error_codes.ts +2 -2
- package/src/errors/media_error.ts +1 -2
- package/src/errors/network_error.ts +1 -2
- package/src/errors/other_error.ts +1 -2
- package/src/manifest/__tests__/adaptation.test.ts +4 -3
- package/src/manifest/__tests__/representation.test.ts +4 -3
- package/src/manifest/manifest.ts +1 -1
- package/src/manifest/representation_index/__tests__/static.test.ts +5 -4
- package/src/manifest/representation_index/static.ts +28 -9
- package/src/manifest/representation_index/types.ts +62 -46
- package/src/parsers/manifest/dash/common/indexes/base.ts +27 -11
- package/src/parsers/manifest/dash/common/indexes/list.ts +32 -15
- package/src/parsers/manifest/dash/common/indexes/template.ts +73 -27
- package/src/parsers/manifest/dash/common/indexes/timeline/timeline_representation_index.ts +60 -8
- package/src/parsers/manifest/dash/common/indexes/{is_period_fulfilled.ts → utils.ts} +4 -13
- package/src/parsers/manifest/dash/common/parse_periods.ts +1 -1
- package/src/parsers/manifest/local/parse_local_manifest.ts +8 -20
- package/src/parsers/manifest/local/representation_index.ts +51 -16
- package/src/parsers/manifest/local/types.ts +13 -0
- package/src/parsers/manifest/metaplaylist/representation_index.ts +31 -11
- package/src/parsers/manifest/smooth/create_parser.ts +4 -4
- package/src/parsers/manifest/smooth/representation_index.ts +40 -15
- package/src/parsers/manifest/utils/__tests__/get_first_time_from_adaptations.test.ts +4 -3
- package/src/parsers/manifest/utils/__tests__/get_last_time_from_adaptation.test.ts +4 -3
- package/src/parsers/manifest/utils/get_first_time_from_adaptation.ts +1 -1
- package/src/parsers/manifest/utils/get_last_time_from_adaptation.ts +1 -1
- package/src/transports/metaplaylist/pipelines.ts +0 -2
- package/src/transports/smooth/segment_loader.ts +1 -1
- package/src/transports/types.ts +1 -1
- package/src/utils/__tests__/initialization_segment_cache.test.ts +7 -0
- package/src/utils/deep_merge.ts +7 -4
- package/src/utils/task_canceller.ts +0 -3
|
@@ -28,7 +28,7 @@ import errorMessage from "./error_message";
|
|
|
28
28
|
*/
|
|
29
29
|
export default class EncryptedMediaError extends Error {
|
|
30
30
|
public readonly name : "EncryptedMediaError";
|
|
31
|
-
public readonly type :
|
|
31
|
+
public readonly type : "ENCRYPTED_MEDIA_ERROR";
|
|
32
32
|
public readonly code : IEncryptedMediaErrorCode;
|
|
33
33
|
public message : string;
|
|
34
34
|
public fatal : boolean;
|
|
@@ -36,7 +36,6 @@ export default class EncryptedMediaError extends Error {
|
|
|
36
36
|
/**
|
|
37
37
|
* @param {string} code
|
|
38
38
|
* @param {string} reason
|
|
39
|
-
* @Param {Boolean} fatal
|
|
40
39
|
*/
|
|
41
40
|
constructor(code : IEncryptedMediaErrorCode, reason : string) {
|
|
42
41
|
super();
|
|
@@ -74,12 +74,12 @@ export type INetworkErrorType = "TIMEOUT" |
|
|
|
74
74
|
"PARSE_ERROR" |
|
|
75
75
|
"ERROR_HTTP_CODE";
|
|
76
76
|
|
|
77
|
-
const ErrorTypes
|
|
77
|
+
const ErrorTypes = {
|
|
78
78
|
NETWORK_ERROR: "NETWORK_ERROR",
|
|
79
79
|
MEDIA_ERROR: "MEDIA_ERROR",
|
|
80
80
|
ENCRYPTED_MEDIA_ERROR: "ENCRYPTED_MEDIA_ERROR",
|
|
81
81
|
OTHER_ERROR: "OTHER_ERROR",
|
|
82
|
-
};
|
|
82
|
+
} as const;
|
|
83
83
|
|
|
84
84
|
const NetworkErrorTypes : Record<INetworkErrorType, INetworkErrorType> = {
|
|
85
85
|
TIMEOUT: "TIMEOUT",
|
|
@@ -28,7 +28,7 @@ import errorMessage from "./error_message";
|
|
|
28
28
|
*/
|
|
29
29
|
export default class MediaError extends Error {
|
|
30
30
|
public readonly name : "MediaError";
|
|
31
|
-
public readonly type :
|
|
31
|
+
public readonly type : "MEDIA_ERROR";
|
|
32
32
|
public readonly message : string;
|
|
33
33
|
public readonly code : IMediaErrorCode;
|
|
34
34
|
public fatal : boolean;
|
|
@@ -36,7 +36,6 @@ export default class MediaError extends Error {
|
|
|
36
36
|
/**
|
|
37
37
|
* @param {string} code
|
|
38
38
|
* @param {string} reason
|
|
39
|
-
* @param {Boolean} fatal
|
|
40
39
|
*/
|
|
41
40
|
constructor(code : IMediaErrorCode, reason : string) {
|
|
42
41
|
super();
|
|
@@ -31,7 +31,7 @@ import RequestError from "./request_error";
|
|
|
31
31
|
*/
|
|
32
32
|
export default class NetworkError extends Error {
|
|
33
33
|
public readonly name : "NetworkError";
|
|
34
|
-
public readonly type :
|
|
34
|
+
public readonly type : "NETWORK_ERROR";
|
|
35
35
|
public readonly message : string;
|
|
36
36
|
public readonly code : INetworkErrorCode;
|
|
37
37
|
public readonly xhr : XMLHttpRequest | null;
|
|
@@ -43,7 +43,6 @@ export default class NetworkError extends Error {
|
|
|
43
43
|
/**
|
|
44
44
|
* @param {string} code
|
|
45
45
|
* @param {Error} baseError
|
|
46
|
-
* @param {Boolean} fatal
|
|
47
46
|
*/
|
|
48
47
|
constructor(code : INetworkErrorCode, baseError : RequestError) {
|
|
49
48
|
super();
|
|
@@ -26,7 +26,7 @@ import errorMessage from "./error_message";
|
|
|
26
26
|
*/
|
|
27
27
|
export default class OtherError extends Error {
|
|
28
28
|
public readonly name : "OtherError";
|
|
29
|
-
public readonly type :
|
|
29
|
+
public readonly type : "OTHER_ERROR";
|
|
30
30
|
public readonly message : string;
|
|
31
31
|
public readonly code : IOtherErrorCode;
|
|
32
32
|
public fatal : boolean;
|
|
@@ -34,7 +34,6 @@ export default class OtherError extends Error {
|
|
|
34
34
|
/**
|
|
35
35
|
* @param {string} code
|
|
36
36
|
* @param {string} reason
|
|
37
|
-
* @param {Boolean} fatal
|
|
38
37
|
*/
|
|
39
38
|
constructor(code : IOtherErrorCode, reason : string) {
|
|
40
39
|
super();
|
|
@@ -28,13 +28,14 @@ const minimalRepresentationIndex = {
|
|
|
28
28
|
getInitSegment() { return null; },
|
|
29
29
|
getSegments() { return []; },
|
|
30
30
|
shouldRefresh() { return false; },
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
getFirstAvailablePosition() : undefined { return ; },
|
|
32
|
+
getLastAvailablePosition() : undefined { return ; },
|
|
33
|
+
getEnd() : undefined { return ; },
|
|
33
34
|
checkDiscontinuity() { return null; },
|
|
34
35
|
isSegmentStillAvailable() : undefined { return ; },
|
|
35
36
|
canBeOutOfSyncError() : true { return true; },
|
|
36
37
|
isFinished() : true { return true; },
|
|
37
|
-
|
|
38
|
+
awaitSegmentBetween() : undefined { return ; },
|
|
38
39
|
_replace() { /* noop */ },
|
|
39
40
|
_update() { /* noop */ },
|
|
40
41
|
};
|
|
@@ -24,10 +24,11 @@
|
|
|
24
24
|
const minimalIndex = { getInitSegment() { return null; },
|
|
25
25
|
getSegments() { return []; },
|
|
26
26
|
shouldRefresh() { return false; },
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
getFirstAvailablePosition() : undefined { return ; },
|
|
28
|
+
getLastAvailablePosition() : undefined { return ; },
|
|
29
|
+
getEnd() : undefined { return ; },
|
|
30
|
+
awaitSegmentBetween() : undefined { return ; },
|
|
29
31
|
checkDiscontinuity() { return null; },
|
|
30
|
-
areSegmentsChronologicallyGenerated() { return true; },
|
|
31
32
|
isSegmentStillAvailable() : undefined { return ; },
|
|
32
33
|
canBeOutOfSyncError() : true { return true; },
|
|
33
34
|
isFinished() : true { return true; },
|
package/src/manifest/manifest.ts
CHANGED
|
@@ -537,7 +537,7 @@ export default class Manifest extends EventEmitter<IManifestEvents> {
|
|
|
537
537
|
* and mark them as being impossible to decrypt.
|
|
538
538
|
* Then trigger a "decipherabilityUpdate" event to notify everyone of the
|
|
539
539
|
* changes performed.
|
|
540
|
-
* @param {
|
|
540
|
+
* @param {Function} isDecipherableCb
|
|
541
541
|
*/
|
|
542
542
|
public updateRepresentationsDeciperability(
|
|
543
543
|
isDecipherableCb : (rep : Representation) => boolean | undefined
|
|
@@ -33,17 +33,18 @@ describe("manifest - StaticRepresentationIndex", () => {
|
|
|
33
33
|
duration: Number.MAX_VALUE,
|
|
34
34
|
end: Number.MAX_VALUE,
|
|
35
35
|
timescale: 1,
|
|
36
|
+
privateInfos: {},
|
|
36
37
|
mediaURLs: ["foo"] }]);
|
|
37
38
|
});
|
|
38
39
|
|
|
39
40
|
it("should return no first position", () => {
|
|
40
41
|
const staticRI = new StaticRepresentationIndex({ media: "foo" });
|
|
41
|
-
expect(staticRI.
|
|
42
|
+
expect(staticRI.getFirstAvailablePosition()).toBe(undefined);
|
|
42
43
|
});
|
|
43
44
|
|
|
44
45
|
it("should return no last position", () => {
|
|
45
46
|
const staticRI = new StaticRepresentationIndex({ media: "foo" });
|
|
46
|
-
expect(staticRI.
|
|
47
|
+
expect(staticRI.getLastAvailablePosition()).toBe(undefined);
|
|
47
48
|
});
|
|
48
49
|
|
|
49
50
|
it("should never be refreshed", () => {
|
|
@@ -56,9 +57,9 @@ describe("manifest - StaticRepresentationIndex", () => {
|
|
|
56
57
|
expect(staticRI.checkDiscontinuity()).toBe(null);
|
|
57
58
|
});
|
|
58
59
|
|
|
59
|
-
it("should
|
|
60
|
+
it("should never be awaiting segments", () => {
|
|
60
61
|
const staticRI = new StaticRepresentationIndex({ media: "foo" });
|
|
61
|
-
expect(staticRI.
|
|
62
|
+
expect(staticRI.awaitSegmentBetween()).toBe(false);
|
|
62
63
|
});
|
|
63
64
|
|
|
64
65
|
it("should never replace and warn when trying to do so", () => {
|
|
@@ -59,6 +59,7 @@ export default class StaticRepresentationIndex implements IRepresentationIndex {
|
|
|
59
59
|
end: Number.MAX_VALUE,
|
|
60
60
|
duration: Number.MAX_VALUE,
|
|
61
61
|
complete: true,
|
|
62
|
+
privateInfos: {},
|
|
62
63
|
timescale: 1 }];
|
|
63
64
|
}
|
|
64
65
|
|
|
@@ -66,7 +67,7 @@ export default class StaticRepresentationIndex implements IRepresentationIndex {
|
|
|
66
67
|
* Returns first position in index.
|
|
67
68
|
* @returns {undefined}
|
|
68
69
|
*/
|
|
69
|
-
|
|
70
|
+
getFirstAvailablePosition() : undefined {
|
|
70
71
|
return ;
|
|
71
72
|
}
|
|
72
73
|
|
|
@@ -74,10 +75,35 @@ export default class StaticRepresentationIndex implements IRepresentationIndex {
|
|
|
74
75
|
* Returns last position in index.
|
|
75
76
|
* @returns {undefined}
|
|
76
77
|
*/
|
|
77
|
-
|
|
78
|
+
getLastAvailablePosition() : undefined {
|
|
78
79
|
return ;
|
|
79
80
|
}
|
|
80
81
|
|
|
82
|
+
/**
|
|
83
|
+
* Returns the absolute end in seconds this RepresentationIndex can reach once
|
|
84
|
+
* all segments are available.
|
|
85
|
+
* @returns {number|null|undefined}
|
|
86
|
+
*/
|
|
87
|
+
getEnd() : undefined {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Returns:
|
|
93
|
+
* - `true` if in the given time interval, at least one new segment is
|
|
94
|
+
* expected to be available in the future.
|
|
95
|
+
* - `false` either if all segments in that time interval are already
|
|
96
|
+
* available for download or if none will ever be available for it.
|
|
97
|
+
* - `undefined` when it is not possible to tell.
|
|
98
|
+
*
|
|
99
|
+
* Always `false` in a `StaticRepresentationIndex` because all segments should
|
|
100
|
+
* be directly available.
|
|
101
|
+
* @returns {boolean}
|
|
102
|
+
*/
|
|
103
|
+
awaitSegmentBetween(): false {
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
|
|
81
107
|
/**
|
|
82
108
|
* Returns false as a static file never need to be refreshed.
|
|
83
109
|
* @returns {Boolean}
|
|
@@ -93,13 +119,6 @@ export default class StaticRepresentationIndex implements IRepresentationIndex {
|
|
|
93
119
|
return null;
|
|
94
120
|
}
|
|
95
121
|
|
|
96
|
-
/**
|
|
97
|
-
* @returns {boolean}
|
|
98
|
-
*/
|
|
99
|
-
areSegmentsChronologicallyGenerated() : boolean {
|
|
100
|
-
return true;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
122
|
/**
|
|
104
123
|
* Returns true as a static file should never need lose availability.
|
|
105
124
|
* @returns {Boolean}
|
|
@@ -112,11 +112,28 @@ export interface ILocalManifestSegmentPrivateInfos {
|
|
|
112
112
|
* exploited by the corresponding transport logic.
|
|
113
113
|
*/
|
|
114
114
|
export interface IPrivateInfos {
|
|
115
|
+
/** Smooth-specific information allowing to generate an initialization segment. */
|
|
115
116
|
smoothInitSegment? : ISmoothInitSegmentPrivateInfos | undefined;
|
|
117
|
+
|
|
118
|
+
/** Smooth-specific information linked to all Smooth media segments. */
|
|
116
119
|
smoothMediaSegment? : ISmoothSegmentPrivateInfos | undefined;
|
|
120
|
+
|
|
121
|
+
/** Information that should be present on all MetaPlaylist segments. */
|
|
117
122
|
metaplaylistInfos? : IMetaPlaylistPrivateInfos | undefined;
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Local Manifest-specific information allowing to request the
|
|
126
|
+
* initialization segment.
|
|
127
|
+
*/
|
|
118
128
|
localManifestInitSegment? : ILocalManifestInitSegmentPrivateInfos | undefined;
|
|
129
|
+
|
|
130
|
+
/** Local Manifest-specific information allowing to request any media segment. */
|
|
119
131
|
localManifestSegment? : ILocalManifestSegmentPrivateInfos | undefined;
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Function allowing to know if a given emsg's event name has been
|
|
135
|
+
* explicitely authorized.
|
|
136
|
+
*/
|
|
120
137
|
isEMSGWhitelisted? : ((evt: IEMSG) => boolean) | undefined;
|
|
121
138
|
}
|
|
122
139
|
|
|
@@ -142,26 +159,16 @@ export interface ISegment {
|
|
|
142
159
|
* segments" in the code.
|
|
143
160
|
*/
|
|
144
161
|
isInit : boolean;
|
|
145
|
-
/** URLs where this segment is available. From the most to least prioritary. */
|
|
146
|
-
mediaURLs : string[]|null;
|
|
147
|
-
/**
|
|
148
|
-
* If set, the corresponding byte-range in the downloaded segment will
|
|
149
|
-
* contain an index describing other Segments
|
|
150
|
-
* TODO put in privateInfos?
|
|
151
|
-
*/
|
|
152
|
-
indexRange? : [number, number] | undefined;
|
|
153
162
|
/**
|
|
154
|
-
*
|
|
155
|
-
*
|
|
163
|
+
* URLs where this segment is available. From the most to least prioritary.
|
|
164
|
+
* `null` if no URL exists.
|
|
156
165
|
*/
|
|
157
|
-
|
|
166
|
+
mediaURLs : string[]|null;
|
|
158
167
|
/**
|
|
159
168
|
* Allows to store supplementary information on a segment that can be later
|
|
160
169
|
* exploited by the transport logic.
|
|
161
170
|
*/
|
|
162
|
-
privateInfos
|
|
163
|
-
/** Optional byte range to retrieve the Segment from its URL(s) */
|
|
164
|
-
range? : [number, number] | undefined;
|
|
171
|
+
privateInfos : IPrivateInfos | undefined;
|
|
165
172
|
/**
|
|
166
173
|
* Estimated time, in seconds, at which the concerned segment should be
|
|
167
174
|
* offseted when decoded.
|
|
@@ -213,7 +220,6 @@ export interface ISegment {
|
|
|
213
220
|
* As both are always in seconds now, this property became unneeded.
|
|
214
221
|
*/
|
|
215
222
|
timescale : 1;
|
|
216
|
-
|
|
217
223
|
/**
|
|
218
224
|
* If `false`, this segment's `duration` property may not be the duration of
|
|
219
225
|
* the full segment as it could still be in the process of being generated
|
|
@@ -224,6 +230,31 @@ export interface ISegment {
|
|
|
224
230
|
* generated.
|
|
225
231
|
*/
|
|
226
232
|
complete : boolean;
|
|
233
|
+
/**
|
|
234
|
+
* Optional byte range to retrieve the Segment from its URL(s).
|
|
235
|
+
* TODO this should probably moved to `privateInfos` as this is
|
|
236
|
+
* transport-specific metadata only useful for performing requests, but it is
|
|
237
|
+
* sadly documented in the API, so moving it is actuall a v3.X.X breaking
|
|
238
|
+
* change.
|
|
239
|
+
*/
|
|
240
|
+
range? : [number, number] | undefined;
|
|
241
|
+
/**
|
|
242
|
+
* If set, the corresponding byte-range in the downloaded segment will
|
|
243
|
+
* contain an index describing other Segments
|
|
244
|
+
* TODO this should probably moved to `privateInfos` as this is
|
|
245
|
+
* transport-specific metadata only useful for performing requests, but it is
|
|
246
|
+
* sadly documented in the API, so moving it is actuall a v3.X.X breaking
|
|
247
|
+
* change.
|
|
248
|
+
*/
|
|
249
|
+
indexRange? : [number, number] | undefined;
|
|
250
|
+
/**
|
|
251
|
+
* Optional number of the Segment.
|
|
252
|
+
* TODO this should probably moved to `privateInfos` as this is
|
|
253
|
+
* transport-specific metadata only useful for performing requests, but it is
|
|
254
|
+
* sadly documented in the API, so moving it is actuall a v3.X.X breaking
|
|
255
|
+
* change.
|
|
256
|
+
*/
|
|
257
|
+
number? : number | undefined;
|
|
227
258
|
}
|
|
228
259
|
|
|
229
260
|
/** Interface that should be implemented by any Representation's `index` value. */
|
|
@@ -265,7 +296,7 @@ export interface IRepresentationIndex {
|
|
|
265
296
|
* Returns `undefined` if we cannot know this value.
|
|
266
297
|
* @returns {Number|null}
|
|
267
298
|
*/
|
|
268
|
-
|
|
299
|
+
getFirstAvailablePosition() : number | null | undefined;
|
|
269
300
|
|
|
270
301
|
/**
|
|
271
302
|
* Returns the ending time, in seconds, of the last playable position
|
|
@@ -279,7 +310,19 @@ export interface IRepresentationIndex {
|
|
|
279
310
|
* instead.
|
|
280
311
|
* @returns {Number|null|undefined}
|
|
281
312
|
*/
|
|
282
|
-
|
|
313
|
+
getLastAvailablePosition() : number | null | undefined;
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Returns the ending time, in seconds, of the Representation once it is
|
|
317
|
+
* "finished" (@see isFinished).
|
|
318
|
+
* Should thus be equivalent to `getLastAvailablePosition` once finished.
|
|
319
|
+
*
|
|
320
|
+
* Returns `null` if nothing is in the index
|
|
321
|
+
* Returns `undefined` if we cannot know this value.
|
|
322
|
+
*
|
|
323
|
+
* @returns {number|undefined}
|
|
324
|
+
*/
|
|
325
|
+
getEnd() : number | null | undefined;
|
|
283
326
|
|
|
284
327
|
/**
|
|
285
328
|
* Returns `true` if a Segment returned by this index is still considered
|
|
@@ -322,35 +365,6 @@ export interface IRepresentationIndex {
|
|
|
322
365
|
*/
|
|
323
366
|
checkDiscontinuity(time : number) : number | null;
|
|
324
367
|
|
|
325
|
-
/**
|
|
326
|
-
* Most RepresentationIndex are linked to segments which are generated in
|
|
327
|
-
* chronological order: from an initial position (obtainable with
|
|
328
|
-
* `getFirstPosition`) to the last position of the corresponding Period
|
|
329
|
-
* (obtainable with `getLastPosition`).
|
|
330
|
-
*
|
|
331
|
-
* However, some RepresentationIndex could announce segments in a more random
|
|
332
|
-
* order.
|
|
333
|
-
* Examples of such RepresentationIndex are ones for contents which are being
|
|
334
|
-
* downloaded locally. Here a seek close to the end could schedule the
|
|
335
|
-
* download of the last segments immediately, which might thus be announced
|
|
336
|
-
* in this index before segments in the middle are.
|
|
337
|
-
*
|
|
338
|
-
* Knowing this value serves for example to check if a discontinuity
|
|
339
|
-
* encountered in the content can be skipped over, or if it's possible that
|
|
340
|
-
* this discontinuity is due to a segment not yet being generated.
|
|
341
|
-
*
|
|
342
|
-
* You should return `true` only if there is a chance that segments are not
|
|
343
|
-
* chronologically generated (even if they all have since been generated, this
|
|
344
|
-
* function is only to know if it's possible, not if it's the case now).
|
|
345
|
-
*
|
|
346
|
-
* In other most likely cases, you should return `false`.
|
|
347
|
-
*
|
|
348
|
-
* TODO find a better way with the "local" RepresentationIndex, like
|
|
349
|
-
* explicitely declaring which segments have not been downloaded yet.
|
|
350
|
-
* @returns {boolean}
|
|
351
|
-
*/
|
|
352
|
-
areSegmentsChronologicallyGenerated() : boolean;
|
|
353
|
-
|
|
354
368
|
/**
|
|
355
369
|
* Returns `true` if the last segments in this index have already been
|
|
356
370
|
* generated so that we can freely go to the next period.
|
|
@@ -382,6 +396,8 @@ export interface IRepresentationIndex {
|
|
|
382
396
|
*/
|
|
383
397
|
isInitialized() : boolean;
|
|
384
398
|
|
|
399
|
+
awaitSegmentBetween(start : number, end : number) : boolean | undefined;
|
|
400
|
+
|
|
385
401
|
/**
|
|
386
402
|
* Replace the index with another one, such as after a Manifest update.
|
|
387
403
|
* @param {Object} newIndex
|
|
@@ -274,7 +274,7 @@ export default class BaseRepresentationIndex implements IRepresentationIndex {
|
|
|
274
274
|
* Returns first position in index.
|
|
275
275
|
* @returns {Number|null}
|
|
276
276
|
*/
|
|
277
|
-
|
|
277
|
+
getFirstAvailablePosition() : number|null {
|
|
278
278
|
const index = this._index;
|
|
279
279
|
if (index.timeline.length === 0) {
|
|
280
280
|
return null;
|
|
@@ -288,7 +288,7 @@ export default class BaseRepresentationIndex implements IRepresentationIndex {
|
|
|
288
288
|
* Returns last position in index.
|
|
289
289
|
* @returns {Number|null}
|
|
290
290
|
*/
|
|
291
|
-
|
|
291
|
+
getLastAvailablePosition() : number|null {
|
|
292
292
|
const { timeline } = this._index;
|
|
293
293
|
if (timeline.length === 0) {
|
|
294
294
|
return null;
|
|
@@ -301,6 +301,31 @@ export default class BaseRepresentationIndex implements IRepresentationIndex {
|
|
|
301
301
|
return fromIndexTime(lastTime, this._index);
|
|
302
302
|
}
|
|
303
303
|
|
|
304
|
+
/**
|
|
305
|
+
* Returns the absolute end in seconds this RepresentationIndex can reach once
|
|
306
|
+
* all segments are available.
|
|
307
|
+
* @returns {number|null|undefined}
|
|
308
|
+
*/
|
|
309
|
+
getEnd(): number | null {
|
|
310
|
+
return this.getLastAvailablePosition();
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* Returns:
|
|
315
|
+
* - `true` if in the given time interval, at least one new segment is
|
|
316
|
+
* expected to be available in the future.
|
|
317
|
+
* - `false` either if all segments in that time interval are already
|
|
318
|
+
* available for download or if none will ever be available for it.
|
|
319
|
+
* - `undefined` when it is not possible to tell.
|
|
320
|
+
*
|
|
321
|
+
* Always `false` in a `BaseRepresentationIndex` because all segments should
|
|
322
|
+
* be directly available.
|
|
323
|
+
* @returns {boolean}
|
|
324
|
+
*/
|
|
325
|
+
awaitSegmentBetween(): false {
|
|
326
|
+
return false;
|
|
327
|
+
}
|
|
328
|
+
|
|
304
329
|
/**
|
|
305
330
|
* Segments in a segmentBase scheme should stay available.
|
|
306
331
|
* @returns {Boolean|undefined}
|
|
@@ -317,15 +342,6 @@ export default class BaseRepresentationIndex implements IRepresentationIndex {
|
|
|
317
342
|
return null;
|
|
318
343
|
}
|
|
319
344
|
|
|
320
|
-
/**
|
|
321
|
-
* `BaseRepresentationIndex` should just already all be generated.
|
|
322
|
-
* Return `true` as a default value here.
|
|
323
|
-
* @returns {boolean}
|
|
324
|
-
*/
|
|
325
|
-
areSegmentsChronologicallyGenerated() : true {
|
|
326
|
-
return true;
|
|
327
|
-
}
|
|
328
|
-
|
|
329
345
|
/**
|
|
330
346
|
* No segment in a `BaseRepresentationIndex` are known initially.
|
|
331
347
|
* It is only defined generally in an "index segment" that will thus need to
|
|
@@ -60,7 +60,10 @@ export interface IListIndex {
|
|
|
60
60
|
} | undefined;
|
|
61
61
|
/** Information on the list of segments for this index. */
|
|
62
62
|
list: Array<{
|
|
63
|
-
/**
|
|
63
|
+
/**
|
|
64
|
+
* URLs of the segment.
|
|
65
|
+
* `null` if no URL exists.
|
|
66
|
+
*/
|
|
64
67
|
mediaURLs : string[] | null;
|
|
65
68
|
/** Possible byte-range of the segment. */
|
|
66
69
|
mediaRange? : [number, number] | undefined;
|
|
@@ -188,7 +191,7 @@ export default class ListRepresentationIndex implements IRepresentationIndex {
|
|
|
188
191
|
|
|
189
192
|
/**
|
|
190
193
|
* @param {Number} fromTime
|
|
191
|
-
* @param {Number}
|
|
194
|
+
* @param {Number} dur
|
|
192
195
|
* @returns {Array.<Object>}
|
|
193
196
|
*/
|
|
194
197
|
getSegments(fromTime : number, dur : number) : ISegment[] {
|
|
@@ -243,7 +246,7 @@ export default class ListRepresentationIndex implements IRepresentationIndex {
|
|
|
243
246
|
* Returns first position in this index, in seconds.
|
|
244
247
|
* @returns {Number}
|
|
245
248
|
*/
|
|
246
|
-
|
|
249
|
+
getFirstAvailablePosition() : number {
|
|
247
250
|
return this._periodStart;
|
|
248
251
|
}
|
|
249
252
|
|
|
@@ -251,17 +254,41 @@ export default class ListRepresentationIndex implements IRepresentationIndex {
|
|
|
251
254
|
* Returns last position in this index, in seconds.
|
|
252
255
|
* @returns {Number}
|
|
253
256
|
*/
|
|
254
|
-
|
|
257
|
+
getLastAvailablePosition() : number {
|
|
255
258
|
const index = this._index;
|
|
256
259
|
const { duration, list } = index;
|
|
257
260
|
return Math.min(((list.length * duration) / index.timescale) + this._periodStart,
|
|
258
261
|
this._periodEnd ?? Infinity);
|
|
259
262
|
}
|
|
260
263
|
|
|
264
|
+
/**
|
|
265
|
+
* Returns the absolute end in seconds this RepresentationIndex can reach once
|
|
266
|
+
* all segments are available.
|
|
267
|
+
* @returns {number|null|undefined}
|
|
268
|
+
*/
|
|
269
|
+
getEnd(): number | null {
|
|
270
|
+
return this.getLastAvailablePosition();
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Returns:
|
|
275
|
+
* - `true` if in the given time interval, at least one new segment is
|
|
276
|
+
* expected to be available in the future.
|
|
277
|
+
* - `false` either if all segments in that time interval are already
|
|
278
|
+
* available for download or if none will ever be available for it.
|
|
279
|
+
* - `undefined` when it is not possible to tell.
|
|
280
|
+
*
|
|
281
|
+
* Always `false` in a `ListRepresentationIndex` because all segments should
|
|
282
|
+
* be directly available.
|
|
283
|
+
* @returns {boolean}
|
|
284
|
+
*/
|
|
285
|
+
awaitSegmentBetween(): false {
|
|
286
|
+
return false;
|
|
287
|
+
}
|
|
288
|
+
|
|
261
289
|
/**
|
|
262
290
|
* Returns true if a Segment returned by this index is still considered
|
|
263
291
|
* available.
|
|
264
|
-
* @param {Object} segment
|
|
265
292
|
* @returns {Boolean}
|
|
266
293
|
*/
|
|
267
294
|
isSegmentStillAvailable() : true {
|
|
@@ -277,13 +304,6 @@ export default class ListRepresentationIndex implements IRepresentationIndex {
|
|
|
277
304
|
return null;
|
|
278
305
|
}
|
|
279
306
|
|
|
280
|
-
/**
|
|
281
|
-
* @returns {boolean}
|
|
282
|
-
*/
|
|
283
|
-
areSegmentsChronologicallyGenerated() : boolean {
|
|
284
|
-
return true;
|
|
285
|
-
}
|
|
286
|
-
|
|
287
307
|
/**
|
|
288
308
|
* SegmentList should not be updated.
|
|
289
309
|
* @returns {Boolean}
|
|
@@ -313,9 +333,6 @@ export default class ListRepresentationIndex implements IRepresentationIndex {
|
|
|
313
333
|
this._index = newIndex._index;
|
|
314
334
|
}
|
|
315
335
|
|
|
316
|
-
/**
|
|
317
|
-
* @param {Object} newIndex
|
|
318
|
-
*/
|
|
319
336
|
_update() : void {
|
|
320
337
|
log.error("List RepresentationIndex: Cannot update a SegmentList");
|
|
321
338
|
}
|