hls.js 1.6.6-0.canary.11351 → 1.6.6-0.canary.11353

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.
@@ -523,7 +523,7 @@ function enableLogs(debugConfig, context, id) {
523
523
  // Some browsers don't allow to use bind on console object anyway
524
524
  // fallback to default if needed
525
525
  try {
526
- newLogger.log(`Debug logs enabled for "${context}" in hls.js version ${"1.6.6-0.canary.11351"}`);
526
+ newLogger.log(`Debug logs enabled for "${context}" in hls.js version ${"1.6.6-0.canary.11353"}`);
527
527
  } catch (e) {
528
528
  /* log fn threw an exception. All logger methods are no-ops. */
529
529
  return createLogger();
@@ -560,6 +560,22 @@ function requireEmptyEs() {
560
560
  var emptyEsExports = requireEmptyEs();
561
561
  var Cues = /*@__PURE__*/getDefaultExportFromCjs(emptyEsExports);
562
562
 
563
+ function getMediaSource(preferManagedMediaSource = true) {
564
+ if (typeof self === 'undefined') return undefined;
565
+ const mms = (preferManagedMediaSource || !self.MediaSource) && self.ManagedMediaSource;
566
+ return mms || self.MediaSource || self.WebKitMediaSource;
567
+ }
568
+ function isManagedMediaSource(source) {
569
+ return typeof self !== 'undefined' && source === self.ManagedMediaSource;
570
+ }
571
+ function isCompatibleTrackChange(currentTracks, requiredTracks) {
572
+ const trackNames = Object.keys(currentTracks);
573
+ const requiredTrackNames = Object.keys(requiredTracks);
574
+ const trackCount = trackNames.length;
575
+ const requiredTrackCount = requiredTrackNames.length;
576
+ return !trackCount || !requiredTrackCount || trackCount === requiredTrackCount && !trackNames.some(name => requiredTrackNames.indexOf(name) === -1);
577
+ }
578
+
563
579
  // http://stackoverflow.com/questions/8936984/uint8array-to-string-in-javascript/22373197
564
580
  // http://www.onicos.com/staff/iz/amuse/javascript/expert/utf.txt
565
581
  /* utf.js - UTF-8 <=> UTF-16 convertion
@@ -2252,22 +2268,6 @@ function parseEmsg(data) {
2252
2268
  };
2253
2269
  }
2254
2270
 
2255
- function getMediaSource(preferManagedMediaSource = true) {
2256
- if (typeof self === 'undefined') return undefined;
2257
- const mms = (preferManagedMediaSource || !self.MediaSource) && self.ManagedMediaSource;
2258
- return mms || self.MediaSource || self.WebKitMediaSource;
2259
- }
2260
- function isManagedMediaSource(source) {
2261
- return typeof self !== 'undefined' && source === self.ManagedMediaSource;
2262
- }
2263
- function isCompatibleTrackChange(currentTracks, requiredTracks) {
2264
- const trackNames = Object.keys(currentTracks);
2265
- const requiredTrackNames = Object.keys(requiredTracks);
2266
- const trackCount = trackNames.length;
2267
- const requiredTrackCount = requiredTrackNames.length;
2268
- return !trackCount || !requiredTrackCount || trackCount === requiredTrackCount && !trackNames.some(name => requiredTrackNames.indexOf(name) === -1);
2269
- }
2270
-
2271
2271
  const userAgentHevcSupportIsInaccurate = () => {
2272
2272
  return /\(Windows.+Firefox\//i.test(navigator.userAgent);
2273
2273
  };
@@ -2958,6 +2958,7 @@ class AbrController extends Logger {
2958
2958
  this.partCurrent = null;
2959
2959
  this.bitrateTestDelay = 0;
2960
2960
  this.rebufferNotice = -1;
2961
+ this.supportedCache = {};
2961
2962
  this.bwEstimator = void 0;
2962
2963
  /*
2963
2964
  This method monitors the download rate of the current fragment, and will downswitch if that fragment will not load
@@ -3168,13 +3169,14 @@ class AbrController extends Logger {
3168
3169
  this.unregisterListeners();
3169
3170
  this.clearTimer();
3170
3171
  // @ts-ignore
3171
- this.hls = this._abandonRulesCheck = null;
3172
+ this.hls = this._abandonRulesCheck = this.supportedCache = null;
3172
3173
  this.fragCurrent = this.partCurrent = null;
3173
3174
  }
3174
3175
  onManifestLoading(event, data) {
3175
3176
  this.lastLoadedFragLevel = -1;
3176
3177
  this.firstSelection = -1;
3177
3178
  this.lastLevelLoadSec = 0;
3179
+ this.supportedCache = {};
3178
3180
  this.fragCurrent = this.partCurrent = null;
3179
3181
  this.onLevelsUpdated();
3180
3182
  this.clearTimer();
@@ -3535,7 +3537,7 @@ class AbrController extends Logger {
3535
3537
  const ttfbEstimateSec = this.bwEstimator.getEstimateTTFB() / 1000;
3536
3538
  const levelsSkipped = [];
3537
3539
  for (let i = maxAutoLevel; i >= minAutoLevel; i--) {
3538
- var _levelInfo$supportedR;
3540
+ var _levelInfo$supportedR, _levelInfo$supportedR2;
3539
3541
  const levelInfo = levels[i];
3540
3542
  const upSwitch = i > selectionBaseLevel;
3541
3543
  if (!levelInfo) {
@@ -3544,7 +3546,7 @@ class AbrController extends Logger {
3544
3546
 
3545
3547
  // skip candidates which change codec-family or video-range,
3546
3548
  // and which decrease or increase frame-rate for up and down-switch respectfully
3547
- if (currentCodecSet && levelInfo.codecSet !== currentCodecSet || currentVideoRange && levelInfo.videoRange !== currentVideoRange || upSwitch && currentFrameRate > levelInfo.frameRate || !upSwitch && currentFrameRate > 0 && currentFrameRate < levelInfo.frameRate || levelInfo.supportedResult && !((_levelInfo$supportedR = levelInfo.supportedResult.decodingInfoResults) != null && _levelInfo$supportedR[0].smooth)) {
3549
+ if (currentCodecSet && levelInfo.codecSet !== currentCodecSet || currentVideoRange && levelInfo.videoRange !== currentVideoRange || upSwitch && currentFrameRate > levelInfo.frameRate || !upSwitch && currentFrameRate > 0 && currentFrameRate < levelInfo.frameRate || (_levelInfo$supportedR = levelInfo.supportedResult) != null && (_levelInfo$supportedR2 = _levelInfo$supportedR.decodingInfoResults) != null && _levelInfo$supportedR2.some(info => info.smooth === false)) {
3548
3550
  if (!firstSelection || i !== minStartIndex) {
3549
3551
  levelsSkipped.push(i);
3550
3552
  continue;
@@ -10393,11 +10395,13 @@ transfer tracks: ${stringify(transferredTracks, (key, value) => key === 'initSeg
10393
10395
  this.updateDuration();
10394
10396
  }
10395
10397
  updateDuration() {
10396
- const durationAndRange = this.getDurationAndRange();
10397
- if (!durationAndRange) {
10398
- return;
10399
- }
10400
- this.blockUntilOpen(() => this.updateMediaSource(durationAndRange));
10398
+ this.blockUntilOpen(() => {
10399
+ const durationAndRange = this.getDurationAndRange();
10400
+ if (!durationAndRange) {
10401
+ return;
10402
+ }
10403
+ this.updateMediaSource(durationAndRange);
10404
+ });
10401
10405
  }
10402
10406
  onError(event, data) {
10403
10407
  if (data.details === ErrorDetails.BUFFER_APPEND_ERROR && data.frag) {
@@ -19887,7 +19891,7 @@ function assignTrackIdsByGroup(tracks) {
19887
19891
  });
19888
19892
  }
19889
19893
 
19890
- const version = "1.6.6-0.canary.11351";
19894
+ const version = "1.6.6-0.canary.11353";
19891
19895
 
19892
19896
  // ensure the worker ends up in the bundle
19893
19897
  // If the worker should not be included this gets aliased to empty.js
@@ -22440,68 +22444,43 @@ function getUnsupportedResult(error, configurations) {
22440
22444
  error
22441
22445
  };
22442
22446
  }
22443
- const SUPPORTED_INFO_CACHE = {};
22444
- function getMediaDecodingInfoPromise(level, audioTracksByGroup, mediaCapabilities) {
22447
+ function getMediaDecodingInfoPromise(level, audioTracksByGroup, mediaCapabilities, cache = {}) {
22445
22448
  const videoCodecs = level.videoCodec;
22446
- const audioCodecs = level.audioCodec;
22447
- if (!videoCodecs && !audioCodecs || !mediaCapabilities) {
22449
+ if (!videoCodecs && !level.audioCodec || !mediaCapabilities) {
22448
22450
  return Promise.resolve(SUPPORTED_INFO_DEFAULT);
22449
22451
  }
22450
22452
  const configurations = [];
22451
- if (videoCodecs) {
22452
- const baseVideoConfiguration = {
22453
- width: level.width,
22454
- height: level.height,
22455
- bitrate: Math.ceil(Math.max(level.bitrate * 0.9, level.averageBitrate)),
22456
- // Assume a framerate of 30fps since MediaCapabilities will not accept Level default of 0.
22457
- framerate: level.frameRate || 30
22453
+ const videoDecodeList = makeVideoConfigurations(level);
22454
+ const videoCount = videoDecodeList.length;
22455
+ const audioDecodeList = makeAudioConfigurations(level, audioTracksByGroup, videoCount > 0);
22456
+ const audioCount = audioDecodeList.length;
22457
+ for (let i = videoCount || 1 * audioCount || 1; i--;) {
22458
+ const configuration = {
22459
+ type: 'media-source'
22458
22460
  };
22459
- const videoRange = level.videoRange;
22460
- if (videoRange !== 'SDR') {
22461
- baseVideoConfiguration.transferFunction = videoRange.toLowerCase();
22461
+ if (videoCount) {
22462
+ configuration.video = videoDecodeList[i % videoCount];
22462
22463
  }
22463
- const videoCodecsArray = videoCodecs.split(',');
22464
+ if (audioCount) {
22465
+ configuration.audio = audioDecodeList[i % audioCount];
22466
+ const audioBitrate = configuration.audio.bitrate;
22467
+ if (configuration.video && audioBitrate) {
22468
+ configuration.video.bitrate -= audioBitrate;
22469
+ }
22470
+ }
22471
+ configurations.push(configuration);
22472
+ }
22473
+ if (videoCodecs) {
22464
22474
  // Override Windows Firefox HEVC MediaCapabilities result (https://github.com/video-dev/hls.js/issues/7046)
22465
22475
  const ua = navigator.userAgent;
22466
- if (videoCodecsArray.some(videoCodec => isHEVC(videoCodec)) && userAgentHevcSupportIsInaccurate()) {
22467
- return Promise.resolve(getUnsupportedResult(new Error(`Overriding Windows Firefox HEVC MediaCapabilities result based on user-agent sting: (${ua})`), configurations));
22476
+ if (videoCodecs.split(',').some(videoCodec => isHEVC(videoCodec)) && userAgentHevcSupportIsInaccurate()) {
22477
+ return Promise.resolve(getUnsupportedResult(new Error(`Overriding Windows Firefox HEVC MediaCapabilities result based on user-agent string: (${ua})`), configurations));
22468
22478
  }
22469
- configurations.push.apply(configurations, videoCodecsArray.map(videoCodec => ({
22470
- type: 'media-source',
22471
- video: _objectSpread2(_objectSpread2({}, baseVideoConfiguration), {}, {
22472
- contentType: mimeTypeForCodec(fillInMissingAV01Params(videoCodec), 'video')
22473
- })
22474
- })));
22475
- }
22476
- if (audioCodecs && level.audioGroups) {
22477
- level.audioGroups.forEach(audioGroupId => {
22478
- var _audioTracksByGroup$g;
22479
- if (!audioGroupId) {
22480
- return;
22481
- }
22482
- (_audioTracksByGroup$g = audioTracksByGroup.groups[audioGroupId]) == null ? void 0 : _audioTracksByGroup$g.tracks.forEach(audioTrack => {
22483
- if (audioTrack.groupId === audioGroupId) {
22484
- const channels = audioTrack.channels || '';
22485
- const channelsNumber = parseFloat(channels);
22486
- if (isFiniteNumber(channelsNumber) && channelsNumber > 2) {
22487
- configurations.push.apply(configurations, audioCodecs.split(',').map(audioCodec => ({
22488
- type: 'media-source',
22489
- audio: {
22490
- contentType: mimeTypeForCodec(audioCodec, 'audio'),
22491
- channels: '' + channelsNumber
22492
- // spatialRendering:
22493
- // audioCodec === 'ec-3' && channels.indexOf('JOC'),
22494
- }
22495
- })));
22496
- }
22497
- }
22498
- });
22499
- });
22500
22479
  }
22501
22480
  return Promise.all(configurations.map(configuration => {
22502
22481
  // Cache MediaCapabilities promises
22503
22482
  const decodingInfoKey = getMediaDecodingInfoKey(configuration);
22504
- return SUPPORTED_INFO_CACHE[decodingInfoKey] || (SUPPORTED_INFO_CACHE[decodingInfoKey] = mediaCapabilities.decodingInfo(configuration));
22483
+ return cache[decodingInfoKey] || (cache[decodingInfoKey] = mediaCapabilities.decodingInfo(configuration));
22505
22484
  })).then(decodingInfoResults => ({
22506
22485
  supported: !decodingInfoResults.some(info => !info.supported),
22507
22486
  configurations,
@@ -22513,22 +22492,90 @@ function getMediaDecodingInfoPromise(level, audioTracksByGroup, mediaCapabilitie
22513
22492
  error
22514
22493
  }));
22515
22494
  }
22495
+ function makeVideoConfigurations(level) {
22496
+ var _level$videoCodec;
22497
+ const videoCodecs = (_level$videoCodec = level.videoCodec) == null ? void 0 : _level$videoCodec.split(',');
22498
+ const bitrate = getVariantDecodingBitrate(level);
22499
+ const width = level.width || 640;
22500
+ const height = level.height || 480;
22501
+ // Assume a framerate of 30fps since MediaCapabilities will not accept Level default of 0.
22502
+ const framerate = level.frameRate || 30;
22503
+ const videoRange = level.videoRange.toLowerCase();
22504
+ return videoCodecs ? videoCodecs.map(videoCodec => {
22505
+ const videoConfiguration = {
22506
+ contentType: mimeTypeForCodec(fillInMissingAV01Params(videoCodec), 'video'),
22507
+ width,
22508
+ height,
22509
+ bitrate,
22510
+ framerate
22511
+ };
22512
+ if (videoRange !== 'sdr') {
22513
+ videoConfiguration.transferFunction = videoRange;
22514
+ }
22515
+ return videoConfiguration;
22516
+ }) : [];
22517
+ }
22518
+ function makeAudioConfigurations(level, audioTracksByGroup, hasVideo) {
22519
+ var _level$audioCodec;
22520
+ const audioCodecs = (_level$audioCodec = level.audioCodec) == null ? void 0 : _level$audioCodec.split(',');
22521
+ const combinedBitrate = getVariantDecodingBitrate(level);
22522
+ if (audioCodecs && level.audioGroups) {
22523
+ return level.audioGroups.reduce((configurations, audioGroupId) => {
22524
+ var _audioTracksByGroup$g;
22525
+ const tracks = audioGroupId ? (_audioTracksByGroup$g = audioTracksByGroup.groups[audioGroupId]) == null ? void 0 : _audioTracksByGroup$g.tracks : null;
22526
+ if (tracks) {
22527
+ return tracks.reduce((configs, audioTrack) => {
22528
+ if (audioTrack.groupId === audioGroupId) {
22529
+ const channelsNumber = parseFloat(audioTrack.channels || '');
22530
+ audioCodecs.forEach(audioCodec => {
22531
+ const audioConfiguration = {
22532
+ contentType: mimeTypeForCodec(audioCodec, 'audio'),
22533
+ bitrate: hasVideo ? estimatedAudioBitrate(audioCodec, combinedBitrate) : combinedBitrate
22534
+ };
22535
+ if (channelsNumber) {
22536
+ audioConfiguration.channels = '' + channelsNumber;
22537
+ }
22538
+ configs.push(audioConfiguration);
22539
+ });
22540
+ }
22541
+ return configs;
22542
+ }, configurations);
22543
+ }
22544
+ return configurations;
22545
+ }, []);
22546
+ }
22547
+ return [];
22548
+ }
22549
+ function estimatedAudioBitrate(audioCodec, levelBitrate) {
22550
+ if (levelBitrate <= 1) {
22551
+ return 1;
22552
+ }
22553
+ let audioBitrate = 128000;
22554
+ if (audioCodec === 'ec-3') {
22555
+ audioBitrate = 768000;
22556
+ } else if (audioCodec === 'ac-3') {
22557
+ audioBitrate = 640000;
22558
+ }
22559
+ return Math.min(levelBitrate / 2, audioBitrate); // Don't exceed some % of level bitrate
22560
+ }
22561
+ function getVariantDecodingBitrate(level) {
22562
+ return Math.ceil(Math.max(level.bitrate * 0.9, level.averageBitrate) / 1000) * 1000 || 1;
22563
+ }
22516
22564
  function getMediaDecodingInfoKey(config) {
22565
+ let key = '';
22517
22566
  const {
22518
22567
  audio,
22519
22568
  video
22520
22569
  } = config;
22521
- const mediaConfig = video || audio;
22522
- if (mediaConfig) {
22523
- const codec = getCodecsForMimeType(mediaConfig.contentType);
22524
- if (video) {
22525
- return `r${video.height}x${video.width}f${Math.ceil(video.framerate)}${video.transferFunction || 'sd'}_${codec}_${Math.ceil(video.bitrate / 1e5)}`;
22526
- }
22527
- if (audio) {
22528
- return `c${audio.channels}${audio.spatialRendering ? 's' : 'n'}_${codec}`;
22529
- }
22570
+ if (video) {
22571
+ const codec = getCodecsForMimeType(video.contentType);
22572
+ key += `${codec}_r${video.height}x${video.width}f${Math.ceil(video.framerate)}${video.transferFunction || 'sd'}_${Math.ceil(video.bitrate / 1e5)}`;
22573
+ }
22574
+ if (audio) {
22575
+ const codec = getCodecsForMimeType(audio.contentType);
22576
+ key += `${video ? '_' : ''}${codec}_c${audio.channels}`;
22530
22577
  }
22531
- return '';
22578
+ return key;
22532
22579
  }
22533
22580
 
22534
22581
  /**