rx-player 3.27.1-dev.2022041500 → 3.27.1-dev.2022051100
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 +11 -5
- package/VERSION +1 -1
- package/dist/_esm5.processed/core/api/public_api.js +2 -2
- package/dist/_esm5.processed/core/decrypt/content_decryptor.js +12 -10
- package/dist/_esm5.processed/core/decrypt/utils/key_session_record.js +2 -1
- package/dist/_esm5.processed/core/init/throw_on_media_error.js +19 -10
- package/dist/_esm5.processed/manifest/representation.js +4 -4
- package/dist/_esm5.processed/parsers/manifest/dash/common/flatten_overlapping_periods.js +11 -1
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/timeline/timeline_representation_index.d.ts +2 -0
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/timeline/timeline_representation_index.js +9 -2
- package/dist/_esm5.processed/parsers/manifest/dash/common/parse_representations.js +10 -3
- package/dist/_esm5.processed/parsers/manifest/types.d.ts +7 -2
- package/dist/_esm5.processed/parsers/texttracks/ttml/html/generate_css_test_outline.js +14 -4
- package/dist/rx-player.js +85 -33
- package/dist/rx-player.min.js +1 -1
- package/package.json +1 -1
- package/sonar-project.properties +1 -1
- package/src/core/api/public_api.ts +2 -2
- package/src/core/decrypt/content_decryptor.ts +12 -10
- package/src/core/decrypt/utils/key_session_record.ts +2 -1
- package/src/core/init/throw_on_media_error.ts +25 -15
- package/src/manifest/representation.ts +2 -2
- package/src/parsers/manifest/dash/common/flatten_overlapping_periods.ts +10 -1
- package/src/parsers/manifest/dash/common/indexes/timeline/timeline_representation_index.ts +12 -2
- package/src/parsers/manifest/dash/common/parse_representations.ts +9 -3
- package/src/parsers/manifest/types.ts +7 -2
- package/src/parsers/texttracks/ttml/html/generate_css_test_outline.ts +15 -4
package/package.json
CHANGED
package/sonar-project.properties
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
sonar.projectKey=rx-player
|
|
2
2
|
sonar.organization=rx-player
|
|
3
3
|
sonar.projectName=rx-player
|
|
4
|
-
sonar.projectVersion=3.27.1-dev.
|
|
4
|
+
sonar.projectVersion=3.27.1-dev.2022051100
|
|
5
5
|
sonar.sources=./src,./demo,./tests
|
|
6
6
|
sonar.exclusions=demo/full/bundle.js,demo/standalone/lib.js,demo/bundle.js
|
|
7
7
|
sonar.host.url=https://sonarcloud.io
|
|
@@ -428,7 +428,7 @@ class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
428
428
|
// See: https://bugzilla.mozilla.org/show_bug.cgi?id=1194624
|
|
429
429
|
videoElement.preload = "auto";
|
|
430
430
|
|
|
431
|
-
this.version = /* PLAYER_VERSION */"3.27.1-dev.
|
|
431
|
+
this.version = /* PLAYER_VERSION */"3.27.1-dev.2022051100";
|
|
432
432
|
this.log = log;
|
|
433
433
|
this.state = "STOPPED";
|
|
434
434
|
this.videoElement = videoElement;
|
|
@@ -2940,7 +2940,7 @@ class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
2940
2940
|
return activeRepresentations[currentPeriod.id];
|
|
2941
2941
|
}
|
|
2942
2942
|
}
|
|
2943
|
-
Player.version = /* PLAYER_VERSION */"3.27.1-dev.
|
|
2943
|
+
Player.version = /* PLAYER_VERSION */"3.27.1-dev.2022051100";
|
|
2944
2944
|
|
|
2945
2945
|
/** Payload emitted with a `positionUpdate` event. */
|
|
2946
2946
|
export interface IPositionUpdateItem {
|
|
@@ -780,16 +780,18 @@ function updateDecipherability(
|
|
|
780
780
|
return representation.decipherable;
|
|
781
781
|
}
|
|
782
782
|
const contentKIDs = representation.contentProtections.keyIds;
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
783
|
+
if (contentKIDs !== undefined) {
|
|
784
|
+
for (let i = 0; i < contentKIDs.length; i++) {
|
|
785
|
+
const elt = contentKIDs[i];
|
|
786
|
+
for (let j = 0; j < blacklistedKeyIDs.length; j++) {
|
|
787
|
+
if (areKeyIdsEqual(blacklistedKeyIDs[j], elt.keyId)) {
|
|
788
|
+
return false;
|
|
789
|
+
}
|
|
788
790
|
}
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
791
|
+
for (let j = 0; j < whitelistedKeyIds.length; j++) {
|
|
792
|
+
if (areKeyIdsEqual(whitelistedKeyIds[j], elt.keyId)) {
|
|
793
|
+
return true;
|
|
794
|
+
}
|
|
793
795
|
}
|
|
794
796
|
}
|
|
795
797
|
}
|
|
@@ -1157,7 +1159,7 @@ function addKeyIdsFromPeriod(
|
|
|
1157
1159
|
for (const adaptation of period.getAdaptations()) {
|
|
1158
1160
|
for (const representation of adaptation.representations) {
|
|
1159
1161
|
if (representation.contentProtections !== undefined &&
|
|
1160
|
-
representation.contentProtections.keyIds
|
|
1162
|
+
representation.contentProtections.keyIds !== undefined)
|
|
1161
1163
|
{
|
|
1162
1164
|
for (const kidInf of representation.contentProtections.keyIds) {
|
|
1163
1165
|
set.add(kidInf.keyId);
|
|
@@ -144,7 +144,7 @@ export default class KeySessionRecord {
|
|
|
144
144
|
initializationData : IProcessedProtectionData
|
|
145
145
|
) : boolean {
|
|
146
146
|
const { keyIds } = initializationData;
|
|
147
|
-
if (keyIds !== undefined) {
|
|
147
|
+
if (keyIds !== undefined && keyIds.length > 0) {
|
|
148
148
|
if (this._keyIds !== null && areAllKeyIdsContainedIn(keyIds, this._keyIds)) {
|
|
149
149
|
return true;
|
|
150
150
|
}
|
|
@@ -159,6 +159,7 @@ export default class KeySessionRecord {
|
|
|
159
159
|
initializationData : IProcessedProtectionData
|
|
160
160
|
) : boolean {
|
|
161
161
|
if (initializationData.keyIds !== undefined &&
|
|
162
|
+
initializationData.keyIds.length > 0 &&
|
|
162
163
|
this._initializationData.keyIds !== undefined)
|
|
163
164
|
{
|
|
164
165
|
return areAllKeyIdsContainedIn(initializationData.keyIds,
|
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
Observable,
|
|
21
21
|
} from "rxjs";
|
|
22
22
|
import { MediaError } from "../../errors";
|
|
23
|
+
import isNullOrUndefined from "../../utils/is_null_or_undefined";
|
|
23
24
|
|
|
24
25
|
/**
|
|
25
26
|
* Returns an observable which throws the right MediaError as soon an "error"
|
|
@@ -32,27 +33,36 @@ export default function throwOnMediaError(
|
|
|
32
33
|
) : Observable<never> {
|
|
33
34
|
return observableFromEvent(mediaElement, "error")
|
|
34
35
|
.pipe(mergeMap(() => {
|
|
35
|
-
const
|
|
36
|
-
|
|
36
|
+
const mediaError = mediaElement.error;
|
|
37
|
+
let errorCode : number | undefined;
|
|
38
|
+
let errorMessage : string | undefined;
|
|
39
|
+
if (!isNullOrUndefined(mediaError)) {
|
|
40
|
+
errorCode = mediaError.code;
|
|
41
|
+
errorMessage = mediaError.message;
|
|
42
|
+
}
|
|
43
|
+
|
|
37
44
|
switch (errorCode) {
|
|
38
45
|
case 1:
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
46
|
+
errorMessage = errorMessage ??
|
|
47
|
+
"The fetching of the associated resource was aborted by the user's request.";
|
|
48
|
+
throw new MediaError("MEDIA_ERR_ABORTED", errorMessage);
|
|
42
49
|
case 2:
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
50
|
+
errorMessage = errorMessage ??
|
|
51
|
+
"A network error occurred which prevented the media from being " +
|
|
52
|
+
"successfully fetched";
|
|
53
|
+
throw new MediaError("MEDIA_ERR_NETWORK", errorMessage);
|
|
46
54
|
case 3:
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
55
|
+
errorMessage = errorMessage ??
|
|
56
|
+
"An error occurred while trying to decode the media resource";
|
|
57
|
+
throw new MediaError("MEDIA_ERR_DECODE", errorMessage);
|
|
50
58
|
case 4:
|
|
51
|
-
|
|
52
|
-
|
|
59
|
+
errorMessage = errorMessage ??
|
|
60
|
+
"The media resource has been found to be unsuitable.";
|
|
61
|
+
throw new MediaError("MEDIA_ERR_SRC_NOT_SUPPORTED", errorMessage);
|
|
53
62
|
default:
|
|
54
|
-
|
|
55
|
-
|
|
63
|
+
errorMessage = errorMessage ??
|
|
64
|
+
"The HTMLMediaElement errored due to an unknown reason.";
|
|
65
|
+
throw new MediaError("MEDIA_ERR_UNKNOWN", errorMessage);
|
|
56
66
|
}
|
|
57
67
|
}));
|
|
58
68
|
}
|
|
@@ -174,7 +174,7 @@ class Representation {
|
|
|
174
174
|
for (let j = 0; j < initData.values.length; j++) {
|
|
175
175
|
if (initData.values[j].systemId.toLowerCase() === drmSystemId.toLowerCase()) {
|
|
176
176
|
if (!createdObjForType) {
|
|
177
|
-
const keyIds = this.contentProtections?.keyIds
|
|
177
|
+
const keyIds = this.contentProtections?.keyIds?.map(val => val.keyId);
|
|
178
178
|
filtered.push({ type: initData.type,
|
|
179
179
|
keyIds,
|
|
180
180
|
values: [initData.values[j]] });
|
|
@@ -221,7 +221,7 @@ class Representation {
|
|
|
221
221
|
{
|
|
222
222
|
return [];
|
|
223
223
|
}
|
|
224
|
-
const keyIds = this.contentProtections?.keyIds
|
|
224
|
+
const keyIds = this.contentProtections?.keyIds?.map(val => val.keyId);
|
|
225
225
|
return this.contentProtections.initData.map((x) => {
|
|
226
226
|
return { type: x.type,
|
|
227
227
|
keyIds,
|
|
@@ -62,7 +62,16 @@ export default function flattenOverlappingPeriods(
|
|
|
62
62
|
parsedPeriod.start);
|
|
63
63
|
lastFlattenedPeriod.duration = parsedPeriod.start - lastFlattenedPeriod.start;
|
|
64
64
|
lastFlattenedPeriod.end = parsedPeriod.start;
|
|
65
|
-
if (lastFlattenedPeriod.duration
|
|
65
|
+
if (lastFlattenedPeriod.duration > 0) {
|
|
66
|
+
// Note: Calling `break` to quit the while loop should theoritically be
|
|
67
|
+
// unnecessary as the previous operations should ensure we do not re-enter
|
|
68
|
+
// the loop's condition.
|
|
69
|
+
// Yet we dit encounter infinite loops without it because of float-related
|
|
70
|
+
// rounding errors.
|
|
71
|
+
break;
|
|
72
|
+
} else {
|
|
73
|
+
// `lastFlattenedPeriod` has now a negative or `0` duration.
|
|
74
|
+
// Remove it, consider the next Period in its place, and re-start the loop.
|
|
66
75
|
flattenedPeriods.pop();
|
|
67
76
|
lastFlattenedPeriod = flattenedPeriods[flattenedPeriods.length - 1];
|
|
68
77
|
}
|
|
@@ -201,6 +201,9 @@ export default class TimelineRepresentationIndex implements IRepresentationIndex
|
|
|
201
201
|
/** Absolute start of the period, timescaled and converted to index time. */
|
|
202
202
|
private _scaledPeriodStart : number;
|
|
203
203
|
|
|
204
|
+
/** Actual un-scaled start of the Period as indicated in the MPD. */
|
|
205
|
+
private _periodStart : number;
|
|
206
|
+
|
|
204
207
|
/** Absolute end of the period, timescaled and converted to index time. */
|
|
205
208
|
private _scaledPeriodEnd : number | undefined;
|
|
206
209
|
|
|
@@ -305,6 +308,7 @@ export default class TimelineRepresentationIndex implements IRepresentationIndex
|
|
|
305
308
|
startNumber: index.startNumber,
|
|
306
309
|
timeline: index.timeline ?? null,
|
|
307
310
|
timescale };
|
|
311
|
+
this._periodStart = periodStart;
|
|
308
312
|
this._scaledPeriodStart = toIndexTime(periodStart, this._index);
|
|
309
313
|
this._scaledPeriodEnd = periodEnd === undefined ? undefined :
|
|
310
314
|
toIndexTime(periodEnd, this._index);
|
|
@@ -461,6 +465,7 @@ export default class TimelineRepresentationIndex implements IRepresentationIndex
|
|
|
461
465
|
this._index = newIndex._index;
|
|
462
466
|
this._isDynamic = newIndex._isDynamic;
|
|
463
467
|
this._scaledPeriodStart = newIndex._scaledPeriodStart;
|
|
468
|
+
this._periodStart = newIndex._periodStart;
|
|
464
469
|
this._scaledPeriodEnd = newIndex._scaledPeriodEnd;
|
|
465
470
|
this._lastUpdate = newIndex._lastUpdate;
|
|
466
471
|
this._manifestBoundsCalculator = newIndex._manifestBoundsCalculator;
|
|
@@ -486,6 +491,7 @@ export default class TimelineRepresentationIndex implements IRepresentationIndex
|
|
|
486
491
|
}
|
|
487
492
|
this._isDynamic = newIndex._isDynamic;
|
|
488
493
|
this._scaledPeriodStart = newIndex._scaledPeriodStart;
|
|
494
|
+
this._periodStart = newIndex._periodStart;
|
|
489
495
|
this._scaledPeriodEnd = newIndex._scaledPeriodEnd;
|
|
490
496
|
this._lastUpdate = newIndex._lastUpdate;
|
|
491
497
|
this._isLastPeriod = newIndex._isLastPeriod;
|
|
@@ -548,6 +554,9 @@ export default class TimelineRepresentationIndex implements IRepresentationIndex
|
|
|
548
554
|
if (this._index.timeline === null) {
|
|
549
555
|
this._index.timeline = this._getTimeline();
|
|
550
556
|
}
|
|
557
|
+
if (!this._isDynamic) {
|
|
558
|
+
return;
|
|
559
|
+
}
|
|
551
560
|
const firstPosition = this._manifestBoundsCalculator.estimateMinimumBound();
|
|
552
561
|
if (firstPosition == null) {
|
|
553
562
|
return; // we don't know yet
|
|
@@ -605,12 +614,13 @@ export default class TimelineRepresentationIndex implements IRepresentationIndex
|
|
|
605
614
|
const newElements = this._parseTimeline();
|
|
606
615
|
this._parseTimeline = null; // Free memory
|
|
607
616
|
|
|
617
|
+
const actualPeriodStart = this._periodStart * this._index.timescale;
|
|
608
618
|
const { MIN_DASH_S_ELEMENTS_TO_PARSE_UNSAFELY } = config.getCurrent();
|
|
609
619
|
if (this._unsafelyBaseOnPreviousIndex === null ||
|
|
610
620
|
newElements.length < MIN_DASH_S_ELEMENTS_TO_PARSE_UNSAFELY)
|
|
611
621
|
{
|
|
612
622
|
// Just completely parse the current timeline
|
|
613
|
-
return constructTimelineFromElements(newElements,
|
|
623
|
+
return constructTimelineFromElements(newElements, actualPeriodStart);
|
|
614
624
|
}
|
|
615
625
|
|
|
616
626
|
// Construct previously parsed timeline if not already done
|
|
@@ -625,7 +635,7 @@ export default class TimelineRepresentationIndex implements IRepresentationIndex
|
|
|
625
635
|
|
|
626
636
|
return constructTimelineFromPreviousTimeline(newElements,
|
|
627
637
|
prevTimeline,
|
|
628
|
-
|
|
638
|
+
actualPeriodStart);
|
|
629
639
|
|
|
630
640
|
}
|
|
631
641
|
}
|
|
@@ -225,7 +225,12 @@ export default function parseRepresentations(
|
|
|
225
225
|
.toLowerCase();
|
|
226
226
|
}
|
|
227
227
|
if (cp.attributes.keyId !== undefined && cp.attributes.keyId.length > 0) {
|
|
228
|
-
|
|
228
|
+
const kidObj = { keyId: cp.attributes.keyId, systemId };
|
|
229
|
+
if (acc.keyIds === undefined) {
|
|
230
|
+
acc.keyIds = [kidObj];
|
|
231
|
+
} else {
|
|
232
|
+
acc.keyIds.push(kidObj);
|
|
233
|
+
}
|
|
229
234
|
}
|
|
230
235
|
if (systemId !== undefined) {
|
|
231
236
|
const { cencPssh } = cp.children;
|
|
@@ -244,9 +249,10 @@ export default function parseRepresentations(
|
|
|
244
249
|
}
|
|
245
250
|
}
|
|
246
251
|
return acc;
|
|
247
|
-
}, { keyIds:
|
|
252
|
+
}, { keyIds: undefined, initData: [] });
|
|
248
253
|
if (Object.keys(contentProtections.initData).length > 0 ||
|
|
249
|
-
contentProtections.keyIds
|
|
254
|
+
(contentProtections.keyIds !== undefined &&
|
|
255
|
+
contentProtections.keyIds.length > 0))
|
|
250
256
|
{
|
|
251
257
|
parsedRepresentation.contentProtections = contentProtections;
|
|
252
258
|
}
|
|
@@ -69,8 +69,13 @@ export interface IContentProtectionInitData {
|
|
|
69
69
|
*/
|
|
70
70
|
/** Describes every encryption protection parsed for a given media. */
|
|
71
71
|
export interface IContentProtections {
|
|
72
|
-
/**
|
|
73
|
-
|
|
72
|
+
/**
|
|
73
|
+
* The different encryption key IDs associated with that content.
|
|
74
|
+
*
|
|
75
|
+
* `undefined` if the key id(s) associated with that content may exist but are
|
|
76
|
+
* not known.
|
|
77
|
+
*/
|
|
78
|
+
keyIds : IContentProtectionKID[] | undefined;
|
|
74
79
|
/** The different encryption initialization data associated with that content. */
|
|
75
80
|
initData : IContentProtectionInitData[];
|
|
76
81
|
}
|
|
@@ -14,6 +14,8 @@
|
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
+
import isNonEmptyString from "../../../../utils/is_non_empty_string";
|
|
18
|
+
|
|
17
19
|
/**
|
|
18
20
|
* Try to replicate the textOutline TTML style property into CSS.
|
|
19
21
|
*
|
|
@@ -28,8 +30,17 @@ export default function generateCSSTextOutline(
|
|
|
28
30
|
color : string,
|
|
29
31
|
thickness : string|number
|
|
30
32
|
) : string {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
let thick = thickness;
|
|
34
|
+
if (isNonEmptyString(thickness) && thickness.trim().endsWith("%")) {
|
|
35
|
+
// As em and % are basically equivalent in CSS
|
|
36
|
+
// (they both are relative to the font-size
|
|
37
|
+
// of the current element)
|
|
38
|
+
// We convert the non supported % into the supported em
|
|
39
|
+
thick = thickness.trim().slice(0, -1);
|
|
40
|
+
thick = (parseInt(thick, 10) / 100).toString() + "em";
|
|
41
|
+
}
|
|
42
|
+
return `-1px -1px ${thick} ${color},` +
|
|
43
|
+
`1px -1px ${thick} ${color},` +
|
|
44
|
+
`-1px 1px ${thick} ${color},` +
|
|
45
|
+
`1px 1px ${thick} ${color}`;
|
|
35
46
|
}
|