shaka-player 4.10.21 → 4.10.23
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 +2 -2
- package/dist/locales.js +35 -35
- package/dist/shaka-player.compiled.debug.js +227 -230
- package/dist/shaka-player.compiled.debug.map +3 -3
- package/dist/shaka-player.compiled.js +487 -486
- package/dist/shaka-player.compiled.map +3 -3
- package/dist/shaka-player.ui.debug.js +69 -71
- package/dist/shaka-player.ui.debug.map +3 -3
- package/dist/shaka-player.ui.js +485 -484
- package/dist/shaka-player.ui.map +3 -3
- package/lib/dash/dash_parser.js +39 -11
- package/lib/dash/segment_template.js +1 -1
- package/lib/media/drm_engine.js +11 -114
- package/lib/media/media_source_engine.js +19 -30
- package/lib/media/playhead.js +3 -1
- package/lib/player.js +6 -1
- package/lib/util/platform.js +3 -2
- package/lib/util/player_configuration.js +3 -1
- package/package.json +1 -1
- package/ui/externs/ui.js +2 -1
- package/ui/remote_button.js +3 -2
- package/ui/save_video_frame_button.js +3 -0
- package/ui/ui.js +6 -4
package/lib/dash/dash_parser.js
CHANGED
|
@@ -1322,11 +1322,13 @@ shaka.dash.DashParser = class {
|
|
|
1322
1322
|
for (let i = 0; i < periodNodes.length; i++) {
|
|
1323
1323
|
const elem = periodNodes[i];
|
|
1324
1324
|
const next = periodNodes[i + 1];
|
|
1325
|
-
|
|
1325
|
+
let start = /** @type {number} */ (
|
|
1326
1326
|
TXml.parseAttr(elem, 'start', TXml.parseDuration, prevEnd));
|
|
1327
1327
|
const periodId = elem.attributes['id'];
|
|
1328
1328
|
const givenDuration =
|
|
1329
1329
|
TXml.parseAttr(elem, 'duration', TXml.parseDuration);
|
|
1330
|
+
start = (i == 0 && start == 0 && this.isTransitionFromDynamicToStatic_) ?
|
|
1331
|
+
seekRangeStart : start;
|
|
1330
1332
|
|
|
1331
1333
|
let periodDuration = null;
|
|
1332
1334
|
if (next) {
|
|
@@ -1336,7 +1338,7 @@ shaka.dash.DashParser = class {
|
|
|
1336
1338
|
const nextStart =
|
|
1337
1339
|
TXml.parseAttr(next, 'start', TXml.parseDuration);
|
|
1338
1340
|
if (nextStart != null) {
|
|
1339
|
-
periodDuration = nextStart - start;
|
|
1341
|
+
periodDuration = nextStart - start + seekRangeStart;
|
|
1340
1342
|
}
|
|
1341
1343
|
} else if (presentationDuration != null) {
|
|
1342
1344
|
// "The Period extends until the Period.start of the next Period, or
|
|
@@ -2626,25 +2628,51 @@ shaka.dash.DashParser = class {
|
|
|
2626
2628
|
return intValue;
|
|
2627
2629
|
}
|
|
2628
2630
|
|
|
2631
|
+
case 'tag:dolby.com,2015:dash:audio_channel_configuration:2015': {
|
|
2632
|
+
// ETSI TS 103 190-2 v1.2.1, Annex G.3
|
|
2633
|
+
// LSB-to-MSB order
|
|
2634
|
+
const channelCountMapping =
|
|
2635
|
+
[2, 1, 2, 2, 2, 2, 1, 2, 2, 1, 1, 1, 1, 2, 1, 1, 2, 2];
|
|
2636
|
+
const hexValue = parseInt(value, 16);
|
|
2637
|
+
if (!hexValue) { // 0 or NaN
|
|
2638
|
+
shaka.log.warning('Channel parsing failure! ' +
|
|
2639
|
+
'Ignoring scheme and value', scheme, value);
|
|
2640
|
+
continue;
|
|
2641
|
+
}
|
|
2642
|
+
let numBits = 0;
|
|
2643
|
+
for (let i = 0; i < channelCountMapping.length; i++) {
|
|
2644
|
+
if (hexValue & (1<<i)) {
|
|
2645
|
+
numBits += channelCountMapping[i];
|
|
2646
|
+
}
|
|
2647
|
+
}
|
|
2648
|
+
if (numBits) {
|
|
2649
|
+
return numBits;
|
|
2650
|
+
}
|
|
2651
|
+
continue;
|
|
2652
|
+
}
|
|
2653
|
+
|
|
2629
2654
|
case 'tag:dolby.com,2014:dash:audio_channel_configuration:2011':
|
|
2630
2655
|
case 'urn:dolby:dash:audio_channel_configuration:2011': {
|
|
2631
|
-
//
|
|
2632
|
-
//
|
|
2633
|
-
|
|
2656
|
+
// Defined by https://ott.dolby.com/OnDelKits/DDP/Dolby_Digital_Plus_Online_Delivery_Kit_v1.5/Documentation/Content_Creation/SDM/help_files/topics/ddp_mpeg_dash_c_mpd_auchlconfig.html
|
|
2657
|
+
// keep list in order of the spec; reverse for LSB-to-MSB order
|
|
2658
|
+
const channelCountMapping =
|
|
2659
|
+
[1, 1, 1, 1, 1, 2, 2, 1, 1, 2, 2, 2, 1, 2, 1, 1].reverse();
|
|
2660
|
+
const hexValue = parseInt(value, 16);
|
|
2634
2661
|
if (!hexValue) { // 0 or NaN
|
|
2635
2662
|
shaka.log.warning('Channel parsing failure! ' +
|
|
2636
2663
|
'Ignoring scheme and value', scheme, value);
|
|
2637
2664
|
continue;
|
|
2638
2665
|
}
|
|
2639
|
-
// Count the 1-bits in hexValue.
|
|
2640
2666
|
let numBits = 0;
|
|
2641
|
-
|
|
2642
|
-
if (hexValue & 1) {
|
|
2643
|
-
|
|
2667
|
+
for (let i = 0; i < channelCountMapping.length; i++) {
|
|
2668
|
+
if (hexValue & (1<<i)) {
|
|
2669
|
+
numBits += channelCountMapping[i];
|
|
2644
2670
|
}
|
|
2645
|
-
hexValue >>= 1;
|
|
2646
2671
|
}
|
|
2647
|
-
|
|
2672
|
+
if (numBits) {
|
|
2673
|
+
return numBits;
|
|
2674
|
+
}
|
|
2675
|
+
continue;
|
|
2648
2676
|
}
|
|
2649
2677
|
|
|
2650
2678
|
// Defined by https://dashif.org/identifiers/audio_source_metadata/ and clause 8.2, in ISO/IEC 23001-8.
|
|
@@ -787,7 +787,7 @@ shaka.dash.TimelineSegmentIndex = class extends shaka.media.SegmentIndex {
|
|
|
787
787
|
if (currentTimeline.length) {
|
|
788
788
|
const lastCurrentEntry = currentTimeline[currentTimeline.length - 1];
|
|
789
789
|
newEntries = info.timeline.filter((entry) => {
|
|
790
|
-
return entry.
|
|
790
|
+
return entry.end > lastCurrentEntry.end;
|
|
791
791
|
});
|
|
792
792
|
} else {
|
|
793
793
|
newEntries = info.timeline.slice();
|
package/lib/media/drm_engine.js
CHANGED
|
@@ -9,7 +9,6 @@ goog.provide('shaka.media.DrmEngine');
|
|
|
9
9
|
goog.require('goog.asserts');
|
|
10
10
|
goog.require('shaka.log');
|
|
11
11
|
goog.require('shaka.net.NetworkingEngine');
|
|
12
|
-
goog.require('shaka.transmuxer.TransmuxerEngine');
|
|
13
12
|
goog.require('shaka.util.BufferUtils');
|
|
14
13
|
goog.require('shaka.util.Destroyer');
|
|
15
14
|
goog.require('shaka.util.DrmUtils');
|
|
@@ -20,7 +19,6 @@ goog.require('shaka.util.IDestroyable');
|
|
|
20
19
|
goog.require('shaka.util.Iterables');
|
|
21
20
|
goog.require('shaka.util.ManifestParserUtils');
|
|
22
21
|
goog.require('shaka.util.MapUtils');
|
|
23
|
-
goog.require('shaka.util.MimeUtils');
|
|
24
22
|
goog.require('shaka.util.ObjectUtils');
|
|
25
23
|
goog.require('shaka.util.Platform');
|
|
26
24
|
goog.require('shaka.util.Pssh');
|
|
@@ -41,9 +39,6 @@ shaka.media.DrmEngine = class {
|
|
|
41
39
|
/** @private {?shaka.media.DrmEngine.PlayerInterface} */
|
|
42
40
|
this.playerInterface_ = playerInterface;
|
|
43
41
|
|
|
44
|
-
/** @private {!Set.<string>} */
|
|
45
|
-
this.supportedTypes_ = new Set();
|
|
46
|
-
|
|
47
42
|
/** @private {MediaKeys} */
|
|
48
43
|
this.mediaKeys_ = null;
|
|
49
44
|
|
|
@@ -197,7 +192,6 @@ shaka.media.DrmEngine = class {
|
|
|
197
192
|
|
|
198
193
|
// Break references to everything else we hold internally.
|
|
199
194
|
this.currentDrmInfo_ = null;
|
|
200
|
-
this.supportedTypes_.clear();
|
|
201
195
|
this.mediaKeys_ = null;
|
|
202
196
|
this.storedPersistentSessions_ = new Map();
|
|
203
197
|
this.config_ = null;
|
|
@@ -743,6 +737,17 @@ shaka.media.DrmEngine = class {
|
|
|
743
737
|
return;
|
|
744
738
|
}
|
|
745
739
|
}
|
|
740
|
+
let duplicate = false;
|
|
741
|
+
this.storedPersistentSessions_.forEach((metadata, sessionId) => {
|
|
742
|
+
if (!duplicate &&
|
|
743
|
+
shaka.util.BufferUtils.equal(initData, metadata.initData)) {
|
|
744
|
+
duplicate = true;
|
|
745
|
+
}
|
|
746
|
+
});
|
|
747
|
+
if (duplicate) {
|
|
748
|
+
shaka.log.debug('Ignoring duplicate init data.');
|
|
749
|
+
return;
|
|
750
|
+
}
|
|
746
751
|
}
|
|
747
752
|
|
|
748
753
|
// If there are pre-existing sessions that have all been loaded
|
|
@@ -762,40 +767,6 @@ shaka.media.DrmEngine = class {
|
|
|
762
767
|
return this.initialized_;
|
|
763
768
|
}
|
|
764
769
|
|
|
765
|
-
/**
|
|
766
|
-
* Check if DrmEngine (as initialized) will likely be able to support the
|
|
767
|
-
* given content type.
|
|
768
|
-
*
|
|
769
|
-
* @param {string} contentType
|
|
770
|
-
* @return {boolean}
|
|
771
|
-
*/
|
|
772
|
-
willSupport(contentType) {
|
|
773
|
-
// Edge 14 does not report correct capabilities. It will only report the
|
|
774
|
-
// first MIME type even if the others are supported. To work around this,
|
|
775
|
-
// we say that Edge supports everything.
|
|
776
|
-
//
|
|
777
|
-
// See https://github.com/shaka-project/shaka-player/issues/1495 for details.
|
|
778
|
-
if (shaka.util.Platform.isLegacyEdge()) {
|
|
779
|
-
return true;
|
|
780
|
-
}
|
|
781
|
-
|
|
782
|
-
contentType = contentType.toLowerCase();
|
|
783
|
-
|
|
784
|
-
if (shaka.util.Platform.isTizen() &&
|
|
785
|
-
contentType.includes('codecs="ac-3"')) {
|
|
786
|
-
// Some Tizen devices seem to misreport AC-3 support. This works around
|
|
787
|
-
// the issue, by falling back to EC-3, which seems to be supported on the
|
|
788
|
-
// same devices and be correctly reported in all cases we have observed.
|
|
789
|
-
// See https://github.com/shaka-project/shaka-player/issues/2989 for
|
|
790
|
-
// details.
|
|
791
|
-
const fallback = contentType.replace('ac-3', 'ec-3');
|
|
792
|
-
return this.supportedTypes_.has(contentType) ||
|
|
793
|
-
this.supportedTypes_.has(fallback);
|
|
794
|
-
}
|
|
795
|
-
|
|
796
|
-
return this.supportedTypes_.has(contentType);
|
|
797
|
-
}
|
|
798
|
-
|
|
799
770
|
/**
|
|
800
771
|
* Returns the ID of the sessions currently active.
|
|
801
772
|
*
|
|
@@ -896,25 +867,6 @@ shaka.media.DrmEngine = class {
|
|
|
896
867
|
return Array.from(this.activeSessions_.keys());
|
|
897
868
|
}
|
|
898
869
|
|
|
899
|
-
|
|
900
|
-
/**
|
|
901
|
-
* @param {shaka.extern.Stream} stream
|
|
902
|
-
* @param {string=} codecOverride
|
|
903
|
-
* @return {string}
|
|
904
|
-
* @private
|
|
905
|
-
*/
|
|
906
|
-
static computeMimeType_(stream, codecOverride) {
|
|
907
|
-
const realMimeType = shaka.util.MimeUtils.getFullType(stream.mimeType,
|
|
908
|
-
codecOverride || stream.codecs);
|
|
909
|
-
const TransmuxerEngine = shaka.transmuxer.TransmuxerEngine;
|
|
910
|
-
if (TransmuxerEngine.isSupported(realMimeType, stream.type)) {
|
|
911
|
-
// This will be handled by the Transmuxer, so use the MIME type that the
|
|
912
|
-
// Transmuxer will produce.
|
|
913
|
-
return TransmuxerEngine.convertCodecs(stream.type, realMimeType);
|
|
914
|
-
}
|
|
915
|
-
return realMimeType;
|
|
916
|
-
}
|
|
917
|
-
|
|
918
870
|
/**
|
|
919
871
|
* @param {!Map.<string, MediaKeySystemConfiguration>} configsByKeySystem
|
|
920
872
|
* A dictionary of configs, indexed by key system, with an iteration order
|
|
@@ -939,11 +891,6 @@ shaka.media.DrmEngine = class {
|
|
|
939
891
|
this.destroyer_.ensureNotDestroyed();
|
|
940
892
|
|
|
941
893
|
try {
|
|
942
|
-
// Get the set of supported content types from the audio and video
|
|
943
|
-
// capabilities. Avoid duplicates so that it is easier to read what is
|
|
944
|
-
// supported.
|
|
945
|
-
this.supportedTypes_.clear();
|
|
946
|
-
|
|
947
894
|
// Store the capabilities of the key system.
|
|
948
895
|
const realConfig = mediaKeySystemAccess.getConfiguration();
|
|
949
896
|
|
|
@@ -951,20 +898,6 @@ shaka.media.DrmEngine = class {
|
|
|
951
898
|
'Got MediaKeySystemAccess with configuration',
|
|
952
899
|
realConfig);
|
|
953
900
|
|
|
954
|
-
const audioCaps = realConfig.audioCapabilities || [];
|
|
955
|
-
const videoCaps = realConfig.videoCapabilities || [];
|
|
956
|
-
|
|
957
|
-
for (const cap of audioCaps) {
|
|
958
|
-
this.supportedTypes_.add(cap.contentType.toLowerCase());
|
|
959
|
-
}
|
|
960
|
-
|
|
961
|
-
for (const cap of videoCaps) {
|
|
962
|
-
this.supportedTypes_.add(cap.contentType.toLowerCase());
|
|
963
|
-
}
|
|
964
|
-
|
|
965
|
-
goog.asserts.assert(this.supportedTypes_.size,
|
|
966
|
-
'We should get at least one supported MIME type');
|
|
967
|
-
|
|
968
901
|
if (variants.length) {
|
|
969
902
|
this.currentDrmInfo_ = this.createDrmInfoByInfos_(
|
|
970
903
|
mediaKeySystemAccess.keySystem,
|
|
@@ -1021,7 +954,6 @@ shaka.media.DrmEngine = class {
|
|
|
1021
954
|
|
|
1022
955
|
// Don't rewrap a shaka.util.Error from earlier in the chain:
|
|
1023
956
|
this.currentDrmInfo_ = null;
|
|
1024
|
-
this.supportedTypes_.clear();
|
|
1025
957
|
if (exception instanceof shaka.util.Error) {
|
|
1026
958
|
throw exception;
|
|
1027
959
|
}
|
|
@@ -2063,41 +1995,6 @@ shaka.media.DrmEngine = class {
|
|
|
2063
1995
|
}));
|
|
2064
1996
|
}
|
|
2065
1997
|
|
|
2066
|
-
/**
|
|
2067
|
-
* Check if a variant is likely to be supported by DrmEngine. This will err on
|
|
2068
|
-
* the side of being too accepting and may not reject a variant that it will
|
|
2069
|
-
* later fail to play.
|
|
2070
|
-
*
|
|
2071
|
-
* @param {!shaka.extern.Variant} variant
|
|
2072
|
-
* @return {boolean}
|
|
2073
|
-
*/
|
|
2074
|
-
supportsVariant(variant) {
|
|
2075
|
-
/** @type {?shaka.extern.Stream} */
|
|
2076
|
-
const audio = variant.audio;
|
|
2077
|
-
/** @type {?shaka.extern.Stream} */
|
|
2078
|
-
const video = variant.video;
|
|
2079
|
-
|
|
2080
|
-
if (audio && audio.encrypted) {
|
|
2081
|
-
const audioContentType = shaka.media.DrmEngine.computeMimeType_(audio);
|
|
2082
|
-
if (!this.willSupport(audioContentType)) {
|
|
2083
|
-
return false;
|
|
2084
|
-
}
|
|
2085
|
-
}
|
|
2086
|
-
|
|
2087
|
-
if (video && video.encrypted) {
|
|
2088
|
-
const videoContentType = shaka.media.DrmEngine.computeMimeType_(video);
|
|
2089
|
-
if (!this.willSupport(videoContentType)) {
|
|
2090
|
-
return false;
|
|
2091
|
-
}
|
|
2092
|
-
}
|
|
2093
|
-
|
|
2094
|
-
const keySystem = shaka.util.DrmUtils.keySystem(this.currentDrmInfo_);
|
|
2095
|
-
const drmInfos = this.getVariantDrmInfos_(variant);
|
|
2096
|
-
|
|
2097
|
-
return drmInfos.length == 0 ||
|
|
2098
|
-
drmInfos.some((drmInfo) => drmInfo.keySystem == keySystem);
|
|
2099
|
-
}
|
|
2100
|
-
|
|
2101
1998
|
/**
|
|
2102
1999
|
* Concat the audio and video drmInfos in a variant.
|
|
2103
2000
|
* @param {shaka.extern.Variant} variant
|
|
@@ -116,7 +116,7 @@ shaka.media.MediaSourceEngine = class {
|
|
|
116
116
|
/** @private {boolean} */
|
|
117
117
|
this.playbackHasBegun_ = false;
|
|
118
118
|
|
|
119
|
-
/** @private {
|
|
119
|
+
/** @private {MediaSource} */
|
|
120
120
|
this.mediaSource_ = this.createMediaSource(this.mediaSourceOpen_);
|
|
121
121
|
|
|
122
122
|
/** @private {boolean} */
|
|
@@ -175,13 +175,16 @@ shaka.media.MediaSourceEngine = class {
|
|
|
175
175
|
* Replaced by unit tests.
|
|
176
176
|
*
|
|
177
177
|
* @param {!shaka.util.PublicPromise} p
|
|
178
|
-
* @return {!
|
|
178
|
+
* @return {!MediaSource}
|
|
179
179
|
*/
|
|
180
180
|
createMediaSource(p) {
|
|
181
|
+
/** @type {!MediaSource} */
|
|
182
|
+
let mediaSource;
|
|
183
|
+
|
|
181
184
|
if (window.ManagedMediaSource) {
|
|
182
185
|
this.video_.disableRemotePlayback = true;
|
|
183
186
|
|
|
184
|
-
|
|
187
|
+
mediaSource = new ManagedMediaSource();
|
|
185
188
|
|
|
186
189
|
this.eventManager_.listen(
|
|
187
190
|
mediaSource, 'startstreaming', () => {
|
|
@@ -192,39 +195,25 @@ shaka.media.MediaSourceEngine = class {
|
|
|
192
195
|
mediaSource, 'endstreaming', () => {
|
|
193
196
|
this.streamingAllowed_ = false;
|
|
194
197
|
});
|
|
195
|
-
|
|
196
|
-
this.eventManager_.listenOnce(
|
|
197
|
-
mediaSource, 'sourceopen', () => this.onSourceOpen_(p));
|
|
198
|
-
|
|
199
|
-
// Correctly set when playback has begun.
|
|
200
|
-
this.eventManager_.listenOnce(this.video_, 'playing', () => {
|
|
201
|
-
this.playbackHasBegun_ = true;
|
|
202
|
-
});
|
|
203
|
-
|
|
204
|
-
this.url_ = shaka.media.MediaSourceEngine.createObjectURL(mediaSource);
|
|
205
|
-
|
|
206
|
-
this.video_.src = this.url_;
|
|
207
|
-
|
|
208
|
-
return mediaSource;
|
|
209
198
|
} else {
|
|
210
|
-
|
|
199
|
+
mediaSource = new MediaSource();
|
|
200
|
+
}
|
|
211
201
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
202
|
+
// Set up MediaSource on the video element.
|
|
203
|
+
this.eventManager_.listenOnce(
|
|
204
|
+
mediaSource, 'sourceopen', () => this.onSourceOpen_(p));
|
|
215
205
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
206
|
+
// Correctly set when playback has begun.
|
|
207
|
+
this.eventManager_.listenOnce(this.video_, 'playing', () => {
|
|
208
|
+
this.playbackHasBegun_ = true;
|
|
209
|
+
});
|
|
220
210
|
|
|
221
|
-
|
|
222
|
-
|
|
211
|
+
// Store the object URL for releasing it later.
|
|
212
|
+
this.url_ = shaka.media.MediaSourceEngine.createObjectURL(mediaSource);
|
|
223
213
|
|
|
224
|
-
|
|
214
|
+
this.video_.src = this.url_;
|
|
225
215
|
|
|
226
|
-
|
|
227
|
-
}
|
|
216
|
+
return mediaSource;
|
|
228
217
|
}
|
|
229
218
|
|
|
230
219
|
/**
|
package/lib/media/playhead.js
CHANGED
|
@@ -427,7 +427,9 @@ shaka.media.MediaSourcePlayhead = class {
|
|
|
427
427
|
// infinite loop on systems where changing currentTime takes a
|
|
428
428
|
// significant amount of time (e.g. Chromecast).
|
|
429
429
|
const time = Date.now() / 1000;
|
|
430
|
-
|
|
430
|
+
const seekDelay = shaka.util.Platform.isFuchsiaCastDevice() ? 3 : 1;
|
|
431
|
+
if (!this.lastCorrectiveSeek_ ||
|
|
432
|
+
this.lastCorrectiveSeek_ < time - seekDelay) {
|
|
431
433
|
this.lastCorrectiveSeek_ = time;
|
|
432
434
|
canCorrectiveSeek = true;
|
|
433
435
|
}
|
package/lib/player.js
CHANGED
|
@@ -2890,6 +2890,11 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
2890
2890
|
}
|
|
2891
2891
|
}
|
|
2892
2892
|
mediaElement.src = playbackUri;
|
|
2893
|
+
// If ManagedMediaSource exists, we've disabled remote playback on our own.
|
|
2894
|
+
// Reenable it so AirPlay can be used via RemotePlayback API.
|
|
2895
|
+
if (this.mediaSourceEngine_ && window.ManagedMediaSource) {
|
|
2896
|
+
mediaElement.disableRemotePlayback = false;
|
|
2897
|
+
}
|
|
2893
2898
|
|
|
2894
2899
|
// Tizen 3 / WebOS won't load anything unless you call load() explicitly,
|
|
2895
2900
|
// no matter the value of the preload attribute. This is harmful on some
|
|
@@ -7859,7 +7864,7 @@ shaka.Player.TYPICAL_BUFFERING_THRESHOLD_ = 0.5;
|
|
|
7859
7864
|
* @export
|
|
7860
7865
|
*/
|
|
7861
7866
|
// eslint-disable-next-line no-useless-concat, max-len
|
|
7862
|
-
shaka.Player.version = 'v4.10.
|
|
7867
|
+
shaka.Player.version = 'v4.10.23' + '-uncompiled'; // x-release-please-version
|
|
7863
7868
|
|
|
7864
7869
|
// Initialize the deprecation system using the version string we just set
|
|
7865
7870
|
// on the player.
|
package/lib/util/platform.js
CHANGED
|
@@ -629,7 +629,7 @@ shaka.util.Platform = class {
|
|
|
629
629
|
*
|
|
630
630
|
* Some devices are known not to support `MediaSource.changeType`
|
|
631
631
|
* well. These devices should use the reload strategy. If a device
|
|
632
|
-
* reports that it supports `changeType` but support it
|
|
632
|
+
* reports that it supports `changeType` but support it unreliably
|
|
633
633
|
* it should be added to this list.
|
|
634
634
|
*
|
|
635
635
|
* @return {boolean}
|
|
@@ -638,7 +638,8 @@ shaka.util.Platform = class {
|
|
|
638
638
|
const Platform = shaka.util.Platform;
|
|
639
639
|
if (Platform.isTizen2() || Platform.isTizen3() || Platform.isTizen4() ||
|
|
640
640
|
Platform.isTizen5() || Platform.isTizen6() || Platform.isWebOS3() ||
|
|
641
|
-
Platform.isWebOS4() || Platform.isWebOS5())
|
|
641
|
+
Platform.isWebOS4() || Platform.isWebOS5() || Platform.isPS4() ||
|
|
642
|
+
Platform.isPS5()) {
|
|
642
643
|
return false;
|
|
643
644
|
}
|
|
644
645
|
// Older chromecasts without GoogleTV seem to not support SMOOTH properly.
|
|
@@ -11,6 +11,7 @@ goog.require('shaka.abr.SimpleAbrManager');
|
|
|
11
11
|
goog.require('shaka.config.AutoShowText');
|
|
12
12
|
goog.require('shaka.config.CodecSwitchingStrategy');
|
|
13
13
|
goog.require('shaka.log');
|
|
14
|
+
goog.require('shaka.media.Capabilities');
|
|
14
15
|
goog.require('shaka.net.NetworkingEngine');
|
|
15
16
|
goog.require('shaka.util.ConfigUtils');
|
|
16
17
|
goog.require('shaka.util.FairPlayUtils');
|
|
@@ -103,7 +104,8 @@ shaka.util.PlayerConfiguration = class {
|
|
|
103
104
|
|
|
104
105
|
let codecSwitchingStrategy = shaka.config.CodecSwitchingStrategy.RELOAD;
|
|
105
106
|
let multiTypeVariantsAllowed = false;
|
|
106
|
-
if (shaka.
|
|
107
|
+
if (shaka.media.Capabilities.isChangeTypeSupported() &&
|
|
108
|
+
shaka.util.Platform.supportsSmoothCodecSwitching()) {
|
|
107
109
|
codecSwitchingStrategy = shaka.config.CodecSwitchingStrategy.SMOOTH;
|
|
108
110
|
multiTypeVariantsAllowed = true;
|
|
109
111
|
}
|
package/package.json
CHANGED
package/ui/externs/ui.js
CHANGED
|
@@ -229,7 +229,8 @@ shaka.extern.UIVolumeBarColors;
|
|
|
229
229
|
* @property {boolean} seekOnTaps
|
|
230
230
|
* Indicates whether or not a fast-forward and rewind tap button that seeks
|
|
231
231
|
* video some seconds.
|
|
232
|
-
* Defaults to true.
|
|
232
|
+
* Defaults to true if the browser <code>navigator.maxTouchPoints > 0</code>
|
|
233
|
+
* is true.
|
|
233
234
|
* @property {number} tapSeekDistance
|
|
234
235
|
* The time interval, in seconds, to seek when the user presses the left or
|
|
235
236
|
* right part of the video. If less than or equal to 0,
|
package/ui/remote_button.js
CHANGED
|
@@ -72,7 +72,7 @@ shaka.ui.RemoteButton = class extends shaka.ui.Element {
|
|
|
72
72
|
|
|
73
73
|
shaka.ui.Utils.setDisplay(this.remoteButton_, false);
|
|
74
74
|
|
|
75
|
-
if (!this.video.remote
|
|
75
|
+
if (!this.video.remote) {
|
|
76
76
|
this.remoteButton_.classList.add('shaka-hidden');
|
|
77
77
|
} else {
|
|
78
78
|
this.eventManager.listen(
|
|
@@ -138,10 +138,11 @@ shaka.ui.RemoteButton = class extends shaka.ui.Element {
|
|
|
138
138
|
} else if (this.video.remote.state == 'disconnected') {
|
|
139
139
|
const handleAvailabilityChange = (availability) => {
|
|
140
140
|
if (this.player) {
|
|
141
|
+
const disableRemote = this.video.disableRemotePlayback;
|
|
141
142
|
const loadMode = this.player.getLoadMode();
|
|
142
143
|
const srcMode = loadMode == shaka.Player.LoadMode.SRC_EQUALS;
|
|
143
144
|
shaka.ui.Utils.setDisplay(
|
|
144
|
-
this.remoteButton_, srcMode && availability);
|
|
145
|
+
this.remoteButton_, srcMode && availability && !disableRemote);
|
|
145
146
|
} else {
|
|
146
147
|
shaka.ui.Utils.setDisplay(this.remoteButton_, false);
|
|
147
148
|
}
|
|
@@ -159,6 +159,9 @@ shaka.ui.SaveVideoFrameButton = class extends shaka.ui.Element {
|
|
|
159
159
|
if (this.ad) {
|
|
160
160
|
available = false;
|
|
161
161
|
}
|
|
162
|
+
if (this.video.remote && this.video.remote.state != 'disconnected') {
|
|
163
|
+
available = false;
|
|
164
|
+
}
|
|
162
165
|
shaka.ui.Utils.setDisplay(this.button_, available);
|
|
163
166
|
}
|
|
164
167
|
|
package/ui/ui.js
CHANGED
|
@@ -192,7 +192,6 @@ shaka.ui.Overlay = class {
|
|
|
192
192
|
'playback_rate',
|
|
193
193
|
'recenter_vr',
|
|
194
194
|
'toggle_stereoscopic',
|
|
195
|
-
'save_video_frame',
|
|
196
195
|
],
|
|
197
196
|
statisticsList: [
|
|
198
197
|
'width',
|
|
@@ -267,7 +266,7 @@ shaka.ui.Overlay = class {
|
|
|
267
266
|
fullScreenElement: this.videoContainer_,
|
|
268
267
|
preferDocumentPictureInPicture: true,
|
|
269
268
|
showAudioChannelCountVariants: true,
|
|
270
|
-
seekOnTaps:
|
|
269
|
+
seekOnTaps: navigator.maxTouchPoints > 0,
|
|
271
270
|
tapSeekDistance: 10,
|
|
272
271
|
refreshTickInSeconds: 0.125,
|
|
273
272
|
displayInVrMode: false,
|
|
@@ -290,6 +289,9 @@ shaka.ui.Overlay = class {
|
|
|
290
289
|
(name) => name != 'play_pause' && name != 'volume');
|
|
291
290
|
}
|
|
292
291
|
|
|
292
|
+
// Set this button here to push it at the end.
|
|
293
|
+
config.overflowMenuButtons.push('save_video_frame');
|
|
294
|
+
|
|
293
295
|
return config;
|
|
294
296
|
}
|
|
295
297
|
|
|
@@ -491,6 +493,8 @@ shaka.ui.Overlay = class {
|
|
|
491
493
|
video.removeAttribute('src');
|
|
492
494
|
}
|
|
493
495
|
|
|
496
|
+
await player.attach(shaka.util.Dom.asHTMLMediaElement(video));
|
|
497
|
+
|
|
494
498
|
for (const elem of video.querySelectorAll('source')) {
|
|
495
499
|
try { // eslint-disable-next-line no-await-in-loop
|
|
496
500
|
await ui.getControls().getPlayer().load(elem.getAttribute('src'));
|
|
@@ -499,8 +503,6 @@ shaka.ui.Overlay = class {
|
|
|
499
503
|
shaka.log.error('Error auto-loading asset', e);
|
|
500
504
|
}
|
|
501
505
|
}
|
|
502
|
-
|
|
503
|
-
await player.attach(shaka.util.Dom.asHTMLMediaElement(video));
|
|
504
506
|
}
|
|
505
507
|
|
|
506
508
|
|