shaka-player 4.7.12 → 4.8.0
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/AUTHORS +1 -0
- package/CONTRIBUTORS +1 -0
- package/LICENSE +54 -0
- package/README.md +22 -1
- package/dist/controls.css +1 -1
- package/dist/controls.css.map +1 -1
- package/dist/deps.js +36 -25
- package/dist/locales.js +40 -30
- package/dist/shaka-player.compiled.d.ts +196 -46
- package/dist/shaka-player.compiled.debug.d.ts +196 -46
- package/dist/shaka-player.compiled.debug.externs.js +474 -337
- package/dist/shaka-player.compiled.debug.js +992 -871
- package/dist/shaka-player.compiled.debug.map +4 -4
- package/dist/shaka-player.compiled.externs.js +474 -337
- package/dist/shaka-player.compiled.js +1248 -1174
- package/dist/shaka-player.compiled.map +4 -4
- package/dist/shaka-player.ui.d.ts +259 -49
- package/dist/shaka-player.ui.debug.d.ts +259 -49
- package/dist/shaka-player.ui.debug.externs.js +591 -376
- package/dist/shaka-player.ui.debug.js +1208 -1003
- package/dist/shaka-player.ui.debug.map +4 -4
- package/dist/shaka-player.ui.externs.js +591 -376
- package/dist/shaka-player.ui.js +1533 -1408
- package/dist/shaka-player.ui.map +4 -4
- package/externs/device_sensor_event.js +18 -0
- package/externs/hisense.js +16 -0
- package/externs/playstation.js +31 -0
- package/externs/shaka/abr_manager.js +3 -1
- package/externs/shaka/ads.js +5 -0
- package/externs/shaka/codecs.js +13 -0
- package/externs/shaka/manifest.js +69 -7
- package/externs/shaka/net.js +13 -1
- package/externs/shaka/offline.js +7 -1
- package/externs/shaka/player.js +184 -13
- package/externs/shaka/text.js +19 -0
- package/externs/tizen.js +41 -0
- package/externs/webos.js +19 -0
- package/externs/xbox.js +43 -0
- package/lib/abr/simple_abr_manager.js +9 -1
- package/lib/ads/ad_manager.js +19 -2
- package/lib/ads/client_side_ad_manager.js +5 -3
- package/lib/ads/media_tailor_ad_manager.js +9 -0
- package/lib/cast/cast_receiver.js +0 -14
- package/lib/cast/cast_utils.js +1 -0
- package/lib/cea/mp4_cea_parser.js +6 -1
- package/lib/dash/content_protection.js +97 -53
- package/lib/dash/dash_parser.js +240 -179
- package/lib/dash/mpd_utils.js +72 -65
- package/lib/dash/segment_base.js +35 -22
- package/lib/dash/segment_list.js +39 -31
- package/lib/dash/segment_template.js +47 -23
- package/lib/hls/hls_parser.js +376 -165
- package/lib/media/buffering_observer.js +25 -1
- package/lib/media/drm_engine.js +91 -71
- package/lib/media/manifest_filterer.js +220 -0
- package/lib/media/media_source_engine.js +108 -29
- package/lib/media/playhead.js +3 -3
- package/lib/media/preload_manager.js +827 -0
- package/lib/media/presentation_timeline.js +11 -0
- package/lib/media/segment_index.js +60 -49
- package/lib/media/segment_prefetch.js +140 -43
- package/lib/media/segment_reference.js +31 -8
- package/lib/media/segment_utils.js +208 -25
- package/lib/media/streaming_engine.js +321 -77
- package/lib/mss/content_protection.js +31 -25
- package/lib/mss/mss_parser.js +78 -55
- package/lib/net/networking_engine.js +49 -4
- package/lib/offline/indexeddb/v1_storage_cell.js +2 -0
- package/lib/offline/indexeddb/v2_storage_cell.js +2 -0
- package/lib/offline/manifest_converter.js +10 -3
- package/lib/offline/storage.js +5 -3
- package/lib/player.js +896 -674
- package/lib/polyfill/media_capabilities.js +16 -1
- package/lib/text/simple_text_displayer.js +9 -0
- package/lib/text/stub_text_displayer.js +7 -0
- package/lib/text/text_engine.js +16 -3
- package/lib/text/ttml_text_parser.js +116 -114
- package/lib/text/ui_text_displayer.js +28 -11
- package/lib/text/vtt_text_parser.js +54 -115
- package/lib/transmuxer/opus.js +91 -0
- package/lib/transmuxer/ts_transmuxer.js +115 -0
- package/lib/util/cmcd_manager.js +152 -3
- package/lib/util/dom_utils.js +11 -0
- package/lib/util/error.js +5 -0
- package/lib/util/fake_event.js +2 -0
- package/lib/util/manifest_parser_utils.js +97 -3
- package/lib/util/mime_utils.js +10 -5
- package/lib/util/mp4_box_parsers.js +346 -17
- package/lib/util/mp4_generator.js +23 -0
- package/lib/util/periods.js +24 -37
- package/lib/util/platform.js +161 -9
- package/lib/util/player_configuration.js +61 -3
- package/lib/util/stats.js +16 -0
- package/lib/util/stream_utils.js +350 -277
- package/lib/util/string_utils.js +36 -0
- package/lib/util/tXml.js +814 -0
- package/lib/util/ts_parser.js +50 -0
- package/lib/util/xml_utils.js +10 -338
- package/package.json +2 -2
- package/shaka-player.uncompiled.js +8 -0
- package/ui/controls.js +187 -5
- package/ui/enums.js +2 -0
- package/ui/externs/ui.js +30 -3
- package/ui/gl_matrix/matrix_4x4.js +568 -0
- package/ui/gl_matrix/matrix_quaternion.js +45 -0
- package/ui/less/containers.less +11 -0
- package/ui/locales/en-GB.json +2 -0
- package/ui/locales/en.json +2 -0
- package/ui/locales/es-419.json +2 -0
- package/ui/locales/es.json +2 -0
- package/ui/locales/source.json +8 -0
- package/ui/recenter_vr.js +126 -0
- package/ui/resolution_selection.js +25 -5
- package/ui/statistics_button.js +12 -0
- package/ui/text_selection.js +1 -1
- package/ui/toggle_stereoscopic.js +127 -0
- package/ui/ui.js +74 -38
- package/ui/vr_manager.js +557 -0
- package/ui/vr_utils.js +232 -0
- package/ui/vr_webgl.js +697 -0
package/lib/util/stream_utils.js
CHANGED
|
@@ -263,13 +263,20 @@ shaka.util.StreamUtils = class {
|
|
|
263
263
|
// |video.width| and |video.height| can be undefined, which breaks
|
|
264
264
|
// the math, so make sure they are there first.
|
|
265
265
|
if (video && video.width && video.height) {
|
|
266
|
-
|
|
266
|
+
let videoWidth = video.width;
|
|
267
|
+
let videoHeight = video.height;
|
|
268
|
+
if (videoHeight > videoWidth) {
|
|
269
|
+
// Vertical video.
|
|
270
|
+
[videoWidth, videoHeight] = [videoHeight, videoWidth];
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
if (!inRange(videoWidth,
|
|
267
274
|
restrictions.minWidth,
|
|
268
275
|
Math.min(restrictions.maxWidth, maxHwRes.width))) {
|
|
269
276
|
return false;
|
|
270
277
|
}
|
|
271
278
|
|
|
272
|
-
if (!inRange(
|
|
279
|
+
if (!inRange(videoHeight,
|
|
273
280
|
restrictions.minHeight,
|
|
274
281
|
Math.min(restrictions.maxHeight, maxHwRes.height))) {
|
|
275
282
|
return false;
|
|
@@ -330,10 +337,12 @@ shaka.util.StreamUtils = class {
|
|
|
330
337
|
*
|
|
331
338
|
* @param {shaka.media.DrmEngine} drmEngine
|
|
332
339
|
* @param {shaka.extern.Manifest} manifest
|
|
340
|
+
* @param {!Array<string>=} preferredKeySystems
|
|
333
341
|
*/
|
|
334
|
-
static async filterManifest(drmEngine, manifest) {
|
|
342
|
+
static async filterManifest(drmEngine, manifest, preferredKeySystems = []) {
|
|
335
343
|
await shaka.util.StreamUtils.filterManifestByMediaCapabilities(
|
|
336
|
-
drmEngine, manifest, manifest.offlineSessionIds.length > 0
|
|
344
|
+
drmEngine, manifest, manifest.offlineSessionIds.length > 0,
|
|
345
|
+
preferredKeySystems);
|
|
337
346
|
shaka.util.StreamUtils.filterTextStreams_(manifest);
|
|
338
347
|
await shaka.util.StreamUtils.filterImageStreams_(manifest);
|
|
339
348
|
}
|
|
@@ -346,15 +355,16 @@ shaka.util.StreamUtils = class {
|
|
|
346
355
|
* @param {shaka.media.DrmEngine} drmEngine
|
|
347
356
|
* @param {shaka.extern.Manifest} manifest
|
|
348
357
|
* @param {boolean} usePersistentLicenses
|
|
358
|
+
* @param {!Array<string>} preferredKeySystems
|
|
349
359
|
*/
|
|
350
360
|
static async filterManifestByMediaCapabilities(
|
|
351
|
-
drmEngine, manifest, usePersistentLicenses) {
|
|
361
|
+
drmEngine, manifest, usePersistentLicenses, preferredKeySystems) {
|
|
352
362
|
goog.asserts.assert(navigator.mediaCapabilities,
|
|
353
363
|
'MediaCapabilities should be valid.');
|
|
354
364
|
|
|
355
365
|
await shaka.util.StreamUtils.getDecodingInfosForVariants(
|
|
356
366
|
manifest.variants, usePersistentLicenses, /* srcEquals= */ false,
|
|
357
|
-
|
|
367
|
+
preferredKeySystems);
|
|
358
368
|
|
|
359
369
|
let keySystem = null;
|
|
360
370
|
if (drmEngine) {
|
|
@@ -364,115 +374,122 @@ shaka.util.StreamUtils = class {
|
|
|
364
374
|
}
|
|
365
375
|
}
|
|
366
376
|
|
|
377
|
+
const StreamUtils = shaka.util.StreamUtils;
|
|
378
|
+
|
|
379
|
+
manifest.variants = manifest.variants.filter((variant) => {
|
|
380
|
+
const supported = StreamUtils.checkVariantSupported_(variant, keySystem);
|
|
381
|
+
// Filter out all unsupported variants.
|
|
382
|
+
if (!supported) {
|
|
383
|
+
shaka.log.debug('Dropping variant - not compatible with platform',
|
|
384
|
+
StreamUtils.getVariantSummaryString_(variant));
|
|
385
|
+
}
|
|
386
|
+
return supported;
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
|
|
391
|
+
/**
|
|
392
|
+
* @param {!shaka.extern.Variant} variant
|
|
393
|
+
* @param {?string} keySystem
|
|
394
|
+
* @return {boolean}
|
|
395
|
+
* @private
|
|
396
|
+
*/
|
|
397
|
+
static checkVariantSupported_(variant, keySystem) {
|
|
367
398
|
const ContentType = shaka.util.ManifestParserUtils.ContentType;
|
|
368
399
|
const Capabilities = shaka.media.Capabilities;
|
|
369
400
|
const ManifestParserUtils = shaka.util.ManifestParserUtils;
|
|
370
401
|
const MimeUtils = shaka.util.MimeUtils;
|
|
371
402
|
const StreamUtils = shaka.util.StreamUtils;
|
|
372
|
-
const isXboxOne = shaka.util.Platform.isXboxOne();
|
|
373
403
|
|
|
404
|
+
const isXboxOne = shaka.util.Platform.isXboxOne();
|
|
374
405
|
const isFirefoxAndroid = shaka.util.Platform.isFirefox() &&
|
|
375
406
|
shaka.util.Platform.isAndroid();
|
|
376
407
|
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
const videoHeight = (video && video.height) || 0;
|
|
382
|
-
|
|
383
|
-
// See: https://github.com/shaka-project/shaka-player/issues/3380
|
|
384
|
-
// Note: it makes sense to drop early
|
|
385
|
-
if (isXboxOne && video &&
|
|
386
|
-
(videoWidth > 1920 || videoHeight > 1080) &&
|
|
387
|
-
(video.codecs.includes('avc1.') || video.codecs.includes('avc3.'))
|
|
388
|
-
) {
|
|
389
|
-
shaka.log.debug('Dropping variant - not compatible with platform',
|
|
390
|
-
StreamUtils.getVariantSummaryString_(variant));
|
|
391
|
-
return false;
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
if (video) {
|
|
395
|
-
let videoCodecs = StreamUtils.getCorrectVideoCodecs_(video.codecs);
|
|
396
|
-
// For multiplexed streams. Here we must check the audio of the
|
|
397
|
-
// stream to see if it is compatible.
|
|
398
|
-
if (video.codecs.includes(',')) {
|
|
399
|
-
const allCodecs = video.codecs.split(',');
|
|
400
|
-
|
|
401
|
-
videoCodecs = ManifestParserUtils.guessCodecs(
|
|
402
|
-
ContentType.VIDEO, allCodecs);
|
|
403
|
-
videoCodecs = StreamUtils.getCorrectVideoCodecs_(videoCodecs);
|
|
404
|
-
let audioCodecs = ManifestParserUtils.guessCodecs(
|
|
405
|
-
ContentType.AUDIO, allCodecs);
|
|
406
|
-
audioCodecs = StreamUtils.getCorrectAudioCodecs_(audioCodecs);
|
|
408
|
+
// See: https://github.com/shaka-project/shaka-player/issues/3860
|
|
409
|
+
const video = variant.video;
|
|
410
|
+
const videoWidth = (video && video.width) || 0;
|
|
411
|
+
const videoHeight = (video && video.height) || 0;
|
|
407
412
|
|
|
408
|
-
|
|
409
|
-
|
|
413
|
+
// See: https://github.com/shaka-project/shaka-player/issues/3380
|
|
414
|
+
// Note: it makes sense to drop early
|
|
415
|
+
if (isXboxOne && video && (videoWidth > 1920 || videoHeight > 1080) &&
|
|
416
|
+
(video.codecs.includes('avc1.') || video.codecs.includes('avc3.'))) {
|
|
417
|
+
return false;
|
|
418
|
+
}
|
|
410
419
|
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
420
|
+
if (video) {
|
|
421
|
+
let videoCodecs = StreamUtils.getCorrectVideoCodecs(video.codecs);
|
|
422
|
+
// For multiplexed streams. Here we must check the audio of the
|
|
423
|
+
// stream to see if it is compatible.
|
|
424
|
+
if (video.codecs.includes(',')) {
|
|
425
|
+
const allCodecs = video.codecs.split(',');
|
|
414
426
|
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
427
|
+
videoCodecs = ManifestParserUtils.guessCodecs(
|
|
428
|
+
ContentType.VIDEO, allCodecs);
|
|
429
|
+
videoCodecs = StreamUtils.getCorrectVideoCodecs(videoCodecs);
|
|
430
|
+
let audioCodecs = ManifestParserUtils.guessCodecs(
|
|
431
|
+
ContentType.AUDIO, allCodecs);
|
|
432
|
+
audioCodecs = StreamUtils.getCorrectAudioCodecs(audioCodecs);
|
|
418
433
|
|
|
419
|
-
const
|
|
420
|
-
video.mimeType,
|
|
434
|
+
const audioFullType = MimeUtils.getFullOrConvertedType(
|
|
435
|
+
video.mimeType, audioCodecs, ContentType.AUDIO);
|
|
421
436
|
|
|
422
|
-
if (!Capabilities.isTypeSupported(
|
|
437
|
+
if (!Capabilities.isTypeSupported(audioFullType)) {
|
|
423
438
|
return false;
|
|
424
439
|
}
|
|
425
440
|
|
|
426
441
|
// Update the codec string with the (possibly) converted codecs.
|
|
427
|
-
|
|
442
|
+
videoCodecs = [videoCodecs, audioCodecs].join(',');
|
|
428
443
|
}
|
|
429
444
|
|
|
430
|
-
const
|
|
445
|
+
const fullType = MimeUtils.getFullOrConvertedType(
|
|
446
|
+
video.mimeType, videoCodecs, ContentType.VIDEO);
|
|
431
447
|
|
|
432
|
-
|
|
433
|
-
// It seems that Firefox Android reports that it supports
|
|
434
|
-
// Opus + Widevine, but it is not actually supported.
|
|
435
|
-
// It makes sense to drop early.
|
|
436
|
-
if (isFirefoxAndroid && audio && audio.encrypted &&
|
|
437
|
-
audio.codecs.toLowerCase().includes('opus')) {
|
|
438
|
-
shaka.log.debug('Dropping variant - not compatible with platform',
|
|
439
|
-
StreamUtils.getVariantSummaryString_(variant));
|
|
448
|
+
if (!Capabilities.isTypeSupported(fullType)) {
|
|
440
449
|
return false;
|
|
441
450
|
}
|
|
442
451
|
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
audio.mimeType, codecs, ContentType.AUDIO);
|
|
452
|
+
// Update the codec string with the (possibly) converted codecs.
|
|
453
|
+
video.codecs = videoCodecs;
|
|
454
|
+
}
|
|
447
455
|
|
|
448
|
-
|
|
449
|
-
return false;
|
|
450
|
-
}
|
|
456
|
+
const audio = variant.audio;
|
|
451
457
|
|
|
452
|
-
|
|
453
|
-
|
|
458
|
+
// See: https://github.com/shaka-project/shaka-player/issues/6111
|
|
459
|
+
// It seems that Firefox Android reports that it supports
|
|
460
|
+
// Opus + Widevine, but it is not actually supported.
|
|
461
|
+
// It makes sense to drop early.
|
|
462
|
+
if (isFirefoxAndroid && audio && audio.encrypted &&
|
|
463
|
+
audio.codecs.toLowerCase().includes('opus')) {
|
|
464
|
+
return false;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
if (audio) {
|
|
468
|
+
const codecs = StreamUtils.getCorrectAudioCodecs(audio.codecs);
|
|
469
|
+
const fullType = MimeUtils.getFullOrConvertedType(
|
|
470
|
+
audio.mimeType, codecs, ContentType.AUDIO);
|
|
471
|
+
|
|
472
|
+
if (!Capabilities.isTypeSupported(fullType)) {
|
|
473
|
+
return false;
|
|
454
474
|
}
|
|
455
475
|
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
476
|
+
// Update the codec string with the (possibly) converted codecs.
|
|
477
|
+
audio.codecs = codecs;
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
return variant.decodingInfos.some((decodingInfo) => {
|
|
481
|
+
if (!decodingInfo.supported) {
|
|
482
|
+
return false;
|
|
483
|
+
}
|
|
484
|
+
if (keySystem) {
|
|
485
|
+
const keySystemAccess = decodingInfo.keySystemAccess;
|
|
486
|
+
if (keySystemAccess) {
|
|
487
|
+
if (keySystemAccess.keySystem != keySystem) {
|
|
488
|
+
return false;
|
|
466
489
|
}
|
|
467
490
|
}
|
|
468
|
-
return true;
|
|
469
|
-
});
|
|
470
|
-
// Filter out all unsupported variants.
|
|
471
|
-
if (!supported) {
|
|
472
|
-
shaka.log.debug('Dropping variant - not compatible with platform',
|
|
473
|
-
StreamUtils.getVariantSummaryString_(variant));
|
|
474
491
|
}
|
|
475
|
-
return
|
|
492
|
+
return true;
|
|
476
493
|
});
|
|
477
494
|
}
|
|
478
495
|
|
|
@@ -516,51 +533,69 @@ shaka.util.StreamUtils = class {
|
|
|
516
533
|
* and assigns it to the given variant.
|
|
517
534
|
* If that query has been done before, instead return a cached result.
|
|
518
535
|
* @param {!shaka.extern.Variant} variant
|
|
519
|
-
* @param {!MediaDecodingConfiguration}
|
|
536
|
+
* @param {!Array.<!MediaDecodingConfiguration>} decodingConfigs
|
|
520
537
|
* @private
|
|
521
538
|
*/
|
|
522
|
-
static async getDecodingInfosForVariant_(variant,
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
// overall variant compatibility.
|
|
539
|
-
const results = await shaka.util.StreamUtils
|
|
540
|
-
.checkEachDecodingConfigCombination_(decodingConfig);
|
|
541
|
-
if (results && results.length) {
|
|
542
|
-
/** @type {?MediaCapabilitiesDecodingInfo} */
|
|
543
|
-
let overallResult = null;
|
|
544
|
-
for (const result of results) {
|
|
545
|
-
if (!overallResult) {
|
|
546
|
-
overallResult = result;
|
|
547
|
-
} else {
|
|
548
|
-
overallResult.supported =
|
|
549
|
-
overallResult.supported && result.supported;
|
|
550
|
-
overallResult.powerEfficient =
|
|
551
|
-
overallResult.powerEfficient && result.powerEfficient;
|
|
552
|
-
overallResult.smooth = overallResult.smooth && result.smooth;
|
|
553
|
-
if (!result.keySystemAccess) {
|
|
554
|
-
overallResult.keySystemAccess = null;
|
|
555
|
-
}
|
|
556
|
-
}
|
|
557
|
-
}
|
|
558
|
-
if (overallResult) {
|
|
559
|
-
cache[cacheKey] = overallResult;
|
|
560
|
-
variant.decodingInfos.push(overallResult);
|
|
539
|
+
static async getDecodingInfosForVariant_(variant, decodingConfigs) {
|
|
540
|
+
/**
|
|
541
|
+
* @param {?MediaCapabilitiesDecodingInfo} a
|
|
542
|
+
* @param {!MediaCapabilitiesDecodingInfo} b
|
|
543
|
+
* @return {!MediaCapabilitiesDecodingInfo}
|
|
544
|
+
*/
|
|
545
|
+
const merge = (a, b) => {
|
|
546
|
+
if (!a) {
|
|
547
|
+
return b;
|
|
548
|
+
} else {
|
|
549
|
+
const res = shaka.util.ObjectUtils.cloneObject(a);
|
|
550
|
+
res.supported = a.supported && b.supported;
|
|
551
|
+
res.powerEfficient = a.powerEfficient && b.powerEfficient;
|
|
552
|
+
res.smooth = a.smooth && b.smooth;
|
|
553
|
+
if (b.keySystemAccess && !res.keySystemAccess) {
|
|
554
|
+
res.keySystemAccess = b.keySystemAccess;
|
|
561
555
|
}
|
|
556
|
+
return res;
|
|
557
|
+
}
|
|
558
|
+
};
|
|
559
|
+
|
|
560
|
+
const StreamUtils = shaka.util.StreamUtils;
|
|
561
|
+
/** @type {?MediaCapabilitiesDecodingInfo} */
|
|
562
|
+
let finalResult = null;
|
|
563
|
+
const promises = [];
|
|
564
|
+
for (const decodingConfig of decodingConfigs) {
|
|
565
|
+
const cacheKey =
|
|
566
|
+
StreamUtils.alphabeticalKeyOrderStringify_(decodingConfig);
|
|
567
|
+
|
|
568
|
+
const cache = StreamUtils.decodingConfigCache_;
|
|
569
|
+
if (cache[cacheKey]) {
|
|
570
|
+
shaka.log.v2('Using cached results of mediaCapabilities.decodingInfo',
|
|
571
|
+
'for key', cacheKey);
|
|
572
|
+
finalResult = merge(finalResult, cache[cacheKey]);
|
|
573
|
+
} else {
|
|
574
|
+
// Do a final pass-over of the decoding config: if a given stream has
|
|
575
|
+
// multiple codecs, that suggests that it switches between those codecs
|
|
576
|
+
// at points of the go-through.
|
|
577
|
+
// mediaCapabilities by itself will report "not supported" when you
|
|
578
|
+
// put in multiple different codecs, so each has to be checked
|
|
579
|
+
// individually. So check each and take the worst result, to determine
|
|
580
|
+
// overall variant compatibility.
|
|
581
|
+
promises.push(StreamUtils
|
|
582
|
+
.checkEachDecodingConfigCombination_(decodingConfig).then((res) => {
|
|
583
|
+
/** @type {?MediaCapabilitiesDecodingInfo} */
|
|
584
|
+
let acc = null;
|
|
585
|
+
for (const result of (res || [])) {
|
|
586
|
+
acc = merge(acc, result);
|
|
587
|
+
}
|
|
588
|
+
if (acc) {
|
|
589
|
+
cache[cacheKey] = acc;
|
|
590
|
+
finalResult = merge(finalResult, acc);
|
|
591
|
+
}
|
|
592
|
+
}));
|
|
562
593
|
}
|
|
563
594
|
}
|
|
595
|
+
await Promise.all(promises);
|
|
596
|
+
if (finalResult) {
|
|
597
|
+
variant.decodingInfos.push(finalResult);
|
|
598
|
+
}
|
|
564
599
|
}
|
|
565
600
|
|
|
566
601
|
/**
|
|
@@ -634,10 +669,12 @@ shaka.util.StreamUtils = class {
|
|
|
634
669
|
for (const preferredKeySystem of preferredKeySystems) {
|
|
635
670
|
let keySystemSatisfied = false;
|
|
636
671
|
for (const variant of variants) {
|
|
637
|
-
/** @type {!Array.<!MediaDecodingConfiguration
|
|
672
|
+
/** @type {!Array.<!Array.<!MediaDecodingConfiguration>>} */
|
|
638
673
|
const decodingConfigs = shaka.util.StreamUtils.getDecodingConfigs_(
|
|
639
674
|
variant, usePersistentLicenses, srcEquals)
|
|
640
|
-
.filter((
|
|
675
|
+
.filter((configs) => {
|
|
676
|
+
// All configs in a batch will have the same keySystem.
|
|
677
|
+
const config = configs[0];
|
|
641
678
|
const keySystem = config.keySystemConfiguration &&
|
|
642
679
|
config.keySystemConfiguration.keySystem;
|
|
643
680
|
return keySystem === preferredKeySystem;
|
|
@@ -646,10 +683,10 @@ shaka.util.StreamUtils = class {
|
|
|
646
683
|
// The reason we are performing this await in a loop rather than
|
|
647
684
|
// batching into a `promise.all` is performance related.
|
|
648
685
|
// https://github.com/shaka-project/shaka-player/pull/4708#discussion_r1022581178
|
|
649
|
-
for (const
|
|
686
|
+
for (const configs of decodingConfigs) {
|
|
650
687
|
// eslint-disable-next-line no-await-in-loop
|
|
651
688
|
await shaka.util.StreamUtils.getDecodingInfosForVariant_(
|
|
652
|
-
variant,
|
|
689
|
+
variant, configs);
|
|
653
690
|
}
|
|
654
691
|
if (variant.decodingInfos.length) {
|
|
655
692
|
keySystemSatisfied = true;
|
|
@@ -662,10 +699,12 @@ shaka.util.StreamUtils = class {
|
|
|
662
699
|
} // for (const preferredKeySystem of preferredKeySystems)
|
|
663
700
|
|
|
664
701
|
for (const variant of variants) {
|
|
665
|
-
/** @type {!Array.<!MediaDecodingConfiguration
|
|
702
|
+
/** @type {!Array.<!Array.<!MediaDecodingConfiguration>>} */
|
|
666
703
|
const decodingConfigs = shaka.util.StreamUtils.getDecodingConfigs_(
|
|
667
704
|
variant, usePersistentLicenses, srcEquals)
|
|
668
|
-
.filter((
|
|
705
|
+
.filter((configs) => {
|
|
706
|
+
// All configs in a batch will have the same keySystem.
|
|
707
|
+
const config = configs[0];
|
|
669
708
|
const keySystem = config.keySystemConfiguration &&
|
|
670
709
|
config.keySystemConfiguration.keySystem;
|
|
671
710
|
// Avoid checking preferred systems twice.
|
|
@@ -675,22 +714,24 @@ shaka.util.StreamUtils = class {
|
|
|
675
714
|
// The reason we are performing this await in a loop rather than
|
|
676
715
|
// batching into a `promise.all` is performance related.
|
|
677
716
|
// https://github.com/shaka-project/shaka-player/pull/4708#discussion_r1022581178
|
|
678
|
-
for (const
|
|
717
|
+
for (const configs of decodingConfigs) {
|
|
679
718
|
// eslint-disable-next-line no-await-in-loop
|
|
680
719
|
await shaka.util.StreamUtils.getDecodingInfosForVariant_(
|
|
681
|
-
variant,
|
|
720
|
+
variant, configs);
|
|
682
721
|
}
|
|
683
722
|
}
|
|
684
723
|
}
|
|
685
724
|
|
|
686
725
|
|
|
687
726
|
/**
|
|
688
|
-
* Generate a MediaDecodingConfiguration
|
|
689
|
-
* results for each variant.
|
|
727
|
+
* Generate a batch of MediaDecodingConfiguration objects to get the
|
|
728
|
+
* decodingInfo results for each variant.
|
|
729
|
+
* Each batch shares the same DRM information, and represents the various
|
|
730
|
+
* fullMimeType combinations of the streams.
|
|
690
731
|
* @param {!shaka.extern.Variant} variant
|
|
691
732
|
* @param {boolean} usePersistentLicenses
|
|
692
733
|
* @param {boolean} srcEquals
|
|
693
|
-
* @return {!Array.<!MediaDecodingConfiguration
|
|
734
|
+
* @return {!Array.<!Array.<!MediaDecodingConfiguration>>}
|
|
694
735
|
* @private
|
|
695
736
|
*/
|
|
696
737
|
static getDecodingConfigs_(variant, usePersistentLicenses, srcEquals) {
|
|
@@ -702,87 +743,118 @@ shaka.util.StreamUtils = class {
|
|
|
702
743
|
const MimeUtils = shaka.util.MimeUtils;
|
|
703
744
|
const StreamUtils = shaka.util.StreamUtils;
|
|
704
745
|
|
|
705
|
-
|
|
706
|
-
const
|
|
707
|
-
type: srcEquals ? 'file' : 'media-source',
|
|
708
|
-
};
|
|
709
|
-
|
|
746
|
+
const videoConfigs = [];
|
|
747
|
+
const audioConfigs = [];
|
|
710
748
|
if (video) {
|
|
711
|
-
|
|
749
|
+
for (const fullMimeType of video.fullMimeTypes) {
|
|
750
|
+
let videoCodecs = MimeUtils.getCodecs(fullMimeType);
|
|
712
751
|
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
752
|
+
// For multiplexed streams with audio+video codecs, the config should
|
|
753
|
+
// have AudioConfiguration and VideoConfiguration.
|
|
754
|
+
// We ignore the multiplexed audio when there is normal audio also.
|
|
755
|
+
if (videoCodecs.includes(',') && !audio) {
|
|
756
|
+
const allCodecs = videoCodecs.split(',');
|
|
717
757
|
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
videoCodecs = StreamUtils.getCorrectVideoCodecs_(videoCodecs);
|
|
758
|
+
videoCodecs = ManifestParserUtils.guessCodecs(
|
|
759
|
+
ContentType.VIDEO, allCodecs);
|
|
721
760
|
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
761
|
+
let audioCodecs = ManifestParserUtils.guessCodecs(
|
|
762
|
+
ContentType.AUDIO, allCodecs);
|
|
763
|
+
audioCodecs = StreamUtils.getCorrectAudioCodecs(audioCodecs);
|
|
725
764
|
|
|
726
|
-
|
|
727
|
-
|
|
765
|
+
const audioFullType = MimeUtils.getFullOrConvertedType(
|
|
766
|
+
MimeUtils.getBasicType(fullMimeType), audioCodecs,
|
|
767
|
+
ContentType.AUDIO);
|
|
768
|
+
|
|
769
|
+
audioConfigs.push({
|
|
770
|
+
contentType: audioFullType,
|
|
771
|
+
channels: 2,
|
|
772
|
+
bitrate: variant.bandwidth || 1,
|
|
773
|
+
samplerate: 1,
|
|
774
|
+
spatialRendering: false,
|
|
775
|
+
});
|
|
776
|
+
}
|
|
728
777
|
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
778
|
+
videoCodecs = StreamUtils.getCorrectVideoCodecs(videoCodecs);
|
|
779
|
+
const fullType = MimeUtils.getFullOrConvertedType(
|
|
780
|
+
MimeUtils.getBasicType(fullMimeType), videoCodecs,
|
|
781
|
+
ContentType.VIDEO);
|
|
782
|
+
|
|
783
|
+
// VideoConfiguration
|
|
784
|
+
const videoConfig = {
|
|
785
|
+
contentType: fullType,
|
|
786
|
+
|
|
787
|
+
// NOTE: Some decoders strictly check the width and height fields and
|
|
788
|
+
// won't decode smaller than 64x64. So if we don't have this info (as
|
|
789
|
+
// is the case in some of our simpler tests), assume a 64x64
|
|
790
|
+
// resolution to fill in this required field for MediaCapabilities.
|
|
791
|
+
//
|
|
792
|
+
// This became an issue specifically on Firefox on M1 Macs.
|
|
793
|
+
width: video.width || 64,
|
|
794
|
+
height: video.height || 64,
|
|
795
|
+
|
|
796
|
+
bitrate: video.bandwidth || variant.bandwidth || 1,
|
|
797
|
+
// framerate must be greater than 0, otherwise the config is invalid.
|
|
798
|
+
framerate: video.frameRate || 1,
|
|
735
799
|
};
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
// is the case in some of our simpler tests), assume a 64x64 resolution
|
|
749
|
-
// to fill in this required field for MediaCapabilities.
|
|
750
|
-
//
|
|
751
|
-
// This became an issue specifically on Firefox on M1 Macs.
|
|
752
|
-
width: video.width || 64,
|
|
753
|
-
height: video.height || 64,
|
|
754
|
-
|
|
755
|
-
bitrate: video.bandwidth || variant.bandwidth || 1,
|
|
756
|
-
// framerate must be greater than 0, otherwise the config is invalid.
|
|
757
|
-
framerate: video.frameRate || 1,
|
|
758
|
-
};
|
|
759
|
-
if (video.hdr) {
|
|
760
|
-
switch (video.hdr) {
|
|
761
|
-
case 'SDR':
|
|
762
|
-
mediaDecodingConfig.video.transferFunction = 'srgb';
|
|
763
|
-
break;
|
|
764
|
-
case 'PQ':
|
|
765
|
-
mediaDecodingConfig.video.transferFunction = 'pq';
|
|
766
|
-
break;
|
|
767
|
-
case 'HLG':
|
|
768
|
-
mediaDecodingConfig.video.transferFunction = 'hlg';
|
|
769
|
-
break;
|
|
800
|
+
if (video.hdr) {
|
|
801
|
+
switch (video.hdr) {
|
|
802
|
+
case 'SDR':
|
|
803
|
+
videoConfig.transferFunction = 'srgb';
|
|
804
|
+
break;
|
|
805
|
+
case 'PQ':
|
|
806
|
+
videoConfig.transferFunction = 'pq';
|
|
807
|
+
break;
|
|
808
|
+
case 'HLG':
|
|
809
|
+
videoConfig.transferFunction = 'hlg';
|
|
810
|
+
break;
|
|
811
|
+
}
|
|
770
812
|
}
|
|
813
|
+
videoConfigs.push(videoConfig);
|
|
771
814
|
}
|
|
772
815
|
}
|
|
773
816
|
if (audio) {
|
|
774
|
-
const
|
|
775
|
-
|
|
776
|
-
|
|
817
|
+
for (const fullMimeType of audio.fullMimeTypes) {
|
|
818
|
+
const codecs = StreamUtils.getCorrectAudioCodecs(MimeUtils.getCodecs(
|
|
819
|
+
fullMimeType));
|
|
820
|
+
const fullType = MimeUtils.getFullOrConvertedType(
|
|
821
|
+
MimeUtils.getBasicType(fullMimeType), codecs, ContentType.AUDIO);
|
|
822
|
+
|
|
823
|
+
// AudioConfiguration
|
|
824
|
+
audioConfigs.push({
|
|
825
|
+
contentType: fullType,
|
|
826
|
+
channels: audio.channelsCount || 2,
|
|
827
|
+
bitrate: audio.bandwidth || variant.bandwidth || 1,
|
|
828
|
+
samplerate: audio.audioSamplingRate || 1,
|
|
829
|
+
spatialRendering: audio.spatialAudio,
|
|
830
|
+
});
|
|
831
|
+
}
|
|
832
|
+
}
|
|
777
833
|
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
834
|
+
// Generate each combination of video and audio config as a separate
|
|
835
|
+
// MediaDecodingConfiguration, inside the main "batch".
|
|
836
|
+
/** @type {!Array.<!MediaDecodingConfiguration>} */
|
|
837
|
+
const mediaDecodingConfigBatch = [];
|
|
838
|
+
if (videoConfigs.length == 0) {
|
|
839
|
+
videoConfigs.push(null);
|
|
840
|
+
}
|
|
841
|
+
if (audioConfigs.length == 0) {
|
|
842
|
+
audioConfigs.push(null);
|
|
843
|
+
}
|
|
844
|
+
for (const videoConfig of videoConfigs) {
|
|
845
|
+
for (const audioConfig of audioConfigs) {
|
|
846
|
+
/** @type {!MediaDecodingConfiguration} */
|
|
847
|
+
const mediaDecodingConfig = {
|
|
848
|
+
type: srcEquals ? 'file' : 'media-source',
|
|
849
|
+
};
|
|
850
|
+
if (videoConfig) {
|
|
851
|
+
mediaDecodingConfig.video = videoConfig;
|
|
852
|
+
}
|
|
853
|
+
if (audioConfig) {
|
|
854
|
+
mediaDecodingConfig.audio = audioConfig;
|
|
855
|
+
}
|
|
856
|
+
mediaDecodingConfigBatch.push(mediaDecodingConfig);
|
|
857
|
+
}
|
|
786
858
|
}
|
|
787
859
|
|
|
788
860
|
const videoDrmInfos = variant.video ? variant.video.drmInfos : [];
|
|
@@ -791,7 +863,7 @@ shaka.util.StreamUtils = class {
|
|
|
791
863
|
|
|
792
864
|
// Return a list containing the mediaDecodingConfig for unencrypted variant.
|
|
793
865
|
if (!allDrmInfos.length) {
|
|
794
|
-
return [
|
|
866
|
+
return [mediaDecodingConfigBatch];
|
|
795
867
|
}
|
|
796
868
|
|
|
797
869
|
// A list of MediaDecodingConfiguration objects created for the variant.
|
|
@@ -813,83 +885,87 @@ shaka.util.StreamUtils = class {
|
|
|
813
885
|
usePersistentLicenses ? ['persistent-license'] : ['temporary'];
|
|
814
886
|
|
|
815
887
|
for (const keySystem of drmInfoByKeySystems.keys()) {
|
|
816
|
-
|
|
817
|
-
const
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
initDataTypes
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
888
|
+
const modifiedMediaDecodingConfigBatch = [];
|
|
889
|
+
for (const base of mediaDecodingConfigBatch) {
|
|
890
|
+
// Create a copy of the mediaDecodingConfig.
|
|
891
|
+
const config = /** @type {!MediaDecodingConfiguration} */
|
|
892
|
+
(Object.assign({}, base));
|
|
893
|
+
|
|
894
|
+
const drmInfos = drmInfoByKeySystems.get(keySystem);
|
|
895
|
+
|
|
896
|
+
/** @type {!MediaCapabilitiesKeySystemConfiguration} */
|
|
897
|
+
const keySystemConfig = {
|
|
898
|
+
keySystem: keySystem,
|
|
899
|
+
initDataType: 'cenc',
|
|
900
|
+
persistentState: persistentState,
|
|
901
|
+
distinctiveIdentifier: 'optional',
|
|
902
|
+
sessionTypes: sessionTypes,
|
|
903
|
+
};
|
|
904
|
+
|
|
905
|
+
for (const info of drmInfos) {
|
|
906
|
+
if (info.initData && info.initData.length) {
|
|
907
|
+
const initDataTypes = new Set();
|
|
908
|
+
for (const initData of info.initData) {
|
|
909
|
+
initDataTypes.add(initData.initDataType);
|
|
910
|
+
}
|
|
911
|
+
if (initDataTypes.size > 1) {
|
|
912
|
+
shaka.log.v2('DrmInfo contains more than one initDataType,',
|
|
913
|
+
'and we use the initDataType of the first initData.',
|
|
914
|
+
info);
|
|
915
|
+
}
|
|
916
|
+
keySystemConfig.initDataType = info.initData[0].initDataType;
|
|
841
917
|
}
|
|
842
|
-
keySystemConfig.initDataType = info.initData[0].initDataType;
|
|
843
|
-
}
|
|
844
918
|
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
919
|
+
if (info.distinctiveIdentifierRequired) {
|
|
920
|
+
keySystemConfig.distinctiveIdentifier = 'required';
|
|
921
|
+
}
|
|
922
|
+
if (info.persistentStateRequired) {
|
|
923
|
+
keySystemConfig.persistentState = 'required';
|
|
924
|
+
}
|
|
925
|
+
if (info.sessionType) {
|
|
926
|
+
keySystemConfig.sessionTypes = [info.sessionType];
|
|
927
|
+
}
|
|
854
928
|
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
929
|
+
if (audio) {
|
|
930
|
+
// See: https://github.com/shaka-project/shaka-player/issues/4659
|
|
931
|
+
if (info.audioRobustness != '') {
|
|
932
|
+
if (!keySystemConfig.audio) {
|
|
933
|
+
// KeySystemTrackConfiguration
|
|
934
|
+
keySystemConfig.audio = {
|
|
935
|
+
robustness: info.audioRobustness,
|
|
936
|
+
};
|
|
937
|
+
} else {
|
|
938
|
+
keySystemConfig.audio.robustness =
|
|
939
|
+
keySystemConfig.audio.robustness || info.audioRobustness;
|
|
940
|
+
}
|
|
941
|
+
} else if (!keySystemConfig.audio) {
|
|
859
942
|
// KeySystemTrackConfiguration
|
|
860
|
-
keySystemConfig.audio = {
|
|
861
|
-
robustness: info.audioRobustness,
|
|
862
|
-
};
|
|
863
|
-
} else {
|
|
864
|
-
keySystemConfig.audio.robustness =
|
|
865
|
-
keySystemConfig.audio.robustness || info.audioRobustness;
|
|
943
|
+
keySystemConfig.audio = {};
|
|
866
944
|
}
|
|
867
|
-
} else if (!keySystemConfig.audio) {
|
|
868
|
-
// KeySystemTrackConfiguration
|
|
869
|
-
keySystemConfig.audio = {};
|
|
870
945
|
}
|
|
871
|
-
}
|
|
872
946
|
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
947
|
+
if (video) {
|
|
948
|
+
// See: https://github.com/shaka-project/shaka-player/issues/4659
|
|
949
|
+
if (info.videoRobustness != '') {
|
|
950
|
+
if (!keySystemConfig.video) {
|
|
951
|
+
// KeySystemTrackConfiguration
|
|
952
|
+
keySystemConfig.video = {
|
|
953
|
+
robustness: info.videoRobustness,
|
|
954
|
+
};
|
|
955
|
+
} else {
|
|
956
|
+
keySystemConfig.video.robustness =
|
|
957
|
+
keySystemConfig.video.robustness || info.videoRobustness;
|
|
958
|
+
}
|
|
959
|
+
} else if (!keySystemConfig.video) {
|
|
877
960
|
// KeySystemTrackConfiguration
|
|
878
|
-
keySystemConfig.video = {
|
|
879
|
-
robustness: info.videoRobustness,
|
|
880
|
-
};
|
|
881
|
-
} else {
|
|
882
|
-
keySystemConfig.video.robustness =
|
|
883
|
-
keySystemConfig.video.robustness || info.videoRobustness;
|
|
961
|
+
keySystemConfig.video = {};
|
|
884
962
|
}
|
|
885
|
-
} else if (!keySystemConfig.video) {
|
|
886
|
-
// KeySystemTrackConfiguration
|
|
887
|
-
keySystemConfig.video = {};
|
|
888
963
|
}
|
|
889
964
|
}
|
|
965
|
+
config.keySystemConfiguration = keySystemConfig;
|
|
966
|
+
modifiedMediaDecodingConfigBatch.push(config);
|
|
890
967
|
}
|
|
891
|
-
|
|
892
|
-
configs.push(config);
|
|
968
|
+
configs.push(modifiedMediaDecodingConfigBatch);
|
|
893
969
|
}
|
|
894
970
|
return configs;
|
|
895
971
|
}
|
|
@@ -900,9 +976,8 @@ shaka.util.StreamUtils = class {
|
|
|
900
976
|
* for MediaSource.isTypeSupported.
|
|
901
977
|
* @param {string} codecs
|
|
902
978
|
* @return {string}
|
|
903
|
-
* @private
|
|
904
979
|
*/
|
|
905
|
-
static
|
|
980
|
+
static getCorrectAudioCodecs(codecs) {
|
|
906
981
|
// According to RFC 6381 section 3.3, 'fLaC' is actually the correct
|
|
907
982
|
// codec string. We still need to map it to 'flac', as some browsers
|
|
908
983
|
// currently don't support 'fLaC', while 'flac' is supported by most
|
|
@@ -926,9 +1001,8 @@ shaka.util.StreamUtils = class {
|
|
|
926
1001
|
* for MediaSource.isTypeSupported.
|
|
927
1002
|
* @param {string} codec
|
|
928
1003
|
* @return {string}
|
|
929
|
-
* @private
|
|
930
1004
|
*/
|
|
931
|
-
static
|
|
1005
|
+
static getCorrectVideoCodecs(codec) {
|
|
932
1006
|
if (codec.includes('avc1')) {
|
|
933
1007
|
// Convert avc1 codec string from RFC-4281 to RFC-6381 for
|
|
934
1008
|
// MediaSource.isTypeSupported
|
|
@@ -1390,8 +1464,6 @@ shaka.util.StreamUtils = class {
|
|
|
1390
1464
|
* @return {shaka.extern.Track}
|
|
1391
1465
|
*/
|
|
1392
1466
|
static html5TextTrackToTrack(textTrack) {
|
|
1393
|
-
const CLOSED_CAPTION_MIMETYPE =
|
|
1394
|
-
shaka.util.MimeUtils.CEA608_CLOSED_CAPTION_MIMETYPE;
|
|
1395
1467
|
const StreamUtils = shaka.util.StreamUtils;
|
|
1396
1468
|
|
|
1397
1469
|
/** @type {shaka.extern.Track} */
|
|
@@ -1400,7 +1472,8 @@ shaka.util.StreamUtils = class {
|
|
|
1400
1472
|
track.type = 'text';
|
|
1401
1473
|
track.originalTextId = textTrack.id;
|
|
1402
1474
|
if (textTrack.kind == 'captions') {
|
|
1403
|
-
|
|
1475
|
+
// See: https://github.com/shaka-project/shaka-player/issues/6233
|
|
1476
|
+
track.mimeType = 'unknown';
|
|
1404
1477
|
}
|
|
1405
1478
|
if (textTrack.kind == 'subtitles') {
|
|
1406
1479
|
track.mimeType = 'text/vtt';
|