shaka-player 4.9.24 → 4.9.26
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/controls.css +2 -2
- package/dist/controls.css.map +1 -1
- package/dist/deps.js +2 -2
- package/dist/locales.js +35 -35
- package/dist/shaka-player.compiled.debug.js +207 -205
- package/dist/shaka-player.compiled.debug.map +3 -3
- package/dist/shaka-player.compiled.js +1147 -1146
- package/dist/shaka-player.compiled.map +3 -3
- package/dist/shaka-player.ui.debug.js +219 -217
- package/dist/shaka-player.ui.debug.map +3 -3
- package/dist/shaka-player.ui.js +1308 -1308
- package/dist/shaka-player.ui.map +2 -2
- package/lib/dash/dash_parser.js +83 -48
- package/lib/media/streaming_engine.js +58 -9
- package/lib/player.js +16 -2
- package/lib/text/ui_text_displayer.js +0 -4
- package/lib/util/periods.js +16 -9
- package/lib/util/tXml.js +58 -7
- package/package.json +1 -1
- package/ui/less/containers.less +3 -4
- package/ui/less/tooltip.less +1 -1
package/lib/dash/dash_parser.js
CHANGED
|
@@ -29,6 +29,7 @@ goog.require('shaka.util.LanguageUtils');
|
|
|
29
29
|
goog.require('shaka.util.ManifestParserUtils');
|
|
30
30
|
goog.require('shaka.util.MimeUtils');
|
|
31
31
|
goog.require('shaka.util.Networking');
|
|
32
|
+
goog.require('shaka.util.ObjectUtils');
|
|
32
33
|
goog.require('shaka.util.OperationManager');
|
|
33
34
|
goog.require('shaka.util.PeriodCombiner');
|
|
34
35
|
goog.require('shaka.util.PlayerConfiguration');
|
|
@@ -92,12 +93,19 @@ shaka.dash.DashParser = class {
|
|
|
92
93
|
|
|
93
94
|
/**
|
|
94
95
|
* A map of IDs to Stream objects.
|
|
95
|
-
* ID: Period@id,
|
|
96
|
-
* e.g.: '1,
|
|
96
|
+
* ID: Period@id,Representation@id
|
|
97
|
+
* e.g.: '1,23'
|
|
97
98
|
* @private {!Object.<string, !shaka.extern.Stream>}
|
|
98
99
|
*/
|
|
99
100
|
this.streamMap_ = {};
|
|
100
101
|
|
|
102
|
+
/**
|
|
103
|
+
* A map of Period IDs to Stream Map IDs.
|
|
104
|
+
* Use to have direct access to streamMap key.
|
|
105
|
+
* @private {!Object.<string, !Array<string>>}
|
|
106
|
+
*/
|
|
107
|
+
this.indexStreamMap_ = {};
|
|
108
|
+
|
|
101
109
|
/**
|
|
102
110
|
* A map of period ids to their durations
|
|
103
111
|
* @private {!Object.<string, number>}
|
|
@@ -235,6 +243,7 @@ shaka.dash.DashParser = class {
|
|
|
235
243
|
this.manifestUris_ = [];
|
|
236
244
|
this.manifest_ = null;
|
|
237
245
|
this.streamMap_ = {};
|
|
246
|
+
this.indexStreamMap_ = {};
|
|
238
247
|
this.contextCache_.clear();
|
|
239
248
|
this.manifestPatchContext_ = {
|
|
240
249
|
mpdId: '',
|
|
@@ -618,7 +627,7 @@ shaka.dash.DashParser = class {
|
|
|
618
627
|
}
|
|
619
628
|
|
|
620
629
|
this.manifestPatchContext_.type = mpdType;
|
|
621
|
-
|
|
630
|
+
this.cleanStreamMap_();
|
|
622
631
|
/** @type {!shaka.media.PresentationTimeline} */
|
|
623
632
|
let presentationTimeline;
|
|
624
633
|
if (this.manifest_) {
|
|
@@ -697,7 +706,8 @@ shaka.dash.DashParser = class {
|
|
|
697
706
|
profiles: profiles.split(','),
|
|
698
707
|
};
|
|
699
708
|
|
|
700
|
-
const periodsAndDuration = this.parsePeriods_(
|
|
709
|
+
const periodsAndDuration = this.parsePeriods_(
|
|
710
|
+
context, getBaseUris, mpd, /* newPeriod= */ false);
|
|
701
711
|
const duration = periodsAndDuration.duration;
|
|
702
712
|
const periods = periodsAndDuration.periods;
|
|
703
713
|
|
|
@@ -977,7 +987,7 @@ shaka.dash.DashParser = class {
|
|
|
977
987
|
};
|
|
978
988
|
|
|
979
989
|
const periodsAndDuration = this.parsePeriods_(context,
|
|
980
|
-
this.manifestPatchContext_.getBaseUris, periods);
|
|
990
|
+
this.manifestPatchContext_.getBaseUris, periods, /* newPeriod= */ true);
|
|
981
991
|
|
|
982
992
|
return periodsAndDuration.periods;
|
|
983
993
|
}
|
|
@@ -996,6 +1006,10 @@ shaka.dash.DashParser = class {
|
|
|
996
1006
|
this.contextCache_.delete(contextId);
|
|
997
1007
|
}
|
|
998
1008
|
}
|
|
1009
|
+
const newPeriods = this.lastManifestUpdatePeriodIds_.filter((pID) => {
|
|
1010
|
+
return pID !== periodId;
|
|
1011
|
+
});
|
|
1012
|
+
this.lastManifestUpdatePeriodIds_ = newPeriods;
|
|
999
1013
|
}
|
|
1000
1014
|
|
|
1001
1015
|
/**
|
|
@@ -1237,6 +1251,7 @@ shaka.dash.DashParser = class {
|
|
|
1237
1251
|
* @param {shaka.dash.DashParser.Context} context
|
|
1238
1252
|
* @param {function():!Array.<string>} getBaseUris
|
|
1239
1253
|
* @param {!shaka.extern.xml.Node} mpd
|
|
1254
|
+
* @param {!boolean} newPeriod
|
|
1240
1255
|
* @return {{
|
|
1241
1256
|
* periods: !Array.<shaka.extern.Period>,
|
|
1242
1257
|
* duration: ?number,
|
|
@@ -1244,7 +1259,7 @@ shaka.dash.DashParser = class {
|
|
|
1244
1259
|
* }}
|
|
1245
1260
|
* @private
|
|
1246
1261
|
*/
|
|
1247
|
-
parsePeriods_(context, getBaseUris, mpd) {
|
|
1262
|
+
parsePeriods_(context, getBaseUris, mpd, newPeriod) {
|
|
1248
1263
|
const TXml = shaka.util.TXml;
|
|
1249
1264
|
let presentationDuration = context.mediaPresentationDuration;
|
|
1250
1265
|
|
|
@@ -1370,8 +1385,18 @@ shaka.dash.DashParser = class {
|
|
|
1370
1385
|
prevEnd = start + periodDuration;
|
|
1371
1386
|
} // end of period parsing loop
|
|
1372
1387
|
|
|
1373
|
-
|
|
1374
|
-
|
|
1388
|
+
if (newPeriod) {
|
|
1389
|
+
// append new period from the patch manifest
|
|
1390
|
+
for (const el of periods) {
|
|
1391
|
+
const periodID = el.id;
|
|
1392
|
+
if (!this.lastManifestUpdatePeriodIds_.includes(periodID)) {
|
|
1393
|
+
this.lastManifestUpdatePeriodIds_.push(periodID);
|
|
1394
|
+
}
|
|
1395
|
+
}
|
|
1396
|
+
} else {
|
|
1397
|
+
// Replace previous seen periods with the current one.
|
|
1398
|
+
this.lastManifestUpdatePeriodIds_ = periods.map((el) => el.id);
|
|
1399
|
+
}
|
|
1375
1400
|
|
|
1376
1401
|
if (presentationDuration != null) {
|
|
1377
1402
|
if (prevEnd != null) {
|
|
@@ -1399,6 +1424,26 @@ shaka.dash.DashParser = class {
|
|
|
1399
1424
|
}
|
|
1400
1425
|
}
|
|
1401
1426
|
|
|
1427
|
+
/**
|
|
1428
|
+
* Clean StreamMap Object to remove reference of deleted Stream Object
|
|
1429
|
+
* @private
|
|
1430
|
+
*/
|
|
1431
|
+
cleanStreamMap_() {
|
|
1432
|
+
const oldPeriodIds = Object.keys(this.indexStreamMap_);
|
|
1433
|
+
if (oldPeriodIds.length === this.lastManifestUpdatePeriodIds_.length) {
|
|
1434
|
+
return;
|
|
1435
|
+
}
|
|
1436
|
+
const diffPeriodsIDs = oldPeriodIds.filter((pId) => {
|
|
1437
|
+
return !this.lastManifestUpdatePeriodIds_.includes(pId);
|
|
1438
|
+
});
|
|
1439
|
+
for (const pId of diffPeriodsIDs) {
|
|
1440
|
+
for (const contextId of this.indexStreamMap_[pId]) {
|
|
1441
|
+
delete this.streamMap_[contextId];
|
|
1442
|
+
}
|
|
1443
|
+
delete this.indexStreamMap_[pId];
|
|
1444
|
+
}
|
|
1445
|
+
}
|
|
1446
|
+
|
|
1402
1447
|
/**
|
|
1403
1448
|
* Parses a Period XML element. Unlike the other parse methods, this is not
|
|
1404
1449
|
* given the Node; it is given a PeriodInfo structure. Also, partial parsing
|
|
@@ -1415,6 +1460,7 @@ shaka.dash.DashParser = class {
|
|
|
1415
1460
|
const TXml = shaka.util.TXml;
|
|
1416
1461
|
const ContentType = shaka.util.ManifestParserUtils.ContentType;
|
|
1417
1462
|
|
|
1463
|
+
goog.asserts.assert(periodInfo.node, 'periodInfo.node should exist');
|
|
1418
1464
|
context.period = this.createFrame_(periodInfo.node, null, getBaseUris);
|
|
1419
1465
|
context.periodInfo = periodInfo;
|
|
1420
1466
|
context.period.availabilityTimeOffset = context.availabilityTimeOffset;
|
|
@@ -2184,7 +2230,12 @@ shaka.dash.DashParser = class {
|
|
|
2184
2230
|
};
|
|
2185
2231
|
|
|
2186
2232
|
if (contextId && context.dynamic && !this.streamMap_[contextId]) {
|
|
2233
|
+
const periodId = context.period.id || '';
|
|
2234
|
+
if (!this.indexStreamMap_[periodId]) {
|
|
2235
|
+
this.indexStreamMap_[periodId] = [];
|
|
2236
|
+
}
|
|
2187
2237
|
this.streamMap_[contextId] = stream;
|
|
2238
|
+
this.indexStreamMap_[periodId].push(contextId);
|
|
2188
2239
|
}
|
|
2189
2240
|
|
|
2190
2241
|
return stream;
|
|
@@ -2198,45 +2249,29 @@ shaka.dash.DashParser = class {
|
|
|
2198
2249
|
* @private
|
|
2199
2250
|
*/
|
|
2200
2251
|
cloneContext_(context) {
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
segmentBase: null,
|
|
2209
|
-
segmentList: null,
|
|
2210
|
-
segmentTemplate: frameRef.segmentTemplate,
|
|
2211
|
-
getBaseUris: frameRef.getBaseUris,
|
|
2212
|
-
width: frameRef.width,
|
|
2213
|
-
height: frameRef.height,
|
|
2214
|
-
contentType: frameRef.contentType,
|
|
2215
|
-
mimeType: frameRef.mimeType,
|
|
2216
|
-
language: frameRef.language,
|
|
2217
|
-
codecs: frameRef.codecs,
|
|
2218
|
-
frameRate: frameRef.frameRate,
|
|
2219
|
-
pixelAspectRatio: frameRef.pixelAspectRatio,
|
|
2220
|
-
emsgSchemeIdUris: frameRef.emsgSchemeIdUris,
|
|
2221
|
-
id: frameRef.id,
|
|
2222
|
-
position: frameRef.position,
|
|
2223
|
-
numChannels: frameRef.numChannels,
|
|
2224
|
-
audioSamplingRate: frameRef.audioSamplingRate,
|
|
2225
|
-
availabilityTimeOffset: frameRef.availabilityTimeOffset,
|
|
2226
|
-
initialization: frameRef.initialization,
|
|
2227
|
-
};
|
|
2228
|
-
} else if (k == 'periodInfo') {
|
|
2229
|
-
/** @type {shaka.dash.DashParser.PeriodInfo} */
|
|
2230
|
-
const frameRef = context[k];
|
|
2231
|
-
contextClone[k] = {
|
|
2232
|
-
start: frameRef.start,
|
|
2233
|
-
duration: frameRef.duration,
|
|
2234
|
-
node: null,
|
|
2235
|
-
isLastPeriod: frameRef.isLastPeriod,
|
|
2236
|
-
};
|
|
2237
|
-
} else {
|
|
2238
|
-
contextClone[k] = context[k];
|
|
2252
|
+
/**
|
|
2253
|
+
* @param {?shaka.dash.DashParser.InheritanceFrame} frame
|
|
2254
|
+
* @return {?shaka.dash.DashParser.InheritanceFrame}
|
|
2255
|
+
*/
|
|
2256
|
+
const cloneFrame = (frame) => {
|
|
2257
|
+
if (!frame) {
|
|
2258
|
+
return null;
|
|
2239
2259
|
}
|
|
2260
|
+
const clone = shaka.util.ObjectUtils.shallowCloneObject(frame);
|
|
2261
|
+
clone.segmentBase = null;
|
|
2262
|
+
clone.segmentList = null;
|
|
2263
|
+
clone.segmentTemplate = shaka.util.TXml.cloneNode(clone.segmentTemplate);
|
|
2264
|
+
return clone;
|
|
2265
|
+
};
|
|
2266
|
+
const contextClone = shaka.util.ObjectUtils.shallowCloneObject(context);
|
|
2267
|
+
contextClone.period = cloneFrame(contextClone.period);
|
|
2268
|
+
contextClone.adaptationSet = cloneFrame(contextClone.adaptationSet);
|
|
2269
|
+
contextClone.representation = cloneFrame(contextClone.representation);
|
|
2270
|
+
|
|
2271
|
+
if (contextClone.periodInfo) {
|
|
2272
|
+
contextClone.periodInfo =
|
|
2273
|
+
shaka.util.ObjectUtils.shallowCloneObject(contextClone.periodInfo);
|
|
2274
|
+
contextClone.periodInfo.node = null;
|
|
2240
2275
|
}
|
|
2241
2276
|
|
|
2242
2277
|
return contextClone;
|
|
@@ -3082,7 +3117,7 @@ shaka.dash.DashParser.Context;
|
|
|
3082
3117
|
* @typedef {{
|
|
3083
3118
|
* start: number,
|
|
3084
3119
|
* duration: ?number,
|
|
3085
|
-
* node:
|
|
3120
|
+
* node: ?shaka.extern.xml.Node,
|
|
3086
3121
|
* isLastPeriod: boolean
|
|
3087
3122
|
* }}
|
|
3088
3123
|
*
|
|
@@ -3094,7 +3129,7 @@ shaka.dash.DashParser.Context;
|
|
|
3094
3129
|
* @property {?number} duration
|
|
3095
3130
|
* The duration of the period; or null if the duration is not given. This
|
|
3096
3131
|
* will be non-null for all periods except the last.
|
|
3097
|
-
* @property {
|
|
3132
|
+
* @property {?shaka.extern.xml.Node} node
|
|
3098
3133
|
* The XML Node for the Period.
|
|
3099
3134
|
* @property {boolean} isLastPeriod
|
|
3100
3135
|
* Whether this Period is the last one in the manifest.
|
|
@@ -73,6 +73,13 @@ shaka.media.StreamingEngine = class {
|
|
|
73
73
|
/** @private {?shaka.extern.StreamingConfiguration} */
|
|
74
74
|
this.config_ = null;
|
|
75
75
|
|
|
76
|
+
/**
|
|
77
|
+
* Retains a reference to the function used to close SegmentIndex objects
|
|
78
|
+
* for streams which were switched away from during an ongoing update_().
|
|
79
|
+
* @private {!Map.<string, !function()>}
|
|
80
|
+
*/
|
|
81
|
+
this.deferredCloseSegmentIndex_ = new Map();
|
|
82
|
+
|
|
76
83
|
/** @private {number} */
|
|
77
84
|
this.bufferingGoalScale_ = 1;
|
|
78
85
|
|
|
@@ -504,6 +511,24 @@ shaka.media.StreamingEngine = class {
|
|
|
504
511
|
}
|
|
505
512
|
|
|
506
513
|
|
|
514
|
+
/**
|
|
515
|
+
* Handles deferred releases of old SegmentIndexes for the mediaState's
|
|
516
|
+
* content type from a previous update.
|
|
517
|
+
* @param {!shaka.media.StreamingEngine.MediaState_} mediaState
|
|
518
|
+
* @private
|
|
519
|
+
*/
|
|
520
|
+
handleDeferredCloseSegmentIndexes_(mediaState) {
|
|
521
|
+
for (const [key, value] of this.deferredCloseSegmentIndex_.entries()) {
|
|
522
|
+
const streamId = /** @type {string} */ (key);
|
|
523
|
+
const closeSegmentIndex = /** @type {!function()} */ (value);
|
|
524
|
+
if (streamId.includes(mediaState.type)) {
|
|
525
|
+
closeSegmentIndex();
|
|
526
|
+
this.deferredCloseSegmentIndex_.delete(streamId);
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
|
|
507
532
|
/**
|
|
508
533
|
* Switches to the given Stream. |stream| may be from any Variant.
|
|
509
534
|
*
|
|
@@ -576,7 +601,23 @@ shaka.media.StreamingEngine = class {
|
|
|
576
601
|
// Do not close segment indexes we are prefetching.
|
|
577
602
|
if (!this.audioPrefetchMap_.has(mediaState.stream)) {
|
|
578
603
|
if (mediaState.stream.closeSegmentIndex) {
|
|
579
|
-
mediaState.
|
|
604
|
+
if (mediaState.performingUpdate) {
|
|
605
|
+
const oldStreamTag =
|
|
606
|
+
shaka.media.StreamingEngine.logPrefix_(mediaState);
|
|
607
|
+
if (!this.deferredCloseSegmentIndex_.has(oldStreamTag)) {
|
|
608
|
+
// The ongoing update is still using the old stream's segment
|
|
609
|
+
// reference information.
|
|
610
|
+
// If we close the old stream now, the update will not complete
|
|
611
|
+
// correctly.
|
|
612
|
+
// The next onUpdate_() for this content type will resume the
|
|
613
|
+
// closeSegmentIndex() operation for the old stream once the ongoing
|
|
614
|
+
// update has finished, then immediately create a new segment index.
|
|
615
|
+
this.deferredCloseSegmentIndex_.set(
|
|
616
|
+
oldStreamTag, mediaState.stream.closeSegmentIndex);
|
|
617
|
+
}
|
|
618
|
+
} else {
|
|
619
|
+
mediaState.stream.closeSegmentIndex();
|
|
620
|
+
}
|
|
580
621
|
}
|
|
581
622
|
}
|
|
582
623
|
|
|
@@ -1169,6 +1210,13 @@ shaka.media.StreamingEngine = class {
|
|
|
1169
1210
|
return;
|
|
1170
1211
|
}
|
|
1171
1212
|
|
|
1213
|
+
// If stream switches happened during the previous update_() for this
|
|
1214
|
+
// content type, close out the old streams that were switched away from.
|
|
1215
|
+
// Even if we had switched away from the active stream 'A' during the
|
|
1216
|
+
// update_(), e.g. (A -> B -> A), closing 'A' is permissible here since we
|
|
1217
|
+
// will immediately re-create it in the logic below.
|
|
1218
|
+
this.handleDeferredCloseSegmentIndexes_(mediaState);
|
|
1219
|
+
|
|
1172
1220
|
// Make sure the segment index exists. If not, create the segment index.
|
|
1173
1221
|
if (!mediaState.stream.segmentIndex) {
|
|
1174
1222
|
const thisStream = mediaState.stream;
|
|
@@ -1450,14 +1498,11 @@ shaka.media.StreamingEngine = class {
|
|
|
1450
1498
|
mediaState.stream.segmentIndex,
|
|
1451
1499
|
'segment index should have been generated already');
|
|
1452
1500
|
|
|
1453
|
-
|
|
1454
|
-
mediaState.segmentIterator.current() : null;
|
|
1455
|
-
|
|
1456
|
-
if (currentSegment) {
|
|
1501
|
+
if (mediaState.segmentIterator) {
|
|
1457
1502
|
// Something is buffered from the same Stream. Use the current position
|
|
1458
1503
|
// in the segment index. This is updated via next() after each segment is
|
|
1459
1504
|
// appended.
|
|
1460
|
-
return
|
|
1505
|
+
return mediaState.segmentIterator.current();
|
|
1461
1506
|
} else if (mediaState.lastSegmentReference || bufferEnd) {
|
|
1462
1507
|
// Something is buffered from another Stream.
|
|
1463
1508
|
const time = mediaState.lastSegmentReference ?
|
|
@@ -1955,8 +2000,8 @@ shaka.media.StreamingEngine = class {
|
|
|
1955
2000
|
reference.startTime <= appendWindowEnd,
|
|
1956
2001
|
logPrefix + ' segment should start before append window end');
|
|
1957
2002
|
|
|
1958
|
-
const
|
|
1959
|
-
|
|
2003
|
+
const fullCodecs = (reference.codecs || mediaState.stream.codecs);
|
|
2004
|
+
const codecs = MimeUtils.getCodecBase(fullCodecs);
|
|
1960
2005
|
const mimeType = MimeUtils.getBasicType(
|
|
1961
2006
|
reference.mimeType || mediaState.stream.mimeType);
|
|
1962
2007
|
const timestampOffset = reference.timestampOffset;
|
|
@@ -1974,7 +2019,7 @@ shaka.media.StreamingEngine = class {
|
|
|
1974
2019
|
const isResetMediaSourceNecessary =
|
|
1975
2020
|
mediaState.lastCodecs && mediaState.lastMimeType &&
|
|
1976
2021
|
this.playerInterface_.mediaSourceEngine.isResetMediaSourceNecessary(
|
|
1977
|
-
mediaState.type, mediaState.stream, mimeType,
|
|
2022
|
+
mediaState.type, mediaState.stream, mimeType, fullCodecs);
|
|
1978
2023
|
if (isResetMediaSourceNecessary) {
|
|
1979
2024
|
let otherState = null;
|
|
1980
2025
|
if (mediaState.type === ContentType.VIDEO) {
|
|
@@ -2717,6 +2762,10 @@ shaka.media.StreamingEngine = class {
|
|
|
2717
2762
|
this.destroyer_.ensureNotDestroyed();
|
|
2718
2763
|
// Try to recover from network errors
|
|
2719
2764
|
if (error.category === shaka.util.Error.Category.NETWORK) {
|
|
2765
|
+
if (mediaState.restoreStreamAfterTrickPlay) {
|
|
2766
|
+
this.setTrickPlay(/* on= */ false);
|
|
2767
|
+
return;
|
|
2768
|
+
}
|
|
2720
2769
|
const maxDisabledTime = this.getDisabledTime_(error);
|
|
2721
2770
|
error.handled = this.playerInterface_.disableStream(
|
|
2722
2771
|
mediaState.stream, maxDisabledTime);
|
package/lib/player.js
CHANGED
|
@@ -5297,6 +5297,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
5297
5297
|
}
|
|
5298
5298
|
|
|
5299
5299
|
if (this.loadMode_ == shaka.Player.LoadMode.SRC_EQUALS) {
|
|
5300
|
+
this.stats_.addBytesDownloaded(NaN);
|
|
5300
5301
|
this.stats_.setResolution(
|
|
5301
5302
|
/* width= */ element.videoWidth || NaN,
|
|
5302
5303
|
/* height= */ element.videoHeight || NaN);
|
|
@@ -6942,19 +6943,32 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
6942
6943
|
if (hasAltStream) {
|
|
6943
6944
|
let didDisableStream = false;
|
|
6944
6945
|
|
|
6946
|
+
let isTrickModeVideo = false;
|
|
6947
|
+
|
|
6945
6948
|
for (const variant of this.manifest_.variants) {
|
|
6946
6949
|
const candidate = variant[stream.type];
|
|
6947
6950
|
|
|
6948
|
-
if (candidate
|
|
6951
|
+
if (!candidate) {
|
|
6952
|
+
continue;
|
|
6953
|
+
}
|
|
6954
|
+
|
|
6955
|
+
if (candidate.id === stream.id) {
|
|
6949
6956
|
variant.disabledUntilTime = (Date.now() / 1000) + disableTime;
|
|
6950
6957
|
didDisableStream = true;
|
|
6951
6958
|
|
|
6952
6959
|
shaka.log.v2(
|
|
6953
6960
|
'Disabled stream ' + stream.type + ':' + stream.id +
|
|
6954
6961
|
' for ' + disableTime + ' seconds...');
|
|
6962
|
+
} else if (candidate.trickModeVideo &&
|
|
6963
|
+
candidate.trickModeVideo.id == stream.id) {
|
|
6964
|
+
isTrickModeVideo = true;
|
|
6955
6965
|
}
|
|
6956
6966
|
}
|
|
6957
6967
|
|
|
6968
|
+
if (!didDisableStream && isTrickModeVideo) {
|
|
6969
|
+
return false;
|
|
6970
|
+
}
|
|
6971
|
+
|
|
6958
6972
|
goog.asserts.assert(didDisableStream, 'Must have disabled stream');
|
|
6959
6973
|
|
|
6960
6974
|
this.checkVariantsTimer_.tickEvery(1);
|
|
@@ -7504,7 +7518,7 @@ shaka.Player.TYPICAL_BUFFERING_THRESHOLD_ = 0.5;
|
|
|
7504
7518
|
* @export
|
|
7505
7519
|
*/
|
|
7506
7520
|
// eslint-disable-next-line no-useless-concat
|
|
7507
|
-
shaka.Player.version = 'v4.9.
|
|
7521
|
+
shaka.Player.version = 'v4.9.26' + '-uncompiled'; // x-release-please-version
|
|
7508
7522
|
|
|
7509
7523
|
// Initialize the deprecation system using the version string we just set
|
|
7510
7524
|
// on the player.
|
|
@@ -710,10 +710,6 @@ shaka.text.UITextDisplayer = class {
|
|
|
710
710
|
// Only do this for the text itself.
|
|
711
711
|
elem.style.backgroundColor = 'rgba(0, 0, 0, 0.8)';
|
|
712
712
|
}
|
|
713
|
-
const fontFamily = inherit((c) => c.fontFamily);
|
|
714
|
-
if (fontFamily) {
|
|
715
|
-
elem.style.fontFamily = fontFamily;
|
|
716
|
-
}
|
|
717
713
|
}
|
|
718
714
|
if (text) {
|
|
719
715
|
elem.textContent = text;
|
package/lib/util/periods.js
CHANGED
|
@@ -890,26 +890,33 @@ shaka.util.PeriodCombiner = class {
|
|
|
890
890
|
// Create a fresh output stream for trick-mode playback.
|
|
891
891
|
output.trickModeVideo = shaka.util.PeriodCombiner.cloneStream_(
|
|
892
892
|
input.trickModeVideo);
|
|
893
|
-
|
|
894
|
-
// The trick-mode tracks in multi-period content should have trick-mode
|
|
895
|
-
// segment indexes whenever available, rather than only regular-mode
|
|
896
|
-
// segment indexes.
|
|
893
|
+
output.trickModeVideo.matchedStreams = [];
|
|
897
894
|
output.trickModeVideo.createSegmentIndex = () => {
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
895
|
+
if (output.trickModeVideo.segmentIndex) {
|
|
896
|
+
return Promise.resolve();
|
|
897
|
+
}
|
|
898
|
+
const segmentIndex = new shaka.media.MetaSegmentIndex();
|
|
899
|
+
goog.asserts.assert(output.trickModeVideo.matchedStreams,
|
|
900
|
+
'trickmode matched streams should exist');
|
|
901
|
+
for (const stream of output.trickModeVideo.matchedStreams) {
|
|
902
|
+
goog.asserts.assert(stream.segmentIndex,
|
|
903
|
+
'trickmode segment index should exist');
|
|
904
|
+
segmentIndex.appendSegmentIndex(stream.segmentIndex);
|
|
905
|
+
}
|
|
906
|
+
output.trickModeVideo.segmentIndex = segmentIndex;
|
|
907
|
+
|
|
903
908
|
return Promise.resolve();
|
|
904
909
|
};
|
|
905
910
|
}
|
|
906
911
|
|
|
907
912
|
// Concatenate the trick mode input onto the trick mode output.
|
|
913
|
+
output.trickModeVideo.matchedStreams.push(input.trickModeVideo);
|
|
908
914
|
shaka.util.PeriodCombiner.concatenateStreams_(
|
|
909
915
|
output.trickModeVideo, input.trickModeVideo);
|
|
910
916
|
} else if (output.trickModeVideo) {
|
|
911
917
|
// We have a trick mode output, but no input from this Period. Fill it in
|
|
912
918
|
// from the standard input Stream.
|
|
919
|
+
output.trickModeVideo.matchedStreams.push(input);
|
|
913
920
|
shaka.util.PeriodCombiner.concatenateStreams_(
|
|
914
921
|
output.trickModeVideo, input);
|
|
915
922
|
}
|
package/lib/util/tXml.js
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
goog.provide('shaka.util.TXml');
|
|
8
8
|
|
|
9
|
+
goog.require('shaka.util.ObjectUtils');
|
|
9
10
|
goog.require('shaka.util.StringUtils');
|
|
10
11
|
goog.require('shaka.log');
|
|
11
12
|
|
|
@@ -71,24 +72,37 @@ shaka.util.TXml = class {
|
|
|
71
72
|
}
|
|
72
73
|
|
|
73
74
|
/**
|
|
74
|
-
*
|
|
75
|
+
* Get namespace based on schema
|
|
75
76
|
* @param {string} schema
|
|
76
77
|
* @return {string}
|
|
77
78
|
*/
|
|
78
79
|
static getKnownNameSpace(schema) {
|
|
79
|
-
if (shaka.util.TXml.
|
|
80
|
-
return shaka.util.TXml.
|
|
80
|
+
if (shaka.util.TXml.uriToNameSpace_.has(schema)) {
|
|
81
|
+
return shaka.util.TXml.uriToNameSpace_.get(schema);
|
|
81
82
|
}
|
|
82
83
|
return '';
|
|
83
84
|
}
|
|
84
85
|
|
|
85
86
|
/**
|
|
86
|
-
*
|
|
87
|
+
* Get schema based on namespace
|
|
88
|
+
* @param {string} NS
|
|
89
|
+
* @return {string}
|
|
90
|
+
*/
|
|
91
|
+
static getKnownSchema(NS) {
|
|
92
|
+
if (shaka.util.TXml.nameSpaceToUri_.has(NS)) {
|
|
93
|
+
return shaka.util.TXml.nameSpaceToUri_.get(NS);
|
|
94
|
+
}
|
|
95
|
+
return '';
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Sets NS <-> schema bidirectional mapping
|
|
87
100
|
* @param {string} schema
|
|
88
101
|
* @param {string} NS
|
|
89
102
|
*/
|
|
90
103
|
static setKnownNameSpace(schema, NS) {
|
|
91
|
-
shaka.util.TXml.
|
|
104
|
+
shaka.util.TXml.uriToNameSpace_.set(schema, NS);
|
|
105
|
+
shaka.util.TXml.nameSpaceToUri_.set(NS, schema);
|
|
92
106
|
}
|
|
93
107
|
|
|
94
108
|
/**
|
|
@@ -873,7 +887,12 @@ shaka.util.TXml = class {
|
|
|
873
887
|
*/
|
|
874
888
|
static txmlNodeToDomElement(node) {
|
|
875
889
|
const TXml = shaka.util.TXml;
|
|
876
|
-
|
|
890
|
+
let namespace = '';
|
|
891
|
+
const parts = node.tagName.split(':');
|
|
892
|
+
if (parts.length > 0) {
|
|
893
|
+
namespace = TXml.getKnownSchema(parts[0]);
|
|
894
|
+
}
|
|
895
|
+
const element = document.createElementNS(namespace, node.tagName);
|
|
877
896
|
|
|
878
897
|
for (const k in node.attributes) {
|
|
879
898
|
const v = node.attributes[k];
|
|
@@ -892,9 +911,41 @@ shaka.util.TXml = class {
|
|
|
892
911
|
|
|
893
912
|
return element;
|
|
894
913
|
}
|
|
914
|
+
|
|
915
|
+
/**
|
|
916
|
+
* Clones node and its children recursively. Skips parent.
|
|
917
|
+
* @param {?shaka.extern.xml.Node} node
|
|
918
|
+
* @return {?shaka.extern.xml.Node}
|
|
919
|
+
*/
|
|
920
|
+
static cloneNode(node) {
|
|
921
|
+
if (!node) {
|
|
922
|
+
return null;
|
|
923
|
+
}
|
|
924
|
+
/** @type {!shaka.extern.xml.Node} */
|
|
925
|
+
const clone = {
|
|
926
|
+
tagName: node.tagName,
|
|
927
|
+
attributes: shaka.util.ObjectUtils.shallowCloneObject(node.attributes),
|
|
928
|
+
children: [],
|
|
929
|
+
parent: null,
|
|
930
|
+
};
|
|
931
|
+
for (const child of node.children) {
|
|
932
|
+
if (typeof child === 'string') {
|
|
933
|
+
clone.children.push(child);
|
|
934
|
+
} else {
|
|
935
|
+
const clonedChild = shaka.util.TXml.cloneNode(child);
|
|
936
|
+
clonedChild.parent = clone;
|
|
937
|
+
clone.children.push(clonedChild);
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
return clone;
|
|
941
|
+
}
|
|
895
942
|
};
|
|
896
943
|
|
|
897
|
-
|
|
944
|
+
/** @private {!Map<string, string>} */
|
|
945
|
+
shaka.util.TXml.uriToNameSpace_ = new Map();
|
|
946
|
+
|
|
947
|
+
/** @private {!Map<string, string>} */
|
|
948
|
+
shaka.util.TXml.nameSpaceToUri_ = new Map();
|
|
898
949
|
|
|
899
950
|
|
|
900
951
|
/**
|
package/package.json
CHANGED
package/ui/less/containers.less
CHANGED
|
@@ -22,10 +22,9 @@
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
/* Set the fonts for all other content. */
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}
|
|
25
|
+
font-family: Roboto, sans-serif, TengwarTelcontar;
|
|
26
|
+
font-weight: normal;
|
|
27
|
+
-webkit-font-smoothing: antialiased;
|
|
29
28
|
}
|
|
30
29
|
|
|
31
30
|
/* Each browser has a different prefixed pseudo-class for fullscreened elements.
|
package/ui/less/tooltip.less
CHANGED
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
content: attr(aria-label);
|
|
48
48
|
|
|
49
49
|
/* Override .material-icons-round text styling */
|
|
50
|
-
font-family: Roboto
|
|
50
|
+
font-family: Roboto, sans-serif;
|
|
51
51
|
line-height: calc(@material-icons-width / 2);
|
|
52
52
|
white-space: nowrap;
|
|
53
53
|
font-size: 13px;
|