shaka-player 4.10.3 → 4.10.4
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/dist/deps.js +3 -3
- package/dist/locales.js +35 -35
- package/dist/shaka-player.compiled.debug.js +336 -334
- package/dist/shaka-player.compiled.debug.map +4 -4
- package/dist/shaka-player.compiled.js +1215 -1215
- package/dist/shaka-player.compiled.map +3 -3
- package/dist/shaka-player.ui.debug.js +309 -307
- package/dist/shaka-player.ui.debug.map +4 -4
- package/dist/shaka-player.ui.js +1436 -1436
- package/dist/shaka-player.ui.map +3 -3
- package/lib/ads/interstitial_ad_manager.js +3 -3
- package/lib/hls/hls_parser.js +24 -14
- package/lib/media/playhead.js +15 -6
- package/lib/media/segment_utils.js +41 -0
- package/lib/media/streaming_engine.js +12 -62
- package/lib/player.js +12 -8
- package/lib/util/platform.js +19 -0
- package/lib/util/stream_utils.js +4 -2
- package/package.json +1 -1
|
@@ -647,12 +647,12 @@ shaka.ads.InterstitialAdManager = class {
|
|
|
647
647
|
const dataAsJson =
|
|
648
648
|
/** @type {!shaka.ads.InterstitialAdManager.AssetsList} */ (
|
|
649
649
|
JSON.parse(data));
|
|
650
|
-
for (const asset of dataAsJson
|
|
651
|
-
if (asset
|
|
650
|
+
for (const asset of dataAsJson['ASSETS']) {
|
|
651
|
+
if (asset['URI']) {
|
|
652
652
|
interstitialsAd.push({
|
|
653
653
|
startTime: interstitial.startTime,
|
|
654
654
|
endTime: interstitial.endTime,
|
|
655
|
-
uri: asset
|
|
655
|
+
uri: asset['URI'],
|
|
656
656
|
isSkippable,
|
|
657
657
|
canJump,
|
|
658
658
|
resumeOffset,
|
package/lib/hls/hls_parser.js
CHANGED
|
@@ -1019,7 +1019,7 @@ shaka.hls.HlsParser = class {
|
|
|
1019
1019
|
if (!segments.length) {
|
|
1020
1020
|
return defaultBasicInfo;
|
|
1021
1021
|
}
|
|
1022
|
-
const segment = this.getAvailableSegment_(segments);
|
|
1022
|
+
const {segment, segmentIndex} = this.getAvailableSegment_(segments);
|
|
1023
1023
|
const segmentUris = segment.getUris();
|
|
1024
1024
|
const segmentUri = segmentUris[0];
|
|
1025
1025
|
const parsedUri = new goog.Uri(segmentUri);
|
|
@@ -1044,6 +1044,10 @@ shaka.hls.HlsParser = class {
|
|
|
1044
1044
|
const initResponse = await this.makeNetworkRequest_(
|
|
1045
1045
|
initSegmentRequest, requestType, {type: initType});
|
|
1046
1046
|
initData = initResponse.data;
|
|
1047
|
+
if (initSegmentRef.aesKey) {
|
|
1048
|
+
initData = await shaka.media.SegmentUtils.aesDecrypt(
|
|
1049
|
+
initData, initSegmentRef.aesKey, 0);
|
|
1050
|
+
}
|
|
1047
1051
|
|
|
1048
1052
|
initMimeType = initResponse.headers['content-type'];
|
|
1049
1053
|
if (initMimeType) {
|
|
@@ -1058,6 +1062,11 @@ shaka.hls.HlsParser = class {
|
|
|
1058
1062
|
const type = shaka.net.NetworkingEngine.AdvancedRequestType.MEDIA_SEGMENT;
|
|
1059
1063
|
const response = await this.makeNetworkRequest_(
|
|
1060
1064
|
segmentRequest, requestType, {type});
|
|
1065
|
+
let data = response.data;
|
|
1066
|
+
if (segment.aesKey) {
|
|
1067
|
+
data = await shaka.media.SegmentUtils.aesDecrypt(
|
|
1068
|
+
data, segment.aesKey, segmentIndex);
|
|
1069
|
+
}
|
|
1061
1070
|
|
|
1062
1071
|
let contentMimeType = response.headers['content-type'];
|
|
1063
1072
|
if (contentMimeType) {
|
|
@@ -1085,9 +1094,9 @@ shaka.hls.HlsParser = class {
|
|
|
1085
1094
|
];
|
|
1086
1095
|
|
|
1087
1096
|
if (shaka.util.TsParser.probe(
|
|
1088
|
-
shaka.util.BufferUtils.toUint8(
|
|
1097
|
+
shaka.util.BufferUtils.toUint8(data))) {
|
|
1089
1098
|
const basicInfo =
|
|
1090
|
-
shaka.media.SegmentUtils.getBasicInfoFromTs(
|
|
1099
|
+
shaka.media.SegmentUtils.getBasicInfoFromTs(data);
|
|
1091
1100
|
if (basicInfo) {
|
|
1092
1101
|
return basicInfo;
|
|
1093
1102
|
}
|
|
@@ -1095,7 +1104,7 @@ shaka.hls.HlsParser = class {
|
|
|
1095
1104
|
validMp4MimeType.includes(contentMimeType) ||
|
|
1096
1105
|
(initMimeType && validMp4MimeType.includes(initMimeType))) {
|
|
1097
1106
|
const basicInfo = shaka.media.SegmentUtils.getBasicInfoFromMp4(
|
|
1098
|
-
initData,
|
|
1107
|
+
initData, data);
|
|
1099
1108
|
if (basicInfo) {
|
|
1100
1109
|
return basicInfo;
|
|
1101
1110
|
}
|
|
@@ -1579,7 +1588,7 @@ shaka.hls.HlsParser = class {
|
|
|
1579
1588
|
videoLayout = videoLayout || 'CH-MONO';
|
|
1580
1589
|
|
|
1581
1590
|
const streamInfos = this.createStreamInfosForVariantTags_(tags,
|
|
1582
|
-
mediaTags, resolution, frameRate
|
|
1591
|
+
mediaTags, resolution, frameRate);
|
|
1583
1592
|
|
|
1584
1593
|
goog.asserts.assert(streamInfos.audio.length ||
|
|
1585
1594
|
streamInfos.video.length, 'We should have created a stream!');
|
|
@@ -1607,12 +1616,10 @@ shaka.hls.HlsParser = class {
|
|
|
1607
1616
|
* @param {!Array.<!shaka.hls.Tag>} mediaTags
|
|
1608
1617
|
* @param {?string} resolution
|
|
1609
1618
|
* @param {?string} frameRate
|
|
1610
|
-
* @param {number} bandwidth
|
|
1611
1619
|
* @return {!shaka.hls.HlsParser.StreamInfos}
|
|
1612
1620
|
* @private
|
|
1613
1621
|
*/
|
|
1614
|
-
createStreamInfosForVariantTags_(
|
|
1615
|
-
tags, mediaTags, resolution, frameRate, bandwidth) {
|
|
1622
|
+
createStreamInfosForVariantTags_(tags, mediaTags, resolution, frameRate) {
|
|
1616
1623
|
const ContentType = shaka.util.ManifestParserUtils.ContentType;
|
|
1617
1624
|
|
|
1618
1625
|
/** @type {shaka.hls.HlsParser.StreamInfos} */
|
|
@@ -1747,9 +1754,6 @@ shaka.hls.HlsParser = class {
|
|
|
1747
1754
|
if (globalGroupId) {
|
|
1748
1755
|
streamInfo.stream.groupId = globalGroupId;
|
|
1749
1756
|
}
|
|
1750
|
-
if (!streamInfos.length) {
|
|
1751
|
-
streamInfo.stream.bandwidth = bandwidth;
|
|
1752
|
-
}
|
|
1753
1757
|
res[streamInfo.stream.type] = [streamInfo];
|
|
1754
1758
|
}
|
|
1755
1759
|
return res;
|
|
@@ -1971,6 +1975,12 @@ shaka.hls.HlsParser = class {
|
|
|
1971
1975
|
videoStream.drmInfos = drmInfos;
|
|
1972
1976
|
videoStream.keyIds = keyIds;
|
|
1973
1977
|
}
|
|
1978
|
+
if (videoStream && !audioStream) {
|
|
1979
|
+
videoStream.bandwidth = bandwidth;
|
|
1980
|
+
}
|
|
1981
|
+
if (!videoStream && audioStream) {
|
|
1982
|
+
audioStream.bandwidth = bandwidth;
|
|
1983
|
+
}
|
|
1974
1984
|
const audioDrmInfos = audioInfo ? audioInfo.stream.drmInfos : null;
|
|
1975
1985
|
const videoDrmInfos = videoInfo ? videoInfo.stream.drmInfos : null;
|
|
1976
1986
|
const videoStreamUri =
|
|
@@ -4224,7 +4234,7 @@ shaka.hls.HlsParser = class {
|
|
|
4224
4234
|
|
|
4225
4235
|
/**
|
|
4226
4236
|
* @param {!Array.<!shaka.media.SegmentReference>} segments
|
|
4227
|
-
* @return {!shaka.media.SegmentReference}
|
|
4237
|
+
* @return {{segment: !shaka.media.SegmentReference, segmentIndex: number}}
|
|
4228
4238
|
* @private
|
|
4229
4239
|
*/
|
|
4230
4240
|
getAvailableSegment_(segments) {
|
|
@@ -4241,7 +4251,7 @@ shaka.hls.HlsParser = class {
|
|
|
4241
4251
|
segmentIndex ++;
|
|
4242
4252
|
segment = segments[segmentIndex];
|
|
4243
4253
|
}
|
|
4244
|
-
return segment;
|
|
4254
|
+
return {segment, segmentIndex};
|
|
4245
4255
|
}
|
|
4246
4256
|
|
|
4247
4257
|
/**
|
|
@@ -4257,7 +4267,7 @@ shaka.hls.HlsParser = class {
|
|
|
4257
4267
|
const HlsParser = shaka.hls.HlsParser;
|
|
4258
4268
|
const requestType = shaka.net.NetworkingEngine.RequestType.SEGMENT;
|
|
4259
4269
|
|
|
4260
|
-
const segment = this.getAvailableSegment_(segments);
|
|
4270
|
+
const {segment} = this.getAvailableSegment_(segments);
|
|
4261
4271
|
|
|
4262
4272
|
if (segment.status == shaka.media.SegmentReference.Status.MISSING) {
|
|
4263
4273
|
return this.guessMimeTypeFallback_(contentType);
|
package/lib/media/playhead.js
CHANGED
|
@@ -18,6 +18,7 @@ goog.require('shaka.media.VideoWrapper');
|
|
|
18
18
|
goog.require('shaka.util.EventManager');
|
|
19
19
|
goog.require('shaka.util.IReleasable');
|
|
20
20
|
goog.require('shaka.util.MediaReadyState');
|
|
21
|
+
goog.require('shaka.util.Platform');
|
|
21
22
|
goog.require('shaka.util.Timer');
|
|
22
23
|
goog.requireType('shaka.media.PresentationTimeline');
|
|
23
24
|
|
|
@@ -420,12 +421,20 @@ shaka.media.MediaSourcePlayhead = class {
|
|
|
420
421
|
|
|
421
422
|
const gapLimit = shaka.media.GapJumpingController.BROWSER_GAP_TOLERANCE;
|
|
422
423
|
if (Math.abs(targetTime - currentTime) > gapLimit) {
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
424
|
+
let canCorrectiveSeek = false;
|
|
425
|
+
if (shaka.util.Platform.isSeekingSlow()) {
|
|
426
|
+
// You can only seek like this every so often. This is to prevent an
|
|
427
|
+
// infinite loop on systems where changing currentTime takes a
|
|
428
|
+
// significant amount of time (e.g. Chromecast).
|
|
429
|
+
const time = Date.now() / 1000;
|
|
430
|
+
if (!this.lastCorrectiveSeek_ || this.lastCorrectiveSeek_ < time - 1) {
|
|
431
|
+
this.lastCorrectiveSeek_ = time;
|
|
432
|
+
canCorrectiveSeek = true;
|
|
433
|
+
}
|
|
434
|
+
} else {
|
|
435
|
+
canCorrectiveSeek = true;
|
|
436
|
+
}
|
|
437
|
+
if (canCorrectiveSeek) {
|
|
429
438
|
this.videoWrapper_.setTime(targetTime);
|
|
430
439
|
return;
|
|
431
440
|
}
|
|
@@ -534,6 +534,47 @@ shaka.media.SegmentUtils = class {
|
|
|
534
534
|
.parse(data, /* partialOkay= */ true);
|
|
535
535
|
return defaultKID;
|
|
536
536
|
}
|
|
537
|
+
|
|
538
|
+
/**
|
|
539
|
+
* @param {!BufferSource} rawResult
|
|
540
|
+
* @param {shaka.extern.aesKey} aesKey
|
|
541
|
+
* @param {number} position
|
|
542
|
+
* @return {!Promise.<!BufferSource>}
|
|
543
|
+
*/
|
|
544
|
+
static async aesDecrypt(rawResult, aesKey, position) {
|
|
545
|
+
const key = aesKey;
|
|
546
|
+
if (!key.cryptoKey) {
|
|
547
|
+
goog.asserts.assert(key.fetchKey, 'If AES cryptoKey was not ' +
|
|
548
|
+
'preloaded, fetchKey function should be provided');
|
|
549
|
+
await key.fetchKey();
|
|
550
|
+
goog.asserts.assert(key.cryptoKey, 'AES cryptoKey should now be set');
|
|
551
|
+
}
|
|
552
|
+
let iv = key.iv;
|
|
553
|
+
if (!iv) {
|
|
554
|
+
iv = shaka.util.BufferUtils.toUint8(new ArrayBuffer(16));
|
|
555
|
+
let sequence = key.firstMediaSequenceNumber + position;
|
|
556
|
+
for (let i = iv.byteLength - 1; i >= 0; i--) {
|
|
557
|
+
iv[i] = sequence & 0xff;
|
|
558
|
+
sequence >>= 8;
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
let algorithm;
|
|
562
|
+
if (aesKey.blockCipherMode == 'CBC') {
|
|
563
|
+
algorithm = {
|
|
564
|
+
name: 'AES-CBC',
|
|
565
|
+
iv,
|
|
566
|
+
};
|
|
567
|
+
} else {
|
|
568
|
+
algorithm = {
|
|
569
|
+
name: 'AES-CTR',
|
|
570
|
+
counter: iv,
|
|
571
|
+
// NIST SP800-38A standard suggests that the counter should occupy half
|
|
572
|
+
// of the counter block
|
|
573
|
+
length: 64,
|
|
574
|
+
};
|
|
575
|
+
}
|
|
576
|
+
return window.crypto.subtle.decrypt(algorithm, key.cryptoKey, rawResult);
|
|
577
|
+
}
|
|
537
578
|
};
|
|
538
579
|
|
|
539
580
|
|
|
@@ -18,9 +18,9 @@ goog.require('shaka.media.MediaSourceEngine');
|
|
|
18
18
|
goog.require('shaka.media.SegmentIterator');
|
|
19
19
|
goog.require('shaka.media.SegmentReference');
|
|
20
20
|
goog.require('shaka.media.SegmentPrefetch');
|
|
21
|
+
goog.require('shaka.media.SegmentUtils');
|
|
21
22
|
goog.require('shaka.net.Backoff');
|
|
22
23
|
goog.require('shaka.net.NetworkingEngine');
|
|
23
|
-
goog.require('shaka.util.BufferUtils');
|
|
24
24
|
goog.require('shaka.util.DelayedTick');
|
|
25
25
|
goog.require('shaka.util.Destroyer');
|
|
26
26
|
goog.require('shaka.util.Error');
|
|
@@ -769,25 +769,16 @@ shaka.media.StreamingEngine = class {
|
|
|
769
769
|
const mediaState = this.mediaStates_.get(type);
|
|
770
770
|
const logPrefix = shaka.media.StreamingEngine.logPrefix_(mediaState);
|
|
771
771
|
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
for (const prefetch of this.audioPrefetchMap_.values()) {
|
|
781
|
-
prefetch.resetPosition();
|
|
772
|
+
if (!newTimeIsBuffered(type)) {
|
|
773
|
+
if (mediaState.segmentPrefetch) {
|
|
774
|
+
mediaState.segmentPrefetch.resetPosition();
|
|
775
|
+
}
|
|
776
|
+
if (mediaState.type === ContentType.AUDIO) {
|
|
777
|
+
for (const prefetch of this.audioPrefetchMap_.values()) {
|
|
778
|
+
prefetch.resetPosition();
|
|
779
|
+
}
|
|
782
780
|
}
|
|
783
|
-
}
|
|
784
|
-
// Only reset the iterator if we seek outside the current segment.
|
|
785
|
-
if (!segment || segment.startTime > presentationTime ||
|
|
786
|
-
segment.endTime < presentationTime) {
|
|
787
781
|
mediaState.segmentIterator = null;
|
|
788
|
-
}
|
|
789
|
-
|
|
790
|
-
if (!newTimeIsBuffered(type)) {
|
|
791
782
|
const bufferEnd =
|
|
792
783
|
this.playerInterface_.mediaSourceEngine.bufferEnd(type);
|
|
793
784
|
const somethingBuffered = bufferEnd != null;
|
|
@@ -1400,7 +1391,7 @@ shaka.media.StreamingEngine = class {
|
|
|
1400
1391
|
|
|
1401
1392
|
if (mediaState.segmentPrefetch && mediaState.segmentIterator &&
|
|
1402
1393
|
!this.audioPrefetchMap_.has(mediaState.stream)) {
|
|
1403
|
-
mediaState.segmentPrefetch.evict(
|
|
1394
|
+
mediaState.segmentPrefetch.evict(reference.startTime);
|
|
1404
1395
|
mediaState.segmentPrefetch.prefetchSegmentsByTime(reference.startTime);
|
|
1405
1396
|
}
|
|
1406
1397
|
|
|
@@ -1758,48 +1749,6 @@ shaka.media.StreamingEngine = class {
|
|
|
1758
1749
|
}
|
|
1759
1750
|
}
|
|
1760
1751
|
|
|
1761
|
-
/**
|
|
1762
|
-
* @param {!BufferSource} rawResult
|
|
1763
|
-
* @param {shaka.extern.aesKey} aesKey
|
|
1764
|
-
* @param {number} position
|
|
1765
|
-
* @return {!Promise.<!BufferSource>} finalResult
|
|
1766
|
-
* @private
|
|
1767
|
-
*/
|
|
1768
|
-
async aesDecrypt_(rawResult, aesKey, position) {
|
|
1769
|
-
const key = aesKey;
|
|
1770
|
-
if (!key.cryptoKey) {
|
|
1771
|
-
goog.asserts.assert(key.fetchKey, 'If AES cryptoKey was not ' +
|
|
1772
|
-
'preloaded, fetchKey function should be provided');
|
|
1773
|
-
await key.fetchKey();
|
|
1774
|
-
goog.asserts.assert(key.cryptoKey, 'AES cryptoKey should now be set');
|
|
1775
|
-
}
|
|
1776
|
-
let iv = key.iv;
|
|
1777
|
-
if (!iv) {
|
|
1778
|
-
iv = shaka.util.BufferUtils.toUint8(new ArrayBuffer(16));
|
|
1779
|
-
let sequence = key.firstMediaSequenceNumber + position;
|
|
1780
|
-
for (let i = iv.byteLength - 1; i >= 0; i--) {
|
|
1781
|
-
iv[i] = sequence & 0xff;
|
|
1782
|
-
sequence >>= 8;
|
|
1783
|
-
}
|
|
1784
|
-
}
|
|
1785
|
-
let algorithm;
|
|
1786
|
-
if (aesKey.blockCipherMode == 'CBC') {
|
|
1787
|
-
algorithm = {
|
|
1788
|
-
name: 'AES-CBC',
|
|
1789
|
-
iv,
|
|
1790
|
-
};
|
|
1791
|
-
} else {
|
|
1792
|
-
algorithm = {
|
|
1793
|
-
name: 'AES-CTR',
|
|
1794
|
-
counter: iv,
|
|
1795
|
-
// NIST SP800-38A standard suggests that the counter should occupy half
|
|
1796
|
-
// of the counter block
|
|
1797
|
-
length: 64,
|
|
1798
|
-
};
|
|
1799
|
-
}
|
|
1800
|
-
return window.crypto.subtle.decrypt(algorithm, key.cryptoKey, rawResult);
|
|
1801
|
-
}
|
|
1802
|
-
|
|
1803
1752
|
|
|
1804
1753
|
/**
|
|
1805
1754
|
* Clear per-stream error states and retry any failed streams.
|
|
@@ -2576,7 +2525,8 @@ shaka.media.StreamingEngine = class {
|
|
|
2576
2525
|
mediaState.operation = null;
|
|
2577
2526
|
let result = response.data;
|
|
2578
2527
|
if (reference.aesKey) {
|
|
2579
|
-
result = await
|
|
2528
|
+
result = await shaka.media.SegmentUtils.aesDecrypt(
|
|
2529
|
+
result, reference.aesKey, position);
|
|
2580
2530
|
}
|
|
2581
2531
|
return result;
|
|
2582
2532
|
}
|
package/lib/player.js
CHANGED
|
@@ -4862,13 +4862,6 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
4862
4862
|
*/
|
|
4863
4863
|
selectVariantTrack(track, clearBuffer = false, safeMargin = 0) {
|
|
4864
4864
|
if (this.manifest_ && this.streamingEngine_) {
|
|
4865
|
-
if (this.config_.abr.enabled) {
|
|
4866
|
-
shaka.log.alwaysWarn('Changing tracks while abr manager is enabled ' +
|
|
4867
|
-
'will likely result in the selected track ' +
|
|
4868
|
-
'being overriden. Consider disabling abr before ' +
|
|
4869
|
-
'calling selectVariantTrack().');
|
|
4870
|
-
}
|
|
4871
|
-
|
|
4872
4865
|
const variant = this.manifest_.variants.find(
|
|
4873
4866
|
(variant) => variant.id == track.id);
|
|
4874
4867
|
if (!variant) {
|
|
@@ -4885,6 +4878,17 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
4885
4878
|
return;
|
|
4886
4879
|
}
|
|
4887
4880
|
|
|
4881
|
+
const active = this.streamingEngine_.getCurrentVariant();
|
|
4882
|
+
if (this.config_.abr.enabled && (active.video != variant.video ||
|
|
4883
|
+
(active.audio && variant.audio &&
|
|
4884
|
+
active.audio.language == variant.audio.language &&
|
|
4885
|
+
active.audio.channelsCount == variant.audio.channelsCount))) {
|
|
4886
|
+
shaka.log.alwaysWarn('Changing tracks while abr manager is enabled ' +
|
|
4887
|
+
'will likely result in the selected track ' +
|
|
4888
|
+
'being overriden. Consider disabling abr before ' +
|
|
4889
|
+
'calling selectVariantTrack().');
|
|
4890
|
+
}
|
|
4891
|
+
|
|
4888
4892
|
this.switchVariant_(
|
|
4889
4893
|
variant, /* fromAdaptation= */ false, clearBuffer, safeMargin);
|
|
4890
4894
|
|
|
@@ -7809,7 +7813,7 @@ shaka.Player.TYPICAL_BUFFERING_THRESHOLD_ = 0.5;
|
|
|
7809
7813
|
* @export
|
|
7810
7814
|
*/
|
|
7811
7815
|
// eslint-disable-next-line no-useless-concat
|
|
7812
|
-
shaka.Player.version = 'v4.10.
|
|
7816
|
+
shaka.Player.version = 'v4.10.4' + '-uncompiled'; // x-release-please-version
|
|
7813
7817
|
|
|
7814
7818
|
// Initialize the deprecation system using the version string we just set
|
|
7815
7819
|
// on the player.
|
package/lib/util/platform.js
CHANGED
|
@@ -645,6 +645,25 @@ shaka.util.Platform = class {
|
|
|
645
645
|
return true;
|
|
646
646
|
}
|
|
647
647
|
|
|
648
|
+
/**
|
|
649
|
+
* On some platforms, such as v1 Chromecasts, the act of seeking can take a
|
|
650
|
+
* significant amount of time.
|
|
651
|
+
*
|
|
652
|
+
* @return {boolean}
|
|
653
|
+
*/
|
|
654
|
+
static isSeekingSlow() {
|
|
655
|
+
const Platform = shaka.util.Platform;
|
|
656
|
+
if (Platform.isChromecast()) {
|
|
657
|
+
if (Platform.isAndroidCastDevice()) {
|
|
658
|
+
// Android-based Chromecasts are new enough to not be a problem.
|
|
659
|
+
return false;
|
|
660
|
+
} else {
|
|
661
|
+
return true;
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
return false;
|
|
665
|
+
}
|
|
666
|
+
|
|
648
667
|
/**
|
|
649
668
|
* Returns true if MediaKeys is polyfilled
|
|
650
669
|
*
|
package/lib/util/stream_utils.js
CHANGED
|
@@ -108,7 +108,8 @@ shaka.util.StreamUtils = class {
|
|
|
108
108
|
const currentCodec =
|
|
109
109
|
MimeUtils.getNormalizedCodec(stream.codecs);
|
|
110
110
|
if (previousCodec == currentCodec) {
|
|
111
|
-
if (stream.bandwidth
|
|
111
|
+
if (!stream.bandwidth || !previousStream.bandwidth ||
|
|
112
|
+
stream.bandwidth > previousStream.bandwidth) {
|
|
112
113
|
validAudioStreams.push(stream);
|
|
113
114
|
validAudioIds.push(stream.id);
|
|
114
115
|
}
|
|
@@ -162,7 +163,8 @@ shaka.util.StreamUtils = class {
|
|
|
162
163
|
const currentCodec =
|
|
163
164
|
MimeUtils.getNormalizedCodec(stream.codecs);
|
|
164
165
|
if (previousCodec == currentCodec) {
|
|
165
|
-
if (stream.bandwidth
|
|
166
|
+
if (!stream.bandwidth || !previousStream.bandwidth ||
|
|
167
|
+
stream.bandwidth > previousStream.bandwidth) {
|
|
166
168
|
validVideoStreams.push(stream);
|
|
167
169
|
validVideoIds.push(stream.id);
|
|
168
170
|
}
|