shaka-player 3.3.5 → 3.3.8

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.
Files changed (139) hide show
  1. package/.github/workflows/release-please.yaml +3 -2
  2. package/AUTHORS +1 -0
  3. package/CHANGELOG.md +32 -0
  4. package/CONTRIBUTORS +3 -0
  5. package/README.md +20 -6
  6. package/demo/demo.less +0 -1
  7. package/demo/index.html +0 -2
  8. package/demo/main.js +3 -3
  9. package/dist/controls.css +3 -3
  10. package/dist/controls.css.map +1 -1
  11. package/dist/demo.compiled.debug.js +2 -2
  12. package/dist/demo.compiled.debug.map +2 -2
  13. package/dist/demo.compiled.js +2 -2
  14. package/dist/demo.compiled.map +2 -2
  15. package/dist/demo.css +1 -1
  16. package/dist/demo.css.map +1 -1
  17. package/dist/deps.js +3 -3
  18. package/dist/locales.js +30 -30
  19. package/dist/shaka-player.compiled.d.ts +248 -237
  20. package/dist/shaka-player.compiled.debug.d.ts +248 -237
  21. package/dist/shaka-player.compiled.debug.externs.js +48 -37
  22. package/dist/shaka-player.compiled.debug.js +38 -33
  23. package/dist/shaka-player.compiled.debug.map +4 -4
  24. package/dist/shaka-player.compiled.externs.js +48 -37
  25. package/dist/shaka-player.compiled.js +771 -770
  26. package/dist/shaka-player.compiled.map +4 -4
  27. package/dist/shaka-player.ui.d.ts +292 -281
  28. package/dist/shaka-player.ui.debug.d.ts +292 -281
  29. package/dist/shaka-player.ui.debug.externs.js +48 -37
  30. package/dist/shaka-player.ui.debug.js +40 -35
  31. package/dist/shaka-player.ui.debug.map +4 -4
  32. package/dist/shaka-player.ui.externs.js +48 -37
  33. package/dist/shaka-player.ui.js +883 -882
  34. package/dist/shaka-player.ui.map +4 -4
  35. package/docs/tutorials/welcome.md +6 -3
  36. package/lib/abr/simple_abr_manager.js +2 -1
  37. package/lib/dash/dash_parser.js +5 -0
  38. package/lib/hls/hls_parser.js +20 -5
  39. package/lib/media/drm_engine.js +3 -0
  40. package/lib/media/presentation_timeline.js +24 -1
  41. package/lib/player.js +1 -1
  42. package/lib/polyfill/media_capabilities.js +1 -0
  43. package/lib/polyfill/videoplaybackquality.js +3 -1
  44. package/lib/util/mime_utils.js +14 -5
  45. package/lib/util/platform.js +41 -1
  46. package/lib/util/stream_utils.js +1 -0
  47. package/lib/util/string_utils.js +56 -14
  48. package/maintained-branches.md +15 -0
  49. package/package.json +2 -4
  50. package/test/hls/hls_live_unit.js +60 -7
  51. package/ui/less/containers.less +1 -1
  52. package/ui/less/general.less +1 -1
  53. package/ui/less/range_elements.less +1 -0
  54. package/.github/pull_request_template.md +0 -10
  55. package/app-engine/README.md +0 -9
  56. package/app-engine/demo-version-index/README.md +0 -14
  57. package/app-engine/demo-version-index/app.yaml +0 -2
  58. package/app-engine/demo-version-index/main.py +0 -162
  59. package/app-engine/demo-version-index/requirements.txt +0 -6
  60. package/app-engine/demo-version-index/templates/index.html +0 -114
  61. package/app-engine/shaka-player-demo/README.md +0 -18
  62. package/app-engine/shaka-player-demo/app.yaml +0 -61
  63. package/app-engine/shaka-player-demo/main.py +0 -95
  64. package/app-engine/shaka-player-demo/posters/10yo.png +0 -0
  65. package/app-engine/shaka-player-demo/posters/10yo.xcf +0 -0
  66. package/app-engine/shaka-player-demo/posters/1yo.jpg +0 -0
  67. package/app-engine/shaka-player-demo/posters/2yo.png +0 -0
  68. package/app-engine/shaka-player-demo/posters/2yo.xcf +0 -0
  69. package/app-engine/shaka-player-demo/posters/3yo.png +0 -0
  70. package/app-engine/shaka-player-demo/posters/3yo.xcf +0 -0
  71. package/app-engine/shaka-player-demo/posters/4yo.png +0 -0
  72. package/app-engine/shaka-player-demo/posters/4yo.xcf +0 -0
  73. package/app-engine/shaka-player-demo/posters/5yo.png +0 -0
  74. package/app-engine/shaka-player-demo/posters/5yo.xcf +0 -0
  75. package/app-engine/shaka-player-demo/posters/6yo.png +0 -0
  76. package/app-engine/shaka-player-demo/posters/6yo.xcf +0 -0
  77. package/app-engine/shaka-player-demo/posters/7yo.png +0 -0
  78. package/app-engine/shaka-player-demo/posters/7yo.xcf +0 -0
  79. package/app-engine/shaka-player-demo/posters/8yo.png +0 -0
  80. package/app-engine/shaka-player-demo/posters/8yo.xcf +0 -0
  81. package/app-engine/shaka-player-demo/posters/9yo.png +0 -0
  82. package/app-engine/shaka-player-demo/posters/9yo.xcf +0 -0
  83. package/app-engine/shaka-player-demo/posters/audioOnly.gif +0 -0
  84. package/app-engine/shaka-player-demo/posters/audioRickRoll.gif +0 -0
  85. package/app-engine/shaka-player-demo/posters/colorbars.gif +0 -0
  86. package/app-engine/shaka-player-demo/posters/fireworks.jpg +0 -0
  87. package/app-engine/shaka-player-demo/posters/party-hat.png +0 -0
  88. package/app-engine/shaka-player-demo/posters/sources.txt +0 -46
  89. package/app-engine/shaka-player-demo/posters/standard.png +0 -0
  90. package/app-engine/shaka-player-demo/posters/trek.jpg +0 -0
  91. package/app-engine/shaka-player-demo/posters/valentines.png +0 -0
  92. package/app-engine/shaka-player-demo/posters/zombie.jpg +0 -0
  93. package/app-engine/shaka-player-demo/posters.py +0 -110
  94. package/app-engine/shaka-player-demo/requirements.txt +0 -5
  95. package/app-engine/shaka-player-demo/time.txt +0 -1
  96. package/build/README.md +0 -127
  97. package/build/__init__.py +0 -0
  98. package/build/all.py +0 -150
  99. package/build/apps.py +0 -186
  100. package/build/build.py +0 -392
  101. package/build/check.py +0 -354
  102. package/build/checkversion.py +0 -84
  103. package/build/compiler.py +0 -513
  104. package/build/conformance.textproto +0 -335
  105. package/build/docker/Dockerfile +0 -20
  106. package/build/docker/docker-compose.yml +0 -10
  107. package/build/docs.py +0 -54
  108. package/build/eslint-plugin-shaka-rules/arg-comment-spacing.js +0 -72
  109. package/build/eslint-plugin-shaka-rules/index.js +0 -24
  110. package/build/eslint-plugin-shaka-rules/package.json +0 -7
  111. package/build/eslint-plugin-shaka-rules/private.js +0 -109
  112. package/build/gendeps.py +0 -71
  113. package/build/generateExterns.js +0 -867
  114. package/build/generateLocalizations.py +0 -262
  115. package/build/generateTsDefs.py +0 -137
  116. package/build/install-linux-prereqs.sh +0 -136
  117. package/build/license-header +0 -5
  118. package/build/misspellings.txt +0 -38
  119. package/build/pixelsChanged.js +0 -35
  120. package/build/shaka-lab.yaml +0 -163
  121. package/build/shakaBuildHelpers.py +0 -356
  122. package/build/stats.py +0 -816
  123. package/build/subprocessWindowsPatch.py +0 -103
  124. package/build/test.py +0 -541
  125. package/build/types/ads +0 -8
  126. package/build/types/cast +0 -6
  127. package/build/types/cea +0 -13
  128. package/build/types/complete +0 -9
  129. package/build/types/core +0 -108
  130. package/build/types/dash +0 -8
  131. package/build/types/hls +0 -9
  132. package/build/types/manifests +0 -5
  133. package/build/types/networking +0 -6
  134. package/build/types/offline +0 -22
  135. package/build/types/polyfill +0 -21
  136. package/build/types/text +0 -11
  137. package/build/types/ui +0 -39
  138. package/build/updateScreenshots.py +0 -85
  139. 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
- #### Join the announcement list
101
+ #### Announcements
102
102
 
103
- If you want to receive release or survey announcements, you should join our
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
@@ -219,8 +219,9 @@ shaka.abr.SimpleAbrManager = class {
219
219
  * @export
220
220
  */
221
221
  getBandwidthEstimate() {
222
+ const defaultBandwidthEstimate = this.getDefaultBandwidth_();
222
223
  return this.bandwidthEstimator_.getBandwidthEstimate(
223
- this.config_.defaultBandwidthEstimate);
224
+ defaultBandwidthEstimate);
224
225
  }
225
226
 
226
227
 
@@ -512,6 +512,11 @@ shaka.dash.DashParser = class {
512
512
  }
513
513
  presentationTimeline.setClockOffset(offset);
514
514
  }
515
+
516
+ // This is the first point where we have a meaningful presentation start
517
+ // time, and we need to tell PresentationTimeline that so that it can
518
+ // maintain consistency from here on.
519
+ presentationTimeline.lockStartTime();
515
520
  } else {
516
521
  // Just update the variants and text streams, which may change as periods
517
522
  // are added or removed.
@@ -549,8 +549,14 @@ shaka.hls.HlsParser = class {
549
549
  for (const stream of streamsToNotify) {
550
550
  this.segmentsToNotifyByStream_.push(stream.segmentIndex.references);
551
551
  }
552
+
552
553
  this.notifySegments_();
553
554
 
555
+ // This is the first point where we have a meaningful presentation start
556
+ // time, and we need to tell PresentationTimeline that so that it can
557
+ // maintain consistency from here on.
558
+ this.presentationTimeline_.lockStartTime();
559
+
554
560
  // This asserts that the live edge is being calculated from segment times.
555
561
  // For VOD and event streams, this check should still pass.
556
562
  goog.asserts.assert(
@@ -1663,8 +1669,6 @@ shaka.hls.HlsParser = class {
1663
1669
  /* presentationStartTime= */ null, /* delay= */ 0);
1664
1670
  this.presentationTimeline_.setStatic(true);
1665
1671
  }
1666
-
1667
- this.notifySegments_();
1668
1672
  }
1669
1673
 
1670
1674
  /**
@@ -1778,9 +1782,20 @@ shaka.hls.HlsParser = class {
1778
1782
  const pPreviousReference = i == 0 ?
1779
1783
  previousReference : partialSegmentRefs[partialSegmentRefs.length - 1];
1780
1784
  const pStartTime = (i == 0) ? startTime : pPreviousReference.endTime;
1781
- const pDuration = Number(item.getAttributeValue('DURATION'));
1782
- // A preload hinted partial segment doesn't have duration information,
1783
- // so its startTime and endTime are the same.
1785
+
1786
+ // If DURATION is missing from this partial segment, use the target
1787
+ // partial duration from the top of the playlist, which is a required
1788
+ // attribute for content with partial segments.
1789
+ const pDuration = Number(item.getAttributeValue('DURATION')) ||
1790
+ this.partialTargetDuration_;
1791
+
1792
+ // If for some reason we have neither an explicit duration, nor a target
1793
+ // partial duration, we should SKIP this partial segment to avoid
1794
+ // duplicating content in the presentation timeline.
1795
+ if (!pDuration) {
1796
+ continue;
1797
+ }
1798
+
1784
1799
  const pEndTime = pStartTime + pDuration;
1785
1800
 
1786
1801
  let pStartByte = 0;
@@ -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
@@ -6634,7 +6634,7 @@ shaka.Player.TYPICAL_BUFFERING_THRESHOLD_ = 0.5;
6634
6634
  * @define {string} A version number taken from git at compile time.
6635
6635
  * @export
6636
6636
  */
6637
- shaka.Player.version = 'v3.3.5-uncompiled';
6637
+ shaka.Player.version = 'v3.3.8-uncompiled';
6638
6638
 
6639
6639
  // Initialize the deprecation system using the version string we just set
6640
6640
  // 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
  }
@@ -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 (!shaka.dependencies.muxjs() ||
45
- !shaka.media.Transmuxer.isTsContainer(fullMimeType)) {
46
- return fullMimeType;
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
 
@@ -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
  *
@@ -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
  }
@@ -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
- // Use the TextDecoder interface to decode the text. This has the advantage
41
- // compared to the previously-standard decodeUriComponent that it will
42
- // continue parsing even if it finds an invalid UTF8 character, rather than
43
- // stop and throw an error.
44
- const utf8decoder = new TextDecoder();
45
- const decoded = utf8decoder.decode(uint8);
46
- if (decoded.includes('\uFFFD')) {
47
- shaka.log.alwaysError('Decoded string contains an "unknown character" ' +
48
- 'codepoint. That probably means the UTF8 ' +
49
- 'encoding was incorrect!');
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
- const utf8Encoder = new TextEncoder();
145
- return shaka.util.BufferUtils.toArrayBuffer(utf8Encoder.encode(str));
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.3.5",
4
+ "version": "3.3.8",
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": "^5.14.1",
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",
@@ -632,11 +632,13 @@ describe('HlsParser live', () => {
632
632
  expect(ref.startTime).not.toBeLessThan(rolloverOffset);
633
633
  });
634
634
 
635
+ // Test for https://github.com/shaka-project/shaka-player/issues/4223
635
636
  it('parses streams with partial and preload hinted segments', async () => {
636
637
  playerInterface.isLowLatencyMode = () => true;
637
638
  const mediaWithPartialSegments = [
638
639
  '#EXTM3U\n',
639
640
  '#EXT-X-TARGETDURATION:5\n',
641
+ '#EXT-X-PART-INF:PART-TARGET=1.5\n',
640
642
  '#EXT-X-MAP:URI="init.mp4",BYTERANGE="616@0"\n',
641
643
  '#EXT-X-MEDIA-SEQUENCE:0\n',
642
644
  // ref includes partialRef, partialRef2
@@ -670,6 +672,11 @@ describe('HlsParser live', () => {
670
672
  segmentDataStartTime + 4, /* baseUri= */ '', /* startByte= */ 200,
671
673
  /* endByte= */ 429);
672
674
 
675
+ const ref = ManifestParser.makeReference(
676
+ 'test:/main.mp4', segmentDataStartTime, segmentDataStartTime + 4,
677
+ /* baseUri= */ '', /* startByte= */ 0, /* endByte= */ 429,
678
+ /* timestampOffset= */ 0, [partialRef, partialRef2]);
679
+
673
680
  const partialRef3 = ManifestParser.makeReference(
674
681
  'test:/partial.mp4', segmentDataStartTime + 4,
675
682
  segmentDataStartTime + 6,
@@ -679,17 +686,12 @@ describe('HlsParser live', () => {
679
686
  // so its startTime and endTime are the same.
680
687
  const preloadRef = ManifestParser.makeReference(
681
688
  'test:/partial.mp4', segmentDataStartTime + 6,
682
- segmentDataStartTime + 6,
689
+ segmentDataStartTime + 7.5,
683
690
  /* baseUri= */ '', /* startByte= */ 210, /* endByte= */ null);
684
691
 
685
- const ref = ManifestParser.makeReference(
686
- 'test:/main.mp4', segmentDataStartTime, segmentDataStartTime + 4,
687
- /* baseUri= */ '', /* startByte= */ 0, /* endByte= */ 429,
688
- /* timestampOffset= */ 0, [partialRef, partialRef2]);
689
-
690
692
  // ref2 is not fully published yet, so it doesn't have a segment uri.
691
693
  const ref2 = ManifestParser.makeReference(
692
- '', segmentDataStartTime + 4, segmentDataStartTime + 6,
694
+ '', segmentDataStartTime + 4, segmentDataStartTime + 7.5,
693
695
  /* baseUri= */ '', /* startByte= */ 0, /* endByte= */ null,
694
696
  /* timestampOffset= */ 0, [partialRef3, preloadRef]);
695
697
 
@@ -699,6 +701,56 @@ describe('HlsParser live', () => {
699
701
  ManifestParser.verifySegmentIndex(video, [ref, ref2]);
700
702
  });
701
703
 
704
+ // Test for https://github.com/shaka-project/shaka-player/issues/4223
705
+ it('ignores preload hinted segments without target duration', async () => {
706
+ playerInterface.isLowLatencyMode = () => true;
707
+
708
+ // Missing PART-TARGET, so preload hints are skipped.
709
+ const mediaWithPartialSegments = [
710
+ '#EXTM3U\n',
711
+ '#EXT-X-TARGETDURATION:5\n',
712
+ '#EXT-X-MAP:URI="init.mp4",BYTERANGE="616@0"\n',
713
+ '#EXT-X-MEDIA-SEQUENCE:0\n',
714
+ '#EXTINF:4,\n',
715
+ // ref1
716
+ 'main.mp4\n',
717
+ // ref2 includes partialRef, but not preloadRef
718
+ // partialRef
719
+ '#EXT-X-PART:DURATION=2,URI="partial.mp4",BYTERANGE=210@0\n',
720
+ // preloadRef
721
+ '#EXT-X-PRELOAD-HINT:TYPE=PART,URI="partial.mp4",BYTERANGE-START=210\n',
722
+ ].join('');
723
+
724
+ fakeNetEngine
725
+ .setResponseText('test:/master', master)
726
+ .setResponseText('test:/video', mediaWithPartialSegments)
727
+ .setResponseValue('test:/init.mp4', initSegmentData)
728
+ .setResponseValue('test:/main.mp4', segmentData)
729
+ .setResponseValue('test:/partial.mp4', segmentData)
730
+ .setResponseValue('test:/partial2.mp4', segmentData);
731
+
732
+ const ref1 = ManifestParser.makeReference(
733
+ 'test:/main.mp4', segmentDataStartTime, segmentDataStartTime + 4,
734
+ /* baseUri= */ '', /* startByte= */ 0, /* endByte= */ null,
735
+ /* timestampOffset= */ 0, []);
736
+
737
+ const partialRef = ManifestParser.makeReference(
738
+ 'test:/partial.mp4', segmentDataStartTime + 4,
739
+ segmentDataStartTime + 6,
740
+ /* baseUri= */ '', /* startByte= */ 0, /* endByte= */ 209);
741
+
742
+ // ref2 is not fully published yet, so it doesn't have a segment uri.
743
+ const ref2 = ManifestParser.makeReference(
744
+ '', segmentDataStartTime + 4, segmentDataStartTime + 6,
745
+ /* baseUri= */ '', /* startByte= */ 0, /* endByte= */ 209,
746
+ /* timestampOffset= */ 0, [partialRef]);
747
+
748
+ const manifest = await parser.start('test:/master', playerInterface);
749
+ const video = manifest.variants[0].video;
750
+ await video.createSegmentIndex();
751
+ ManifestParser.verifySegmentIndex(video, [ref1, ref2]);
752
+ });
753
+
702
754
  // Test for https://github.com/shaka-project/shaka-player/issues/4185
703
755
  it('does not fail on preload hints with LL mode off', async () => {
704
756
  // LL mode must be off for this test!
@@ -708,6 +760,7 @@ describe('HlsParser live', () => {
708
760
  '#EXTM3U\n',
709
761
  '#EXT-X-TARGETDURATION:5\n',
710
762
  '#EXT-X-MAP:URI="init.mp4",BYTERANGE="616@0"\n',
763
+ '#EXT-X-PART-INF:PART-TARGET=1.5\n',
711
764
  '#EXTINF:4,\n',
712
765
  'main.mp4\n',
713
766
  '#EXT-X-PART:DURATION=2,URI="partial.mp4",BYTERANGE=210@0\n',
@@ -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. */
@@ -37,7 +37,7 @@
37
37
  }
38
38
 
39
39
  .bottom-panels-elements-margin() {
40
- margin: 1px 6px;
40
+ margin: 1px;
41
41
  }
42
42
 
43
43
  /* For containers which host elements overlaying other things. */
@@ -140,6 +140,7 @@
140
140
 
141
141
  .shaka-volume-bar-container {
142
142
  width: 100px;
143
+ padding: 0;
143
144
  }
144
145
 
145
146
  .shaka-range-element {
@@ -1,10 +0,0 @@
1
- <!--
2
- Please remember to:
3
-
4
- 1. Use Conventional Commits syntax (fix: ..., feat: ..., etc.) in commits and
5
- PR title (https://www.conventionalcommits.org/)
6
- 2. Tag any related or fixed issues ("Issue #123", "Closes #420")
7
- 3. Sign the Google CLA if you haven't (https://cla.developers.google.com)
8
-
9
- You may delete this comment from the PR description.
10
- -->
@@ -1,9 +0,0 @@
1
- # Google App Engine Code
2
-
3
- This folder contains source code for the services we run on Google App Engine
4
- (appspot.com).
5
-
6
- - shaka-player-demo: Our hosted demo on https://shaka-player-demo.appspot.com/
7
-
8
- - demo-version-index: An index of Shaka Player releases and demos, hosted at
9
- https://index-dot-shaka-player-demo.appspot.com/
@@ -1,14 +0,0 @@
1
- # Google App Engine Version Index
2
-
3
- This folder contains everything necessary to host an index of Shaka Player
4
- releases and demos at https://index-dot-shaka-player-demo.appspot.com/
5
-
6
- - app.yaml: App Engine config file. Defines the runtime (Python 3).
7
-
8
- - main.py: A python service that queries available versions and generates the
9
- index from a template.
10
-
11
- - requirements.txt: Used by App Engine to install the necessary Python server
12
- requirements (Flask, App Engine API).
13
-
14
- - templates/index.html: A Jinja2 template used to generate the index HTML.
@@ -1,2 +0,0 @@
1
- runtime: python39
2
- default_expiration: 1s