shaka-player 4.12.2 → 4.12.3
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/.csslintrc +2 -1
- package/dist/controls.css +3 -3
- package/dist/controls.css.map +1 -1
- package/dist/deps.js +3 -2
- package/dist/locales.js +36 -36
- package/dist/shaka-player.compiled.d.ts +1 -1
- package/dist/shaka-player.compiled.debug.d.ts +1 -1
- package/dist/shaka-player.compiled.debug.js +236 -237
- package/dist/shaka-player.compiled.debug.map +4 -4
- package/dist/shaka-player.compiled.js +1328 -1323
- package/dist/shaka-player.compiled.map +4 -4
- package/dist/shaka-player.ui.d.ts +1 -1
- package/dist/shaka-player.ui.debug.d.ts +1 -1
- package/dist/shaka-player.ui.debug.js +274 -275
- package/dist/shaka-player.ui.debug.map +4 -4
- package/dist/shaka-player.ui.js +1536 -1531
- package/dist/shaka-player.ui.map +4 -4
- package/externs/managedmediasource.js +6 -0
- package/externs/shaka/ads.js +3 -0
- package/lib/ads/ad_utils.js +1 -0
- package/lib/ads/interstitial_ad_manager.js +64 -24
- package/lib/cast/cast_utils.js +4 -2
- package/lib/media/media_source_capabilities.js +6 -8
- package/lib/media/media_source_engine.js +3 -4
- package/lib/media/segment_utils.js +7 -3
- package/lib/net/http_xhr_plugin.js +1 -0
- package/lib/player.js +42 -36
- package/lib/text/vtt_text_parser.js +9 -4
- package/lib/util/abortable_operation.js +3 -0
- package/lib/util/buffer_utils.js +10 -8
- package/lib/util/mime_utils.js +2 -0
- package/lib/util/number_utils.js +37 -0
- package/lib/util/object_utils.js +1 -1
- package/lib/util/uint8array_utils.js +3 -2
- package/package.json +2 -2
- package/ui/language_utils.js +3 -1
- package/ui/less/ad_controls.less +3 -3
- package/ui/less/buttons.less +4 -4
- package/ui/less/containers.less +7 -7
- package/ui/less/overflow_menu.less +4 -4
- package/ui/less/thumbnails.less +3 -3
- package/ui/less/tooltip.less +1 -1
package/externs/shaka/ads.js
CHANGED
|
@@ -63,6 +63,7 @@ shaka.extern.AdCuePoint;
|
|
|
63
63
|
* startTime: number,
|
|
64
64
|
* endTime: ?number,
|
|
65
65
|
* uri: string,
|
|
66
|
+
* mimeType: ?string,
|
|
66
67
|
* isSkippable: boolean,
|
|
67
68
|
* skipOffset: ?number,
|
|
68
69
|
* skipFor: ?number,
|
|
@@ -87,6 +88,8 @@ shaka.extern.AdCuePoint;
|
|
|
87
88
|
* @property {string} uri
|
|
88
89
|
* The uri of the interstitial, can be any type that
|
|
89
90
|
* ShakaPlayer supports (either in MSE or src=)
|
|
91
|
+
* @property {?string} mimeType
|
|
92
|
+
* The mimeType of the interstitial if known.
|
|
90
93
|
* @property {boolean} isSkippable
|
|
91
94
|
* Indicate if the interstitial is skippable.
|
|
92
95
|
* @property {?number} skipOffset
|
package/lib/ads/ad_utils.js
CHANGED
|
@@ -102,7 +102,7 @@ shaka.ads.InterstitialAdManager = class {
|
|
|
102
102
|
}
|
|
103
103
|
this.lastTime_ = this.baseVideo_.currentTime;
|
|
104
104
|
const currentInterstitial = this.getCurrentInterstitial_(
|
|
105
|
-
/* needPreRoll= */ true
|
|
105
|
+
/* needPreRoll= */ true);
|
|
106
106
|
if (currentInterstitial) {
|
|
107
107
|
this.setupAd_(currentInterstitial, /* sequenceLength= */ 1,
|
|
108
108
|
/* adPosition= */ 1, /* initialTime= */ Date.now());
|
|
@@ -121,14 +121,17 @@ shaka.ads.InterstitialAdManager = class {
|
|
|
121
121
|
this.lastTime_ < this.lastPlayedAd_.startTime) {
|
|
122
122
|
this.lastPlayedAd_ = null;
|
|
123
123
|
}
|
|
124
|
-
const currentInterstitial = this.getCurrentInterstitial_(
|
|
125
|
-
/* needPreRoll= */ false, /* numberToSkip= */ 0, this.lastPlayedAd_);
|
|
124
|
+
const currentInterstitial = this.getCurrentInterstitial_();
|
|
126
125
|
if (currentInterstitial) {
|
|
127
126
|
this.setupAd_(currentInterstitial, /* sequenceLength= */ 1,
|
|
128
127
|
/* adPosition= */ 1, /* initialTime= */ Date.now());
|
|
129
128
|
}
|
|
130
129
|
};
|
|
131
130
|
|
|
131
|
+
this.eventManager_.listen(this.baseVideo_, 'ended', () => {
|
|
132
|
+
checkForInterstitials();
|
|
133
|
+
});
|
|
134
|
+
|
|
132
135
|
/** @private {shaka.util.Timer} */
|
|
133
136
|
this.timeUpdateTimer_ = new shaka.util.Timer(checkForInterstitials);
|
|
134
137
|
|
|
@@ -181,7 +184,10 @@ shaka.ads.InterstitialAdManager = class {
|
|
|
181
184
|
if (difference > 0 && difference <= 10) {
|
|
182
185
|
if (!this.preloadManagerInterstitials_.has(interstitial)) {
|
|
183
186
|
this.preloadManagerInterstitials_.set(
|
|
184
|
-
interstitial, this.player_.preload(
|
|
187
|
+
interstitial, this.player_.preload(
|
|
188
|
+
interstitial.uri,
|
|
189
|
+
/* startTime= */ null,
|
|
190
|
+
interstitial.mimeType || undefined));
|
|
185
191
|
}
|
|
186
192
|
}
|
|
187
193
|
}
|
|
@@ -322,10 +328,11 @@ shaka.ads.InterstitialAdManager = class {
|
|
|
322
328
|
|
|
323
329
|
/** @type {!shaka.extern.AdInterstitial} */
|
|
324
330
|
const interstitial = {
|
|
325
|
-
id:
|
|
331
|
+
id: region.id,
|
|
326
332
|
startTime: region.startTime,
|
|
327
333
|
endTime: region.endTime,
|
|
328
334
|
uri: alternativeMPDUri,
|
|
335
|
+
mimeType: null,
|
|
329
336
|
isSkippable: false,
|
|
330
337
|
skipOffset: null,
|
|
331
338
|
skipFor: null,
|
|
@@ -407,7 +414,10 @@ shaka.ads.InterstitialAdManager = class {
|
|
|
407
414
|
if (shouldPreload) {
|
|
408
415
|
if (!this.preloadManagerInterstitials_.has(interstitial)) {
|
|
409
416
|
this.preloadManagerInterstitials_.set(
|
|
410
|
-
interstitial, this.player_.preload(
|
|
417
|
+
interstitial, this.player_.preload(
|
|
418
|
+
interstitial.uri,
|
|
419
|
+
/* startTime= */ null,
|
|
420
|
+
interstitial.mimeType || undefined));
|
|
411
421
|
}
|
|
412
422
|
}
|
|
413
423
|
}
|
|
@@ -436,13 +446,12 @@ shaka.ads.InterstitialAdManager = class {
|
|
|
436
446
|
|
|
437
447
|
|
|
438
448
|
/**
|
|
439
|
-
* @param {boolean} needPreRoll
|
|
440
|
-
* @param {number} numberToSkip
|
|
441
|
-
* @param {?shaka.extern.AdInterstitial=} lastPlayedAd
|
|
449
|
+
* @param {boolean=} needPreRoll
|
|
450
|
+
* @param {?number=} numberToSkip
|
|
442
451
|
* @return {?shaka.extern.AdInterstitial}
|
|
443
452
|
* @private
|
|
444
453
|
*/
|
|
445
|
-
getCurrentInterstitial_(needPreRoll, numberToSkip
|
|
454
|
+
getCurrentInterstitial_(needPreRoll = false, numberToSkip = null) {
|
|
446
455
|
let skipped = 0;
|
|
447
456
|
let currentInterstitial = null;
|
|
448
457
|
if (this.interstitials_.size && this.lastTime_ != null) {
|
|
@@ -453,7 +462,15 @@ shaka.ads.InterstitialAdManager = class {
|
|
|
453
462
|
const roundDecimals = (number) => {
|
|
454
463
|
return Math.round(number * 1000) / 1000;
|
|
455
464
|
};
|
|
456
|
-
|
|
465
|
+
let interstitialsToCheck = interstitials;
|
|
466
|
+
if (needPreRoll) {
|
|
467
|
+
interstitialsToCheck = interstitials.filter((i) => i.pre);
|
|
468
|
+
} else if (isEnded) {
|
|
469
|
+
interstitialsToCheck = interstitials.filter((i) => i.post);
|
|
470
|
+
} else {
|
|
471
|
+
interstitialsToCheck = interstitials.filter((i) => !i.pre && !i.post);
|
|
472
|
+
}
|
|
473
|
+
for (const interstitial of interstitialsToCheck) {
|
|
457
474
|
let isValid = false;
|
|
458
475
|
if (needPreRoll) {
|
|
459
476
|
isValid = interstitial.pre;
|
|
@@ -464,18 +481,28 @@ shaka.ads.InterstitialAdManager = class {
|
|
|
464
481
|
this.lastTime_ - roundDecimals(interstitial.startTime);
|
|
465
482
|
if (difference > 0 &&
|
|
466
483
|
(difference <= 1 || !interstitial.canJump)) {
|
|
467
|
-
if (
|
|
468
|
-
|
|
484
|
+
if (numberToSkip == null && this.lastPlayedAd_ &&
|
|
485
|
+
!this.lastPlayedAd_.pre && !this.lastPlayedAd_.post &&
|
|
486
|
+
this.lastPlayedAd_.startTime >= interstitial.startTime) {
|
|
469
487
|
isValid = false;
|
|
470
488
|
} else {
|
|
471
489
|
isValid = true;
|
|
472
490
|
}
|
|
473
491
|
}
|
|
474
492
|
}
|
|
475
|
-
if (isValid
|
|
476
|
-
|
|
493
|
+
if (isValid && (!this.lastPlayedAd_ ||
|
|
494
|
+
interstitial.startTime >= this.lastPlayedAd_.startTime)) {
|
|
495
|
+
if (skipped == (numberToSkip || 0)) {
|
|
477
496
|
currentInterstitial = interstitial;
|
|
478
|
-
|
|
497
|
+
} else if (currentInterstitial && !interstitial.canJump) {
|
|
498
|
+
const currentStartTime =
|
|
499
|
+
roundDecimals(currentInterstitial.startTime);
|
|
500
|
+
const newStartTime =
|
|
501
|
+
roundDecimals(interstitial.startTime);
|
|
502
|
+
if (newStartTime - currentStartTime > 0.001) {
|
|
503
|
+
currentInterstitial = interstitial;
|
|
504
|
+
skipped = 0;
|
|
505
|
+
}
|
|
479
506
|
}
|
|
480
507
|
skipped++;
|
|
481
508
|
}
|
|
@@ -520,7 +547,7 @@ shaka.ads.InterstitialAdManager = class {
|
|
|
520
547
|
}).length;
|
|
521
548
|
}
|
|
522
549
|
|
|
523
|
-
if (interstitial.once
|
|
550
|
+
if (interstitial.once) {
|
|
524
551
|
oncePlayed++;
|
|
525
552
|
this.interstitials_.delete(interstitial);
|
|
526
553
|
this.cuepointsChanged_();
|
|
@@ -594,6 +621,10 @@ shaka.ads.InterstitialAdManager = class {
|
|
|
594
621
|
this.setupAd_(nextCurrentInterstitial, sequenceLength,
|
|
595
622
|
++adPosition, initialTime, oncePlayed);
|
|
596
623
|
} else {
|
|
624
|
+
if (interstitial.post) {
|
|
625
|
+
this.lastTime_ = null;
|
|
626
|
+
this.lastPlayedAd_ = null;
|
|
627
|
+
}
|
|
597
628
|
if (this.usingBaseVideo_) {
|
|
598
629
|
await this.player_.detach();
|
|
599
630
|
} else {
|
|
@@ -754,10 +785,16 @@ shaka.ads.InterstitialAdManager = class {
|
|
|
754
785
|
if (preloadManager) {
|
|
755
786
|
await this.player_.load(preloadManager);
|
|
756
787
|
} else {
|
|
757
|
-
await this.player_.load(
|
|
788
|
+
await this.player_.load(
|
|
789
|
+
interstitial.uri,
|
|
790
|
+
/* startTime= */ null,
|
|
791
|
+
interstitial.mimeType || undefined);
|
|
758
792
|
}
|
|
759
793
|
} else {
|
|
760
|
-
await this.player_.load(
|
|
794
|
+
await this.player_.load(
|
|
795
|
+
interstitial.uri,
|
|
796
|
+
/* startTime= */ null,
|
|
797
|
+
interstitial.mimeType || undefined);
|
|
761
798
|
}
|
|
762
799
|
if (interstitial.playoutLimit) {
|
|
763
800
|
if (playoutLimitTimer) {
|
|
@@ -887,6 +924,7 @@ shaka.ads.InterstitialAdManager = class {
|
|
|
887
924
|
startTime,
|
|
888
925
|
endTime,
|
|
889
926
|
uri,
|
|
927
|
+
mimeType: null,
|
|
890
928
|
isSkippable,
|
|
891
929
|
skipOffset,
|
|
892
930
|
skipFor,
|
|
@@ -916,27 +954,29 @@ shaka.ads.InterstitialAdManager = class {
|
|
|
916
954
|
const skipControl = dataAsJson['SKIP-CONTROL'];
|
|
917
955
|
if (skipControl) {
|
|
918
956
|
const enableSkipAfterValue = skipControl['ENABLE-SKIP-AFTER'];
|
|
919
|
-
if (enableSkipAfterValue
|
|
957
|
+
if ((typeof enableSkipAfterValue) == 'number') {
|
|
920
958
|
skipOffset = parseFloat(enableSkipAfterValue);
|
|
921
959
|
if (isNaN(enableSkipAfterValue)) {
|
|
922
960
|
skipOffset = isSkippable ? 0 : null;
|
|
923
961
|
}
|
|
924
962
|
}
|
|
925
|
-
const enableSkipForValue = skipControl['
|
|
926
|
-
if (enableSkipForValue
|
|
963
|
+
const enableSkipForValue = skipControl['ENABLE-SKIP-FOR'];
|
|
964
|
+
if ((typeof enableSkipForValue) == 'number') {
|
|
927
965
|
skipFor = parseFloat(enableSkipForValue);
|
|
928
966
|
if (isNaN(enableSkipForValue)) {
|
|
929
967
|
skipFor = null;
|
|
930
968
|
}
|
|
931
969
|
}
|
|
932
970
|
}
|
|
933
|
-
for (
|
|
971
|
+
for (let i = 0; i < dataAsJson['ASSETS'].length; i++) {
|
|
972
|
+
const asset = dataAsJson['ASSETS'][i];
|
|
934
973
|
if (asset['URI']) {
|
|
935
974
|
interstitialsAd.push({
|
|
936
|
-
id,
|
|
975
|
+
id: id + '_asset_' + i,
|
|
937
976
|
startTime,
|
|
938
977
|
endTime,
|
|
939
978
|
uri: asset['URI'],
|
|
979
|
+
mimeType: null,
|
|
940
980
|
isSkippable,
|
|
941
981
|
skipOffset,
|
|
942
982
|
skipFor,
|
package/lib/cast/cast_utils.js
CHANGED
|
@@ -66,10 +66,12 @@ shaka.cast.CastUtils = class {
|
|
|
66
66
|
return shaka.cast.CastUtils.unpackTimeRanges_(value);
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
if (value
|
|
69
|
+
if (ArrayBuffer.isView(value) &&
|
|
70
|
+
/** @type {TypedArray} */(value).BYTES_PER_ELEMENT === 1) {
|
|
70
71
|
// Some of our code cares about Uint8Arrays actually being Uint8Arrays,
|
|
71
72
|
// so this gives them special treatment.
|
|
72
|
-
return shaka.cast.CastUtils.unpackUint8Array_(
|
|
73
|
+
return shaka.cast.CastUtils.unpackUint8Array_(
|
|
74
|
+
/** @type {!Uint8Array} */(value));
|
|
73
75
|
}
|
|
74
76
|
|
|
75
77
|
if (typeof value == 'number') {
|
|
@@ -23,12 +23,9 @@ shaka.media.Capabilities = class {
|
|
|
23
23
|
if (supportMap.has(type)) {
|
|
24
24
|
return supportMap.get(type);
|
|
25
25
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
return currentSupport;
|
|
30
|
-
} else if (window.MediaSource) {
|
|
31
|
-
const currentSupport = MediaSource.isTypeSupported(type);
|
|
26
|
+
const mediaSource = window.ManagedMediaSource || window.MediaSource;
|
|
27
|
+
if (mediaSource) {
|
|
28
|
+
const currentSupport = mediaSource.isTypeSupported(type);
|
|
32
29
|
supportMap.set(type, currentSupport);
|
|
33
30
|
return currentSupport;
|
|
34
31
|
}
|
|
@@ -40,9 +37,10 @@ shaka.media.Capabilities = class {
|
|
|
40
37
|
* @return {boolean}
|
|
41
38
|
*/
|
|
42
39
|
static isChangeTypeSupported() {
|
|
43
|
-
|
|
40
|
+
const sourceBuffer = window.ManagedSourceBuffer || window.SourceBuffer;
|
|
41
|
+
return !!sourceBuffer &&
|
|
44
42
|
// eslint-disable-next-line no-restricted-syntax
|
|
45
|
-
!!
|
|
43
|
+
!!sourceBuffer.prototype && !!sourceBuffer.prototype.changeType;
|
|
46
44
|
}
|
|
47
45
|
};
|
|
48
46
|
|
|
@@ -271,7 +271,7 @@ shaka.media.MediaSourceEngine = class {
|
|
|
271
271
|
* @param {string} mimeType
|
|
272
272
|
*/
|
|
273
273
|
addSecondarySource(uri, mimeType) {
|
|
274
|
-
if (!this.video_ || !
|
|
274
|
+
if (!this.video_ || !window.ManagedMediaSource || !this.mediaSource_) {
|
|
275
275
|
shaka.log.warning(
|
|
276
276
|
'Secondary source is used only with ManagedMediaSource');
|
|
277
277
|
return;
|
|
@@ -882,7 +882,7 @@ shaka.media.MediaSourceEngine = class {
|
|
|
882
882
|
return frame.description ===
|
|
883
883
|
'com.apple.streaming.transportStreamTimestamp';
|
|
884
884
|
});
|
|
885
|
-
if (metadataTimestamp
|
|
885
|
+
if (metadataTimestamp) {
|
|
886
886
|
timestamp = Math.round(metadataTimestamp.data) / 1000;
|
|
887
887
|
}
|
|
888
888
|
/** @private {shaka.extern.ID3Metadata} */
|
|
@@ -1139,8 +1139,7 @@ shaka.media.MediaSourceEngine = class {
|
|
|
1139
1139
|
const ContentType = shaka.util.ManifestParserUtils.ContentType;
|
|
1140
1140
|
|
|
1141
1141
|
if (contentType == ContentType.TEXT) {
|
|
1142
|
-
if (this.manifestType_ == shaka.media.ManifestParser.HLS
|
|
1143
|
-
reference.discontinuitySequence >= 0) {
|
|
1142
|
+
if (this.manifestType_ == shaka.media.ManifestParser.HLS) {
|
|
1144
1143
|
// This won't be known until the first video segment is appended.
|
|
1145
1144
|
const offset = await this.textSequenceModeOffset_;
|
|
1146
1145
|
this.textEngine_.setTimestampOffset(offset);
|
|
@@ -417,9 +417,13 @@ shaka.media.SegmentUtils = class {
|
|
|
417
417
|
if (initData) {
|
|
418
418
|
captionParser.init(initData);
|
|
419
419
|
}
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
420
|
+
try {
|
|
421
|
+
captionParser.parseFrom(data);
|
|
422
|
+
for (const stream of captionParser.getStreams()) {
|
|
423
|
+
closedCaptions.set(stream, stream);
|
|
424
|
+
}
|
|
425
|
+
} catch (e) {
|
|
426
|
+
shaka.log.debug('Error detecting CC streams', e);
|
|
423
427
|
}
|
|
424
428
|
captionParser.reset();
|
|
425
429
|
}
|
|
@@ -64,6 +64,7 @@ shaka.net.HttpXHRPlugin = class {
|
|
|
64
64
|
};
|
|
65
65
|
xhr.onload = (event) => {
|
|
66
66
|
const headers = shaka.net.HttpXHRPlugin.headersToGenericObject_(xhr);
|
|
67
|
+
// eslint-disable-next-line shaka-rules/buffersource-no-instanceof
|
|
67
68
|
goog.asserts.assert(xhr.response instanceof ArrayBuffer,
|
|
68
69
|
'XHR should have a response by now!');
|
|
69
70
|
const xhrResponse = xhr.response;
|
package/lib/player.js
CHANGED
|
@@ -58,6 +58,7 @@ goog.require('shaka.util.ManifestParserUtils');
|
|
|
58
58
|
goog.require('shaka.util.MediaReadyState');
|
|
59
59
|
goog.require('shaka.util.MimeUtils');
|
|
60
60
|
goog.require('shaka.util.Mutex');
|
|
61
|
+
goog.require('shaka.util.NumberUtils');
|
|
61
62
|
goog.require('shaka.util.ObjectUtils');
|
|
62
63
|
goog.require('shaka.util.Platform');
|
|
63
64
|
goog.require('shaka.util.PlayerConfiguration');
|
|
@@ -752,7 +753,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
752
753
|
this.externalSrcEqualsThumbnailsStreams_ = [];
|
|
753
754
|
|
|
754
755
|
/** @private {number} */
|
|
755
|
-
this.completionPercent_ =
|
|
756
|
+
this.completionPercent_ = -1;
|
|
756
757
|
|
|
757
758
|
/** @private {?shaka.extern.PlayerConfiguration} */
|
|
758
759
|
this.config_ = this.defaultConfig_();
|
|
@@ -1522,7 +1523,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
1522
1523
|
|
|
1523
1524
|
this.externalSrcEqualsThumbnailsStreams_ = [];
|
|
1524
1525
|
|
|
1525
|
-
this.completionPercent_ =
|
|
1526
|
+
this.completionPercent_ = -1;
|
|
1526
1527
|
|
|
1527
1528
|
// Make sure that the app knows of the new buffering state.
|
|
1528
1529
|
this.updateBufferState_();
|
|
@@ -7016,41 +7017,46 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
7016
7017
|
if (!this.video_) {
|
|
7017
7018
|
return;
|
|
7018
7019
|
}
|
|
7019
|
-
|
|
7020
|
-
const
|
|
7021
|
-
|
|
7022
|
-
|
|
7023
|
-
if (
|
|
7024
|
-
|
|
7025
|
-
|
|
7026
|
-
|
|
7027
|
-
|
|
7028
|
-
if (this.completionPercent_ != newCompletionPercent) {
|
|
7029
|
-
this.completionPercent_ = newCompletionPercent;
|
|
7030
|
-
hasNewCompletionPercent = true;
|
|
7031
|
-
}
|
|
7020
|
+
|
|
7021
|
+
const isQuartile = (quartilePercent, currentPercent) => {
|
|
7022
|
+
const NumberUtils = shaka.util.NumberUtils;
|
|
7023
|
+
|
|
7024
|
+
if ((NumberUtils.isFloatEqual(quartilePercent, currentPercent) ||
|
|
7025
|
+
currentPercent > quartilePercent) &&
|
|
7026
|
+
this.completionPercent_ < quartilePercent) {
|
|
7027
|
+
this.completionPercent_ = quartilePercent;
|
|
7028
|
+
return true;
|
|
7032
7029
|
}
|
|
7030
|
+
return false;
|
|
7031
|
+
};
|
|
7032
|
+
|
|
7033
|
+
const completionRatio = this.video_.currentTime / this.video_.duration;
|
|
7034
|
+
|
|
7035
|
+
if (isNaN(completionRatio)) {
|
|
7036
|
+
return;
|
|
7033
7037
|
}
|
|
7034
|
-
|
|
7035
|
-
|
|
7036
|
-
|
|
7037
|
-
|
|
7038
|
-
|
|
7039
|
-
|
|
7040
|
-
|
|
7041
|
-
|
|
7042
|
-
|
|
7043
|
-
|
|
7044
|
-
|
|
7045
|
-
|
|
7046
|
-
|
|
7047
|
-
|
|
7048
|
-
|
|
7049
|
-
|
|
7050
|
-
|
|
7051
|
-
|
|
7052
|
-
|
|
7053
|
-
|
|
7038
|
+
|
|
7039
|
+
const percent = completionRatio * 100;
|
|
7040
|
+
|
|
7041
|
+
let event;
|
|
7042
|
+
if (isQuartile(0, percent)) {
|
|
7043
|
+
event = shaka.Player.makeEvent_(shaka.util.FakeEvent.EventName.Started);
|
|
7044
|
+
} else if (isQuartile(25, percent)) {
|
|
7045
|
+
event = shaka.Player.makeEvent_(
|
|
7046
|
+
shaka.util.FakeEvent.EventName.FirstQuartile);
|
|
7047
|
+
} else if (isQuartile(50, percent)) {
|
|
7048
|
+
event = shaka.Player.makeEvent_(
|
|
7049
|
+
shaka.util.FakeEvent.EventName.Midpoint);
|
|
7050
|
+
} else if (isQuartile(75, percent)) {
|
|
7051
|
+
event = shaka.Player.makeEvent_(
|
|
7052
|
+
shaka.util.FakeEvent.EventName.ThirdQuartile);
|
|
7053
|
+
} else if (isQuartile(100, percent)) {
|
|
7054
|
+
event = shaka.Player.makeEvent_(
|
|
7055
|
+
shaka.util.FakeEvent.EventName.Complete);
|
|
7056
|
+
}
|
|
7057
|
+
|
|
7058
|
+
if (event) {
|
|
7059
|
+
this.dispatchEvent(event);
|
|
7054
7060
|
}
|
|
7055
7061
|
}
|
|
7056
7062
|
|
|
@@ -8269,7 +8275,7 @@ shaka.Player.TYPICAL_BUFFERING_THRESHOLD_ = 0.5;
|
|
|
8269
8275
|
* @export
|
|
8270
8276
|
*/
|
|
8271
8277
|
// eslint-disable-next-line no-useless-concat, max-len
|
|
8272
|
-
shaka.Player.version = 'v4.12.
|
|
8278
|
+
shaka.Player.version = 'v4.12.3' + '-uncompiled'; // x-release-please-version
|
|
8273
8279
|
|
|
8274
8280
|
// Initialize the deprecation system using the version string we just set
|
|
8275
8281
|
// on the player.
|
|
@@ -83,10 +83,15 @@ shaka.text.VttTextParser = class {
|
|
|
83
83
|
// HLS content, which should use X-TIMESTAMP-MAP and periodStart instead.
|
|
84
84
|
let offset = time.vttOffset;
|
|
85
85
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
86
|
+
if (this.manifestType_ == shaka.media.ManifestParser.HLS) {
|
|
87
|
+
// Only use 'X-TIMESTAMP-MAP' with HLS.
|
|
88
|
+
if (blocks[0].includes('X-TIMESTAMP-MAP')) {
|
|
89
|
+
offset = this.computeHlsOffset_(blocks[0], time);
|
|
90
|
+
} else if (time.periodStart && time.vttOffset == time.periodStart) {
|
|
91
|
+
// In the case where X-TIMESTAMP-MAP is not used and it is HLS, we
|
|
92
|
+
// should not use offset unless segment-relative times are used.
|
|
93
|
+
offset = 0;
|
|
94
|
+
}
|
|
90
95
|
}
|
|
91
96
|
|
|
92
97
|
// Parse VTT regions.
|
|
@@ -166,6 +166,9 @@ shaka.util.AbortableOperation = class {
|
|
|
166
166
|
*/
|
|
167
167
|
chain(onSuccess, onError) {
|
|
168
168
|
const newPromise = new shaka.util.PublicPromise();
|
|
169
|
+
// Silence uncaught rejection errors, which may otherwise occur any place
|
|
170
|
+
// we don't explicitly handle aborted operations.
|
|
171
|
+
newPromise.catch(() => {});
|
|
169
172
|
const abortError = shaka.util.AbortableOperation.abortError();
|
|
170
173
|
|
|
171
174
|
// If called before "this" completes, just abort "this".
|
package/lib/util/buffer_utils.js
CHANGED
|
@@ -62,10 +62,10 @@ shaka.util.BufferUtils = class {
|
|
|
62
62
|
* @private
|
|
63
63
|
*/
|
|
64
64
|
static unsafeGetArrayBuffer_(view) {
|
|
65
|
-
if (view
|
|
66
|
-
return view;
|
|
65
|
+
if (!ArrayBuffer.isView(view)) {
|
|
66
|
+
return /** @type {!ArrayBuffer} */(view);
|
|
67
67
|
} else {
|
|
68
|
-
return view.buffer;
|
|
68
|
+
return /** @type {!ArrayBufferView} */(view).buffer;
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
71
|
|
|
@@ -79,17 +79,19 @@ shaka.util.BufferUtils = class {
|
|
|
79
79
|
* @export
|
|
80
80
|
*/
|
|
81
81
|
static toArrayBuffer(view) {
|
|
82
|
-
if (view
|
|
83
|
-
return view;
|
|
82
|
+
if (!ArrayBuffer.isView(view)) {
|
|
83
|
+
return /** @type {!ArrayBuffer} */(view);
|
|
84
84
|
} else {
|
|
85
|
-
|
|
85
|
+
const aView = /** @type {!ArrayBufferView} */(view);
|
|
86
|
+
if (aView.byteOffset == 0 &&
|
|
87
|
+
aView.byteLength == aView.buffer.byteLength) {
|
|
86
88
|
// This is a TypedArray over the whole buffer.
|
|
87
|
-
return
|
|
89
|
+
return aView.buffer;
|
|
88
90
|
}
|
|
89
91
|
// This is a "view" on the buffer. Create a new buffer that only contains
|
|
90
92
|
// the data. Note that since this isn't an ArrayBuffer, the "new" call
|
|
91
93
|
// will allocate a new buffer to hold the copy.
|
|
92
|
-
return new Uint8Array(
|
|
94
|
+
return new Uint8Array(aView).buffer;
|
|
93
95
|
}
|
|
94
96
|
}
|
|
95
97
|
|
package/lib/util/mime_utils.js
CHANGED
|
@@ -166,6 +166,8 @@ shaka.util.MimeUtils = class {
|
|
|
166
166
|
return 'dtsx'; // DTS:X
|
|
167
167
|
case base === 'mp4a' && profile === 'a9':
|
|
168
168
|
return 'dtsc'; // DTS Digital Surround
|
|
169
|
+
case base === 'vp09':
|
|
170
|
+
return 'vp9';
|
|
169
171
|
case base === 'avc1':
|
|
170
172
|
case base === 'avc3':
|
|
171
173
|
return 'avc'; // H264
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/*! @license
|
|
2
|
+
* Shaka Player
|
|
3
|
+
* Copyright 2016 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
goog.provide('shaka.util.NumberUtils');
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
shaka.util.NumberUtils = class {
|
|
11
|
+
/**
|
|
12
|
+
* Compare two float numbers, taking a configurable tolerance margin into
|
|
13
|
+
* account.
|
|
14
|
+
*
|
|
15
|
+
* @param {number} a
|
|
16
|
+
* @param {number} b
|
|
17
|
+
* @param {number=} tolerance
|
|
18
|
+
* @return {boolean}
|
|
19
|
+
*/
|
|
20
|
+
static isFloatEqual(a, b, tolerance = Number.EPSILON) {
|
|
21
|
+
if (a === b) {
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const error = Math.abs(a - b);
|
|
26
|
+
|
|
27
|
+
if (error <= tolerance) {
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (tolerance !== Number.EPSILON) {
|
|
32
|
+
return Math.abs(error - tolerance) <= Number.EPSILON;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
};
|
package/lib/util/object_utils.js
CHANGED
|
@@ -41,7 +41,7 @@ shaka.util.ObjectUtils = class {
|
|
|
41
41
|
|
|
42
42
|
// This covers Uint8Array and friends, even without a TypedArray
|
|
43
43
|
// base-class constructor.
|
|
44
|
-
const isTypedArray = val
|
|
44
|
+
const isTypedArray = ArrayBuffer.isView(val);
|
|
45
45
|
if (isTypedArray) {
|
|
46
46
|
return val;
|
|
47
47
|
}
|
|
@@ -119,8 +119,9 @@ shaka.util.Uint8ArrayUtils = class {
|
|
|
119
119
|
|
|
120
120
|
for (let i = 0; i < varArgs.length; ++i) {
|
|
121
121
|
const value = varArgs[i];
|
|
122
|
-
if (value
|
|
123
|
-
|
|
122
|
+
if (ArrayBuffer.isView(value) &&
|
|
123
|
+
/** @type {TypedArray} */ (value).BYTES_PER_ELEMENT === 1) {
|
|
124
|
+
result.set(/** @type {!Uint8Array} */(value), offset);
|
|
124
125
|
} else {
|
|
125
126
|
result.set(BufferUtils.toUint8(value), offset);
|
|
126
127
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "shaka-player",
|
|
3
3
|
"description": "DASH/EME video player library",
|
|
4
|
-
"version": "4.12.
|
|
4
|
+
"version": "4.12.3",
|
|
5
5
|
"homepage": "https://github.com/shaka-project/shaka-player",
|
|
6
6
|
"author": "Google",
|
|
7
7
|
"maintainers": [
|
|
@@ -105,7 +105,7 @@
|
|
|
105
105
|
"prepublishOnly": "python build/checkversion.py && python build/all.py --force"
|
|
106
106
|
},
|
|
107
107
|
"dependencies": {
|
|
108
|
-
"eme-encryption-scheme-polyfill": "^2.1.
|
|
108
|
+
"eme-encryption-scheme-polyfill": "^2.1.6"
|
|
109
109
|
},
|
|
110
110
|
"clean-package": {
|
|
111
111
|
"remove": [
|
package/ui/language_utils.js
CHANGED
|
@@ -14,6 +14,7 @@ goog.require('shaka.ui.Overlay.TrackLabelFormat');
|
|
|
14
14
|
goog.require('shaka.ui.Utils');
|
|
15
15
|
goog.require('shaka.util.Dom');
|
|
16
16
|
goog.require('shaka.util.LanguageUtils');
|
|
17
|
+
goog.require('shaka.util.MimeUtils');
|
|
17
18
|
goog.requireType('shaka.ui.Localization');
|
|
18
19
|
|
|
19
20
|
|
|
@@ -48,7 +49,8 @@ shaka.ui.LanguageUtils = class {
|
|
|
48
49
|
if (!codecsByLanguage.has(track.language)) {
|
|
49
50
|
codecsByLanguage.set(track.language, new Set());
|
|
50
51
|
}
|
|
51
|
-
codecsByLanguage.get(track.language).add(
|
|
52
|
+
codecsByLanguage.get(track.language).add(
|
|
53
|
+
shaka.util.MimeUtils.getNormalizedCodec(track.audioCodec));
|
|
52
54
|
}
|
|
53
55
|
const hasDifferentAudioCodecs = (language) =>
|
|
54
56
|
codecsByLanguage.has(language) && codecsByLanguage.get(language).size > 1;
|