shaka-player 3.2.7 → 3.2.10
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/.github/workflows/release-please.yaml +3 -2
- package/AUTHORS +1 -1
- package/CHANGELOG.md +35 -0
- package/CONTRIBUTORS +4 -1
- package/README.md +20 -6
- package/demo/common/assets.js +1 -1
- package/demo/demo.less +0 -1
- package/demo/index.html +0 -2
- package/demo/main.js +3 -3
- package/dist/controls.css +2 -2
- package/dist/controls.css.map +1 -1
- package/dist/demo.compiled.debug.js +3 -3
- package/dist/demo.compiled.debug.map +2 -2
- package/dist/demo.compiled.js +3 -3
- package/dist/demo.compiled.map +2 -2
- package/dist/demo.css +1 -1
- package/dist/demo.css.map +1 -1
- package/dist/deps.js +3 -3
- package/dist/locales.js +27 -27
- package/dist/receiver.compiled.debug.js +1 -1
- package/dist/receiver.compiled.debug.map +1 -1
- package/dist/receiver.compiled.js +1 -1
- package/dist/receiver.compiled.map +1 -1
- package/dist/shaka-player.compiled.d.ts +235 -224
- package/dist/shaka-player.compiled.debug.d.ts +235 -224
- package/dist/shaka-player.compiled.debug.externs.js +48 -37
- package/dist/shaka-player.compiled.debug.js +176 -170
- package/dist/shaka-player.compiled.debug.map +4 -4
- package/dist/shaka-player.compiled.externs.js +48 -37
- package/dist/shaka-player.compiled.js +763 -760
- package/dist/shaka-player.compiled.map +4 -4
- package/dist/shaka-player.ui.d.ts +277 -266
- package/dist/shaka-player.ui.debug.d.ts +277 -266
- package/dist/shaka-player.ui.debug.externs.js +48 -37
- package/dist/shaka-player.ui.debug.js +156 -151
- package/dist/shaka-player.ui.debug.map +4 -4
- package/dist/shaka-player.ui.externs.js +48 -37
- package/dist/shaka-player.ui.js +868 -865
- package/dist/shaka-player.ui.map +4 -4
- package/docs/tutorials/welcome.md +6 -3
- package/lib/abr/simple_abr_manager.js +2 -1
- package/lib/dash/dash_parser.js +5 -0
- package/lib/hls/hls_parser.js +28 -9
- package/lib/media/drm_engine.js +3 -0
- package/lib/media/presentation_timeline.js +24 -1
- package/lib/player.js +1 -1
- package/lib/polyfill/media_capabilities.js +1 -0
- package/lib/polyfill/videoplaybackquality.js +3 -1
- package/lib/util/mime_utils.js +14 -5
- package/lib/util/platform.js +41 -1
- package/lib/util/stream_utils.js +1 -0
- package/lib/util/string_utils.js +56 -14
- package/maintained-branches.md +15 -0
- package/package.json +6 -5
- package/test/hls/hls_live_unit.js +60 -7
- package/ui/less/containers.less +1 -1
- package/ui/less/general.less +1 -1
- package/ui/less/range_elements.less +1 -0
- package/.github/pull_request_template.md +0 -38
- package/app-engine/README.md +0 -9
- package/app-engine/demo-version-index/README.md +0 -14
- package/app-engine/demo-version-index/app.yaml +0 -2
- package/app-engine/demo-version-index/main.py +0 -162
- package/app-engine/demo-version-index/requirements.txt +0 -6
- package/app-engine/demo-version-index/templates/index.html +0 -114
- package/app-engine/shaka-player-demo/README.md +0 -18
- package/app-engine/shaka-player-demo/app.yaml +0 -61
- package/app-engine/shaka-player-demo/main.py +0 -95
- package/app-engine/shaka-player-demo/posters/10yo.png +0 -0
- package/app-engine/shaka-player-demo/posters/10yo.xcf +0 -0
- package/app-engine/shaka-player-demo/posters/1yo.jpg +0 -0
- package/app-engine/shaka-player-demo/posters/2yo.png +0 -0
- package/app-engine/shaka-player-demo/posters/2yo.xcf +0 -0
- package/app-engine/shaka-player-demo/posters/3yo.png +0 -0
- package/app-engine/shaka-player-demo/posters/3yo.xcf +0 -0
- package/app-engine/shaka-player-demo/posters/4yo.png +0 -0
- package/app-engine/shaka-player-demo/posters/4yo.xcf +0 -0
- package/app-engine/shaka-player-demo/posters/5yo.png +0 -0
- package/app-engine/shaka-player-demo/posters/5yo.xcf +0 -0
- package/app-engine/shaka-player-demo/posters/6yo.png +0 -0
- package/app-engine/shaka-player-demo/posters/6yo.xcf +0 -0
- package/app-engine/shaka-player-demo/posters/7yo.png +0 -0
- package/app-engine/shaka-player-demo/posters/7yo.xcf +0 -0
- package/app-engine/shaka-player-demo/posters/8yo.png +0 -0
- package/app-engine/shaka-player-demo/posters/8yo.xcf +0 -0
- package/app-engine/shaka-player-demo/posters/9yo.png +0 -0
- package/app-engine/shaka-player-demo/posters/9yo.xcf +0 -0
- package/app-engine/shaka-player-demo/posters/audioOnly.gif +0 -0
- package/app-engine/shaka-player-demo/posters/audioRickRoll.gif +0 -0
- package/app-engine/shaka-player-demo/posters/colorbars.gif +0 -0
- package/app-engine/shaka-player-demo/posters/fireworks.jpg +0 -0
- package/app-engine/shaka-player-demo/posters/party-hat.png +0 -0
- package/app-engine/shaka-player-demo/posters/sources.txt +0 -46
- package/app-engine/shaka-player-demo/posters/standard.png +0 -0
- package/app-engine/shaka-player-demo/posters/trek.jpg +0 -0
- package/app-engine/shaka-player-demo/posters/valentines.png +0 -0
- package/app-engine/shaka-player-demo/posters/zombie.jpg +0 -0
- package/app-engine/shaka-player-demo/posters.py +0 -110
- package/app-engine/shaka-player-demo/requirements.txt +0 -5
- package/app-engine/shaka-player-demo/time.txt +0 -1
- package/build/README.md +0 -127
- package/build/__init__.py +0 -0
- package/build/all.py +0 -150
- package/build/apps.py +0 -186
- package/build/build.py +0 -392
- package/build/check.py +0 -354
- package/build/checkversion.py +0 -84
- package/build/compiler.py +0 -513
- package/build/conformance.textproto +0 -321
- package/build/docker/Dockerfile +0 -20
- package/build/docker/docker-compose.yml +0 -10
- package/build/docs.py +0 -54
- package/build/eslint-plugin-shaka-rules/arg-comment-spacing.js +0 -72
- package/build/eslint-plugin-shaka-rules/index.js +0 -24
- package/build/eslint-plugin-shaka-rules/package.json +0 -7
- package/build/eslint-plugin-shaka-rules/private.js +0 -109
- package/build/gendeps.py +0 -71
- package/build/generateExterns.js +0 -867
- package/build/generateLocalizations.py +0 -262
- package/build/generateTsDefs.py +0 -137
- package/build/install-linux-prereqs.sh +0 -136
- package/build/license-header +0 -5
- package/build/misspellings.txt +0 -38
- package/build/pixelsChanged.js +0 -35
- package/build/shaka-lab.yaml +0 -163
- package/build/shakaBuildHelpers.py +0 -356
- package/build/stats.py +0 -816
- package/build/subprocessWindowsPatch.py +0 -103
- package/build/test.py +0 -541
- package/build/types/ads +0 -8
- package/build/types/cast +0 -6
- package/build/types/cea +0 -13
- package/build/types/complete +0 -9
- package/build/types/core +0 -106
- package/build/types/dash +0 -8
- package/build/types/hls +0 -9
- package/build/types/manifests +0 -5
- package/build/types/networking +0 -6
- package/build/types/offline +0 -21
- package/build/types/polyfill +0 -19
- package/build/types/text +0 -11
- package/build/types/ui +0 -37
- package/build/updateScreenshots.py +0 -85
- package/build/wrapper.template.js +0 -52
|
@@ -98,11 +98,14 @@ You can find a full list of available browsers with `--browsers help`, and you
|
|
|
98
98
|
can find a complete list of testing options with `--help`.
|
|
99
99
|
|
|
100
100
|
|
|
101
|
-
####
|
|
101
|
+
#### Announcements
|
|
102
102
|
|
|
103
|
-
|
|
103
|
+
To subscribe to new releases on GitHub, you can follow
|
|
104
|
+
[instructions from this blog](https://www.jessesquires.com/blog/2020/07/30/github-tip-watching-releases/).
|
|
105
|
+
|
|
106
|
+
To receive infrequent announcements and surveys from us, you can join our
|
|
104
107
|
[mailing list](https://groups.google.com/forum/#!forum/shaka-player-users).
|
|
105
|
-
The list is very low volume.
|
|
108
|
+
The list is very low volume, and can only be written to by us.
|
|
106
109
|
|
|
107
110
|
|
|
108
111
|
#### Continue the Tutorials
|
|
@@ -216,8 +216,9 @@ shaka.abr.SimpleAbrManager = class {
|
|
|
216
216
|
* @export
|
|
217
217
|
*/
|
|
218
218
|
getBandwidthEstimate() {
|
|
219
|
+
const defaultBandwidthEstimate = this.getDefaultBandwidth_();
|
|
219
220
|
return this.bandwidthEstimator_.getBandwidthEstimate(
|
|
220
|
-
|
|
221
|
+
defaultBandwidthEstimate);
|
|
221
222
|
}
|
|
222
223
|
|
|
223
224
|
|
package/lib/dash/dash_parser.js
CHANGED
|
@@ -503,6 +503,11 @@ shaka.dash.DashParser = class {
|
|
|
503
503
|
}
|
|
504
504
|
presentationTimeline.setClockOffset(offset);
|
|
505
505
|
}
|
|
506
|
+
|
|
507
|
+
// This is the first point where we have a meaningful presentation start
|
|
508
|
+
// time, and we need to tell PresentationTimeline that so that it can
|
|
509
|
+
// maintain consistency from here on.
|
|
510
|
+
presentationTimeline.lockStartTime();
|
|
506
511
|
} else {
|
|
507
512
|
// Just update the variants and text streams, which may change as periods
|
|
508
513
|
// are added or removed.
|
package/lib/hls/hls_parser.js
CHANGED
|
@@ -547,8 +547,14 @@ shaka.hls.HlsParser = class {
|
|
|
547
547
|
for (const stream of streamsToNotify) {
|
|
548
548
|
this.segmentsToNotifyByStream_.push(stream.segmentIndex.references);
|
|
549
549
|
}
|
|
550
|
+
|
|
550
551
|
this.notifySegments_();
|
|
551
552
|
|
|
553
|
+
// This is the first point where we have a meaningful presentation start
|
|
554
|
+
// time, and we need to tell PresentationTimeline that so that it can
|
|
555
|
+
// maintain consistency from here on.
|
|
556
|
+
this.presentationTimeline_.lockStartTime();
|
|
557
|
+
|
|
552
558
|
// This asserts that the live edge is being calculated from segment times.
|
|
553
559
|
// For VOD and event streams, this check should still pass.
|
|
554
560
|
goog.asserts.assert(
|
|
@@ -1660,8 +1666,6 @@ shaka.hls.HlsParser = class {
|
|
|
1660
1666
|
/* presentationStartTime= */ null, /* delay= */ 0);
|
|
1661
1667
|
this.presentationTimeline_.setStatic(true);
|
|
1662
1668
|
}
|
|
1663
|
-
|
|
1664
|
-
this.notifySegments_();
|
|
1665
1669
|
}
|
|
1666
1670
|
|
|
1667
1671
|
/**
|
|
@@ -1775,9 +1779,20 @@ shaka.hls.HlsParser = class {
|
|
|
1775
1779
|
const pPreviousReference = i == 0 ?
|
|
1776
1780
|
previousReference : partialSegmentRefs[partialSegmentRefs.length - 1];
|
|
1777
1781
|
const pStartTime = (i == 0) ? startTime : pPreviousReference.endTime;
|
|
1778
|
-
|
|
1779
|
-
//
|
|
1780
|
-
//
|
|
1782
|
+
|
|
1783
|
+
// If DURATION is missing from this partial segment, use the target
|
|
1784
|
+
// partial duration from the top of the playlist, which is a required
|
|
1785
|
+
// attribute for content with partial segments.
|
|
1786
|
+
const pDuration = Number(item.getAttributeValue('DURATION')) ||
|
|
1787
|
+
this.partialTargetDuration_;
|
|
1788
|
+
|
|
1789
|
+
// If for some reason we have neither an explicit duration, nor a target
|
|
1790
|
+
// partial duration, we should SKIP this partial segment to avoid
|
|
1791
|
+
// duplicating content in the presentation timeline.
|
|
1792
|
+
if (!pDuration) {
|
|
1793
|
+
continue;
|
|
1794
|
+
}
|
|
1795
|
+
|
|
1781
1796
|
const pEndTime = pStartTime + pDuration;
|
|
1782
1797
|
|
|
1783
1798
|
let pStartByte = 0;
|
|
@@ -2551,12 +2566,16 @@ shaka.hls.HlsParser = class {
|
|
|
2551
2566
|
const ContentType = shaka.util.ManifestParserUtils.ContentType;
|
|
2552
2567
|
const requestType = shaka.net.NetworkingEngine.RequestType.SEGMENT;
|
|
2553
2568
|
|
|
2569
|
+
// If you wait long enough, requesting the first segment can fail
|
|
2570
|
+
// because it has fallen off the left edge of DVR, so to be safer,
|
|
2571
|
+
// let's request the middle segment.
|
|
2554
2572
|
goog.asserts.assert(playlist.segments.length,
|
|
2555
2573
|
'Playlist should have segments!');
|
|
2556
|
-
const
|
|
2557
|
-
|
|
2574
|
+
const middleSegmentIdx = Math.trunc((playlist.segments.length - 1) / 2);
|
|
2575
|
+
const middleSegmentUri = this.variableSubstitution_(
|
|
2576
|
+
playlist.segments[middleSegmentIdx].absoluteUri, variables);
|
|
2558
2577
|
|
|
2559
|
-
const parsedUri = new goog.Uri(
|
|
2578
|
+
const parsedUri = new goog.Uri(middleSegmentUri);
|
|
2560
2579
|
const extension = parsedUri.getPath().split('.').pop();
|
|
2561
2580
|
const map = HlsParser.EXTENSION_MAP_BY_CONTENT_TYPE_[contentType];
|
|
2562
2581
|
|
|
@@ -2587,7 +2606,7 @@ shaka.hls.HlsParser = class {
|
|
|
2587
2606
|
// If unable to guess mime type, request a segment and try getting it
|
|
2588
2607
|
// from the response.
|
|
2589
2608
|
const headRequest = shaka.net.NetworkingEngine.makeRequest(
|
|
2590
|
-
[
|
|
2609
|
+
[middleSegmentUri], this.config_.retryParameters);
|
|
2591
2610
|
headRequest.method = 'HEAD';
|
|
2592
2611
|
|
|
2593
2612
|
const response = await this.makeNetworkRequest_(
|
package/lib/media/drm_engine.js
CHANGED
|
@@ -1372,6 +1372,9 @@ shaka.media.DrmEngine = class {
|
|
|
1372
1372
|
}
|
|
1373
1373
|
return;
|
|
1374
1374
|
}
|
|
1375
|
+
if (this.destroyer_.destroyed()) {
|
|
1376
|
+
return;
|
|
1377
|
+
}
|
|
1375
1378
|
|
|
1376
1379
|
const updateEvent = new shaka.util.FakeEvent('drmsessionupdate');
|
|
1377
1380
|
this.playerInterface_.onEvent(updateEvent);
|
|
@@ -93,6 +93,9 @@ shaka.media.PresentationTimeline = class {
|
|
|
93
93
|
* @private {number}
|
|
94
94
|
*/
|
|
95
95
|
this.availabilityTimeOffset_ = 0;
|
|
96
|
+
|
|
97
|
+
/** @private {boolean} */
|
|
98
|
+
this.startTimeLocked_ = false;
|
|
96
99
|
}
|
|
97
100
|
|
|
98
101
|
|
|
@@ -229,7 +232,8 @@ shaka.media.PresentationTimeline = class {
|
|
|
229
232
|
this.maxSegmentEndTime_ =
|
|
230
233
|
Math.max(this.maxSegmentEndTime_, lastReferenceEndTime);
|
|
231
234
|
|
|
232
|
-
if (this.presentationStartTime_ != null && this.autoCorrectDrift_
|
|
235
|
+
if (this.presentationStartTime_ != null && this.autoCorrectDrift_ &&
|
|
236
|
+
!this.startTimeLocked_) {
|
|
233
237
|
// Since we have explicit segment end times, calculate a presentation
|
|
234
238
|
// start based on them. This start time accounts for drift.
|
|
235
239
|
// Date.now() is in milliseconds, from which we compute "now" in seconds.
|
|
@@ -243,6 +247,25 @@ shaka.media.PresentationTimeline = class {
|
|
|
243
247
|
}
|
|
244
248
|
|
|
245
249
|
|
|
250
|
+
/**
|
|
251
|
+
* Lock the presentation timeline's start time. After this is called, no
|
|
252
|
+
* further adjustments to presentationStartTime_ will be permitted.
|
|
253
|
+
*
|
|
254
|
+
* This should be called after all Periods have been parsed, and all calls to
|
|
255
|
+
* notifySegments() from the initial manifest parse have been made.
|
|
256
|
+
*
|
|
257
|
+
* Without this, we can get assertion failures in SegmentIndex for certain
|
|
258
|
+
* DAI content. If DAI adds ad segments to the manifest faster than
|
|
259
|
+
* real-time, adjustments to presentationStartTime_ can cause availability
|
|
260
|
+
* windows to jump around on updates.
|
|
261
|
+
*
|
|
262
|
+
* @export
|
|
263
|
+
*/
|
|
264
|
+
lockStartTime() {
|
|
265
|
+
this.startTimeLocked_ = true;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
|
|
246
269
|
/**
|
|
247
270
|
* Gives PresentationTimeline a Stream's minimum segment start time.
|
|
248
271
|
*
|
package/lib/player.js
CHANGED
|
@@ -6430,7 +6430,7 @@ shaka.Player.TYPICAL_BUFFERING_THRESHOLD_ = 0.5;
|
|
|
6430
6430
|
* @define {string} A version number taken from git at compile time.
|
|
6431
6431
|
* @export
|
|
6432
6432
|
*/
|
|
6433
|
-
shaka.Player.version = 'v3.2.
|
|
6433
|
+
shaka.Player.version = 'v3.2.10-uncompiled';
|
|
6434
6434
|
|
|
6435
6435
|
// Initialize the deprecation system using the version string we just set
|
|
6436
6436
|
// on the player.
|
|
@@ -39,6 +39,7 @@ shaka.polyfill.MediaCapabilities = class {
|
|
|
39
39
|
// Browsers.
|
|
40
40
|
if (!shaka.util.Platform.isChromecast() &&
|
|
41
41
|
!shaka.util.Platform.isApple() &&
|
|
42
|
+
!shaka.util.Platform.isPS4() &&
|
|
42
43
|
!shaka.util.Platform.isPS5() &&
|
|
43
44
|
navigator.mediaCapabilities) {
|
|
44
45
|
shaka.log.info(
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
goog.provide('shaka.polyfill.VideoPlaybackQuality');
|
|
8
8
|
|
|
9
9
|
goog.require('shaka.polyfill');
|
|
10
|
+
goog.require('shaka.util.Platform');
|
|
10
11
|
|
|
11
12
|
|
|
12
13
|
/**
|
|
@@ -33,7 +34,8 @@ shaka.polyfill.VideoPlaybackQuality = class {
|
|
|
33
34
|
return;
|
|
34
35
|
}
|
|
35
36
|
|
|
36
|
-
if ('webkitDroppedFrameCount' in proto
|
|
37
|
+
if ('webkitDroppedFrameCount' in proto ||
|
|
38
|
+
shaka.util.Platform.isWebOS3()) {
|
|
37
39
|
proto.getVideoPlaybackQuality =
|
|
38
40
|
shaka.polyfill.VideoPlaybackQuality.webkit_;
|
|
39
41
|
}
|
package/lib/util/mime_utils.js
CHANGED
|
@@ -8,6 +8,7 @@ goog.provide('shaka.util.MimeUtils');
|
|
|
8
8
|
|
|
9
9
|
goog.require('shaka.dependencies');
|
|
10
10
|
goog.require('shaka.media.Transmuxer');
|
|
11
|
+
goog.require('shaka.util.ManifestParserUtils');
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
14
|
* @summary A set of utility functions for dealing with MIME types.
|
|
@@ -32,6 +33,8 @@ shaka.util.MimeUtils = class {
|
|
|
32
33
|
/**
|
|
33
34
|
* Takes a MIME type and a codecs string and produces the full MIME
|
|
34
35
|
* type. If it's a transport stream, convert its codecs to MP4 codecs.
|
|
36
|
+
* Otherwise for multiplexed content, convert the video MIME types to
|
|
37
|
+
* their audio equivalents if the content type is audio.
|
|
35
38
|
*
|
|
36
39
|
* @param {string} mimeType
|
|
37
40
|
* @param {string} codecs
|
|
@@ -40,13 +43,19 @@ shaka.util.MimeUtils = class {
|
|
|
40
43
|
*/
|
|
41
44
|
static getFullOrConvertedType(mimeType, codecs, contentType) {
|
|
42
45
|
const fullMimeType = shaka.util.MimeUtils.getFullType(mimeType, codecs);
|
|
46
|
+
const ContentType = shaka.util.ManifestParserUtils.ContentType;
|
|
43
47
|
|
|
44
|
-
if (
|
|
45
|
-
|
|
46
|
-
|
|
48
|
+
if (shaka.media.Transmuxer.isTsContainer(fullMimeType)) {
|
|
49
|
+
if (shaka.dependencies.muxjs()) {
|
|
50
|
+
return shaka.media.Transmuxer.convertTsCodecs(
|
|
51
|
+
contentType, fullMimeType);
|
|
52
|
+
}
|
|
53
|
+
} else if (contentType == ContentType.AUDIO) {
|
|
54
|
+
// video/mp2t is the correct mime type for TS audio, so only replace the
|
|
55
|
+
// word "video" with "audio" for non-TS audio content.
|
|
56
|
+
return fullMimeType.replace('video', 'audio');
|
|
47
57
|
}
|
|
48
|
-
|
|
49
|
-
return shaka.media.Transmuxer.convertTsCodecs(contentType, fullMimeType);
|
|
58
|
+
return fullMimeType;
|
|
50
59
|
}
|
|
51
60
|
|
|
52
61
|
|
package/lib/util/platform.js
CHANGED
|
@@ -142,6 +142,18 @@ shaka.util.Platform = class {
|
|
|
142
142
|
return shaka.util.Platform.userAgentContains_('Web0S');
|
|
143
143
|
}
|
|
144
144
|
|
|
145
|
+
/**
|
|
146
|
+
* Check if the current platform is a WebOS 3.
|
|
147
|
+
*
|
|
148
|
+
* @return {boolean}
|
|
149
|
+
*/
|
|
150
|
+
static isWebOS3() {
|
|
151
|
+
// See: http://webostv.developer.lge.com/discover/specifications/web-engine/
|
|
152
|
+
return shaka.util.Platform.userAgentContains_('Web0S') &&
|
|
153
|
+
shaka.util.Platform.userAgentContains_(
|
|
154
|
+
'Chrome/38.0.2125.122 Safari/537.36');
|
|
155
|
+
}
|
|
156
|
+
|
|
145
157
|
/**
|
|
146
158
|
* Check if the current platform is a Google Chromecast.
|
|
147
159
|
*
|
|
@@ -175,7 +187,9 @@ shaka.util.Platform = class {
|
|
|
175
187
|
*/
|
|
176
188
|
static isApple() {
|
|
177
189
|
return !!navigator.vendor && navigator.vendor.includes('Apple') &&
|
|
178
|
-
!shaka.util.Platform.isTizen()
|
|
190
|
+
!shaka.util.Platform.isTizen() &&
|
|
191
|
+
!shaka.util.Platform.isEOS() &&
|
|
192
|
+
!shaka.util.Platform.isPS4();
|
|
179
193
|
}
|
|
180
194
|
|
|
181
195
|
/**
|
|
@@ -191,6 +205,13 @@ shaka.util.Platform = class {
|
|
|
191
205
|
return shaka.util.Platform.userAgentContains_('PlayStation 5');
|
|
192
206
|
}
|
|
193
207
|
|
|
208
|
+
/**
|
|
209
|
+
* Check if the current platform is Playstation 4.
|
|
210
|
+
*/
|
|
211
|
+
static isPS4() {
|
|
212
|
+
return shaka.util.Platform.userAgentContains_('PlayStation 4');
|
|
213
|
+
}
|
|
214
|
+
|
|
194
215
|
/**
|
|
195
216
|
* Returns a major version number for Safari, or Safari-based iOS browsers.
|
|
196
217
|
*
|
|
@@ -228,6 +249,25 @@ shaka.util.Platform = class {
|
|
|
228
249
|
return null;
|
|
229
250
|
}
|
|
230
251
|
|
|
252
|
+
/**
|
|
253
|
+
* Check if the current platform is Apple Safari
|
|
254
|
+
* or Safari-based iOS browsers.
|
|
255
|
+
*
|
|
256
|
+
* @return {boolean}
|
|
257
|
+
*/
|
|
258
|
+
static isSafari() {
|
|
259
|
+
return !!shaka.util.Platform.safariVersion();
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Check if the current platform is an EOS set-top box.
|
|
264
|
+
*
|
|
265
|
+
* @return {boolean}
|
|
266
|
+
*/
|
|
267
|
+
static isEOS() {
|
|
268
|
+
return shaka.util.Platform.userAgentContains_('PC=EOS');
|
|
269
|
+
}
|
|
270
|
+
|
|
231
271
|
/**
|
|
232
272
|
* Guesses if the platform is a mobile one (iOS or Android).
|
|
233
273
|
*
|
package/lib/util/stream_utils.js
CHANGED
|
@@ -981,6 +981,7 @@ shaka.util.StreamUtils = class {
|
|
|
981
981
|
track.channelsCount = audio.channelsCount;
|
|
982
982
|
track.audioSamplingRate = audio.audioSamplingRate;
|
|
983
983
|
track.audioBandwidth = audio.bandwidth || null;
|
|
984
|
+
track.spatialAudio = audio.spatialAudio;
|
|
984
985
|
track.label = audio.label;
|
|
985
986
|
track.audioRoles = audio.roles;
|
|
986
987
|
}
|
package/lib/util/string_utils.js
CHANGED
|
@@ -11,6 +11,7 @@ goog.require('shaka.log');
|
|
|
11
11
|
goog.require('shaka.util.BufferUtils');
|
|
12
12
|
goog.require('shaka.util.Error');
|
|
13
13
|
goog.require('shaka.util.Lazy');
|
|
14
|
+
goog.require('shaka.util.Platform');
|
|
14
15
|
|
|
15
16
|
|
|
16
17
|
/**
|
|
@@ -36,19 +37,38 @@ shaka.util.StringUtils = class {
|
|
|
36
37
|
if (uint8[0] == 0xef && uint8[1] == 0xbb && uint8[2] == 0xbf) {
|
|
37
38
|
uint8 = uint8.subarray(3);
|
|
38
39
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
40
|
+
if (window.TextDecoder && !shaka.util.Platform.isPS4()) {
|
|
41
|
+
// Use the TextDecoder interface to decode the text. This has the
|
|
42
|
+
// advantage compared to the previously-standard decodeUriComponent that
|
|
43
|
+
// it will continue parsing even if it finds an invalid UTF8 character,
|
|
44
|
+
// rather than stop and throw an error.
|
|
45
|
+
const utf8decoder = new TextDecoder();
|
|
46
|
+
const decoded = utf8decoder.decode(uint8);
|
|
47
|
+
if (decoded.includes('\uFFFD')) {
|
|
48
|
+
shaka.log.alwaysError('Decoded string contains an "unknown character' +
|
|
49
|
+
'" codepoint. That probably means the UTF8 ' +
|
|
50
|
+
'encoding was incorrect!');
|
|
51
|
+
}
|
|
52
|
+
return decoded;
|
|
53
|
+
} else {
|
|
54
|
+
// http://stackoverflow.com/a/13691499
|
|
55
|
+
const utf8 = shaka.util.StringUtils.fromCharCode(uint8);
|
|
56
|
+
// This converts each character in the string to an escape sequence. If
|
|
57
|
+
// the character is in the ASCII range, it is not converted; otherwise it
|
|
58
|
+
// is converted to a URI escape sequence.
|
|
59
|
+
// Example: '\x67\x35\xe3\x82\xac' -> 'g#%E3%82%AC'
|
|
60
|
+
const escaped = escape(utf8);
|
|
61
|
+
// Decode the escaped sequence. This will interpret UTF-8 sequences into
|
|
62
|
+
// the correct character.
|
|
63
|
+
// Example: 'g#%E3%82%AC' -> 'g#€'
|
|
64
|
+
try {
|
|
65
|
+
return decodeURIComponent(escaped);
|
|
66
|
+
} catch (e) {
|
|
67
|
+
throw new shaka.util.Error(
|
|
68
|
+
shaka.util.Error.Severity.CRITICAL, shaka.util.Error.Category.TEXT,
|
|
69
|
+
shaka.util.Error.Code.BAD_ENCODING);
|
|
70
|
+
}
|
|
50
71
|
}
|
|
51
|
-
return decoded;
|
|
52
72
|
}
|
|
53
73
|
|
|
54
74
|
|
|
@@ -141,8 +161,30 @@ shaka.util.StringUtils = class {
|
|
|
141
161
|
* @export
|
|
142
162
|
*/
|
|
143
163
|
static toUTF8(str) {
|
|
144
|
-
|
|
145
|
-
|
|
164
|
+
if (window.TextEncoder && !shaka.util.Platform.isPS4()) {
|
|
165
|
+
const utf8Encoder = new TextEncoder();
|
|
166
|
+
return shaka.util.BufferUtils.toArrayBuffer(utf8Encoder.encode(str));
|
|
167
|
+
} else {
|
|
168
|
+
// http://stackoverflow.com/a/13691499
|
|
169
|
+
// Converts the given string to a URI encoded string. If a character
|
|
170
|
+
// falls in the ASCII range, it is not converted; otherwise it will be
|
|
171
|
+
// converted to a series of URI escape sequences according to UTF-8.
|
|
172
|
+
// Example: 'g#€' -> 'g#%E3%82%AC'
|
|
173
|
+
const encoded = encodeURIComponent(str);
|
|
174
|
+
// Convert each escape sequence individually into a character. Each
|
|
175
|
+
// escape sequence is interpreted as a code-point, so if an escape
|
|
176
|
+
// sequence happens to be part of a multi-byte sequence, each byte will
|
|
177
|
+
// be converted to a single character.
|
|
178
|
+
// Example: 'g#%E3%82%AC' -> '\x67\x35\xe3\x82\xac'
|
|
179
|
+
const utf8 = unescape(encoded);
|
|
180
|
+
|
|
181
|
+
const result = new Uint8Array(utf8.length);
|
|
182
|
+
for (let i = 0; i < utf8.length; i++) {
|
|
183
|
+
const item = utf8[i];
|
|
184
|
+
result[i] = item.charCodeAt(0);
|
|
185
|
+
}
|
|
186
|
+
return shaka.util.BufferUtils.toArrayBuffer(result);
|
|
187
|
+
}
|
|
146
188
|
}
|
|
147
189
|
|
|
148
190
|
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Maintained Shaka Player Branches
|
|
2
|
+
|
|
3
|
+
We are currently maintaining the following branches of Shaka Player:
|
|
4
|
+
|
|
5
|
+
- v4.1 (latest)
|
|
6
|
+
- v4.0 (previous)
|
|
7
|
+
- v3.3 (LTS until April 30, 2023)
|
|
8
|
+
- v3.2 (in use by the Cast Application Framework)
|
|
9
|
+
|
|
10
|
+
Other branches are no longer receiving bug fixes, and we recommend you upgrade
|
|
11
|
+
to a maintained branch. For details on upgrading, please see our
|
|
12
|
+
[upgrade guide](https://shaka-player-demo.appspot.com/docs/api/tutorial-upgrade.html).
|
|
13
|
+
|
|
14
|
+
For more information on how these branches are chosen, please refer to our
|
|
15
|
+
[Branch Maintenance Policy](https://shaka-project.github.io/maintenance/shaka-player.html#branch-maintenance-policy).
|
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": "3.2.
|
|
4
|
+
"version": "3.2.10",
|
|
5
5
|
"homepage": "https://github.com/shaka-project/shaka-player",
|
|
6
6
|
"author": "Google",
|
|
7
7
|
"maintainers": [
|
|
@@ -27,7 +27,6 @@
|
|
|
27
27
|
"eslint-config-google": "^0.14.0",
|
|
28
28
|
"eslint-plugin-shaka-rules": "file:./build/eslint-plugin-shaka-rules",
|
|
29
29
|
"esprima": "^4.0.1",
|
|
30
|
-
"fastestsmallesttextencoderdecoder": "^1.0.22",
|
|
31
30
|
"fontfaceonload": "^1.0.2",
|
|
32
31
|
"google-closure-compiler-java": "^20220301.0.0",
|
|
33
32
|
"google-closure-deps": "https://gitpkg.now.sh/google/closure-library/closure-deps?d7736da6",
|
|
@@ -50,7 +49,7 @@
|
|
|
50
49
|
"less": "https://gitpkg.now.sh/joeyparrish/less.js/packages/less?28c63a43",
|
|
51
50
|
"less-plugin-clean-css": "github:austingardner/less-plugin-clean-css#4e9e77bf",
|
|
52
51
|
"material-design-lite": "^1.3.0",
|
|
53
|
-
"mux.js": "^
|
|
52
|
+
"mux.js": "^6.2.0",
|
|
54
53
|
"open-sans-fonts": "^1.6.2",
|
|
55
54
|
"postcss-less": "^6.0.0",
|
|
56
55
|
"pwacompat": "^2.0.17",
|
|
@@ -71,7 +70,6 @@
|
|
|
71
70
|
"dialog-polyfill/dist/dialog-polyfill.js",
|
|
72
71
|
"eme-encryption-scheme-polyfill/index.js",
|
|
73
72
|
"es6-promise-polyfill/promise.min.js",
|
|
74
|
-
"fastestsmallesttextencoderdecoder/EncoderDecoderTogether.min.js",
|
|
75
73
|
"google-closure-library/closure/goog/base.js",
|
|
76
74
|
"less/dist/less.js",
|
|
77
75
|
"material-design-lite/dist/material.indigo-blue.min.css",
|
|
@@ -96,6 +94,9 @@
|
|
|
96
94
|
"prepublishOnly": "python build/checkversion.py && python build/all.py --force"
|
|
97
95
|
},
|
|
98
96
|
"dependencies": {
|
|
99
|
-
"eme-encryption-scheme-polyfill": "^2.0.
|
|
97
|
+
"eme-encryption-scheme-polyfill": "^2.0.5"
|
|
98
|
+
},
|
|
99
|
+
"engines": {
|
|
100
|
+
"node": ">=14"
|
|
100
101
|
}
|
|
101
102
|
}
|
|
@@ -630,11 +630,13 @@ describe('HlsParser live', () => {
|
|
|
630
630
|
expect(ref.startTime).not.toBeLessThan(rolloverOffset);
|
|
631
631
|
});
|
|
632
632
|
|
|
633
|
+
// Test for https://github.com/shaka-project/shaka-player/issues/4223
|
|
633
634
|
it('parses streams with partial and preload hinted segments', async () => {
|
|
634
635
|
playerInterface.isLowLatencyMode = () => true;
|
|
635
636
|
const mediaWithPartialSegments = [
|
|
636
637
|
'#EXTM3U\n',
|
|
637
638
|
'#EXT-X-TARGETDURATION:5\n',
|
|
639
|
+
'#EXT-X-PART-INF:PART-TARGET=1.5\n',
|
|
638
640
|
'#EXT-X-MAP:URI="init.mp4",BYTERANGE="616@0"\n',
|
|
639
641
|
'#EXT-X-MEDIA-SEQUENCE:0\n',
|
|
640
642
|
// ref includes partialRef, partialRef2
|
|
@@ -668,6 +670,11 @@ describe('HlsParser live', () => {
|
|
|
668
670
|
segmentDataStartTime + 4, /* baseUri= */ '', /* startByte= */ 200,
|
|
669
671
|
/* endByte= */ 429);
|
|
670
672
|
|
|
673
|
+
const ref = ManifestParser.makeReference(
|
|
674
|
+
'test:/main.mp4', segmentDataStartTime, segmentDataStartTime + 4,
|
|
675
|
+
/* baseUri= */ '', /* startByte= */ 0, /* endByte= */ 429,
|
|
676
|
+
/* timestampOffset= */ 0, [partialRef, partialRef2]);
|
|
677
|
+
|
|
671
678
|
const partialRef3 = ManifestParser.makeReference(
|
|
672
679
|
'test:/partial.mp4', segmentDataStartTime + 4,
|
|
673
680
|
segmentDataStartTime + 6,
|
|
@@ -677,17 +684,12 @@ describe('HlsParser live', () => {
|
|
|
677
684
|
// so its startTime and endTime are the same.
|
|
678
685
|
const preloadRef = ManifestParser.makeReference(
|
|
679
686
|
'test:/partial.mp4', segmentDataStartTime + 6,
|
|
680
|
-
segmentDataStartTime +
|
|
687
|
+
segmentDataStartTime + 7.5,
|
|
681
688
|
/* baseUri= */ '', /* startByte= */ 210, /* endByte= */ null);
|
|
682
689
|
|
|
683
|
-
const ref = ManifestParser.makeReference(
|
|
684
|
-
'test:/main.mp4', segmentDataStartTime, segmentDataStartTime + 4,
|
|
685
|
-
/* baseUri= */ '', /* startByte= */ 0, /* endByte= */ 429,
|
|
686
|
-
/* timestampOffset= */ 0, [partialRef, partialRef2]);
|
|
687
|
-
|
|
688
690
|
// ref2 is not fully published yet, so it doesn't have a segment uri.
|
|
689
691
|
const ref2 = ManifestParser.makeReference(
|
|
690
|
-
'', segmentDataStartTime + 4, segmentDataStartTime +
|
|
692
|
+
'', segmentDataStartTime + 4, segmentDataStartTime + 7.5,
|
|
691
693
|
/* baseUri= */ '', /* startByte= */ 0, /* endByte= */ null,
|
|
692
694
|
/* timestampOffset= */ 0, [partialRef3, preloadRef]);
|
|
693
695
|
|
|
@@ -697,6 +699,56 @@ describe('HlsParser live', () => {
|
|
|
697
699
|
ManifestParser.verifySegmentIndex(video, [ref, ref2]);
|
|
698
700
|
});
|
|
699
701
|
|
|
702
|
+
// Test for https://github.com/shaka-project/shaka-player/issues/4223
|
|
703
|
+
it('ignores preload hinted segments without target duration', async () => {
|
|
704
|
+
playerInterface.isLowLatencyMode = () => true;
|
|
705
|
+
|
|
706
|
+
// Missing PART-TARGET, so preload hints are skipped.
|
|
707
|
+
const mediaWithPartialSegments = [
|
|
708
|
+
'#EXTM3U\n',
|
|
709
|
+
'#EXT-X-TARGETDURATION:5\n',
|
|
710
|
+
'#EXT-X-MAP:URI="init.mp4",BYTERANGE="616@0"\n',
|
|
711
|
+
'#EXT-X-MEDIA-SEQUENCE:0\n',
|
|
712
|
+
'#EXTINF:4,\n',
|
|
713
|
+
// ref1
|
|
714
|
+
'main.mp4\n',
|
|
715
|
+
// ref2 includes partialRef, but not preloadRef
|
|
716
|
+
// partialRef
|
|
717
|
+
'#EXT-X-PART:DURATION=2,URI="partial.mp4",BYTERANGE=210@0\n',
|
|
718
|
+
// preloadRef
|
|
719
|
+
'#EXT-X-PRELOAD-HINT:TYPE=PART,URI="partial.mp4",BYTERANGE-START=210\n',
|
|
720
|
+
].join('');
|
|
721
|
+
|
|
722
|
+
fakeNetEngine
|
|
723
|
+
.setResponseText('test:/master', master)
|
|
724
|
+
.setResponseText('test:/video', mediaWithPartialSegments)
|
|
725
|
+
.setResponseValue('test:/init.mp4', initSegmentData)
|
|
726
|
+
.setResponseValue('test:/main.mp4', segmentData)
|
|
727
|
+
.setResponseValue('test:/partial.mp4', segmentData)
|
|
728
|
+
.setResponseValue('test:/partial2.mp4', segmentData);
|
|
729
|
+
|
|
730
|
+
const ref1 = ManifestParser.makeReference(
|
|
731
|
+
'test:/main.mp4', segmentDataStartTime, segmentDataStartTime + 4,
|
|
732
|
+
/* baseUri= */ '', /* startByte= */ 0, /* endByte= */ null,
|
|
733
|
+
/* timestampOffset= */ 0, []);
|
|
734
|
+
|
|
735
|
+
const partialRef = ManifestParser.makeReference(
|
|
736
|
+
'test:/partial.mp4', segmentDataStartTime + 4,
|
|
737
|
+
segmentDataStartTime + 6,
|
|
738
|
+
/* baseUri= */ '', /* startByte= */ 0, /* endByte= */ 209);
|
|
739
|
+
|
|
740
|
+
// ref2 is not fully published yet, so it doesn't have a segment uri.
|
|
741
|
+
const ref2 = ManifestParser.makeReference(
|
|
742
|
+
'', segmentDataStartTime + 4, segmentDataStartTime + 6,
|
|
743
|
+
/* baseUri= */ '', /* startByte= */ 0, /* endByte= */ 209,
|
|
744
|
+
/* timestampOffset= */ 0, [partialRef]);
|
|
745
|
+
|
|
746
|
+
const manifest = await parser.start('test:/master', playerInterface);
|
|
747
|
+
const video = manifest.variants[0].video;
|
|
748
|
+
await video.createSegmentIndex();
|
|
749
|
+
ManifestParser.verifySegmentIndex(video, [ref1, ref2]);
|
|
750
|
+
});
|
|
751
|
+
|
|
700
752
|
// Test for https://github.com/shaka-project/shaka-player/issues/4185
|
|
701
753
|
it('does not fail on preload hints with LL mode off', async () => {
|
|
702
754
|
// LL mode must be off for this test!
|
|
@@ -706,6 +758,7 @@ describe('HlsParser live', () => {
|
|
|
706
758
|
'#EXTM3U\n',
|
|
707
759
|
'#EXT-X-TARGETDURATION:5\n',
|
|
708
760
|
'#EXT-X-MAP:URI="init.mp4",BYTERANGE="616@0"\n',
|
|
761
|
+
'#EXT-X-PART-INF:PART-TARGET=1.5\n',
|
|
709
762
|
'#EXTINF:4,\n',
|
|
710
763
|
'main.mp4\n',
|
|
711
764
|
'#EXT-X-PART:DURATION=2,URI="partial.mp4",BYTERANGE=210@0\n',
|
package/ui/less/containers.less
CHANGED
|
@@ -161,7 +161,7 @@
|
|
|
161
161
|
/* Consistent margins (external) and padding (internal) between controls. */
|
|
162
162
|
.bottom-panels-elements-margin();
|
|
163
163
|
|
|
164
|
-
padding: 0;
|
|
164
|
+
padding: 0 5px;
|
|
165
165
|
|
|
166
166
|
/* Transparent backgrounds, no borders, and a pointer when you mouse over
|
|
167
167
|
* them. */
|
package/ui/less/general.less
CHANGED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
## Description
|
|
2
|
-
|
|
3
|
-
<!--
|
|
4
|
-
Give the PR a helpful title that summaries what this PR changes. Here, include
|
|
5
|
-
a summary of the change and which issue is fixed. Also include relevant
|
|
6
|
-
motivation and context. List any dependencies that are required for this
|
|
7
|
-
change.
|
|
8
|
-
|
|
9
|
-
If this fixes any issues, include lines like this:
|
|
10
|
-
Fixes #123
|
|
11
|
-
-->
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
## Screenshots (optional)
|
|
15
|
-
|
|
16
|
-
<!--
|
|
17
|
-
If you change the UI, add before and after screenshots demonstrating your
|
|
18
|
-
changes.
|
|
19
|
-
-->
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
## Type of change
|
|
23
|
-
|
|
24
|
-
- [ ] Bug fix (non-breaking change which fixes an issue)
|
|
25
|
-
- [ ] New feature (non-breaking change which adds functionality)
|
|
26
|
-
- [ ] Breaking change (fix or feature that would cause existing functionality to
|
|
27
|
-
not work as expected)
|
|
28
|
-
- [ ] This change requires a documentation update
|
|
29
|
-
|
|
30
|
-
## Checklist:
|
|
31
|
-
|
|
32
|
-
- [ ] I have signed the Google CLA <https://cla.developers.google.com>
|
|
33
|
-
- [ ] My code follows the style guidelines of this project
|
|
34
|
-
- [ ] I have made corresponding changes to the documentation
|
|
35
|
-
- [ ] I have added tests that prove my fix is effective or that my feature works
|
|
36
|
-
- [ ] I have verified my change on multiple browsers on different platforms
|
|
37
|
-
- [ ] I have run `./build/all.py` and the build passes
|
|
38
|
-
- [ ] I have run `./build/test.py` and all tests pass
|