shaka-player 4.6.2 → 4.6.3

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/externs/lcevc.js CHANGED
@@ -1,3 +1,9 @@
1
+ /*! @license
2
+ * Shaka Player
3
+ * Copyright 2023 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
1
7
  /**
2
8
  * @fileoverview Externs for LcevcDec
3
9
  * compiler.
@@ -1,3 +1,9 @@
1
+ /*! @license
2
+ * Shaka Player
3
+ * Copyright 2023 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
1
7
  /**
2
8
  * @typedef {{
3
9
  * data: !Uint8Array,
@@ -1,3 +1,9 @@
1
+ /*! @license
2
+ * Shaka Player
3
+ * Copyright 2023 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
1
7
  /**
2
8
  * @fileoverview Externs for Transmuxer.
3
9
  *
@@ -1433,11 +1433,11 @@ shaka.dash.DashParser = class {
1433
1433
  'Must have Segment* with non-text streams.');
1434
1434
 
1435
1435
  const duration = context.periodInfo.duration || 0;
1436
+ const getBaseUris = context.representation.getBaseUris;
1436
1437
  streamInfo = {
1437
1438
  generateSegmentIndex: () => {
1438
- const baseUris = context.representation.getBaseUris();
1439
1439
  return Promise.resolve(shaka.media.SegmentIndex.forSingleSegment(
1440
- periodStart, duration, baseUris));
1440
+ periodStart, duration, getBaseUris()));
1441
1441
  },
1442
1442
  };
1443
1443
  }
@@ -934,7 +934,8 @@ shaka.hls.HlsParser = class {
934
934
  return basicInfo;
935
935
  }
936
936
  } else if (extension == 'mp4' || extension == 'cmfv' ||
937
- contentMimeType == 'video/mp4' || contentMimeType == 'audio/mp4' ||
937
+ extension == 'm4s' || contentMimeType == 'video/mp4' ||
938
+ contentMimeType == 'audio/mp4' ||
938
939
  contentMimeType == 'video/iso.segment') {
939
940
  const basicInfo = shaka.media.SegmentUtils.getBasicInfoFromMp4(
940
941
  initData, response.data);
@@ -1661,6 +1661,7 @@ shaka.media.MediaSourceEngine = class {
1661
1661
  if (shaka.media.Capabilities.isChangeTypeSupported()) {
1662
1662
  if (this.transmuxers_[contentType]) {
1663
1663
  this.transmuxers_[contentType].destroy();
1664
+ delete this.transmuxers_[contentType];
1664
1665
  }
1665
1666
  if (transmuxer) {
1666
1667
  this.transmuxers_[contentType] = transmuxer;
@@ -1859,8 +1860,8 @@ shaka.media.MediaSourceEngine = class {
1859
1860
  }
1860
1861
  }
1861
1862
 
1862
- const newCodec = MimeUtils.getCodecBase(
1863
- MimeUtils.getCodecs(newMimeType));
1863
+ const newAllCodecs = MimeUtils.getCodecs(newMimeType);
1864
+ const newCodec = MimeUtils.getCodecBase(newAllCodecs);
1864
1865
  const newBasicType = MimeUtils.getBasicType(newMimeType);
1865
1866
 
1866
1867
  // Current/new codecs base and basic type match then no need to switch
@@ -1868,10 +1869,15 @@ shaka.media.MediaSourceEngine = class {
1868
1869
  return false;
1869
1870
  }
1870
1871
 
1871
- if (this.config_.codecSwitchingStrategy ===
1872
+ let allowChangeType = true;
1873
+ if (this.needSplitMuxedContent_ || (newAllCodecs.split(',').length &&
1874
+ transmuxer && !this.transmuxers_[contentType])) {
1875
+ allowChangeType = false;
1876
+ }
1877
+
1878
+ if (allowChangeType && this.config_.codecSwitchingStrategy ===
1872
1879
  shaka.config.CodecSwitchingStrategy.SMOOTH &&
1873
- shaka.media.Capabilities.isChangeTypeSupported() &&
1874
- !this.needSplitMuxedContent_) {
1880
+ shaka.media.Capabilities.isChangeTypeSupported()) {
1875
1881
  await this.changeType(contentType, newMimeType, transmuxer);
1876
1882
  } else {
1877
1883
  if (transmuxer) {
package/lib/player.js CHANGED
@@ -6781,7 +6781,7 @@ shaka.Player.TYPICAL_BUFFERING_THRESHOLD_ = 0.5;
6781
6781
  * @export
6782
6782
  */
6783
6783
  // eslint-disable-next-line no-useless-concat
6784
- shaka.Player.version = 'v4.6.2' + '-uncompiled'; // x-release-please-version
6784
+ shaka.Player.version = 'v4.6.3' + '-uncompiled'; // x-release-please-version
6785
6785
 
6786
6786
  // Initialize the deprecation system using the version string we just set
6787
6787
  // on the player.
@@ -44,6 +44,9 @@ shaka.text.UITextDisplayer = class {
44
44
  /** @private {HTMLElement} */
45
45
  this.videoContainer_ = videoContainer;
46
46
 
47
+ /** @private {?number} */
48
+ this.aspectRatio_ = null;
49
+
47
50
  /** @type {HTMLElement} */
48
51
  this.textContainer_ = shaka.util.Dom.createHTMLElement('div');
49
52
  this.textContainer_.classList.add('shaka-text-container');
@@ -90,6 +93,23 @@ shaka.text.UITextDisplayer = class {
90
93
  this.updateCaptions_(/* forceUpdate= */ true);
91
94
  });
92
95
 
96
+ // From: https://html.spec.whatwg.org/multipage/media.html#dom-video-videowidth
97
+ // Whenever the natural width or natural height of the video changes
98
+ // (including, for example, because the selected video track was changed),
99
+ // if the element's readyState attribute is not HAVE_NOTHING, the user
100
+ // agent must queue a media element task given the media element to fire an
101
+ // event named resize at the media element.
102
+ this.eventManager_.listen(this.video_, 'resize', () => {
103
+ const element = /** @type {!HTMLVideoElement} */ (this.video_);
104
+ const width = element.videoWidth;
105
+ const height = element.videoHeight;
106
+ if (width && height) {
107
+ this.aspectRatio_ = width / height;
108
+ } else {
109
+ this.aspectRatio_ = null;
110
+ }
111
+ });
112
+
93
113
  /** @private {ResizeObserver} */
94
114
  this.resizeObserver_ = null;
95
115
  if ('ResizeObserver' in window) {
@@ -400,6 +420,10 @@ shaka.text.UITextDisplayer = class {
400
420
  */
401
421
  getRegionElement_(cue) {
402
422
  const region = cue.region;
423
+ // from https://dvcs.w3.org/hg/text-tracks/raw-file/default/608toVTT/608toVTT.html#caption-window-size
424
+ // if aspect ratio is 4/3, use that value, otherwise, use the 16:9 value
425
+ const lineWidthMultiple = this.aspectRatio_ === 4/3 ? 2.5 : 1.9;
426
+ const lineHeightMultiple = 5.33;
403
427
 
404
428
  const regionId = this.generateRegionId_(region);
405
429
  if (this.regionElements_.has(regionId)) {
@@ -417,11 +441,33 @@ shaka.text.UITextDisplayer = class {
417
441
  regionElement.id = 'shaka-text-region---' + regionId;
418
442
  regionElement.classList.add('shaka-text-region');
419
443
 
420
- regionElement.style.height = region.height + heightUnit;
421
- regionElement.style.width = region.width + widthUnit;
422
444
  regionElement.style.position = 'absolute';
423
- regionElement.style.top = region.viewportAnchorY + viewportAnchorUnit;
424
- regionElement.style.left = region.viewportAnchorX + viewportAnchorUnit;
445
+
446
+ const linesUnit = shaka.text.CueRegion.units.LINES;
447
+ if (region.heightUnits === linesUnit && region.widthUnits === linesUnit) {
448
+ regionElement.style.height = region.height * lineHeightMultiple + '%';
449
+ regionElement.style.width = region.width * lineWidthMultiple + '%';
450
+ } else {
451
+ regionElement.style.height = region.height + heightUnit;
452
+ regionElement.style.width = region.width + widthUnit;
453
+ }
454
+
455
+ if (region.viewportAnchorUnits === linesUnit) {
456
+ // from https://dvcs.w3.org/hg/text-tracks/raw-file/default/608toVTT/608toVTT.html#positioning-in-cea-708
457
+ let top = region.viewportAnchorY / 75 * 100;
458
+ const windowWidth = this.aspectRatio_ === 4/3 ? 160 : 210;
459
+ let left = region.viewportAnchorX / windowWidth * 100;
460
+ // adjust top and left values based on the region anchor and window size
461
+ top -= region.regionAnchorY * region.height * lineHeightMultiple / 100;
462
+ left -= region.regionAnchorX * region.width * lineWidthMultiple / 100;
463
+ regionElement.style.top = top + '%';
464
+ regionElement.style.left = left + '%';
465
+ } else {
466
+ regionElement.style.top = region.viewportAnchorY -
467
+ region.regionAnchorY * region.height / 100 + viewportAnchorUnit;
468
+ regionElement.style.left = region.viewportAnchorX -
469
+ region.regionAnchorX * region.width / 100 + viewportAnchorUnit;
470
+ }
425
471
 
426
472
  regionElement.style.display = 'flex';
427
473
  regionElement.style.flexDirection = 'column';
@@ -301,11 +301,45 @@ shaka.util.Mp4BoxParsers = class {
301
301
  */
302
302
  static parseESDS(reader) {
303
303
  let codec = 'mp4a';
304
- reader.skip(11);
305
- codec += '.' + this.toHex_(reader.readUint8());
306
- // this value is only a single digit
307
- codec += '.' +
308
- this.toHex_((reader.readUint8() >>> 2) & 0x3f).replace(/^0/, '');
304
+ let tag;
305
+ let oti;
306
+ while (reader.hasMoreData()) {
307
+ tag = reader.readUint8();
308
+ let byteRead = reader.readUint8();
309
+ while (byteRead & 0x80) {
310
+ byteRead = reader.readUint8();
311
+ }
312
+ if (tag == 0x03) {
313
+ reader.readUint16();
314
+ const flags = reader.readUint8();
315
+ if (flags & 0x80) {
316
+ reader.readUint16();
317
+ }
318
+ if (flags & 0x40) {
319
+ reader.skip(reader.readUint8());
320
+ }
321
+ if (flags & 0x20) {
322
+ reader.readUint16();
323
+ }
324
+ } else if (tag == 0x04) {
325
+ oti = reader.readUint8();
326
+ reader.skip(12);
327
+ } else if (tag == 0x05) {
328
+ break;
329
+ }
330
+ }
331
+ if (oti) {
332
+ codec += '.' + this.toHex_(oti);
333
+ if (tag == 0x05 && reader.hasMoreData()) {
334
+ const firstData = reader.readUint8();
335
+ let audioObjectType = (firstData & 0xF8) >> 3;
336
+ if (audioObjectType === 31 && reader.hasMoreData()) {
337
+ audioObjectType = 32 + ((firstData & 0x7) << 3) +
338
+ ((reader.readUint8() & 0xE0) >> 5);
339
+ }
340
+ codec += '.' + audioObjectType;
341
+ }
342
+ }
309
343
  return {codec};
310
344
  }
311
345
 
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.6.2",
4
+ "version": "4.6.3",
5
5
  "homepage": "https://github.com/shaka-project/shaka-player",
6
6
  "author": "Google",
7
7
  "maintainers": [
@@ -8,18 +8,24 @@ describe('Mp4BoxParsers', () => {
8
8
  const videoInitSegmentUri = '/base/test/test/assets/sintel-video-init.mp4';
9
9
  const videoSegmentUri = '/base/test/test/assets/sintel-video-segment.mp4';
10
10
 
11
+ const audioInitSegmentXheAacUri = '/base/test/test/assets/audio-xhe-aac.mp4';
12
+
11
13
  /** @type {!ArrayBuffer} */
12
14
  let videoInitSegment;
13
15
  /** @type {!ArrayBuffer} */
14
16
  let videoSegment;
17
+ /** @type {!ArrayBuffer} */
18
+ let audioInitSegmentXheAac;
15
19
 
16
20
  beforeAll(async () => {
17
21
  const responses = await Promise.all([
18
22
  shaka.test.Util.fetch(videoInitSegmentUri),
19
23
  shaka.test.Util.fetch(videoSegmentUri),
24
+ shaka.test.Util.fetch(audioInitSegmentXheAacUri),
20
25
  ]);
21
26
  videoInitSegment = responses[0];
22
27
  videoSegment = responses[1];
28
+ audioInitSegmentXheAac = responses[2];
23
29
  });
24
30
 
25
31
  it('parses init segment', () => {
@@ -157,6 +163,36 @@ describe('Mp4BoxParsers', () => {
157
163
  expect(baseMediaDecodeTime).toBe(expectedBaseMediaDecodeTime);
158
164
  });
159
165
 
166
+ it('parses ESDS box for xHE-AAC segment', () => {
167
+ let channelCount;
168
+ let sampleRate;
169
+ let codec;
170
+
171
+ const Mp4Parser = shaka.util.Mp4Parser;
172
+ new Mp4Parser()
173
+ .box('moov', Mp4Parser.children)
174
+ .box('trak', Mp4Parser.children)
175
+ .box('mdia', Mp4Parser.children)
176
+ .box('minf', Mp4Parser.children)
177
+ .box('stbl', Mp4Parser.children)
178
+ .fullBox('stsd', Mp4Parser.sampleDescription)
179
+ .box('mp4a', (box) => {
180
+ const parsedMP4ABox = shaka.util.Mp4BoxParsers.parseMP4A(box.reader);
181
+ channelCount = parsedMP4ABox.channelCount;
182
+ sampleRate = parsedMP4ABox.sampleRate;
183
+ if (box.reader.hasMoreData()) {
184
+ Mp4Parser.children(box);
185
+ }
186
+ })
187
+ .box('esds', (box) => {
188
+ const parsedESDSBox = shaka.util.Mp4BoxParsers.parseESDS(box.reader);
189
+ codec = parsedESDSBox.codec;
190
+ }).parse(audioInitSegmentXheAac, /* partialOkay= */ false);
191
+ expect(channelCount).toBe(2);
192
+ expect(sampleRate).toBe(48000);
193
+ expect(codec).toBe('mp4a.40.42');
194
+ });
195
+
160
196
  /**
161
197
  *
162
198
  * Explanation on the Uint8Array: