shaka-player 4.11.13 → 4.11.14
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/.eslintrc.js +1 -0
- package/AUTHORS +1 -0
- package/CONTRIBUTORS +1 -0
- package/dist/locales.js +33 -33
- package/dist/shaka-player.compiled.d.ts +7 -7
- package/dist/shaka-player.compiled.debug.d.ts +7 -7
- package/dist/shaka-player.compiled.debug.js +143 -140
- package/dist/shaka-player.compiled.debug.map +3 -3
- package/dist/shaka-player.compiled.js +1252 -1252
- package/dist/shaka-player.compiled.map +2 -2
- package/dist/shaka-player.ui.d.ts +7 -7
- package/dist/shaka-player.ui.debug.d.ts +7 -7
- package/dist/shaka-player.ui.debug.js +133 -130
- package/dist/shaka-player.ui.debug.map +3 -3
- package/dist/shaka-player.ui.js +1451 -1451
- package/dist/shaka-player.ui.map +2 -2
- package/externs/shaka/abortable.js +36 -36
- package/lib/ads/interstitial_ad_manager.js +2 -0
- package/lib/hls/hls_parser.js +1 -1
- package/lib/media/drm_engine.js +2 -0
- package/lib/media/media_source_engine.js +61 -3
- package/lib/media/preload_manager.js +6 -1
- package/lib/media/segment_reference.js +1 -1
- package/lib/media/streaming_engine.js +9 -11
- package/lib/player.js +1 -1
- package/lib/polyfill/media_capabilities.js +46 -8
- package/lib/text/vtt_text_parser.js +2 -8
- package/lib/util/abortable_operation.js +8 -6
- package/lib/util/platform.js +18 -7
- package/package.json +2 -2
- package/ui/chapter_selection.js +6 -2
|
@@ -18,39 +18,39 @@
|
|
|
18
18
|
* @template T
|
|
19
19
|
* @exportDoc
|
|
20
20
|
*/
|
|
21
|
-
shaka.extern.IAbortableOperation =
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
21
|
+
shaka.extern.IAbortableOperation = class {
|
|
22
|
+
constructor() {
|
|
23
|
+
/**
|
|
24
|
+
* A Promise which represents the underlying operation. It is resolved when
|
|
25
|
+
* the operation is complete, and rejected if the operation fails or is
|
|
26
|
+
* aborted. Aborted operations should be rejected with a shaka.util.Error
|
|
27
|
+
* object using the error code OPERATION_ABORTED.
|
|
28
|
+
*
|
|
29
|
+
* @const {!Promise.<T>}
|
|
30
|
+
* @exportDoc
|
|
31
|
+
*/
|
|
32
|
+
this.promise;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Can be called by anyone holding this object to abort the underlying
|
|
37
|
+
* operation. This is not cancelation, and will not necessarily result in
|
|
38
|
+
* any work being undone. abort() should return a Promise which is resolved
|
|
39
|
+
* when the underlying operation has been aborted. The returned Promise
|
|
40
|
+
* should never be rejected.
|
|
41
|
+
*
|
|
42
|
+
* @return {!Promise}
|
|
43
|
+
* @exportDoc
|
|
44
|
+
*/
|
|
45
|
+
abort() {}
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* @param {function(boolean)} onFinal A callback to be invoked after the
|
|
50
|
+
* operation succeeds or fails. The boolean argument is true
|
|
51
|
+
* if the operation succeeded and false if it failed.
|
|
52
|
+
* @return {!shaka.extern.IAbortableOperation.<T>} Returns this.
|
|
53
|
+
* @exportDoc
|
|
54
|
+
*/
|
|
55
|
+
finally(onFinal) {}
|
|
56
|
+
};
|
|
@@ -955,6 +955,8 @@ shaka.ads.InterstitialAdManager = class {
|
|
|
955
955
|
goog.asserts.assert(this.player_, 'Must have player');
|
|
956
956
|
goog.asserts.assert(this.basePlayer_, 'Must have base player');
|
|
957
957
|
this.player_.configure(this.basePlayer_.getNonDefaultConfiguration());
|
|
958
|
+
this.player_.configure('ads.disableHLSInterstitial', true);
|
|
959
|
+
this.player_.configure('ads.disableDASHInterstitial', true);
|
|
958
960
|
const netEngine = this.player_.getNetworkingEngine();
|
|
959
961
|
goog.asserts.assert(netEngine, 'Need networking engine');
|
|
960
962
|
netEngine.clearAllRequestFilters();
|
package/lib/hls/hls_parser.js
CHANGED
|
@@ -4122,7 +4122,7 @@ shaka.hls.HlsParser = class {
|
|
|
4122
4122
|
let aesKey = undefined;
|
|
4123
4123
|
|
|
4124
4124
|
let discontinuitySequence = shaka.hls.Utils.getFirstTagWithNameAsNumber(
|
|
4125
|
-
playlist.tags, 'EXT-X-DISCONTINUITY-SEQUENCE',
|
|
4125
|
+
playlist.tags, 'EXT-X-DISCONTINUITY-SEQUENCE', -1);
|
|
4126
4126
|
const mediaSequenceNumber = shaka.hls.Utils.getFirstTagWithNameAsNumber(
|
|
4127
4127
|
playlist.tags, 'EXT-X-MEDIA-SEQUENCE', 0);
|
|
4128
4128
|
const skipTag = shaka.hls.Utils.getFirstTagWithName(
|
package/lib/media/drm_engine.js
CHANGED
|
@@ -1715,6 +1715,7 @@ shaka.media.DrmEngine = class {
|
|
|
1715
1715
|
const testKeySystems = [
|
|
1716
1716
|
'org.w3.clearkey',
|
|
1717
1717
|
'com.widevine.alpha',
|
|
1718
|
+
'com.widevine.alpha.experiment', // Widevine L1 in Windows
|
|
1718
1719
|
'com.microsoft.playready',
|
|
1719
1720
|
'com.microsoft.playready.hardware',
|
|
1720
1721
|
'com.microsoft.playready.recommendation',
|
|
@@ -1739,6 +1740,7 @@ shaka.media.DrmEngine = class {
|
|
|
1739
1740
|
|
|
1740
1741
|
const testRobustness = {
|
|
1741
1742
|
'com.widevine.alpha': widevineRobustness,
|
|
1743
|
+
'com.widevine.alpha.experiment': widevineRobustness,
|
|
1742
1744
|
'com.microsoft.playready.recommendation': playreadyRobustness,
|
|
1743
1745
|
};
|
|
1744
1746
|
|
|
@@ -883,7 +883,8 @@ shaka.media.MediaSourceEngine = class {
|
|
|
883
883
|
const ContentType = shaka.util.ManifestParserUtils.ContentType;
|
|
884
884
|
|
|
885
885
|
if (contentType == ContentType.TEXT) {
|
|
886
|
-
if (this.
|
|
886
|
+
if (this.manifestType_ == shaka.media.ManifestParser.HLS &&
|
|
887
|
+
reference.discontinuitySequence >= 0) {
|
|
887
888
|
// This won't be known until the first video segment is appended.
|
|
888
889
|
const offset = await this.textSequenceModeOffset_;
|
|
889
890
|
this.textEngine_.setTimestampOffset(offset);
|
|
@@ -977,7 +978,7 @@ shaka.media.MediaSourceEngine = class {
|
|
|
977
978
|
const isBestSourceBufferForTimestamps =
|
|
978
979
|
contentType == ContentType.VIDEO ||
|
|
979
980
|
!(ContentType.VIDEO in this.sourceBuffers_);
|
|
980
|
-
if (
|
|
981
|
+
if (isBestSourceBufferForTimestamps) {
|
|
981
982
|
this.textSequenceModeOffset_.resolve(timestampOffset);
|
|
982
983
|
}
|
|
983
984
|
}
|
|
@@ -1306,6 +1307,10 @@ shaka.media.MediaSourceEngine = class {
|
|
|
1306
1307
|
this.textSequenceModeOffset_ = new shaka.util.PublicPromise();
|
|
1307
1308
|
}
|
|
1308
1309
|
|
|
1310
|
+
if (!this.sequenceMode_) {
|
|
1311
|
+
return;
|
|
1312
|
+
}
|
|
1313
|
+
|
|
1309
1314
|
// Queue an abort() to help MSE splice together overlapping segments.
|
|
1310
1315
|
// We set appendWindowEnd when we change periods in DASH content, and the
|
|
1311
1316
|
// period transition may result in overlap.
|
|
@@ -1839,6 +1844,48 @@ shaka.media.MediaSourceEngine = class {
|
|
|
1839
1844
|
null);
|
|
1840
1845
|
}
|
|
1841
1846
|
|
|
1847
|
+
/**
|
|
1848
|
+
* Returns the source buffer parameters
|
|
1849
|
+
* @param {shaka.util.ManifestParserUtils.ContentType} contentType
|
|
1850
|
+
* @return {?shaka.media.MediaSourceEngine.SourceBufferParams}
|
|
1851
|
+
* @private
|
|
1852
|
+
*/
|
|
1853
|
+
getSourceBufferParams_(contentType) {
|
|
1854
|
+
if (!this.sourceBuffers_[contentType]) {
|
|
1855
|
+
return null;
|
|
1856
|
+
}
|
|
1857
|
+
return {
|
|
1858
|
+
timestampOffset: this.sourceBuffers_[contentType].timestampOffset,
|
|
1859
|
+
appendWindowStart: this.sourceBuffers_[contentType].appendWindowStart,
|
|
1860
|
+
appendWindowEnd: this.sourceBuffers_[contentType].appendWindowEnd,
|
|
1861
|
+
};
|
|
1862
|
+
}
|
|
1863
|
+
|
|
1864
|
+
/**
|
|
1865
|
+
* Restore source buffer parameters
|
|
1866
|
+
* @param {shaka.util.ManifestParserUtils.ContentType} contentType
|
|
1867
|
+
* @param {?shaka.media.MediaSourceEngine.SourceBufferParams} params
|
|
1868
|
+
* @private
|
|
1869
|
+
*/
|
|
1870
|
+
restoreSourceBufferParams_(contentType, params) {
|
|
1871
|
+
if (!params) {
|
|
1872
|
+
return;
|
|
1873
|
+
}
|
|
1874
|
+
|
|
1875
|
+
if (!this.sourceBuffers_[contentType]) {
|
|
1876
|
+
shaka.log.warning('Attempted to restore a non-existent source buffer');
|
|
1877
|
+
return;
|
|
1878
|
+
}
|
|
1879
|
+
|
|
1880
|
+
this.sourceBuffers_[contentType].timestampOffset =
|
|
1881
|
+
params.timestampOffset;
|
|
1882
|
+
// `end` needs to be set before `start`
|
|
1883
|
+
this.sourceBuffers_[contentType].appendWindowEnd =
|
|
1884
|
+
params.appendWindowEnd;
|
|
1885
|
+
this.sourceBuffers_[contentType].appendWindowStart =
|
|
1886
|
+
params.appendWindowStart;
|
|
1887
|
+
}
|
|
1888
|
+
|
|
1842
1889
|
/**
|
|
1843
1890
|
* Resets the MediaSource and re-adds source buffers due to codec mismatch
|
|
1844
1891
|
*
|
|
@@ -1899,7 +1946,6 @@ shaka.media.MediaSourceEngine = class {
|
|
|
1899
1946
|
}
|
|
1900
1947
|
await Promise.all(cleanup);
|
|
1901
1948
|
this.transmuxers_ = {};
|
|
1902
|
-
this.sourceBuffers_ = {};
|
|
1903
1949
|
|
|
1904
1950
|
const previousDuration = this.mediaSource_.duration;
|
|
1905
1951
|
this.mediaSourceOpen_ = new shaka.util.PublicPromise();
|
|
@@ -1930,6 +1976,7 @@ shaka.media.MediaSourceEngine = class {
|
|
|
1930
1976
|
onSourceBufferAdded);
|
|
1931
1977
|
|
|
1932
1978
|
for (const contentType of streamsByType.keys()) {
|
|
1979
|
+
const previousParams = this.getSourceBufferParams_(contentType);
|
|
1933
1980
|
const stream = streamsByType.get(contentType);
|
|
1934
1981
|
// eslint-disable-next-line no-await-in-loop
|
|
1935
1982
|
await this.initSourceBuffer_(contentType, stream, stream.codecs);
|
|
@@ -1939,6 +1986,8 @@ shaka.media.MediaSourceEngine = class {
|
|
|
1939
1986
|
} else {
|
|
1940
1987
|
this.queues_[contentType] = [];
|
|
1941
1988
|
}
|
|
1989
|
+
|
|
1990
|
+
this.restoreSourceBufferParams_(contentType, previousParams);
|
|
1942
1991
|
}
|
|
1943
1992
|
|
|
1944
1993
|
// Fake a seek to catchup the playhead.
|
|
@@ -2226,3 +2275,12 @@ shaka.media.MediaSourceEngine.SourceBufferMode_ = {
|
|
|
2226
2275
|
* Callback to use when metadata arrives.
|
|
2227
2276
|
*/
|
|
2228
2277
|
shaka.media.MediaSourceEngine.PlayerInterface;
|
|
2278
|
+
|
|
2279
|
+
/**
|
|
2280
|
+
* @typedef {{
|
|
2281
|
+
* timestampOffset: number,
|
|
2282
|
+
* appendWindowStart: number,
|
|
2283
|
+
* appendWindowEnd: number
|
|
2284
|
+
* }}
|
|
2285
|
+
*/
|
|
2286
|
+
shaka.media.MediaSourceEngine.SourceBufferParams;
|
|
@@ -403,7 +403,12 @@ shaka.media.PreloadManager = class extends shaka.util.FakeEventTarget {
|
|
|
403
403
|
|
|
404
404
|
this.successPromise_.resolve();
|
|
405
405
|
} catch (error) {
|
|
406
|
-
|
|
406
|
+
// Ignore OPERATION_ABORTED and OBJECT_DESTROYED errors.
|
|
407
|
+
if (!(error instanceof shaka.util.Error) ||
|
|
408
|
+
(error.code != shaka.util.Error.Code.OPERATION_ABORTED &&
|
|
409
|
+
error.code != shaka.util.Error.Code.OBJECT_DESTROYED)) {
|
|
410
|
+
this.successPromise_.reject(error);
|
|
411
|
+
}
|
|
407
412
|
}
|
|
408
413
|
})();
|
|
409
414
|
}
|
|
@@ -295,7 +295,7 @@ shaka.media.SegmentReference = class {
|
|
|
295
295
|
this.thumbnailSprite = null;
|
|
296
296
|
|
|
297
297
|
/** @type {number} */
|
|
298
|
-
this.discontinuitySequence =
|
|
298
|
+
this.discontinuitySequence = -1;
|
|
299
299
|
|
|
300
300
|
/** @type {boolean} */
|
|
301
301
|
this.allPartialSegments = allPartialSegments;
|
|
@@ -2148,17 +2148,15 @@ shaka.media.StreamingEngine = class {
|
|
|
2148
2148
|
}
|
|
2149
2149
|
}
|
|
2150
2150
|
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
mediaState.type, reference.startTime));
|
|
2161
|
-
}
|
|
2151
|
+
const lastDiscontinuitySequence =
|
|
2152
|
+
mediaState.lastSegmentReference ?
|
|
2153
|
+
mediaState.lastSegmentReference.discontinuitySequence : null;
|
|
2154
|
+
// Across discontinuity bounds, we should resync timestamps. The next
|
|
2155
|
+
// segment appended should land at its theoretical timestamp from the
|
|
2156
|
+
// segment index.
|
|
2157
|
+
if (reference.discontinuitySequence != lastDiscontinuitySequence) {
|
|
2158
|
+
operations.push(this.playerInterface_.mediaSourceEngine.resync(
|
|
2159
|
+
mediaState.type, reference.startTime));
|
|
2162
2160
|
}
|
|
2163
2161
|
|
|
2164
2162
|
await Promise.all(operations);
|
package/lib/player.js
CHANGED
|
@@ -8123,7 +8123,7 @@ shaka.Player.TYPICAL_BUFFERING_THRESHOLD_ = 0.5;
|
|
|
8123
8123
|
* @export
|
|
8124
8124
|
*/
|
|
8125
8125
|
// eslint-disable-next-line no-useless-concat, max-len
|
|
8126
|
-
shaka.Player.version = 'v4.11.
|
|
8126
|
+
shaka.Player.version = 'v4.11.14' + '-uncompiled'; // x-release-please-version
|
|
8127
8127
|
|
|
8128
8128
|
// Initialize the deprecation system using the version string we just set
|
|
8129
8129
|
// on the player.
|
|
@@ -327,18 +327,56 @@ shaka.polyfill.MediaCapabilities = class {
|
|
|
327
327
|
|
|
328
328
|
let displayType = videoConfig.contentType;
|
|
329
329
|
if (videoConfig.width && videoConfig.height) {
|
|
330
|
-
|
|
331
|
-
|
|
330
|
+
// All Chromecast can support 720p videos
|
|
331
|
+
if (videoConfig.width > 1280 || videoConfig.height > 720) {
|
|
332
|
+
displayType +=
|
|
333
|
+
`; width=${videoConfig.width}; height=${videoConfig.height}`;
|
|
334
|
+
}
|
|
332
335
|
}
|
|
333
336
|
if (videoConfig.framerate) {
|
|
334
|
-
|
|
337
|
+
// All Chromecast can support a framerate of 24, 25 or 30.
|
|
338
|
+
const framerate = Math.round(videoConfig.framerate);
|
|
339
|
+
if (framerate < 24 || framerate > 30) {
|
|
340
|
+
displayType += `; framerate=${videoConfig.framerate}`;
|
|
341
|
+
}
|
|
335
342
|
}
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
343
|
+
|
|
344
|
+
// Don't trust Closure types here. Although transferFunction is string or
|
|
345
|
+
// undefined, we don't want to count on the input type. A switch statement
|
|
346
|
+
// will, however, differentiate between null and undefined. So we default
|
|
347
|
+
// to a blank string.
|
|
348
|
+
const transferFunction = videoConfig.transferFunction || '';
|
|
349
|
+
|
|
350
|
+
// Based on internal sources. Googlers, see go/cast-hdr-queries for source.
|
|
351
|
+
switch (transferFunction) {
|
|
352
|
+
// The empty case falls through to SDR.
|
|
353
|
+
case '':
|
|
354
|
+
// These are the only 3 values defined by MCap as of November 2024.
|
|
355
|
+
case 'srgb':
|
|
356
|
+
// https://en.wikipedia.org/wiki/Standard-dynamic-range_video
|
|
357
|
+
// https://en.wikipedia.org/wiki/SRGB
|
|
358
|
+
// https://en.wikipedia.org/wiki/Rec._709
|
|
359
|
+
// This is SDR, standardized in BT 709.
|
|
360
|
+
// The platform recognizes "eotf=bt709", but we can also omit it.
|
|
361
|
+
break;
|
|
362
|
+
|
|
363
|
+
case 'pq':
|
|
364
|
+
// https://en.wikipedia.org/wiki/Perceptual_quantizer
|
|
365
|
+
// This HDR transfer function is standardized as SMPTE ST 2084.
|
|
366
|
+
displayType += '; eotf=smpte2084';
|
|
367
|
+
break;
|
|
368
|
+
|
|
369
|
+
case 'hlg':
|
|
370
|
+
// https://en.wikipedia.org/wiki/Hybrid_log%E2%80%93gamma
|
|
371
|
+
// This HDR transfer function is standardized as ARIB STD-B67.
|
|
372
|
+
displayType += '; eotf=arib-std-b67';
|
|
373
|
+
break;
|
|
374
|
+
|
|
375
|
+
default:
|
|
376
|
+
// An unrecognized transfer function. Reject this query.
|
|
377
|
+
return false;
|
|
341
378
|
}
|
|
379
|
+
|
|
342
380
|
let result = false;
|
|
343
381
|
if (displayType in shaka.polyfill.MediaCapabilities
|
|
344
382
|
.memoizedCanDisplayTypeRequests_) {
|
|
@@ -86,13 +86,7 @@ shaka.text.VttTextParser = class {
|
|
|
86
86
|
// Only use 'X-TIMESTAMP-MAP' with HLS. This overrides offset above.
|
|
87
87
|
if (blocks[0].includes('X-TIMESTAMP-MAP') &&
|
|
88
88
|
this.manifestType_ == shaka.media.ManifestParser.HLS) {
|
|
89
|
-
|
|
90
|
-
// Compute a different, rollover-based offset for sequence mode.
|
|
91
|
-
offset = this.computeHlsSequenceModeOffset_(blocks[0], time);
|
|
92
|
-
} else {
|
|
93
|
-
// Calculate the offset from the segment startTime.
|
|
94
|
-
offset = time.segmentStart;
|
|
95
|
-
}
|
|
89
|
+
offset = this.computeHlsOffset_(blocks[0], time);
|
|
96
90
|
}
|
|
97
91
|
|
|
98
92
|
// Parse VTT regions.
|
|
@@ -129,7 +123,7 @@ shaka.text.VttTextParser = class {
|
|
|
129
123
|
* @return {number}
|
|
130
124
|
* @private
|
|
131
125
|
*/
|
|
132
|
-
|
|
126
|
+
computeHlsOffset_(headerBlock, time) {
|
|
133
127
|
// https://bit.ly/2K92l7y
|
|
134
128
|
// The 'X-TIMESTAMP-MAP' header is used in HLS to align text with
|
|
135
129
|
// the rest of the media.
|
|
@@ -39,8 +39,8 @@ shaka.util.AbortableOperation = class {
|
|
|
39
39
|
/** @private {function():!Promise} */
|
|
40
40
|
this.onAbort_ = onAbort;
|
|
41
41
|
|
|
42
|
-
/** @private {
|
|
43
|
-
this.
|
|
42
|
+
/** @private {?Promise} */
|
|
43
|
+
this.abortPromise_ = null;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
/**
|
|
@@ -48,7 +48,7 @@ shaka.util.AbortableOperation = class {
|
|
|
48
48
|
* @export
|
|
49
49
|
*/
|
|
50
50
|
get aborted() {
|
|
51
|
-
return this.
|
|
51
|
+
return this.abortPromise_ !== null;
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
/**
|
|
@@ -118,8 +118,10 @@ shaka.util.AbortableOperation = class {
|
|
|
118
118
|
* @export
|
|
119
119
|
*/
|
|
120
120
|
abort() {
|
|
121
|
-
this.
|
|
122
|
-
|
|
121
|
+
if (!this.abortPromise_) {
|
|
122
|
+
this.abortPromise_ = this.onAbort_();
|
|
123
|
+
}
|
|
124
|
+
return this.abortPromise_;
|
|
123
125
|
}
|
|
124
126
|
|
|
125
127
|
/**
|
|
@@ -174,7 +176,7 @@ shaka.util.AbortableOperation = class {
|
|
|
174
176
|
|
|
175
177
|
const makeCallback = (isSuccess) => {
|
|
176
178
|
return (value) => {
|
|
177
|
-
if (this.
|
|
179
|
+
if (this.abortPromise_ && isSuccess) {
|
|
178
180
|
// If "this" is not abortable(), or if abort() is called after "this"
|
|
179
181
|
// is complete but before the next stage in the chain begins, we
|
|
180
182
|
// should stop right away.
|
package/lib/util/platform.js
CHANGED
|
@@ -205,6 +205,17 @@ shaka.util.Platform = class {
|
|
|
205
205
|
shaka.util.Platform.chromeVersion() === 68;
|
|
206
206
|
}
|
|
207
207
|
|
|
208
|
+
/**
|
|
209
|
+
* Check if the current platform is a WebOS 6.
|
|
210
|
+
*
|
|
211
|
+
* @return {boolean}
|
|
212
|
+
*/
|
|
213
|
+
static isWebOS6() {
|
|
214
|
+
// See: https://webostv.developer.lge.com/develop/specifications/web-api-and-web-engine#useragent-string
|
|
215
|
+
return shaka.util.Platform.isWebOS() &&
|
|
216
|
+
shaka.util.Platform.chromeVersion() === 79;
|
|
217
|
+
}
|
|
218
|
+
|
|
208
219
|
/**
|
|
209
220
|
* Check if the current platform is a Google Chromecast.
|
|
210
221
|
*
|
|
@@ -627,19 +638,19 @@ shaka.util.Platform = class {
|
|
|
627
638
|
/**
|
|
628
639
|
* Returns if codec switching SMOOTH is known reliable device support.
|
|
629
640
|
*
|
|
630
|
-
* Some devices are known not to support
|
|
641
|
+
* Some devices are known not to support <code>SourceBuffer.changeType</code>
|
|
631
642
|
* well. These devices should use the reload strategy. If a device
|
|
632
|
-
* reports that it supports
|
|
633
|
-
* it should be
|
|
643
|
+
* reports that it supports <code<changeType</code> but supports it unreliably
|
|
644
|
+
* it should be disallowed in this method.
|
|
634
645
|
*
|
|
635
646
|
* @return {boolean}
|
|
636
647
|
*/
|
|
637
648
|
static supportsSmoothCodecSwitching() {
|
|
638
649
|
const Platform = shaka.util.Platform;
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
Platform.
|
|
650
|
+
// All Tizen versions (up to Tizen 8) do not support SMOOTH so far.
|
|
651
|
+
// webOS seems to support SMOOTH from webOS 22.
|
|
652
|
+
if (Platform.isTizen() || Platform.isPS4() || Platform.isPS5() ||
|
|
653
|
+
Platform.isWebOS6()) {
|
|
643
654
|
return false;
|
|
644
655
|
}
|
|
645
656
|
// Older chromecasts without GoogleTV seem to not support SMOOTH properly.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "shaka-player",
|
|
3
3
|
"description": "DASH/EME video player library",
|
|
4
|
-
"version": "4.11.
|
|
4
|
+
"version": "4.11.14",
|
|
5
5
|
"homepage": "https://github.com/shaka-project/shaka-player",
|
|
6
6
|
"author": "Google",
|
|
7
7
|
"maintainers": [
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"core-js": "^3.21.1",
|
|
27
27
|
"dialog-polyfill": "^0.5.6",
|
|
28
28
|
"es6-promise-polyfill": "^1.2.0",
|
|
29
|
-
"eslint": "^8.
|
|
29
|
+
"eslint": "^8.57.1",
|
|
30
30
|
"eslint-config-google": "^0.14.0",
|
|
31
31
|
"eslint-plugin-shaka-rules": "file:./build/eslint-plugin-shaka-rules",
|
|
32
32
|
"esprima": "^4.0.1",
|
package/ui/chapter_selection.js
CHANGED
|
@@ -119,14 +119,18 @@ shaka.ui.ChapterSelection = class extends shaka.ui.SettingsMenu {
|
|
|
119
119
|
const currentLocales = this.localization.getCurrentLocales();
|
|
120
120
|
for (const locale of Array.from(currentLocales)) {
|
|
121
121
|
nextLanguage = locale;
|
|
122
|
-
|
|
122
|
+
// If player is a proxy, and the cast receiver doesn't support this
|
|
123
|
+
// method, you get back undefined.
|
|
124
|
+
nextChapters = this.player.getChapters(nextLanguage) || [];
|
|
123
125
|
if (nextChapters.length) {
|
|
124
126
|
break;
|
|
125
127
|
}
|
|
126
128
|
}
|
|
127
129
|
if (!nextChapters.length) {
|
|
128
130
|
nextLanguage = 'und';
|
|
129
|
-
|
|
131
|
+
// If player is a proxy, and the cast receiver doesn't support this
|
|
132
|
+
// method, you get back undefined.
|
|
133
|
+
nextChapters = this.player.getChapters(nextLanguage) || [];
|
|
130
134
|
}
|
|
131
135
|
|
|
132
136
|
const languageChanged = nextLanguage !== this.chaptersLanguage_;
|