shaka-player 4.11.13 → 4.12.1

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 (71) hide show
  1. package/README.md +47 -0
  2. package/dist/deps.js +8 -8
  3. package/dist/locales.js +35 -35
  4. package/dist/shaka-player.compiled.d.ts +36 -13
  5. package/dist/shaka-player.compiled.debug.d.ts +36 -13
  6. package/dist/shaka-player.compiled.debug.externs.js +46 -11
  7. package/dist/shaka-player.compiled.debug.js +543 -517
  8. package/dist/shaka-player.compiled.debug.map +4 -4
  9. package/dist/shaka-player.compiled.externs.js +46 -11
  10. package/dist/shaka-player.compiled.js +1348 -1331
  11. package/dist/shaka-player.compiled.map +4 -4
  12. package/dist/shaka-player.ui.d.ts +37 -14
  13. package/dist/shaka-player.ui.debug.d.ts +37 -14
  14. package/dist/shaka-player.ui.debug.externs.js +46 -11
  15. package/dist/shaka-player.ui.debug.js +629 -598
  16. package/dist/shaka-player.ui.debug.map +4 -4
  17. package/dist/shaka-player.ui.externs.js +46 -11
  18. package/dist/shaka-player.ui.js +1624 -1603
  19. package/dist/shaka-player.ui.map +4 -4
  20. package/externs/shaka/ads.js +9 -0
  21. package/externs/shaka/manifest.js +26 -1
  22. package/externs/shaka/offline.js +8 -2
  23. package/externs/shaka/player.js +80 -28
  24. package/externs/shaka/text.js +9 -0
  25. package/lib/ads/ad_manager.js +6 -0
  26. package/lib/ads/ad_utils.js +1 -0
  27. package/lib/ads/client_side_ad.js +8 -0
  28. package/lib/ads/interstitial_ad.js +25 -4
  29. package/lib/ads/interstitial_ad_manager.js +67 -8
  30. package/lib/ads/media_tailor_ad.js +8 -0
  31. package/lib/ads/server_side_ad.js +8 -0
  32. package/lib/dash/content_protection.js +31 -0
  33. package/lib/dash/dash_parser.js +22 -12
  34. package/lib/hls/hls_parser.js +63 -49
  35. package/lib/media/adaptation_set.js +11 -17
  36. package/lib/media/adaptation_set_criteria.js +4 -9
  37. package/lib/media/drm_engine.js +3 -1
  38. package/lib/media/manifest_filterer.js +2 -1
  39. package/lib/media/media_source_engine.js +286 -20
  40. package/lib/media/playhead.js +3 -1
  41. package/lib/media/preload_manager.js +10 -7
  42. package/lib/media/segment_prefetch.js +32 -13
  43. package/lib/media/segment_reference.js +3 -3
  44. package/lib/media/streaming_engine.js +87 -261
  45. package/lib/mss/mss_parser.js +1 -0
  46. package/lib/offline/download_info.js +5 -1
  47. package/lib/offline/indexeddb/storage_mechanism.js +4 -3
  48. package/lib/offline/indexeddb/v1_storage_cell.js +2 -0
  49. package/lib/offline/indexeddb/v2_storage_cell.js +2 -0
  50. package/lib/offline/manifest_converter.js +4 -0
  51. package/lib/offline/storage.js +277 -5
  52. package/lib/player.js +224 -78
  53. package/lib/text/simple_text_displayer.js +7 -0
  54. package/lib/text/stub_text_displayer.js +7 -0
  55. package/lib/text/ui_text_displayer.js +12 -0
  56. package/lib/util/dom_utils.js +14 -0
  57. package/lib/util/error.js +5 -0
  58. package/lib/util/periods.js +2 -0
  59. package/lib/util/platform.js +15 -0
  60. package/lib/util/player_configuration.js +11 -4
  61. package/lib/util/stream_utils.js +20 -1
  62. package/package.json +1 -1
  63. package/ui/ad_statistics_button.js +12 -0
  64. package/ui/controls.js +31 -7
  65. package/ui/externs/ui.js +8 -1
  66. package/ui/fullscreen_button.js +9 -0
  67. package/ui/locales/be.json +49 -0
  68. package/ui/mute_button.js +42 -11
  69. package/ui/skip_ad_button.js +16 -11
  70. package/ui/statistics_button.js +12 -0
  71. package/ui/ui.js +10 -5
@@ -27,7 +27,6 @@ goog.require('shaka.util.Destroyer');
27
27
  goog.require('shaka.util.Error');
28
28
  goog.require('shaka.util.FakeEvent');
29
29
  goog.require('shaka.util.IDestroyable');
30
- goog.require('shaka.util.Id3Utils');
31
30
  goog.require('shaka.util.LanguageUtils');
32
31
  goog.require('shaka.util.ManifestParserUtils');
33
32
  goog.require('shaka.util.MimeUtils');
@@ -93,9 +92,6 @@ shaka.media.StreamingEngine = class {
93
92
  /** @private {number} */
94
93
  this.textStreamSequenceId_ = 0;
95
94
 
96
- /** @private {boolean} */
97
- this.parsedPrftEventRaised_ = false;
98
-
99
95
  /**
100
96
  * Maps a content type, e.g., 'audio', 'video', or 'text', to a MediaState.
101
97
  *
@@ -628,6 +624,9 @@ shaka.media.StreamingEngine = class {
628
624
  }
629
625
  }
630
626
 
627
+ const shouldResetMediaSource =
628
+ mediaState.stream.isAudioMuxedInVideo != stream.isAudioMuxedInVideo;
629
+
631
630
  mediaState.stream = stream;
632
631
  mediaState.segmentIterator = null;
633
632
  mediaState.adaptation = !!adaptation;
@@ -635,6 +634,11 @@ shaka.media.StreamingEngine = class {
635
634
  const streamTag = shaka.media.StreamingEngine.logPrefix_(mediaState);
636
635
  shaka.log.debug('switch: switching to Stream ' + streamTag);
637
636
 
637
+ if (shouldResetMediaSource) {
638
+ this.resetMediaSource(/* force= */ true, /* clearBuffer= */ false);
639
+ return;
640
+ }
641
+
638
642
  if (clearBuffer) {
639
643
  if (mediaState.clearingBuffer) {
640
644
  // We are already going to clear the buffer, but make sure it is also
@@ -1319,6 +1323,10 @@ shaka.media.StreamingEngine = class {
1319
1323
  this.playerInterface_.mediaSourceEngine.clearSelectedClosedCaptionId();
1320
1324
  }
1321
1325
 
1326
+ if (mediaState.stream.isAudioMuxedInVideo) {
1327
+ return null;
1328
+ }
1329
+
1322
1330
  if (!this.playerInterface_.mediaSourceEngine.isStreamingAllowed() &&
1323
1331
  mediaState.type != ContentType.TEXT) {
1324
1332
  // It is not allowed to add segments yet, so we schedule an update to
@@ -2241,84 +2249,64 @@ shaka.media.StreamingEngine = class {
2241
2249
  const hasClosedCaptions = stream.closedCaptions &&
2242
2250
  stream.closedCaptions.size > 0;
2243
2251
 
2244
- let parser;
2245
- const hasEmsg = ((stream.emsgSchemeIdUris != null &&
2246
- stream.emsgSchemeIdUris.length > 0) ||
2247
- this.config_.dispatchAllEmsgBoxes);
2248
- const shouldParsePrftBox =
2249
- (this.config_.parsePrftBox && !this.parsedPrftEventRaised_);
2250
-
2251
- const isMP4 = stream.mimeType == 'video/mp4' ||
2252
- stream.mimeType == 'audio/mp4';
2253
- let timescale = null;
2254
- if (reference.initSegmentReference) {
2255
- timescale = reference.initSegmentReference.timescale;
2256
- }
2257
- const shouldFixTimestampOffset = isMP4 && timescale &&
2258
- stream.type === shaka.util.ManifestParserUtils.ContentType.VIDEO &&
2259
- this.manifest_.type == shaka.media.ManifestParser.DASH &&
2260
- this.config_.shouldFixTimestampOffset;
2261
-
2262
- if (hasEmsg || shouldParsePrftBox || shouldFixTimestampOffset) {
2263
- parser = new shaka.util.Mp4Parser();
2264
- }
2265
-
2266
- if (hasEmsg) {
2267
- parser
2268
- .fullBox(
2269
- 'emsg',
2270
- (box) => this.parseEMSG_(
2271
- reference, stream.emsgSchemeIdUris, box));
2272
- }
2273
-
2274
- if (shouldParsePrftBox) {
2275
- parser
2276
- .fullBox(
2277
- 'prft',
2278
- (box) => this.parsePrft_(
2279
- reference, box));
2280
- }
2281
-
2282
- if (shouldFixTimestampOffset) {
2283
- parser
2284
- .box('moof', shaka.util.Mp4Parser.children)
2285
- .box('traf', shaka.util.Mp4Parser.children)
2286
- .fullBox('tfdt', async (box) => {
2287
- goog.asserts.assert(
2288
- box.version != null,
2289
- 'TFDT is a full box and should have a valid version.');
2290
-
2291
- const parsedTFDT = shaka.util.Mp4BoxParsers.parseTFDTInaccurate(
2292
- box.reader, box.version);
2293
-
2294
- const baseMediaDecodeTime = parsedTFDT.baseMediaDecodeTime;
2295
-
2296
- // In case the time is 0, it is not updated
2297
- if (!baseMediaDecodeTime) {
2298
- return;
2299
- }
2300
- goog.asserts.assert(typeof(timescale) == 'number',
2301
- 'Should be an number!');
2252
+ if (this.config_.shouldFixTimestampOffset) {
2253
+ let parser;
2302
2254
 
2303
- const scaledMediaDecodeTime = -baseMediaDecodeTime / timescale;
2255
+ const isMP4 = stream.mimeType == 'video/mp4' ||
2256
+ stream.mimeType == 'audio/mp4';
2257
+ let timescale = null;
2258
+ if (reference.initSegmentReference) {
2259
+ timescale = reference.initSegmentReference.timescale;
2260
+ }
2261
+ const shouldFixTimestampOffset = isMP4 && timescale &&
2262
+ stream.type === shaka.util.ManifestParserUtils.ContentType.VIDEO &&
2263
+ this.manifest_.type == shaka.media.ManifestParser.DASH;
2304
2264
 
2305
- const comparison1 = Number(mediaState.lastTimestampOffset) || 0;
2265
+ if (shouldFixTimestampOffset) {
2266
+ parser = new shaka.util.Mp4Parser();
2267
+ }
2306
2268
 
2307
- if (comparison1 < scaledMediaDecodeTime) {
2308
- const lastAppendWindowStart = mediaState.lastAppendWindowStart;
2309
- const lastAppendWindowEnd = mediaState.lastAppendWindowEnd;
2310
- goog.asserts.assert(typeof(lastAppendWindowStart) == 'number',
2311
- 'Should be an number!');
2312
- goog.asserts.assert(typeof(lastAppendWindowEnd) == 'number',
2269
+ if (shouldFixTimestampOffset) {
2270
+ parser
2271
+ .box('moof', shaka.util.Mp4Parser.children)
2272
+ .box('traf', shaka.util.Mp4Parser.children)
2273
+ .fullBox('tfdt', async (box) => {
2274
+ goog.asserts.assert(
2275
+ box.version != null,
2276
+ 'TFDT is a full box and should have a valid version.');
2277
+
2278
+ const parsedTFDT = shaka.util.Mp4BoxParsers.parseTFDTInaccurate(
2279
+ box.reader, box.version);
2280
+
2281
+ const baseMediaDecodeTime = parsedTFDT.baseMediaDecodeTime;
2282
+
2283
+ // In case the time is 0, it is not updated
2284
+ if (!baseMediaDecodeTime) {
2285
+ return;
2286
+ }
2287
+ goog.asserts.assert(typeof(timescale) == 'number',
2313
2288
  'Should be an number!');
2314
- await this.setProperties_(mediaState, scaledMediaDecodeTime,
2315
- lastAppendWindowStart, lastAppendWindowEnd, reference);
2316
- }
2317
- });
2318
- }
2319
2289
 
2320
- if (hasEmsg || shouldParsePrftBox || shouldFixTimestampOffset) {
2321
- parser.parse(segment, /* partialOkay= */ false, isChunkedData);
2290
+ const scaledMediaDecodeTime = -baseMediaDecodeTime / timescale;
2291
+
2292
+ const comparison1 = Number(mediaState.lastTimestampOffset) || 0;
2293
+
2294
+ if (comparison1 < scaledMediaDecodeTime) {
2295
+ const lastAppendWindowStart = mediaState.lastAppendWindowStart;
2296
+ const lastAppendWindowEnd = mediaState.lastAppendWindowEnd;
2297
+ goog.asserts.assert(typeof(lastAppendWindowStart) == 'number',
2298
+ 'Should be an number!');
2299
+ goog.asserts.assert(typeof(lastAppendWindowEnd) == 'number',
2300
+ 'Should be an number!');
2301
+ await this.setProperties_(mediaState, scaledMediaDecodeTime,
2302
+ lastAppendWindowStart, lastAppendWindowEnd, reference);
2303
+ }
2304
+ });
2305
+ }
2306
+
2307
+ if (shouldFixTimestampOffset) {
2308
+ parser.parse(segment, /* partialOkay= */ false, isChunkedData);
2309
+ }
2322
2310
  }
2323
2311
 
2324
2312
  await this.evict_(mediaState, presentationTime);
@@ -2343,176 +2331,6 @@ shaka.media.StreamingEngine = class {
2343
2331
  shaka.log.v2(logPrefix, 'appended media segment');
2344
2332
  }
2345
2333
 
2346
-
2347
- /**
2348
- * Parse the EMSG box from a MP4 container.
2349
- *
2350
- * @param {!shaka.media.SegmentReference} reference
2351
- * @param {?Array.<string>} emsgSchemeIdUris Array of emsg
2352
- * scheme_id_uri for which emsg boxes should be parsed.
2353
- * @param {!shaka.extern.ParsedBox} box
2354
- * @private
2355
- * https://dashif-documents.azurewebsites.net/Events/master/event.html#emsg-format
2356
- * aligned(8) class DASHEventMessageBox
2357
- * extends FullBox(‘emsg’, version, flags = 0){
2358
- * if (version==0) {
2359
- * string scheme_id_uri;
2360
- * string value;
2361
- * unsigned int(32) timescale;
2362
- * unsigned int(32) presentation_time_delta;
2363
- * unsigned int(32) event_duration;
2364
- * unsigned int(32) id;
2365
- * } else if (version==1) {
2366
- * unsigned int(32) timescale;
2367
- * unsigned int(64) presentation_time;
2368
- * unsigned int(32) event_duration;
2369
- * unsigned int(32) id;
2370
- * string scheme_id_uri;
2371
- * string value;
2372
- * }
2373
- * unsigned int(8) message_data[];
2374
- */
2375
- parseEMSG_(reference, emsgSchemeIdUris, box) {
2376
- let timescale;
2377
- let id;
2378
- let eventDuration;
2379
- let schemeId;
2380
- let startTime;
2381
- let presentationTimeDelta;
2382
- let value;
2383
-
2384
- if (box.version === 0) {
2385
- schemeId = box.reader.readTerminatedString();
2386
- value = box.reader.readTerminatedString();
2387
- timescale = box.reader.readUint32();
2388
- presentationTimeDelta = box.reader.readUint32();
2389
- eventDuration = box.reader.readUint32();
2390
- id = box.reader.readUint32();
2391
- startTime = reference.startTime + (presentationTimeDelta / timescale);
2392
- } else {
2393
- timescale = box.reader.readUint32();
2394
- const pts = box.reader.readUint64();
2395
- startTime = (pts / timescale) + reference.timestampOffset;
2396
- presentationTimeDelta = startTime - reference.startTime;
2397
- eventDuration = box.reader.readUint32();
2398
- id = box.reader.readUint32();
2399
- schemeId = box.reader.readTerminatedString();
2400
- value = box.reader.readTerminatedString();
2401
- }
2402
- const messageData = box.reader.readBytes(
2403
- box.reader.getLength() - box.reader.getPosition());
2404
-
2405
- // See DASH sec. 5.10.3.3.1
2406
- // If a DASH client detects an event message box with a scheme that is not
2407
- // defined in MPD, the client is expected to ignore it.
2408
- if ((emsgSchemeIdUris && emsgSchemeIdUris.includes(schemeId)) ||
2409
- this.config_.dispatchAllEmsgBoxes) {
2410
- // See DASH sec. 5.10.4.1
2411
- // A special scheme in DASH used to signal manifest updates.
2412
- if (schemeId == 'urn:mpeg:dash:event:2012') {
2413
- this.playerInterface_.onManifestUpdate();
2414
- } else {
2415
- // All other schemes are dispatched as a general 'emsg' event.
2416
- const endTime = startTime + (eventDuration / timescale);
2417
- /** @type {shaka.extern.EmsgInfo} */
2418
- const emsg = {
2419
- startTime: startTime,
2420
- endTime: endTime,
2421
- schemeIdUri: schemeId,
2422
- value: value,
2423
- timescale: timescale,
2424
- presentationTimeDelta: presentationTimeDelta,
2425
- eventDuration: eventDuration,
2426
- id: id,
2427
- messageData: messageData,
2428
- };
2429
-
2430
- // Dispatch an event to notify the application about the emsg box.
2431
- const eventName = shaka.util.FakeEvent.EventName.Emsg;
2432
- const data = (new Map()).set('detail', emsg);
2433
- const event = new shaka.util.FakeEvent(eventName, data);
2434
- // A user can call preventDefault() on a cancelable event.
2435
- event.cancelable = true;
2436
-
2437
- this.playerInterface_.onEvent(event);
2438
-
2439
- if (event.defaultPrevented) {
2440
- // If the caller uses preventDefault() on the 'emsg' event, don't
2441
- // process any further, and don't generate an ID3 'metadata' event
2442
- // for the same data.
2443
- return;
2444
- }
2445
-
2446
- // Additionally, ID3 events generate a 'metadata' event. This is a
2447
- // pre-parsed version of the metadata blob already dispatched in the
2448
- // 'emsg' event.
2449
- if (schemeId == 'https://aomedia.org/emsg/ID3' ||
2450
- schemeId == 'https://developer.apple.com/streaming/emsg-id3') {
2451
- // See https://aomediacodec.github.io/id3-emsg/
2452
- const frames = shaka.util.Id3Utils.getID3Frames(messageData);
2453
- if (frames.length) {
2454
- /** @private {shaka.extern.ID3Metadata} */
2455
- const metadata = {
2456
- cueTime: startTime,
2457
- data: messageData,
2458
- frames: frames,
2459
- dts: startTime,
2460
- pts: startTime,
2461
- };
2462
- this.playerInterface_.onMetadata(
2463
- [metadata], /* offset= */ 0, endTime);
2464
- }
2465
- }
2466
- }
2467
- }
2468
- }
2469
-
2470
- /**
2471
- * Parse PRFT box.
2472
- * @param {!shaka.media.SegmentReference} reference
2473
- * @param {!shaka.extern.ParsedBox} box
2474
- * @private
2475
- */
2476
- parsePrft_(reference, box) {
2477
- if (this.parsedPrftEventRaised_ ||
2478
- !reference.initSegmentReference.timescale) {
2479
- return;
2480
- }
2481
- goog.asserts.assert(
2482
- box.version == 0 || box.version == 1,
2483
- 'PRFT version can only be 0 or 1');
2484
- const parsed = shaka.util.Mp4BoxParsers.parsePRFTInaccurate(
2485
- box.reader, box.version);
2486
-
2487
- const timescale = reference.initSegmentReference.timescale;
2488
- const wallClockTime = this.convertNtp(parsed.ntpTimestamp);
2489
- const programStartDate = new Date(wallClockTime -
2490
- (parsed.mediaTime / timescale) * 1000);
2491
- const prftInfo = {
2492
- wallClockTime,
2493
- programStartDate,
2494
- };
2495
-
2496
- const eventName = shaka.util.FakeEvent.EventName.Prft;
2497
- const data = (new Map()).set('detail', prftInfo);
2498
- const event = new shaka.util.FakeEvent(
2499
- eventName, data);
2500
- this.playerInterface_.onEvent(event);
2501
- this.parsedPrftEventRaised_ = true;
2502
- }
2503
-
2504
-
2505
- /**
2506
- * Convert Ntp ntpTimeStamp to UTC Time
2507
- *
2508
- * @param {number} ntpTimeStamp
2509
- * @return {number} utcTime
2510
- */
2511
- convertNtp(ntpTimeStamp) {
2512
- const start = new Date(Date.UTC(1900, 0, 1, 0, 0, 0));
2513
- return new Date(start.getTime() + ntpTimeStamp).getTime();
2514
- }
2515
-
2516
2334
  /**
2517
2335
  * Evicts media to meet the max buffer behind limit.
2518
2336
  *
@@ -2896,21 +2714,26 @@ shaka.media.StreamingEngine = class {
2896
2714
  /**
2897
2715
  * Reset Media Source
2898
2716
  *
2717
+ * @param {boolean=} force
2899
2718
  * @return {!Promise.<boolean>}
2900
2719
  */
2901
- async resetMediaSource() {
2720
+ async resetMediaSource(force = false, clearBuffer = true) {
2902
2721
  const now = (Date.now() / 1000);
2903
2722
  const minTimeBetweenRecoveries = this.config_.minTimeBetweenRecoveries;
2904
- if (!this.config_.allowMediaSourceRecoveries ||
2905
- (now - this.lastMediaSourceReset_) < minTimeBetweenRecoveries) {
2906
- return false;
2723
+ if (!force) {
2724
+ if (!this.config_.allowMediaSourceRecoveries ||
2725
+ (now - this.lastMediaSourceReset_) < minTimeBetweenRecoveries) {
2726
+ return false;
2727
+ }
2728
+ this.lastMediaSourceReset_ = now;
2907
2729
  }
2908
- this.lastMediaSourceReset_ = now;
2909
2730
  const ContentType = shaka.util.ManifestParserUtils.ContentType;
2910
2731
  const audioMediaState = this.mediaStates_.get(ContentType.AUDIO);
2911
2732
  if (audioMediaState) {
2912
2733
  audioMediaState.lastInitSegmentReference = null;
2913
- this.forceClearBuffer_(audioMediaState);
2734
+ if (clearBuffer) {
2735
+ this.forceClearBuffer_(audioMediaState);
2736
+ }
2914
2737
  this.abortOperations_(audioMediaState).catch(() => {});
2915
2738
  if (audioMediaState.segmentIterator) {
2916
2739
  audioMediaState.segmentIterator.resetToLastIndependent();
@@ -2919,7 +2742,9 @@ shaka.media.StreamingEngine = class {
2919
2742
  const videoMediaState = this.mediaStates_.get(ContentType.VIDEO);
2920
2743
  if (videoMediaState) {
2921
2744
  videoMediaState.lastInitSegmentReference = null;
2922
- this.forceClearBuffer_(videoMediaState);
2745
+ if (clearBuffer) {
2746
+ this.forceClearBuffer_(videoMediaState);
2747
+ }
2923
2748
  this.abortOperations_(videoMediaState).catch(() => {});
2924
2749
  if (videoMediaState.segmentIterator) {
2925
2750
  videoMediaState.segmentIterator.resetToLastIndependent();
@@ -2937,6 +2762,14 @@ shaka.media.StreamingEngine = class {
2937
2762
  streamsByType.set(ContentType.VIDEO, this.currentVariant_.video);
2938
2763
  }
2939
2764
  await this.playerInterface_.mediaSourceEngine.reset(streamsByType);
2765
+ if (videoMediaState &&
2766
+ !videoMediaState.performingUpdate && !videoMediaState.updateTimer) {
2767
+ this.scheduleUpdate_(videoMediaState, 0);
2768
+ }
2769
+ if (audioMediaState &&
2770
+ !audioMediaState.performingUpdate && !audioMediaState.updateTimer) {
2771
+ this.scheduleUpdate_(audioMediaState, 0);
2772
+ }
2940
2773
  return true;
2941
2774
  }
2942
2775
 
@@ -3006,13 +2839,11 @@ shaka.media.StreamingEngine = class {
3006
2839
  * netEngine: shaka.net.NetworkingEngine,
3007
2840
  * onError: function(!shaka.util.Error),
3008
2841
  * onEvent: function(!Event),
3009
- * onManifestUpdate: function(),
3010
2842
  * onSegmentAppended: function(!shaka.media.SegmentReference,
3011
2843
  * !shaka.extern.Stream),
3012
2844
  * onInitSegmentAppended: function(!number,!shaka.media.InitSegmentReference),
3013
2845
  * beforeAppendSegment: function(
3014
2846
  * shaka.util.ManifestParserUtils.ContentType,!BufferSource):Promise,
3015
- * onMetadata: !function(!Array.<shaka.extern.ID3Metadata>, number, ?number),
3016
2847
  * disableStream: function(!shaka.extern.Stream, number):boolean
3017
2848
  * }}
3018
2849
  *
@@ -3033,8 +2864,6 @@ shaka.media.StreamingEngine = class {
3033
2864
  * StreamingEngine.switch*() or StreamingEngine.seeked() to attempt recovery.
3034
2865
  * @property {function(!Event)} onEvent
3035
2866
  * Called when an event occurs that should be sent to the app.
3036
- * @property {function()} onManifestUpdate
3037
- * Called when an embedded 'emsg' box should trigger a manifest update.
3038
2867
  * @property {function(!shaka.media.SegmentReference,
3039
2868
  * !shaka.extern.Stream)} onSegmentAppended
3040
2869
  * Called after a segment is successfully appended to a MediaSource.
@@ -3044,9 +2873,6 @@ shaka.media.StreamingEngine = class {
3044
2873
  * @property {!function(shaka.util.ManifestParserUtils.ContentType,
3045
2874
  * !BufferSource):Promise} beforeAppendSegment
3046
2875
  * A function called just before appending to the source buffer.
3047
- * @property
3048
- * {!function(!Array.<shaka.extern.ID3Metadata>, number, ?number)} onMetadata
3049
- * Called when an ID3 is found in a EMSG.
3050
2876
  * @property {function(!shaka.extern.Stream, number):boolean} disableStream
3051
2877
  * Called to temporarily disable a stream i.e. disabling all variant
3052
2878
  * containing said stream.
@@ -605,6 +605,7 @@ shaka.mss.MssParser = class {
605
605
  external: false,
606
606
  fastSwitching: false,
607
607
  fullMimeTypes: new Set(),
608
+ isAudioMuxedInVideo: false,
608
609
  };
609
610
 
610
611
  // This is specifically for text tracks.
@@ -45,7 +45,11 @@ shaka.offline.DownloadInfo = class {
45
45
  static idForSegmentRef(ref) {
46
46
  // Escape the URIs using encodeURI, to make sure that a weirdly formed URI
47
47
  // cannot cause two unrelated refs to be considered equivalent.
48
- return ref.getUris().map((uri) => '{' + encodeURI(uri) + '}').join('') +
48
+ const removeSprites = (uri) => {
49
+ return uri.split('#xywh=')[0];
50
+ };
51
+ return ref.getUris().map(
52
+ (uri) => '{' + encodeURI(removeSprites(uri)) + '}').join('') +
49
53
  ':' + ref.startByte + ':' + ref.endByte;
50
54
  }
51
55
 
@@ -392,9 +392,10 @@ shaka.offline.indexeddb.StorageMechanism.SESSION_ID_STORE = 'session-ids';
392
392
  shaka.offline.StorageMuxer.register(
393
393
  'idb',
394
394
  () => {
395
- // Offline storage is not supported on the Chromecast or Xbox One
396
- // platforms.
397
- if (shaka.util.Platform.isChromecast() ||
395
+ // Offline storage is not supported on the Chromecast Linux/Fuschia or
396
+ // Xbox One platforms.
397
+ if ((shaka.util.Platform.isChromecast() &&
398
+ !shaka.util.Platform.isAndroidCastDevice()) ||
398
399
  shaka.util.Platform.isXboxOne()) {
399
400
  return null;
400
401
  }
@@ -182,6 +182,7 @@ shaka.offline.indexeddb.V1StorageCell = class
182
182
  tilesLayout: undefined,
183
183
  external: false,
184
184
  fastSwitching: false,
185
+ isAudioMuxedInVideo: false,
185
186
  };
186
187
  }
187
188
 
@@ -214,6 +215,7 @@ shaka.offline.indexeddb.V1StorageCell = class
214
215
  tilesLayout: '',
215
216
  mimeType: null,
216
217
  codecs: null,
218
+ thumbnailSprite: null,
217
219
  };
218
220
  }
219
221
 
@@ -131,6 +131,7 @@ shaka.offline.indexeddb.V2StorageCell = class
131
131
  tilesLayout: undefined,
132
132
  external: false,
133
133
  fastSwitching: false,
134
+ isAudioMuxedInVideo: false,
134
135
  };
135
136
  }
136
137
 
@@ -158,6 +159,7 @@ shaka.offline.indexeddb.V2StorageCell = class
158
159
  tilesLayout: '',
159
160
  mimeType: null,
160
161
  codecs: null,
162
+ thumbnailSprite: null,
161
163
  };
162
164
  }
163
165
  };
@@ -221,6 +221,7 @@ shaka.offline.ManifestConverter = class {
221
221
  fastSwitching: streamDB.fastSwitching,
222
222
  fullMimeTypes: new Set([shaka.util.MimeUtils.getFullType(
223
223
  streamDB.mimeType, streamDB.codecs)]),
224
+ isAudioMuxedInVideo: false,
224
225
  };
225
226
 
226
227
  return stream;
@@ -255,6 +256,9 @@ shaka.offline.ManifestConverter = class {
255
256
  segmentDB.tilesLayout || '');
256
257
  ref.mimeType = segmentDB.mimeType || streamDB.mimeType || '';
257
258
  ref.codecs = segmentDB.codecs || streamDB.codecs || '';
259
+ if (segmentDB.thumbnailSprite) {
260
+ ref.setThumbnailSprite(segmentDB.thumbnailSprite);
261
+ }
258
262
  return ref;
259
263
  }
260
264