hls.js 1.5.12-0.canary.10351 → 1.5.12-0.canary.10353
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.js +60 -46
- package/dist/hls.js.d.ts +1 -0
- package/dist/hls.js.map +1 -1
- package/dist/hls.light.js +57 -43
- package/dist/hls.light.js.map +1 -1
- package/dist/hls.light.min.js +1 -1
- package/dist/hls.light.min.js.map +1 -1
- package/dist/hls.light.mjs +55 -41
- package/dist/hls.light.mjs.map +1 -1
- package/dist/hls.min.js +1 -1
- package/dist/hls.min.js.map +1 -1
- package/dist/hls.mjs +58 -44
- package/dist/hls.mjs.map +1 -1
- package/dist/hls.worker.js +1 -1
- package/dist/hls.worker.js.map +1 -1
- package/package.json +1 -1
- package/src/controller/abr-controller.ts +15 -5
- package/src/demux/video/avc-video-parser.ts +3 -3
- package/src/demux/video/base-video-parser.ts +24 -20
- package/src/demux/video/hevc-video-parser.ts +3 -3
- package/src/hls.ts +4 -3
- package/src/types/demuxer.ts +0 -1
- package/src/types/media-playlist.ts +9 -1
- package/src/utils/hdr.ts +4 -7
- package/src/utils/rendition-helper.ts +26 -5
package/dist/hls.light.mjs
CHANGED
@@ -420,7 +420,7 @@ function enableLogs(debugConfig, context, id) {
|
|
420
420
|
// Some browsers don't allow to use bind on console object anyway
|
421
421
|
// fallback to default if needed
|
422
422
|
try {
|
423
|
-
newLogger.log(`Debug logs enabled for "${context}" in hls.js version ${"1.5.12-0.canary.
|
423
|
+
newLogger.log(`Debug logs enabled for "${context}" in hls.js version ${"1.5.12-0.canary.10353"}`);
|
424
424
|
} catch (e) {
|
425
425
|
/* log fn threw an exception. All logger methods are no-ops. */
|
426
426
|
return createLogger();
|
@@ -6319,10 +6319,9 @@ function getVideoSelectionOptions(currentVideoRange, videoPreference) {
|
|
6319
6319
|
}
|
6320
6320
|
if (videoPreference) {
|
6321
6321
|
allowedVideoRanges = videoPreference.allowedVideoRanges || VideoRangeValues.slice(0);
|
6322
|
-
|
6323
|
-
|
6324
|
-
|
6325
|
-
} else {
|
6322
|
+
const allowAutoPreferHDR = allowedVideoRanges.join('') !== 'SDR' && !videoPreference.videoCodec;
|
6323
|
+
preferHDR = videoPreference.preferHDR !== undefined ? videoPreference.preferHDR : allowAutoPreferHDR && isHdrSupported();
|
6324
|
+
if (!preferHDR) {
|
6326
6325
|
allowedVideoRanges = ['SDR'];
|
6327
6326
|
}
|
6328
6327
|
}
|
@@ -6336,13 +6335,15 @@ function getStartCodecTier(codecTiers, currentVideoRange, currentBw, audioPrefer
|
|
6336
6335
|
const codecSets = Object.keys(codecTiers);
|
6337
6336
|
const channelsPreference = audioPreference == null ? void 0 : audioPreference.channels;
|
6338
6337
|
const audioCodecPreference = audioPreference == null ? void 0 : audioPreference.audioCodec;
|
6338
|
+
const videoCodecPreference = videoPreference == null ? void 0 : videoPreference.videoCodec;
|
6339
6339
|
const preferStereo = channelsPreference && parseInt(channelsPreference) === 2;
|
6340
6340
|
// Use first level set to determine stereo, and minimum resolution and framerate
|
6341
|
-
let hasStereo =
|
6341
|
+
let hasStereo = false;
|
6342
6342
|
let hasCurrentVideoRange = false;
|
6343
6343
|
let minHeight = Infinity;
|
6344
6344
|
let minFramerate = Infinity;
|
6345
6345
|
let minBitrate = Infinity;
|
6346
|
+
let minIndex = Infinity;
|
6346
6347
|
let selectedScore = 0;
|
6347
6348
|
let videoRanges = [];
|
6348
6349
|
const {
|
@@ -6351,14 +6352,13 @@ function getStartCodecTier(codecTiers, currentVideoRange, currentBw, audioPrefer
|
|
6351
6352
|
} = getVideoSelectionOptions(currentVideoRange, videoPreference);
|
6352
6353
|
for (let i = codecSets.length; i--;) {
|
6353
6354
|
const tier = codecTiers[codecSets[i]];
|
6354
|
-
hasStereo = tier.channels[2] > 0;
|
6355
|
+
hasStereo || (hasStereo = tier.channels[2] > 0);
|
6355
6356
|
minHeight = Math.min(minHeight, tier.minHeight);
|
6356
6357
|
minFramerate = Math.min(minFramerate, tier.minFramerate);
|
6357
6358
|
minBitrate = Math.min(minBitrate, tier.minBitrate);
|
6358
6359
|
const matchingVideoRanges = allowedVideoRanges.filter(range => tier.videoRanges[range] > 0);
|
6359
6360
|
if (matchingVideoRanges.length > 0) {
|
6360
6361
|
hasCurrentVideoRange = true;
|
6361
|
-
videoRanges = matchingVideoRanges;
|
6362
6362
|
}
|
6363
6363
|
}
|
6364
6364
|
minHeight = isFiniteNumber(minHeight) ? minHeight : 0;
|
@@ -6370,7 +6370,6 @@ function getStartCodecTier(codecTiers, currentVideoRange, currentBw, audioPrefer
|
|
6370
6370
|
// If there are no variants with matching preference, set currentVideoRange to undefined
|
6371
6371
|
if (!hasCurrentVideoRange) {
|
6372
6372
|
currentVideoRange = undefined;
|
6373
|
-
videoRanges = [];
|
6374
6373
|
}
|
6375
6374
|
const codecSet = codecSets.reduce((selected, candidate) => {
|
6376
6375
|
// Remove candiates which do not meet bitrate, default audio, stereo or channels preference, 1080p or lower, 30fps or lower, or SDR/HDR selection if present
|
@@ -6378,6 +6377,7 @@ function getStartCodecTier(codecTiers, currentVideoRange, currentBw, audioPrefer
|
|
6378
6377
|
if (candidate === selected) {
|
6379
6378
|
return selected;
|
6380
6379
|
}
|
6380
|
+
videoRanges = hasCurrentVideoRange ? allowedVideoRanges.filter(range => candidateTier.videoRanges[range] > 0) : [];
|
6381
6381
|
if (candidateTier.minBitrate > currentBw) {
|
6382
6382
|
logStartCodecCandidateIgnored(candidate, `min bitrate of ${candidateTier.minBitrate} > current estimate of ${currentBw}`);
|
6383
6383
|
return selected;
|
@@ -6411,6 +6411,10 @@ function getStartCodecTier(codecTiers, currentVideoRange, currentBw, audioPrefer
|
|
6411
6411
|
logStartCodecCandidateIgnored(candidate, `no variants with VIDEO-RANGE of ${JSON.stringify(videoRanges)} found`);
|
6412
6412
|
return selected;
|
6413
6413
|
}
|
6414
|
+
if (videoCodecPreference && candidate.indexOf(videoCodecPreference.substring(0, 4)) % 5 !== 0) {
|
6415
|
+
logStartCodecCandidateIgnored(candidate, `video codec preference "${videoCodecPreference}" not found`);
|
6416
|
+
return selected;
|
6417
|
+
}
|
6414
6418
|
if (candidateTier.maxScore < selectedScore) {
|
6415
6419
|
logStartCodecCandidateIgnored(candidate, `max score of ${candidateTier.maxScore} < selected max of ${selectedScore}`);
|
6416
6420
|
return selected;
|
@@ -6419,6 +6423,7 @@ function getStartCodecTier(codecTiers, currentVideoRange, currentBw, audioPrefer
|
|
6419
6423
|
if (selected && (codecsSetSelectionPreferenceValue(candidate) >= codecsSetSelectionPreferenceValue(selected) || candidateTier.fragmentError > codecTiers[selected].fragmentError)) {
|
6420
6424
|
return selected;
|
6421
6425
|
}
|
6426
|
+
minIndex = candidateTier.minIndex;
|
6422
6427
|
selectedScore = candidateTier.maxScore;
|
6423
6428
|
return candidate;
|
6424
6429
|
}, undefined);
|
@@ -6427,7 +6432,8 @@ function getStartCodecTier(codecTiers, currentVideoRange, currentBw, audioPrefer
|
|
6427
6432
|
videoRanges,
|
6428
6433
|
preferHDR,
|
6429
6434
|
minFramerate,
|
6430
|
-
minBitrate
|
6435
|
+
minBitrate,
|
6436
|
+
minIndex
|
6431
6437
|
};
|
6432
6438
|
}
|
6433
6439
|
function logStartCodecCandidateIgnored(codeSet, reason) {
|
@@ -6465,7 +6471,7 @@ function getAudioTracksByGroup(allAudioTracks) {
|
|
6465
6471
|
});
|
6466
6472
|
}
|
6467
6473
|
function getCodecTiers(levels, audioTracksByGroup, minAutoLevel, maxAutoLevel) {
|
6468
|
-
return levels.slice(minAutoLevel, maxAutoLevel + 1).reduce((tiers, level) => {
|
6474
|
+
return levels.slice(minAutoLevel, maxAutoLevel + 1).reduce((tiers, level, index) => {
|
6469
6475
|
if (!level.codecSet) {
|
6470
6476
|
return tiers;
|
6471
6477
|
}
|
@@ -6476,6 +6482,7 @@ function getCodecTiers(levels, audioTracksByGroup, minAutoLevel, maxAutoLevel) {
|
|
6476
6482
|
minBitrate: Infinity,
|
6477
6483
|
minHeight: Infinity,
|
6478
6484
|
minFramerate: Infinity,
|
6485
|
+
minIndex: index,
|
6479
6486
|
maxScore: 0,
|
6480
6487
|
videoRanges: {
|
6481
6488
|
SDR: 0
|
@@ -6491,6 +6498,7 @@ function getCodecTiers(levels, audioTracksByGroup, minAutoLevel, maxAutoLevel) {
|
|
6491
6498
|
const lesserWidthOrHeight = Math.min(level.height, level.width);
|
6492
6499
|
tier.minHeight = Math.min(tier.minHeight, lesserWidthOrHeight);
|
6493
6500
|
tier.minFramerate = Math.min(tier.minFramerate, level.frameRate);
|
6501
|
+
tier.minIndex = Math.min(tier.minIndex, index);
|
6494
6502
|
tier.maxScore = Math.max(tier.maxScore, level.score);
|
6495
6503
|
tier.fragmentError += level.fragmentError;
|
6496
6504
|
tier.videoRanges[level.videoRange] = (tier.videoRanges[level.videoRange] || 0) + 1;
|
@@ -7010,6 +7018,7 @@ class AbrController extends Logger {
|
|
7010
7018
|
videoPreference
|
7011
7019
|
} = config;
|
7012
7020
|
const audioTracksByGroup = this.audioTracksByGroup || (this.audioTracksByGroup = getAudioTracksByGroup(allAudioTracks));
|
7021
|
+
let minStartIndex = -1;
|
7013
7022
|
if (firstSelection) {
|
7014
7023
|
if (this.firstSelection !== -1) {
|
7015
7024
|
return this.firstSelection;
|
@@ -7021,8 +7030,10 @@ class AbrController extends Logger {
|
|
7021
7030
|
videoRanges,
|
7022
7031
|
minFramerate,
|
7023
7032
|
minBitrate,
|
7033
|
+
minIndex,
|
7024
7034
|
preferHDR
|
7025
7035
|
} = startTier;
|
7036
|
+
minStartIndex = minIndex;
|
7026
7037
|
currentCodecSet = codecSet;
|
7027
7038
|
currentVideoRange = preferHDR ? videoRanges[videoRanges.length - 1] : videoRanges[0];
|
7028
7039
|
currentFrameRate = minFramerate;
|
@@ -7046,8 +7057,10 @@ class AbrController extends Logger {
|
|
7046
7057
|
// skip candidates which change codec-family or video-range,
|
7047
7058
|
// and which decrease or increase frame-rate for up and down-switch respectfully
|
7048
7059
|
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)) {
|
7049
|
-
|
7050
|
-
|
7060
|
+
if (firstSelection && i !== minStartIndex) {
|
7061
|
+
levelsSkipped.push(i);
|
7062
|
+
continue;
|
7063
|
+
}
|
7051
7064
|
}
|
7052
7065
|
const levelDetails = levelInfo.details;
|
7053
7066
|
const avgDuration = (partCurrent ? levelDetails == null ? void 0 : levelDetails.partTarget : levelDetails == null ? void 0 : levelDetails.averagetargetduration) || currentFragDuration;
|
@@ -7082,7 +7095,7 @@ class AbrController extends Logger {
|
|
7082
7095
|
if (levelsSkipped.length) {
|
7083
7096
|
this.trace(`Skipped level(s) ${levelsSkipped.join(',')} of ${maxAutoLevel} max with CODECS and VIDEO-RANGE:"${levels[levelsSkipped[0]].codecs}" ${levels[levelsSkipped[0]].videoRange}; not compatible with "${level.codecs}" ${currentVideoRange}`);
|
7084
7097
|
}
|
7085
|
-
this.info(`switch candidate:${selectionBaseLevel}->${i} adjustedbw(${Math.round(adjustedbw)})-bitrate=${Math.round(adjustedbw - bitrate)} ttfb:${ttfbEstimateSec.toFixed(1)} avgDuration:${avgDuration.toFixed(1)} maxFetchDuration:${maxFetchDuration.toFixed(1)} fetchDuration:${fetchDuration.toFixed(1)} firstSelection:${firstSelection} codecSet:${
|
7098
|
+
this.info(`switch candidate:${selectionBaseLevel}->${i} adjustedbw(${Math.round(adjustedbw)})-bitrate=${Math.round(adjustedbw - bitrate)} ttfb:${ttfbEstimateSec.toFixed(1)} avgDuration:${avgDuration.toFixed(1)} maxFetchDuration:${maxFetchDuration.toFixed(1)} fetchDuration:${fetchDuration.toFixed(1)} firstSelection:${firstSelection} codecSet:${level.codecSet} videoRange:${level.videoRange} hls.loadLevel:${loadLevel}`);
|
7086
7099
|
}
|
7087
7100
|
if (firstSelection) {
|
7088
7101
|
this.firstSelection = i;
|
@@ -14669,6 +14682,20 @@ class BaseVideoParser {
|
|
14669
14682
|
length: 0
|
14670
14683
|
};
|
14671
14684
|
}
|
14685
|
+
getLastNalUnit(samples) {
|
14686
|
+
var _VideoSample;
|
14687
|
+
let VideoSample = this.VideoSample;
|
14688
|
+
let lastUnit;
|
14689
|
+
// try to fallback to previous sample if current one is empty
|
14690
|
+
if (!VideoSample || VideoSample.units.length === 0) {
|
14691
|
+
VideoSample = samples[samples.length - 1];
|
14692
|
+
}
|
14693
|
+
if ((_VideoSample = VideoSample) != null && _VideoSample.units) {
|
14694
|
+
const units = VideoSample.units;
|
14695
|
+
lastUnit = units[units.length - 1];
|
14696
|
+
}
|
14697
|
+
return lastUnit;
|
14698
|
+
}
|
14672
14699
|
pushAccessUnit(VideoSample, videoTrack) {
|
14673
14700
|
if (VideoSample.units.length && VideoSample.frame) {
|
14674
14701
|
// if sample does not have PTS/DTS, patch with last sample PTS/DTS
|
@@ -14691,7 +14718,7 @@ class BaseVideoParser {
|
|
14691
14718
|
logger.log(VideoSample.pts + '/' + VideoSample.dts + ':' + VideoSample.debug);
|
14692
14719
|
}
|
14693
14720
|
}
|
14694
|
-
parseNALu(track, array,
|
14721
|
+
parseNALu(track, array, endOfSegment) {
|
14695
14722
|
const len = array.byteLength;
|
14696
14723
|
let state = track.naluState || 0;
|
14697
14724
|
const lastState = state;
|
@@ -14733,10 +14760,6 @@ class BaseVideoParser {
|
|
14733
14760
|
data: array.subarray(lastUnitStart, overflow),
|
14734
14761
|
type: lastUnitType
|
14735
14762
|
};
|
14736
|
-
if (track.lastNalu) {
|
14737
|
-
units.push(track.lastNalu);
|
14738
|
-
track.lastNalu = null;
|
14739
|
-
}
|
14740
14763
|
// logger.log('pushing NALU, type/size:' + unit.type + '/' + unit.data.byteLength);
|
14741
14764
|
units.push(unit);
|
14742
14765
|
} else {
|
@@ -14744,7 +14767,7 @@ class BaseVideoParser {
|
|
14744
14767
|
// first check if start code delimiter is overlapping between 2 PES packets,
|
14745
14768
|
// ie it started in last packet (lastState not zero)
|
14746
14769
|
// and ended at the beginning of this PES packet (i <= 4 - lastState)
|
14747
|
-
const lastUnit = track.
|
14770
|
+
const lastUnit = this.getLastNalUnit(track.samples);
|
14748
14771
|
if (lastUnit) {
|
14749
14772
|
if (lastState && i <= 4 - lastState) {
|
14750
14773
|
// start delimiter overlapping between PES packets
|
@@ -14761,8 +14784,6 @@ class BaseVideoParser {
|
|
14761
14784
|
// logger.log('first NALU found with overflow:' + overflow);
|
14762
14785
|
lastUnit.data = appendUint8Array(lastUnit.data, array.subarray(0, overflow));
|
14763
14786
|
lastUnit.state = 0;
|
14764
|
-
units.push(lastUnit);
|
14765
|
-
track.lastNalu = null;
|
14766
14787
|
}
|
14767
14788
|
}
|
14768
14789
|
}
|
@@ -14787,21 +14808,15 @@ class BaseVideoParser {
|
|
14787
14808
|
type: lastUnitType,
|
14788
14809
|
state: state
|
14789
14810
|
};
|
14790
|
-
|
14791
|
-
|
14792
|
-
|
14793
|
-
|
14794
|
-
|
14795
|
-
// logger.log('pushing NALU, type/size/state:' + unit.type + '/' + unit.data.byteLength + '/' + state);
|
14796
|
-
}
|
14797
|
-
} else if (units.length === 0) {
|
14798
|
-
// no NALu found
|
14811
|
+
units.push(unit);
|
14812
|
+
// logger.log('pushing NALU, type/size/state:' + unit.type + '/' + unit.data.byteLength + '/' + state);
|
14813
|
+
}
|
14814
|
+
// no NALu found
|
14815
|
+
if (units.length === 0) {
|
14799
14816
|
// append pes.data to previous NAL unit
|
14800
|
-
const lastUnit = track.
|
14817
|
+
const lastUnit = this.getLastNalUnit(track.samples);
|
14801
14818
|
if (lastUnit) {
|
14802
14819
|
lastUnit.data = appendUint8Array(lastUnit.data, array);
|
14803
|
-
units.push(lastUnit);
|
14804
|
-
track.lastNalu = null;
|
14805
14820
|
}
|
14806
14821
|
}
|
14807
14822
|
track.naluState = state;
|
@@ -14952,8 +14967,8 @@ class ExpGolomb {
|
|
14952
14967
|
}
|
14953
14968
|
|
14954
14969
|
class AvcVideoParser extends BaseVideoParser {
|
14955
|
-
parsePES(track, textTrack, pes,
|
14956
|
-
const units = this.parseNALu(track, pes.data,
|
14970
|
+
parsePES(track, textTrack, pes, endOfSegment, duration) {
|
14971
|
+
const units = this.parseNALu(track, pes.data, endOfSegment);
|
14957
14972
|
let VideoSample = this.VideoSample;
|
14958
14973
|
let push;
|
14959
14974
|
let spsfound = false;
|
@@ -15083,7 +15098,7 @@ class AvcVideoParser extends BaseVideoParser {
|
|
15083
15098
|
}
|
15084
15099
|
});
|
15085
15100
|
// if last PES packet, push samples
|
15086
|
-
if (
|
15101
|
+
if (endOfSegment && VideoSample) {
|
15087
15102
|
this.pushAccessUnit(VideoSample, track);
|
15088
15103
|
this.VideoSample = null;
|
15089
15104
|
}
|
@@ -20563,7 +20578,7 @@ class Hls {
|
|
20563
20578
|
* Get the video-dev/hls.js package version.
|
20564
20579
|
*/
|
20565
20580
|
static get version() {
|
20566
|
-
return "1.5.12-0.canary.
|
20581
|
+
return "1.5.12-0.canary.10353";
|
20567
20582
|
}
|
20568
20583
|
|
20569
20584
|
/**
|
@@ -21213,7 +21228,7 @@ class Hls {
|
|
21213
21228
|
*/
|
21214
21229
|
setAudioOption(audioOption) {
|
21215
21230
|
var _this$audioTrackContr;
|
21216
|
-
return (_this$audioTrackContr = this.audioTrackController) == null ? void 0 : _this$audioTrackContr.setAudioOption(audioOption);
|
21231
|
+
return ((_this$audioTrackContr = this.audioTrackController) == null ? void 0 : _this$audioTrackContr.setAudioOption(audioOption)) || null;
|
21217
21232
|
}
|
21218
21233
|
/**
|
21219
21234
|
* Find and select the best matching subtitle track, making a level switch when a Group change is necessary.
|
@@ -21221,8 +21236,7 @@ class Hls {
|
|
21221
21236
|
*/
|
21222
21237
|
setSubtitleOption(subtitleOption) {
|
21223
21238
|
var _this$subtitleTrackCo;
|
21224
|
-
(_this$subtitleTrackCo = this.subtitleTrackController) == null ? void 0 : _this$subtitleTrackCo.setSubtitleOption(subtitleOption);
|
21225
|
-
return null;
|
21239
|
+
return ((_this$subtitleTrackCo = this.subtitleTrackController) == null ? void 0 : _this$subtitleTrackCo.setSubtitleOption(subtitleOption)) || null;
|
21226
21240
|
}
|
21227
21241
|
|
21228
21242
|
/**
|