shaka-player 4.11.11 → 4.11.13
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/AUTHORS +1 -0
- package/CONTRIBUTORS +1 -0
- package/dist/deps.js +1 -1
- package/dist/locales.js +37 -37
- 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.externs.js +1 -1
- package/dist/shaka-player.compiled.debug.js +243 -242
- package/dist/shaka-player.compiled.debug.map +3 -3
- package/dist/shaka-player.compiled.externs.js +1 -1
- package/dist/shaka-player.compiled.js +915 -913
- package/dist/shaka-player.compiled.map +3 -3
- 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.externs.js +1 -1
- package/dist/shaka-player.ui.debug.js +353 -351
- package/dist/shaka-player.ui.debug.map +3 -3
- package/dist/shaka-player.ui.externs.js +1 -1
- package/dist/shaka-player.ui.js +1232 -1229
- package/dist/shaka-player.ui.map +3 -3
- package/lib/ads/interstitial_ad_manager.js +83 -29
- package/lib/dash/segment_template.js +6 -2
- package/lib/media/adaptation_set_criteria.js +22 -47
- package/lib/media/media_source_engine.js +9 -8
- package/lib/media/preload_manager.js +2 -1
- package/lib/media/streaming_engine.js +1 -2
- package/lib/net/networking_engine.js +3 -3
- package/lib/player.js +57 -20
- package/lib/polyfill/media_capabilities.js +2 -1
- package/lib/polyfill/mediasource.js +12 -0
- package/lib/text/cue.js +1 -0
- package/lib/text/ui_text_displayer.js +8 -0
- package/lib/util/error.js +1 -1
- package/lib/util/mp4_generator.js +1 -1
- package/lib/util/platform.js +3 -3
- package/package.json +1 -1
- package/ui/controls.js +17 -7
- package/ui/language_utils.js +3 -1
- package/ui/playback_rate_selection.js +6 -2
- package/ui/remote_button.js +42 -17
- package/ui/seek_bar.js +3 -0
|
@@ -39,6 +39,9 @@ shaka.ads.InterstitialAdManager = class {
|
|
|
39
39
|
* @param {function(!shaka.util.FakeEvent)} onEvent
|
|
40
40
|
*/
|
|
41
41
|
constructor(adContainer, basePlayer, baseVideo, onEvent) {
|
|
42
|
+
/** @private {?shaka.extern.AdsConfiguration} */
|
|
43
|
+
this.config_ = null;
|
|
44
|
+
|
|
42
45
|
/** @private {HTMLElement} */
|
|
43
46
|
this.adContainer_ = adContainer;
|
|
44
47
|
|
|
@@ -93,10 +96,24 @@ shaka.ads.InterstitialAdManager = class {
|
|
|
93
96
|
this.lastPlayedAd_ = null;
|
|
94
97
|
|
|
95
98
|
this.eventManager_.listen(this.baseVideo_, 'timeupdate', () => {
|
|
96
|
-
if (this.playingAd_ || this.
|
|
99
|
+
if (this.playingAd_ || this.lastTime_ ||
|
|
100
|
+
this.basePlayer_.isRemotePlayback()) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
this.lastTime_ = this.baseVideo_.currentTime;
|
|
104
|
+
const currentInterstitial = this.getCurrentInterstitial_(
|
|
105
|
+
/* needPreRoll= */ true, /* numberToSkip= */ 0, this.lastPlayedAd_);
|
|
106
|
+
if (currentInterstitial) {
|
|
107
|
+
this.setupAd_(currentInterstitial, /* sequenceLength= */ 1,
|
|
108
|
+
/* adPosition= */ 1, /* initialTime= */ Date.now());
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
const checkForInterstitials = () => {
|
|
113
|
+
if (this.playingAd_ || !this.lastTime_ ||
|
|
114
|
+
this.basePlayer_.isRemotePlayback()) {
|
|
97
115
|
return;
|
|
98
116
|
}
|
|
99
|
-
const needPreRoll = this.lastTime_ == null || this.lastTime_ == 0;
|
|
100
117
|
this.lastTime_ = this.baseVideo_.currentTime;
|
|
101
118
|
// Remove last played add when the new time is before to the ad time.
|
|
102
119
|
if (this.lastPlayedAd_ &&
|
|
@@ -105,12 +122,27 @@ shaka.ads.InterstitialAdManager = class {
|
|
|
105
122
|
this.lastPlayedAd_ = null;
|
|
106
123
|
}
|
|
107
124
|
const currentInterstitial = this.getCurrentInterstitial_(
|
|
108
|
-
needPreRoll, /* numberToSkip= */ 0, this.lastPlayedAd_);
|
|
125
|
+
/* needPreRoll= */ false, /* numberToSkip= */ 0, this.lastPlayedAd_);
|
|
109
126
|
if (currentInterstitial) {
|
|
110
127
|
this.setupAd_(currentInterstitial, /* sequenceLength= */ 1,
|
|
111
128
|
/* adPosition= */ 1, /* initialTime= */ Date.now());
|
|
112
129
|
}
|
|
113
|
-
}
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
/** @private {shaka.util.Timer} */
|
|
133
|
+
this.timeUpdateTimer_ = new shaka.util.Timer(checkForInterstitials);
|
|
134
|
+
|
|
135
|
+
if ('requestVideoFrameCallback' in this.baseVideo_ &&
|
|
136
|
+
!shaka.util.Platform.isSmartTV()) {
|
|
137
|
+
const baseVideo = /** @type {!HTMLVideoElement} */ (this.baseVideo_);
|
|
138
|
+
const videoFrameCallback = () => {
|
|
139
|
+
checkForInterstitials();
|
|
140
|
+
baseVideo.requestVideoFrameCallback(videoFrameCallback);
|
|
141
|
+
};
|
|
142
|
+
baseVideo.requestVideoFrameCallback(videoFrameCallback);
|
|
143
|
+
} else {
|
|
144
|
+
this.timeUpdateTimer_.tickEvery(/* seconds= */ 0.025);
|
|
145
|
+
}
|
|
114
146
|
|
|
115
147
|
/** @private {shaka.util.Timer} */
|
|
116
148
|
this.pollTimer_ = new shaka.util.Timer(async () => {
|
|
@@ -168,11 +200,27 @@ shaka.ads.InterstitialAdManager = class {
|
|
|
168
200
|
* @param {shaka.extern.AdsConfiguration} config
|
|
169
201
|
*/
|
|
170
202
|
configure(config) {
|
|
171
|
-
|
|
172
|
-
|
|
203
|
+
this.config_ = config;
|
|
204
|
+
this.determineIfUsingBaseVideo_();
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* @private
|
|
209
|
+
*/
|
|
210
|
+
determineIfUsingBaseVideo_() {
|
|
211
|
+
if (!this.adContainer_ || !this.config_ || this.playingAd_) {
|
|
173
212
|
return;
|
|
174
213
|
}
|
|
175
|
-
|
|
214
|
+
let supportsMultipleMediaElements =
|
|
215
|
+
this.config_.supportsMultipleMediaElements;
|
|
216
|
+
const video = /** @type {HTMLVideoElement} */(this.baseVideo_);
|
|
217
|
+
if (video.webkitSupportsFullscreen && video.webkitDisplayingFullscreen) {
|
|
218
|
+
supportsMultipleMediaElements = false;
|
|
219
|
+
}
|
|
220
|
+
if (this.usingBaseVideo_ != supportsMultipleMediaElements) {
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
this.usingBaseVideo_ = !supportsMultipleMediaElements;
|
|
176
224
|
if (this.usingBaseVideo_) {
|
|
177
225
|
this.video_ = this.baseVideo_;
|
|
178
226
|
if (this.adVideo_) {
|
|
@@ -219,6 +267,10 @@ shaka.ads.InterstitialAdManager = class {
|
|
|
219
267
|
if (this.adContainer_) {
|
|
220
268
|
shaka.util.Dom.removeAllChildren(this.adContainer_);
|
|
221
269
|
}
|
|
270
|
+
if (this.timeUpdateTimer_) {
|
|
271
|
+
this.timeUpdateTimer_.stop();
|
|
272
|
+
this.timeUpdateTimer_ = null;
|
|
273
|
+
}
|
|
222
274
|
if (this.pollTimer_) {
|
|
223
275
|
this.pollTimer_.stop();
|
|
224
276
|
this.pollTimer_ = null;
|
|
@@ -231,13 +283,6 @@ shaka.ads.InterstitialAdManager = class {
|
|
|
231
283
|
* @param {shaka.extern.HLSInterstitial} hlsInterstitial
|
|
232
284
|
*/
|
|
233
285
|
async addMetadata(hlsInterstitial) {
|
|
234
|
-
if (this.basePlayer_.getLoadMode() == shaka.Player.LoadMode.SRC_EQUALS &&
|
|
235
|
-
this.usingBaseVideo_) {
|
|
236
|
-
shaka.log.alwaysWarn(
|
|
237
|
-
'Unsupported HLS interstitial when using single media element',
|
|
238
|
-
hlsInterstitial);
|
|
239
|
-
return;
|
|
240
|
-
}
|
|
241
286
|
this.updatePlayerConfig_();
|
|
242
287
|
const adInterstitials = await this.getInterstitialsInfo_(hlsInterstitial);
|
|
243
288
|
if (adInterstitials.length) {
|
|
@@ -277,7 +322,7 @@ shaka.ads.InterstitialAdManager = class {
|
|
|
277
322
|
const interstitial = {
|
|
278
323
|
id: null,
|
|
279
324
|
startTime: region.startTime,
|
|
280
|
-
endTime:
|
|
325
|
+
endTime: region.endTime,
|
|
281
326
|
uri: alternativeMPDUri,
|
|
282
327
|
isSkippable: false,
|
|
283
328
|
skipOffset: null,
|
|
@@ -336,16 +381,9 @@ shaka.ads.InterstitialAdManager = class {
|
|
|
336
381
|
* @param {!Array.<shaka.extern.AdInterstitial>} interstitials
|
|
337
382
|
*/
|
|
338
383
|
addInterstitials(interstitials) {
|
|
339
|
-
if (this.basePlayer_.getLoadMode() == shaka.Player.LoadMode.SRC_EQUALS &&
|
|
340
|
-
this.usingBaseVideo_) {
|
|
341
|
-
shaka.log.alwaysWarn(
|
|
342
|
-
'Unsupported interstitial when using single media element',
|
|
343
|
-
interstitials);
|
|
344
|
-
return;
|
|
345
|
-
}
|
|
346
384
|
let cuepointsChanged = false;
|
|
347
385
|
for (const interstitial of interstitials) {
|
|
348
|
-
const interstitialId = JSON.stringify(interstitial);
|
|
386
|
+
const interstitialId = interstitial.id || JSON.stringify(interstitial);
|
|
349
387
|
if (this.interstitialIds_.has(interstitialId)) {
|
|
350
388
|
continue;
|
|
351
389
|
}
|
|
@@ -423,8 +461,7 @@ shaka.ads.InterstitialAdManager = class {
|
|
|
423
461
|
this.lastTime_ - roundDecimals(interstitial.startTime);
|
|
424
462
|
if (difference > 0 &&
|
|
425
463
|
(difference <= 1 || !interstitial.canJump)) {
|
|
426
|
-
if (
|
|
427
|
-
!lastPlayedAd.pre && !lastPlayedAd.post &&
|
|
464
|
+
if (lastPlayedAd && !lastPlayedAd.pre && !lastPlayedAd.post &&
|
|
428
465
|
lastPlayedAd.startTime >= interstitial.startTime) {
|
|
429
466
|
isValid = false;
|
|
430
467
|
} else {
|
|
@@ -455,10 +492,14 @@ shaka.ads.InterstitialAdManager = class {
|
|
|
455
492
|
*/
|
|
456
493
|
async setupAd_(interstitial, sequenceLength, adPosition, initialTime,
|
|
457
494
|
oncePlayed = 0) {
|
|
495
|
+
this.determineIfUsingBaseVideo_();
|
|
458
496
|
goog.asserts.assert(this.video_, 'Must have video');
|
|
459
497
|
|
|
460
498
|
this.lastPlayedAd_ = interstitial;
|
|
461
499
|
|
|
500
|
+
shaka.log.info('Starting interstitial',
|
|
501
|
+
interstitial.startTime, 'at', this.lastTime_);
|
|
502
|
+
|
|
462
503
|
const startTime = Date.now();
|
|
463
504
|
|
|
464
505
|
if (!this.video_.parentElement && this.adContainer_) {
|
|
@@ -578,7 +619,10 @@ shaka.ads.InterstitialAdManager = class {
|
|
|
578
619
|
if (!this.baseVideo_.ended) {
|
|
579
620
|
this.baseVideo_.play();
|
|
580
621
|
}
|
|
622
|
+
} else {
|
|
623
|
+
this.cuepointsChanged_();
|
|
581
624
|
}
|
|
625
|
+
this.determineIfUsingBaseVideo_();
|
|
582
626
|
}
|
|
583
627
|
};
|
|
584
628
|
const error = async (e) => {
|
|
@@ -750,6 +794,16 @@ shaka.ads.InterstitialAdManager = class {
|
|
|
750
794
|
if (hlsInterstitialId) {
|
|
751
795
|
id = /** @type {string} */(hlsInterstitialId.data);
|
|
752
796
|
}
|
|
797
|
+
const startTime = id == null ?
|
|
798
|
+
Math.floor(hlsInterstitial.startTime * 10) / 10:
|
|
799
|
+
hlsInterstitial.startTime;
|
|
800
|
+
let endTime = hlsInterstitial.endTime;
|
|
801
|
+
if (hlsInterstitial.endTime && hlsInterstitial.endTime != Infinity &&
|
|
802
|
+
typeof(hlsInterstitial.endTime) == 'number') {
|
|
803
|
+
endTime = id == null ?
|
|
804
|
+
Math.floor(hlsInterstitial.endTime * 10) / 10:
|
|
805
|
+
hlsInterstitial.endTime;
|
|
806
|
+
}
|
|
753
807
|
const restrict = hlsInterstitial.values.find((v) => v.key == 'X-RESTRICT');
|
|
754
808
|
let isSkippable = true;
|
|
755
809
|
let canJump = true;
|
|
@@ -804,8 +858,8 @@ shaka.ads.InterstitialAdManager = class {
|
|
|
804
858
|
}
|
|
805
859
|
interstitialsAd.push({
|
|
806
860
|
id,
|
|
807
|
-
startTime
|
|
808
|
-
endTime
|
|
861
|
+
startTime,
|
|
862
|
+
endTime,
|
|
809
863
|
uri,
|
|
810
864
|
isSkippable,
|
|
811
865
|
skipOffset: isSkippable ? 0 : null,
|
|
@@ -836,8 +890,8 @@ shaka.ads.InterstitialAdManager = class {
|
|
|
836
890
|
if (asset['URI']) {
|
|
837
891
|
interstitialsAd.push({
|
|
838
892
|
id,
|
|
839
|
-
startTime
|
|
840
|
-
endTime
|
|
893
|
+
startTime,
|
|
894
|
+
endTime,
|
|
841
895
|
uri: asset['URI'],
|
|
842
896
|
isSkippable,
|
|
843
897
|
skipOffset: isSkippable ? 0 : null,
|
|
@@ -85,7 +85,9 @@ shaka.dash.SegmentTemplate = class {
|
|
|
85
85
|
},
|
|
86
86
|
};
|
|
87
87
|
} else if (info.segmentDuration) {
|
|
88
|
-
if (!isUpdate &&
|
|
88
|
+
if (!isUpdate &&
|
|
89
|
+
context.adaptationSet.contentType !== 'image' &&
|
|
90
|
+
context.adaptationSet.contentType !== 'text') {
|
|
89
91
|
const periodStart = context.periodInfo.start;
|
|
90
92
|
const periodId = context.period.id;
|
|
91
93
|
const initialPeriodDuration = context.periodInfo.duration;
|
|
@@ -172,7 +174,9 @@ shaka.dash.SegmentTemplate = class {
|
|
|
172
174
|
tsi.evict(availabilityStart);
|
|
173
175
|
}
|
|
174
176
|
|
|
175
|
-
if (info.timeline &&
|
|
177
|
+
if (info.timeline &&
|
|
178
|
+
context.adaptationSet.contentType !== 'image' &&
|
|
179
|
+
context.adaptationSet.contentType !== 'text') {
|
|
176
180
|
const timeline = info.timeline;
|
|
177
181
|
context.presentationTimeline.notifyTimeRange(
|
|
178
182
|
timeline,
|
|
@@ -41,60 +41,36 @@ shaka.media.AdaptationSetCriteria = class {
|
|
|
41
41
|
shaka.media.ExampleBasedCriteria = class {
|
|
42
42
|
/**
|
|
43
43
|
* @param {shaka.extern.Variant} example
|
|
44
|
-
* @param {shaka.config.CodecSwitchingStrategy
|
|
45
|
-
* @param {boolean
|
|
44
|
+
* @param {shaka.config.CodecSwitchingStrategy} codecSwitchingStrategy
|
|
45
|
+
* @param {boolean} enableAudioGroups
|
|
46
46
|
*/
|
|
47
|
-
constructor(example,
|
|
48
|
-
codecSwitchingStrategy = shaka.config.CodecSwitchingStrategy.RELOAD,
|
|
49
|
-
enableAudioGroups = false) {
|
|
50
|
-
/** @private {shaka.extern.Variant} */
|
|
51
|
-
this.example_ = example;
|
|
52
|
-
/** @private {shaka.config.CodecSwitchingStrategy} */
|
|
53
|
-
this.codecSwitchingStrategy_ = codecSwitchingStrategy;
|
|
54
|
-
/** @private {boolean} */
|
|
55
|
-
this.enableAudioGroups_ = enableAudioGroups;
|
|
56
|
-
|
|
57
|
-
|
|
47
|
+
constructor(example, codecSwitchingStrategy, enableAudioGroups) {
|
|
58
48
|
// We can't know if role and label are really important, so we don't use
|
|
59
49
|
// role and label for this.
|
|
60
50
|
const role = '';
|
|
61
51
|
const audioLabel = '';
|
|
62
52
|
const videoLabel = '';
|
|
63
|
-
const hdrLevel =
|
|
64
|
-
|
|
65
|
-
const
|
|
53
|
+
const hdrLevel = example.video && example.video.hdr ?
|
|
54
|
+
example.video.hdr : '';
|
|
55
|
+
const spatialAudio = example.audio && example.audio.spatialAudio ?
|
|
56
|
+
example.audio.spatialAudio : false;
|
|
57
|
+
const videoLayout = example.video && example.video.videoLayout ?
|
|
58
|
+
example.video.videoLayout : '';
|
|
66
59
|
const channelCount = example.audio && example.audio.channelsCount ?
|
|
67
|
-
|
|
68
|
-
|
|
60
|
+
example.audio.channelsCount : 0;
|
|
61
|
+
const audioCodec = example.audio && example.audio.codecs ?
|
|
62
|
+
example.audio.codecs : '';
|
|
69
63
|
|
|
70
64
|
/** @private {!shaka.media.AdaptationSetCriteria} */
|
|
71
|
-
this.
|
|
65
|
+
this.preferenceBasedCriteria_ = new shaka.media.PreferenceBasedCriteria(
|
|
72
66
|
example.language, role, channelCount, hdrLevel, spatialAudio,
|
|
73
67
|
videoLayout, audioLabel, videoLabel,
|
|
74
|
-
codecSwitchingStrategy, enableAudioGroups);
|
|
68
|
+
codecSwitchingStrategy, enableAudioGroups, audioCodec);
|
|
75
69
|
}
|
|
76
70
|
|
|
77
71
|
/** @override */
|
|
78
72
|
create(variants) {
|
|
79
|
-
|
|
80
|
-
shaka.config.CodecSwitchingStrategy.SMOOTH &&
|
|
81
|
-
shaka.media.Capabilities.isChangeTypeSupported();
|
|
82
|
-
// We can't assume that the example is in |variants| because it could
|
|
83
|
-
// actually be from another period.
|
|
84
|
-
const shortList = variants.filter((variant) => {
|
|
85
|
-
return shaka.media.AdaptationSet.areAdaptable(this.example_, variant,
|
|
86
|
-
!supportsSmoothCodecTransitions, this.enableAudioGroups_);
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
if (shortList.length) {
|
|
90
|
-
// Use the first item in the short list as the root. It should not matter
|
|
91
|
-
// which element we use as all items in the short list should already be
|
|
92
|
-
// compatible.
|
|
93
|
-
return new shaka.media.AdaptationSet(shortList[0], shortList,
|
|
94
|
-
!supportsSmoothCodecTransitions, this.enableAudioGroups_);
|
|
95
|
-
} else {
|
|
96
|
-
return this.fallback_.create(variants);
|
|
97
|
-
}
|
|
73
|
+
return this.preferenceBasedCriteria_.create(variants);
|
|
98
74
|
}
|
|
99
75
|
};
|
|
100
76
|
|
|
@@ -111,16 +87,15 @@ shaka.media.PreferenceBasedCriteria = class {
|
|
|
111
87
|
* @param {string} hdrLevel
|
|
112
88
|
* @param {boolean} spatialAudio
|
|
113
89
|
* @param {string} videoLayout
|
|
114
|
-
* @param {string
|
|
115
|
-
* @param {string
|
|
116
|
-
* @param {shaka.config.CodecSwitchingStrategy
|
|
117
|
-
* @param {boolean
|
|
118
|
-
* @param {string
|
|
90
|
+
* @param {string} audioLabel
|
|
91
|
+
* @param {string} videoLabel
|
|
92
|
+
* @param {shaka.config.CodecSwitchingStrategy} codecSwitchingStrategy
|
|
93
|
+
* @param {boolean} enableAudioGroups
|
|
94
|
+
* @param {string} audioCodec
|
|
119
95
|
*/
|
|
120
96
|
constructor(language, role, channelCount, hdrLevel, spatialAudio,
|
|
121
|
-
videoLayout, audioLabel
|
|
122
|
-
|
|
123
|
-
enableAudioGroups = false, audioCodec = '') {
|
|
97
|
+
videoLayout, audioLabel, videoLabel, codecSwitchingStrategy,
|
|
98
|
+
enableAudioGroups, audioCodec) {
|
|
124
99
|
/** @private {string} */
|
|
125
100
|
this.language_ = language;
|
|
126
101
|
/** @private {string} */
|
|
@@ -149,8 +149,9 @@ shaka.media.MediaSourceEngine = class {
|
|
|
149
149
|
/** @private {?number} */
|
|
150
150
|
this.lastDuration_ = null;
|
|
151
151
|
|
|
152
|
-
/** @private {
|
|
153
|
-
|
|
152
|
+
/** @private {!Object.<shaka.util.ManifestParserUtils.ContentType,
|
|
153
|
+
!shaka.util.TsParser>} */
|
|
154
|
+
this.tsParsers_ = {};
|
|
154
155
|
|
|
155
156
|
/** @private {?number} */
|
|
156
157
|
this.firstVideoTimestamp_ = null;
|
|
@@ -438,7 +439,7 @@ shaka.media.MediaSourceEngine = class {
|
|
|
438
439
|
// This object is owned by Player
|
|
439
440
|
this.lcevcDec_ = null;
|
|
440
441
|
|
|
441
|
-
this.
|
|
442
|
+
this.tsParsers_ = {};
|
|
442
443
|
this.playerInterface_ = null;
|
|
443
444
|
}
|
|
444
445
|
|
|
@@ -490,7 +491,7 @@ shaka.media.MediaSourceEngine = class {
|
|
|
490
491
|
this.manifestType_ == shaka.media.ManifestParser.HLS &&
|
|
491
492
|
!this.ignoreManifestTimestampsInSegmentsMode_;
|
|
492
493
|
|
|
493
|
-
this.
|
|
494
|
+
this.tsParsers_ = {};
|
|
494
495
|
|
|
495
496
|
for (const contentType of streamsByType.keys()) {
|
|
496
497
|
const stream = streamsByType.get(contentType);
|
|
@@ -841,12 +842,12 @@ shaka.media.MediaSourceEngine = class {
|
|
|
841
842
|
}
|
|
842
843
|
} else if (!mimeType.includes('/mp4') && !mimeType.includes('/webm') &&
|
|
843
844
|
shaka.util.TsParser.probe(uint8ArrayData)) {
|
|
844
|
-
if (!this.
|
|
845
|
-
this.
|
|
845
|
+
if (!this.tsParsers_[contentType]) {
|
|
846
|
+
this.tsParsers_[contentType] = new shaka.util.TsParser();
|
|
846
847
|
} else {
|
|
847
|
-
this.
|
|
848
|
+
this.tsParsers_[contentType].clearData();
|
|
848
849
|
}
|
|
849
|
-
const tsParser = this.
|
|
850
|
+
const tsParser = this.tsParsers_[contentType].parse(uint8ArrayData);
|
|
850
851
|
const startTime = tsParser.getStartTime(contentType);
|
|
851
852
|
if (startTime != null) {
|
|
852
853
|
timestamp = startTime;
|
|
@@ -630,7 +630,8 @@ shaka.media.PreloadManager = class extends shaka.util.FakeEventTarget {
|
|
|
630
630
|
this.config_.preferredAudioLabel,
|
|
631
631
|
this.config_.preferredVideoLabel,
|
|
632
632
|
this.config_.mediaSource.codecSwitchingStrategy,
|
|
633
|
-
this.config_.manifest.dash.enableAudioGroups
|
|
633
|
+
this.config_.manifest.dash.enableAudioGroups,
|
|
634
|
+
/* audioCodec= */ '');
|
|
634
635
|
}
|
|
635
636
|
|
|
636
637
|
// Make the ABR manager.
|
|
@@ -1966,8 +1966,7 @@ shaka.media.StreamingEngine = class {
|
|
|
1966
1966
|
const MimeUtils = shaka.util.MimeUtils;
|
|
1967
1967
|
const StreamingEngine = shaka.media.StreamingEngine;
|
|
1968
1968
|
const logPrefix = StreamingEngine.logPrefix_(mediaState);
|
|
1969
|
-
const nullLastReferences = mediaState.lastSegmentReference == null
|
|
1970
|
-
mediaState.lastInitSegmentReference == null;
|
|
1969
|
+
const nullLastReferences = mediaState.lastSegmentReference == null;
|
|
1971
1970
|
|
|
1972
1971
|
/** @type {!Array.<!Promise>} */
|
|
1973
1972
|
const operations = [];
|
|
@@ -576,12 +576,12 @@ shaka.net.NetworkingEngine = class extends shaka.util.FakeEventTarget {
|
|
|
576
576
|
}
|
|
577
577
|
};
|
|
578
578
|
const headersReceived = (headers) => {
|
|
579
|
-
if (this.onHeadersReceived_) {
|
|
580
|
-
this.onHeadersReceived_(headers, request, type);
|
|
581
|
-
}
|
|
582
579
|
headersReceivedCalled = true;
|
|
583
580
|
request.timeToFirstByte = Date.now() -
|
|
584
581
|
/** @type {number} */ (request.requestStartTime);
|
|
582
|
+
if (this.onHeadersReceived_) {
|
|
583
|
+
this.onHeadersReceived_(headers, request, type);
|
|
584
|
+
}
|
|
585
585
|
};
|
|
586
586
|
request.requestStartTime = Date.now();
|
|
587
587
|
|
package/lib/player.js
CHANGED
|
@@ -786,7 +786,8 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
786
786
|
this.config_.preferredAudioLabel,
|
|
787
787
|
this.config_.preferredVideoLabel,
|
|
788
788
|
this.config_.mediaSource.codecSwitchingStrategy,
|
|
789
|
-
this.config_.manifest.dash.enableAudioGroups
|
|
789
|
+
this.config_.manifest.dash.enableAudioGroups,
|
|
790
|
+
/* audioCodec= */ '');
|
|
790
791
|
|
|
791
792
|
/** @private {string} */
|
|
792
793
|
this.currentTextLanguage_ = this.config_.preferredTextLanguage;
|
|
@@ -2929,22 +2930,47 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
2929
2930
|
|
|
2930
2931
|
if (mediaElement.textTracks) {
|
|
2931
2932
|
this.createTextDisplayer_();
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
|
|
2946
|
-
|
|
2947
|
-
|
|
2933
|
+
const setShowingMode = () => {
|
|
2934
|
+
const track = this.getFilteredTextTracks_()
|
|
2935
|
+
.find((t) => t.mode !== 'disabled');
|
|
2936
|
+
if (track) {
|
|
2937
|
+
track.mode = 'showing';
|
|
2938
|
+
}
|
|
2939
|
+
};
|
|
2940
|
+
const setHiddenMode = () => {
|
|
2941
|
+
const track = this.getFilteredTextTracks_()
|
|
2942
|
+
.find((t) => t.mode !== 'disabled');
|
|
2943
|
+
if (track) {
|
|
2944
|
+
track.mode = 'hidden';
|
|
2945
|
+
}
|
|
2946
|
+
};
|
|
2947
|
+
this.loadEventManager_.listen(mediaElement, 'enterpictureinpicture',
|
|
2948
|
+
() => setShowingMode());
|
|
2949
|
+
this.loadEventManager_.listen(mediaElement, 'leavepictureinpicture',
|
|
2950
|
+
() => setHiddenMode());
|
|
2951
|
+
if (mediaElement.remote) {
|
|
2952
|
+
this.loadEventManager_.listen(mediaElement.remote, 'connect',
|
|
2953
|
+
() => setHiddenMode());
|
|
2954
|
+
this.loadEventManager_.listen(mediaElement.remote, 'connecting',
|
|
2955
|
+
() => setHiddenMode());
|
|
2956
|
+
this.loadEventManager_.listen(mediaElement.remote, 'disconnect',
|
|
2957
|
+
() => setHiddenMode());
|
|
2958
|
+
} else if ('webkitCurrentPlaybackTargetIsWireless' in mediaElement) {
|
|
2959
|
+
this.loadEventManager_.listen(mediaElement,
|
|
2960
|
+
'webkitcurrentplaybacktargetiswirelesschanged',
|
|
2961
|
+
() => setHiddenMode());
|
|
2962
|
+
}
|
|
2963
|
+
const video = /** @type {HTMLVideoElement} */(mediaElement);
|
|
2964
|
+
if (video.webkitSupportsFullscreen) {
|
|
2965
|
+
this.loadEventManager_.listen(video, 'webkitpresentationmodechanged',
|
|
2966
|
+
() => {
|
|
2967
|
+
if (video.webkitPresentationMode != 'inline') {
|
|
2968
|
+
setShowingMode();
|
|
2969
|
+
} else {
|
|
2970
|
+
setHiddenMode();
|
|
2971
|
+
}
|
|
2972
|
+
});
|
|
2973
|
+
}
|
|
2948
2974
|
}
|
|
2949
2975
|
// Add all media element listeners.
|
|
2950
2976
|
this.addBasicMediaListeners_(mediaElement, startTimeOfLoad);
|
|
@@ -5271,7 +5297,8 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
5271
5297
|
label,
|
|
5272
5298
|
/* videoLabel= */ '',
|
|
5273
5299
|
this.config_.mediaSource.codecSwitchingStrategy,
|
|
5274
|
-
this.config_.manifest.dash.enableAudioGroups
|
|
5300
|
+
this.config_.manifest.dash.enableAudioGroups,
|
|
5301
|
+
/* audioCodec= */ '');
|
|
5275
5302
|
|
|
5276
5303
|
this.chooseVariantAndSwitch_(clearBuffer, safeMargin);
|
|
5277
5304
|
} else if (this.video_ && this.video_.audioTracks) {
|
|
@@ -6352,7 +6379,12 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
6352
6379
|
// Because this.video_ may not be set when the config is built, the default
|
|
6353
6380
|
// TextDisplay factory must capture a reference to "this".
|
|
6354
6381
|
config.textDisplayFactory = () => {
|
|
6355
|
-
|
|
6382
|
+
// On iOS where the Fullscreen API is not available we prefer
|
|
6383
|
+
// SimpleTextDisplayer because it works with the Fullscreen API of the
|
|
6384
|
+
// video element itself.
|
|
6385
|
+
const Platform = shaka.util.Platform;
|
|
6386
|
+
if (this.videoContainer_ &&
|
|
6387
|
+
(!Platform.safariVersion() || document.fullscreenEnabled)) {
|
|
6356
6388
|
const latestConfig = this.getConfiguration();
|
|
6357
6389
|
return new shaka.text.UITextDisplayer(
|
|
6358
6390
|
this.video_, this.videoContainer_, latestConfig.textDisplayer);
|
|
@@ -6707,6 +6739,11 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
6707
6739
|
return;
|
|
6708
6740
|
}
|
|
6709
6741
|
|
|
6742
|
+
// We don't want to block the user from pausing the stream.
|
|
6743
|
+
if (this.video_.paused) {
|
|
6744
|
+
return;
|
|
6745
|
+
}
|
|
6746
|
+
|
|
6710
6747
|
let targetLatency;
|
|
6711
6748
|
let maxLatency;
|
|
6712
6749
|
let maxPlaybackRate;
|
|
@@ -8086,7 +8123,7 @@ shaka.Player.TYPICAL_BUFFERING_THRESHOLD_ = 0.5;
|
|
|
8086
8123
|
* @export
|
|
8087
8124
|
*/
|
|
8088
8125
|
// eslint-disable-next-line no-useless-concat, max-len
|
|
8089
|
-
shaka.Player.version = 'v4.11.
|
|
8126
|
+
shaka.Player.version = 'v4.11.13' + '-uncompiled'; // x-release-please-version
|
|
8090
8127
|
|
|
8091
8128
|
// Initialize the deprecation system using the version string we just set
|
|
8092
8129
|
// on the player.
|
|
@@ -61,7 +61,8 @@ shaka.polyfill.MediaCapabilities = class {
|
|
|
61
61
|
shaka.util.Platform.isWebOS() ||
|
|
62
62
|
shaka.util.Platform.isTizen() ||
|
|
63
63
|
shaka.util.Platform.isEOS() ||
|
|
64
|
-
shaka.util.Platform.isHisense()
|
|
64
|
+
shaka.util.Platform.isHisense() ||
|
|
65
|
+
shaka.util.Platform.isComcastX1()) {
|
|
65
66
|
canUseNativeMCap = false;
|
|
66
67
|
}
|
|
67
68
|
if (canUseNativeMCap && navigator.mediaCapabilities) {
|
|
@@ -87,6 +87,18 @@ shaka.polyfill.MediaSource = class {
|
|
|
87
87
|
// the player from trying to play opus on Tizen, we will override media
|
|
88
88
|
// source to always reject opus content.
|
|
89
89
|
shaka.polyfill.MediaSource.rejectCodec_('opus');
|
|
90
|
+
} else if (shaka.util.Platform.isComcastX1()) {
|
|
91
|
+
// XOne look to be like safari 8 which do not correctly
|
|
92
|
+
// implement abort() on SourceBuffer.
|
|
93
|
+
// Calling abort() before appending a segment causes that segment to be
|
|
94
|
+
// incomplete in the buffer.
|
|
95
|
+
// Bug filed: https://bugs.webkit.org/show_bug.cgi?id=165342
|
|
96
|
+
shaka.polyfill.MediaSource.stubAbort_();
|
|
97
|
+
// If you remove up to a keyframe, Webkit 601.x.x incorrectly will also
|
|
98
|
+
// remove that keyframe and the content up to the next.
|
|
99
|
+
// Offsetting the end of the removal range seems to help.
|
|
100
|
+
// Bug filed: https://bugs.webkit.org/show_bug.cgi?id=177884
|
|
101
|
+
shaka.polyfill.MediaSource.patchRemovalRange_();
|
|
90
102
|
} else {
|
|
91
103
|
shaka.log.info('Using native MSE as-is.');
|
|
92
104
|
}
|
package/lib/text/cue.js
CHANGED
|
@@ -632,6 +632,7 @@ shaka.text.Cue = class {
|
|
|
632
632
|
nestedCue.region = new shaka.text.CueRegion();
|
|
633
633
|
nestedCue.position = null;
|
|
634
634
|
nestedCue.size = 0;
|
|
635
|
+
nestedCue.textAlign = shaka.text.Cue.textAlign.CENTER;
|
|
635
636
|
|
|
636
637
|
if (TXml.isNode(element)) {
|
|
637
638
|
const bold = shaka.text.Cue.fontWeight.BOLD;
|
|
@@ -9,6 +9,7 @@ goog.provide('shaka.text.UITextDisplayer');
|
|
|
9
9
|
|
|
10
10
|
goog.require('goog.asserts');
|
|
11
11
|
goog.require('shaka.Deprecate');
|
|
12
|
+
goog.require('shaka.log');
|
|
12
13
|
goog.require('shaka.text.Cue');
|
|
13
14
|
goog.require('shaka.text.CueRegion');
|
|
14
15
|
goog.require('shaka.text.Utils');
|
|
@@ -35,6 +36,12 @@ shaka.text.UITextDisplayer = class {
|
|
|
35
36
|
constructor(video, videoContainer, config) {
|
|
36
37
|
goog.asserts.assert(videoContainer, 'videoContainer should be valid.');
|
|
37
38
|
|
|
39
|
+
if (!document.fullscreenEnabled) {
|
|
40
|
+
shaka.log.alwaysWarn('Using UITextDisplayer in a browser without ' +
|
|
41
|
+
'Fullscreen API support causes subtitles to not be rendered in ' +
|
|
42
|
+
'fullscreen');
|
|
43
|
+
}
|
|
44
|
+
|
|
38
45
|
/** @private {boolean} */
|
|
39
46
|
this.isTextVisible_ = false;
|
|
40
47
|
|
|
@@ -248,6 +255,7 @@ shaka.text.UITextDisplayer = class {
|
|
|
248
255
|
*/
|
|
249
256
|
setTextVisibility(on) {
|
|
250
257
|
this.isTextVisible_ = on;
|
|
258
|
+
this.updateCaptions_(/* forceUpdate= */ true);
|
|
251
259
|
}
|
|
252
260
|
|
|
253
261
|
/**
|
package/lib/util/error.js
CHANGED
|
@@ -765,7 +765,7 @@ shaka.util.Mp4Generator = class {
|
|
|
765
765
|
0x00, 0x00, 0x00, 0x01, // default_sample_description_index
|
|
766
766
|
0x00, 0x00, 0x00, 0x00, // default_sample_duration
|
|
767
767
|
0x00, 0x00, 0x00, 0x00, // default_sample_size
|
|
768
|
-
0x00,
|
|
768
|
+
0x00, 0x00, 0x00, 0x00, // default_sample_flags
|
|
769
769
|
]);
|
|
770
770
|
return Mp4Generator.box('trex', bytes);
|
|
771
771
|
}
|
package/lib/util/platform.js
CHANGED
|
@@ -300,7 +300,7 @@ shaka.util.Platform = class {
|
|
|
300
300
|
!shaka.util.Platform.isOrange() &&
|
|
301
301
|
!shaka.util.Platform.isPS4() &&
|
|
302
302
|
!shaka.util.Platform.isAmazonFireTV() &&
|
|
303
|
-
!shaka.util.Platform.
|
|
303
|
+
!shaka.util.Platform.isComcastX1() &&
|
|
304
304
|
!shaka.util.Platform.isZenterio() &&
|
|
305
305
|
!shaka.util.Platform.isSkyQ();
|
|
306
306
|
}
|
|
@@ -368,7 +368,7 @@ shaka.util.Platform = class {
|
|
|
368
368
|
* Check if the current platform is Comcast X1.
|
|
369
369
|
* @return {boolean}
|
|
370
370
|
*/
|
|
371
|
-
static
|
|
371
|
+
static isComcastX1() {
|
|
372
372
|
return shaka.util.Platform.userAgentContains_('WPE');
|
|
373
373
|
}
|
|
374
374
|
|
|
@@ -536,7 +536,7 @@ shaka.util.Platform = class {
|
|
|
536
536
|
Platform.isPS5() || Platform.isAmazonFireTV() ||
|
|
537
537
|
Platform.isEOS() || Platform.isAPL() ||
|
|
538
538
|
Platform.isVirginMedia() || Platform.isOrange() ||
|
|
539
|
-
Platform.
|
|
539
|
+
Platform.isComcastX1() || Platform.isChromecast() ||
|
|
540
540
|
Platform.isHisense() || Platform.isZenterio()) {
|
|
541
541
|
return true;
|
|
542
542
|
}
|