hls.js 1.5.14-0.canary.10668 → 1.5.14-0.canary.10670

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/dist/hls.light.js CHANGED
@@ -513,7 +513,7 @@
513
513
  // Some browsers don't allow to use bind on console object anyway
514
514
  // fallback to default if needed
515
515
  try {
516
- newLogger.log("Debug logs enabled for \"" + context + "\" in hls.js version " + "1.5.14-0.canary.10668");
516
+ newLogger.log("Debug logs enabled for \"" + context + "\" in hls.js version " + "1.5.14-0.canary.10670");
517
517
  } catch (e) {
518
518
  /* log fn threw an exception. All logger methods are no-ops. */
519
519
  return createLogger();
@@ -2664,7 +2664,7 @@
2664
2664
  return (_MediaSource$isTypeSu = MediaSource == null ? void 0 : MediaSource.isTypeSupported(mimeTypeForCodec(codec, type))) != null ? _MediaSource$isTypeSu : false;
2665
2665
  }
2666
2666
  function mimeTypeForCodec(codec, type) {
2667
- return type + "/mp4;codecs=\"" + codec + "\"";
2667
+ return type + "/mp4;codecs=" + codec;
2668
2668
  }
2669
2669
  function videoCodecPreferenceValue(videoCodec) {
2670
2670
  if (videoCodec) {
@@ -2723,15 +2723,28 @@
2723
2723
  function pickMostCompleteCodecName(parsedCodec, levelCodec) {
2724
2724
  // Parsing of mp4a codecs strings in mp4-tools from media is incomplete as of d8c6c7a
2725
2725
  // so use level codec is parsed codec is unavailable or incomplete
2726
- if (parsedCodec && parsedCodec !== 'mp4a') {
2726
+ if (parsedCodec && (parsedCodec.length > 4 || ['ac-3', 'ec-3', 'alac', 'fLaC', 'Opus'].indexOf(parsedCodec) !== -1)) {
2727
2727
  return parsedCodec;
2728
2728
  }
2729
- return levelCodec ? levelCodec.split(',')[0] : levelCodec;
2729
+ if (levelCodec) {
2730
+ var levelCodecs = levelCodec.split(',');
2731
+ if (levelCodecs.length > 1) {
2732
+ if (parsedCodec) {
2733
+ for (var i = levelCodecs.length; i--;) {
2734
+ if (levelCodecs[i].substring(0, 4) === parsedCodec.substring(0, 4)) {
2735
+ return levelCodecs[i];
2736
+ }
2737
+ }
2738
+ }
2739
+ return levelCodecs[0];
2740
+ }
2741
+ }
2742
+ return levelCodec || parsedCodec;
2730
2743
  }
2731
- function convertAVC1ToAVCOTI(codec) {
2744
+ function convertAVC1ToAVCOTI(videoCodecs) {
2732
2745
  // Convert avc1 codec string from RFC-4281 to RFC-6381 for MediaSource.isTypeSupported
2733
2746
  // Examples: avc1.66.30 to avc1.42001e and avc1.77.30,avc1.66.30 to avc1.4d001e,avc1.42001e.
2734
- var codecs = codec.split(',');
2747
+ var codecs = videoCodecs.split(',');
2735
2748
  for (var i = 0; i < codecs.length; i++) {
2736
2749
  var avcdata = codecs[i].split('.');
2737
2750
  if (avcdata.length > 2) {
@@ -2743,6 +2756,18 @@
2743
2756
  }
2744
2757
  return codecs.join(',');
2745
2758
  }
2759
+ function fillInMissingAV01Params(videoCodec) {
2760
+ // Used to fill in incomplete AV1 playlist CODECS strings for mediaCapabilities.decodingInfo queries
2761
+ if (videoCodec.startsWith('av01.')) {
2762
+ var av1params = videoCodec.split('.');
2763
+ var placeholders = ['0', '111', '01', '01', '01', '0'];
2764
+ for (var i = av1params.length; i > 4 && i < 10; i++) {
2765
+ av1params[i] = placeholders[i - 4];
2766
+ }
2767
+ return av1params.join('.');
2768
+ }
2769
+ return videoCodec;
2770
+ }
2746
2771
  function getM2TSSupportedAudioTypes(preferManagedMediaSource) {
2747
2772
  var MediaSource = getMediaSource(preferManagedMediaSource) || {
2748
2773
  isTypeSupported: function isTypeSupported() {
@@ -6614,6 +6639,7 @@
6614
6639
  this.resetLevels();
6615
6640
  };
6616
6641
  _proto.onManifestLoaded = function onManifestLoaded(event, data) {
6642
+ var _this2 = this;
6617
6643
  var preferManagedMediaSource = this.hls.config.preferManagedMediaSource;
6618
6644
  var levels = [];
6619
6645
  var redundantSet = {};
@@ -6638,10 +6664,27 @@
6638
6664
  var width = levelParsed.width,
6639
6665
  height = levelParsed.height,
6640
6666
  unknownCodecs = levelParsed.unknownCodecs;
6667
+ var unknownUnsupportedCodecCount = unknownCodecs ? unknownCodecs.length : 0;
6668
+ if (unknownCodecs) {
6669
+ // Treat unknown codec as audio or video codec based on passing `isTypeSupported` check
6670
+ // (allows for playback of any supported codec even if not indexed in utils/codecs)
6671
+ for (var i = unknownUnsupportedCodecCount; i--;) {
6672
+ var unknownCodec = unknownCodecs[i];
6673
+ if (_this2.isAudioSupported(unknownCodec)) {
6674
+ levelParsed.audioCodec = audioCodec = audioCodec ? audioCodec + "," + unknownCodec : unknownCodec;
6675
+ unknownUnsupportedCodecCount--;
6676
+ sampleEntryCodesISO.audio[audioCodec.substring(0, 4)] = 2;
6677
+ } else if (_this2.isVideoSupported(unknownCodec)) {
6678
+ levelParsed.videoCodec = videoCodec = videoCodec ? videoCodec + "," + unknownCodec : unknownCodec;
6679
+ unknownUnsupportedCodecCount--;
6680
+ sampleEntryCodesISO.video[videoCodec.substring(0, 4)] = 2;
6681
+ }
6682
+ }
6683
+ }
6641
6684
  resolutionFound || (resolutionFound = !!(width && height));
6642
6685
  videoCodecFound || (videoCodecFound = !!videoCodec);
6643
6686
  audioCodecFound || (audioCodecFound = !!audioCodec);
6644
- if (unknownCodecs != null && unknownCodecs.length || audioCodec && !areCodecsMediaSourceSupported(audioCodec, 'audio', preferManagedMediaSource) || videoCodec && !areCodecsMediaSourceSupported(videoCodec, 'video', preferManagedMediaSource)) {
6687
+ if (unknownUnsupportedCodecCount || audioCodec && !_this2.isAudioSupported(audioCodec) || videoCodec && !_this2.isVideoSupported(videoCodec)) {
6645
6688
  return;
6646
6689
  }
6647
6690
  var CODECS = attributes.CODECS,
@@ -6672,8 +6715,14 @@
6672
6715
  });
6673
6716
  this.filterAndSortMediaOptions(levels, data, resolutionFound, videoCodecFound, audioCodecFound);
6674
6717
  };
6718
+ _proto.isAudioSupported = function isAudioSupported(codec) {
6719
+ return areCodecsMediaSourceSupported(codec, 'audio', this.hls.config.preferManagedMediaSource);
6720
+ };
6721
+ _proto.isVideoSupported = function isVideoSupported(codec) {
6722
+ return areCodecsMediaSourceSupported(codec, 'video', this.hls.config.preferManagedMediaSource);
6723
+ };
6675
6724
  _proto.filterAndSortMediaOptions = function filterAndSortMediaOptions(filteredLevels, data, resolutionFound, videoCodecFound, audioCodecFound) {
6676
- var _this2 = this;
6725
+ var _this3 = this;
6677
6726
  var audioTracks = [];
6678
6727
  var subtitleTracks = [];
6679
6728
  var levels = filteredLevels;
@@ -6691,12 +6740,12 @@
6691
6740
  if (levels.length === 0) {
6692
6741
  // Dispatch error after MANIFEST_LOADED is done propagating
6693
6742
  Promise.resolve().then(function () {
6694
- if (_this2.hls) {
6743
+ if (_this3.hls) {
6695
6744
  if (data.levels.length) {
6696
- _this2.warn("One or more CODECS in variant not supported: " + JSON.stringify(data.levels[0].attrs));
6745
+ _this3.warn("One or more CODECS in variant not supported: " + JSON.stringify(data.levels[0].attrs));
6697
6746
  }
6698
6747
  var error = new Error('no level with compatible codecs found in manifest');
6699
- _this2.hls.trigger(Events.ERROR, {
6748
+ _this3.hls.trigger(Events.ERROR, {
6700
6749
  type: ErrorTypes.MEDIA_ERROR,
6701
6750
  details: ErrorDetails.MANIFEST_INCOMPATIBLE_CODECS_ERROR,
6702
6751
  fatal: true,
@@ -6709,9 +6758,8 @@
6709
6758
  return;
6710
6759
  }
6711
6760
  if (data.audioTracks) {
6712
- var preferManagedMediaSource = this.hls.config.preferManagedMediaSource;
6713
6761
  audioTracks = data.audioTracks.filter(function (track) {
6714
- return !track.audioCodec || areCodecsMediaSourceSupported(track.audioCodec, 'audio', preferManagedMediaSource);
6762
+ return !track.audioCodec || _this3.isAudioSupported(track.audioCodec);
6715
6763
  });
6716
6764
  // Assign ids after filtering as array indices by group-id
6717
6765
  assignTrackIdsByGroup(audioTracks);
@@ -6907,18 +6955,18 @@
6907
6955
  }
6908
6956
  };
6909
6957
  _proto.removeLevel = function removeLevel(levelIndex) {
6910
- var _this3 = this,
6958
+ var _this4 = this,
6911
6959
  _this$currentLevel;
6912
6960
  var levels = this._levels.filter(function (level, index) {
6913
6961
  if (index !== levelIndex) {
6914
6962
  return true;
6915
6963
  }
6916
- if (_this3.steering) {
6917
- _this3.steering.removeLevel(level);
6964
+ if (_this4.steering) {
6965
+ _this4.steering.removeLevel(level);
6918
6966
  }
6919
- if (level === _this3.currentLevel) {
6920
- _this3.currentLevel = null;
6921
- _this3.currentLevelIndex = -1;
6967
+ if (level === _this4.currentLevel) {
6968
+ _this4.currentLevel = null;
6969
+ _this4.currentLevelIndex = -1;
6922
6970
  if (level.details) {
6923
6971
  level.details.fragments.forEach(function (f) {
6924
6972
  return f.level = -1;
@@ -14552,7 +14600,7 @@
14552
14600
  }
14553
14601
  var initData = this.initData = parseInitSegment(initSegment);
14554
14602
 
14555
- // Get codec from initSegment or fallback to default
14603
+ // Get codec from initSegment
14556
14604
  if (initData.audio) {
14557
14605
  audioCodec = getParsedTrackCodec(initData.audio, ElementaryStreamTypes.AUDIO);
14558
14606
  }
@@ -14706,20 +14754,13 @@
14706
14754
  var preferManagedMediaSource = false;
14707
14755
  return getCodecCompatibleName(parsedCodec, preferManagedMediaSource);
14708
14756
  }
14709
- var result = 'mp4a.40.5';
14710
- this.logger.info("Parsed audio codec \"" + parsedCodec + "\" or audio object type not handled. Using \"" + result + "\"");
14711
- return result;
14757
+ logger.warn("Unhandled audio codec \"" + parsedCodec + "\" in mp4 MAP");
14758
+ return parsedCodec || 'mp4a';
14712
14759
  }
14713
14760
  // Provide defaults based on codec type
14714
14761
  // This allows for some playback of some fmp4 playlists without CODECS defined in manifest
14715
- this.logger.warn("Unhandled video codec \"" + parsedCodec + "\"");
14716
- if (parsedCodec === 'hvc1' || parsedCodec === 'hev1') {
14717
- return 'hvc1.1.6.L120.90';
14718
- }
14719
- if (parsedCodec === 'av01') {
14720
- return 'av01.0.04M.08';
14721
- }
14722
- return 'avc1.42e01e';
14762
+ logger.warn("Unhandled video codec \"" + parsedCodec + "\" in mp4 MAP");
14763
+ return parsedCodec || 'avc1';
14723
14764
  }
14724
14765
 
14725
14766
  var now;
@@ -15590,7 +15631,7 @@
15590
15631
  return !remuxResult.audio && !remuxResult.video && !remuxResult.text && !remuxResult.id3 && !remuxResult.initSegment;
15591
15632
  }
15592
15633
 
15593
- var version = "1.5.14-0.canary.10668";
15634
+ var version = "1.5.14-0.canary.10670";
15594
15635
 
15595
15636
  // ensure the worker ends up in the bundle
15596
15637
  // If the worker should not be included this gets aliased to empty.js
@@ -17317,7 +17358,13 @@
17317
17358
  video = tracks.video,
17318
17359
  audiovideo = tracks.audiovideo;
17319
17360
  if (audio) {
17320
- var audioCodec = currentLevel.audioCodec;
17361
+ var audioCodec = pickMostCompleteCodecName(audio.codec, currentLevel.audioCodec);
17362
+ // Add level and profile to make up for passthrough-remuxer not being able to parse full codec
17363
+ // (logger warning "Unhandled audio codec...")
17364
+ if (audioCodec === 'mp4a') {
17365
+ audioCodec = 'mp4a.40.5';
17366
+ }
17367
+ // Handle `audioCodecSwitch`
17321
17368
  var ua = navigator.userAgent.toLowerCase();
17322
17369
  if (this.audioCodecSwitch) {
17323
17370
  if (audioCodec) {
@@ -17352,7 +17399,24 @@
17352
17399
  if (video) {
17353
17400
  video.levelCodec = currentLevel.videoCodec;
17354
17401
  video.id = 'main';
17355
- this.log("Init video buffer, container:" + video.container + ", codecs[level/parsed]=[" + (currentLevel.videoCodec || '') + "/" + video.codec + "]");
17402
+ var parsedVideoCodec = video.codec;
17403
+ if ((parsedVideoCodec == null ? void 0 : parsedVideoCodec.length) === 4) {
17404
+ // Make up for passthrough-remuxer not being able to parse full codec
17405
+ // (logger warning "Unhandled video codec...")
17406
+ switch (parsedVideoCodec) {
17407
+ case 'hvc1':
17408
+ case 'hev1':
17409
+ video.codec = 'hvc1.1.6.L120.90';
17410
+ break;
17411
+ case 'av01':
17412
+ video.codec = 'av01.0.04M.08';
17413
+ break;
17414
+ case 'avc1':
17415
+ video.codec = 'avc1.42e01e';
17416
+ break;
17417
+ }
17418
+ }
17419
+ this.log("Init video buffer, container:" + video.container + ", codecs[level/parsed]=[" + (currentLevel.videoCodec || '') + "/" + parsedVideoCodec + (video.codec !== parsedVideoCodec ? ' parsed-corrected=' + video.codec : '') + "}]");
17356
17420
  delete tracks.audiovideo;
17357
17421
  }
17358
17422
  if (audiovideo) {
@@ -19163,7 +19227,7 @@
19163
19227
  if (trackName.slice(0, 5) === 'audio') {
19164
19228
  trackCodec = getCodecCompatibleName(trackCodec, _this9.appendSource);
19165
19229
  }
19166
- _this9.log("switching codec " + sbCodec + " to " + codec);
19230
+ _this9.log("switching codec " + sbCodec + " to " + trackCodec);
19167
19231
  if (trackCodec !== (track.pendingCodec || track.codec)) {
19168
19232
  track.pendingCodec = trackCodec;
19169
19233
  }
@@ -19827,7 +19891,7 @@
19827
19891
  }
19828
19892
  };
19829
19893
  _proto.getTrackCodec = function getTrackCodec(track, trackName) {
19830
- var codec = track.codec || track.levelCodec;
19894
+ var codec = pickMostCompleteCodecName(track.codec, track.levelCodec);
19831
19895
  if (codec) {
19832
19896
  if (trackName.slice(0, 5) === 'audio') {
19833
19897
  return getCodecCompatibleName(codec, this.appendSource);
@@ -21867,6 +21931,108 @@
21867
21931
  }
21868
21932
  }
21869
21933
 
21934
+ var SUPPORTED_INFO_DEFAULT = {
21935
+ supported: true,
21936
+ configurations: [],
21937
+ decodingInfoResults: [{
21938
+ supported: true,
21939
+ powerEfficient: true,
21940
+ smooth: true
21941
+ }]
21942
+ };
21943
+ var SUPPORTED_INFO_CACHE = {};
21944
+ function getMediaDecodingInfoPromise(level, audioTracksByGroup, mediaCapabilities) {
21945
+ var videoCodecs = level.videoCodec;
21946
+ var audioCodecs = level.audioCodec;
21947
+ if (!videoCodecs && !audioCodecs || !mediaCapabilities) {
21948
+ return Promise.resolve(SUPPORTED_INFO_DEFAULT);
21949
+ }
21950
+ var configurations = [];
21951
+ if (videoCodecs) {
21952
+ var baseVideoConfiguration = {
21953
+ width: level.width,
21954
+ height: level.height,
21955
+ bitrate: Math.ceil(Math.max(level.bitrate * 0.9, level.averageBitrate)),
21956
+ // Assume a framerate of 30fps since MediaCapabilities will not accept Level default of 0.
21957
+ framerate: level.frameRate || 30
21958
+ };
21959
+ var videoRange = level.videoRange;
21960
+ if (videoRange !== 'SDR') {
21961
+ baseVideoConfiguration.transferFunction = videoRange.toLowerCase();
21962
+ }
21963
+ configurations.push.apply(configurations, videoCodecs.split(',').map(function (videoCodec) {
21964
+ return {
21965
+ type: 'media-source',
21966
+ video: _objectSpread2(_objectSpread2({}, baseVideoConfiguration), {}, {
21967
+ contentType: mimeTypeForCodec(fillInMissingAV01Params(videoCodec), 'video')
21968
+ })
21969
+ };
21970
+ }));
21971
+ }
21972
+ if (audioCodecs && level.audioGroups) {
21973
+ level.audioGroups.forEach(function (audioGroupId) {
21974
+ var _audioTracksByGroup$g;
21975
+ if (!audioGroupId) {
21976
+ return;
21977
+ }
21978
+ (_audioTracksByGroup$g = audioTracksByGroup.groups[audioGroupId]) == null ? void 0 : _audioTracksByGroup$g.tracks.forEach(function (audioTrack) {
21979
+ if (audioTrack.groupId === audioGroupId) {
21980
+ var channels = audioTrack.channels || '';
21981
+ var channelsNumber = parseFloat(channels);
21982
+ if (isFiniteNumber(channelsNumber) && channelsNumber > 2) {
21983
+ configurations.push.apply(configurations, audioCodecs.split(',').map(function (audioCodec) {
21984
+ return {
21985
+ type: 'media-source',
21986
+ audio: {
21987
+ contentType: mimeTypeForCodec(audioCodec, 'audio'),
21988
+ channels: '' + channelsNumber
21989
+ // spatialRendering:
21990
+ // audioCodec === 'ec-3' && channels.indexOf('JOC'),
21991
+ }
21992
+ };
21993
+ }));
21994
+ }
21995
+ }
21996
+ });
21997
+ });
21998
+ }
21999
+ return Promise.all(configurations.map(function (configuration) {
22000
+ // Cache MediaCapabilities promises
22001
+ var decodingInfoKey = getMediaDecodingInfoKey(configuration);
22002
+ return SUPPORTED_INFO_CACHE[decodingInfoKey] || (SUPPORTED_INFO_CACHE[decodingInfoKey] = mediaCapabilities.decodingInfo(configuration));
22003
+ })).then(function (decodingInfoResults) {
22004
+ return {
22005
+ supported: !decodingInfoResults.some(function (info) {
22006
+ return !info.supported;
22007
+ }),
22008
+ configurations: configurations,
22009
+ decodingInfoResults: decodingInfoResults
22010
+ };
22011
+ }).catch(function (error) {
22012
+ return {
22013
+ supported: false,
22014
+ configurations: configurations,
22015
+ decodingInfoResults: [],
22016
+ error: error
22017
+ };
22018
+ });
22019
+ }
22020
+ function getMediaDecodingInfoKey(config) {
22021
+ var audio = config.audio,
22022
+ video = config.video;
22023
+ var mediaConfig = video || audio;
22024
+ if (mediaConfig) {
22025
+ var codec = mediaConfig.contentType.split('"')[1];
22026
+ if (video) {
22027
+ return "r" + video.height + "x" + video.width + "f" + Math.ceil(video.framerate) + (video.transferFunction || 'sd') + "_" + codec + "_" + Math.ceil(video.bitrate / 1e5);
22028
+ }
22029
+ if (audio) {
22030
+ return "c" + audio.channels + (audio.spatialRendering ? 's' : 'n') + "_" + codec;
22031
+ }
22032
+ }
22033
+ return '';
22034
+ }
22035
+
21870
22036
  /**
21871
22037
  * The `Hls` class is the core of the HLS.js library used to instantiate player instances.
21872
22038
  * @public
@@ -22281,6 +22447,16 @@
22281
22447
  /**
22282
22448
  * Get the complete list of audio tracks across all media groups
22283
22449
  */;
22450
+ /**
22451
+ * returns mediaCapabilities.decodingInfo for a variant/rendition
22452
+ */
22453
+ _proto.getMediaDecodingInfo = function getMediaDecodingInfo(level, audioTracks) {
22454
+ if (audioTracks === void 0) {
22455
+ audioTracks = this.allAudioTracks;
22456
+ }
22457
+ var audioTracksByGroup = getAudioTracksByGroup(audioTracks);
22458
+ return getMediaDecodingInfoPromise(level, audioTracksByGroup, navigator.mediaCapabilities);
22459
+ };
22284
22460
  return _createClass(Hls, [{
22285
22461
  key: "url",
22286
22462
  get: function get() {