hls.js 1.5.6-0.canary.9999 → 1.5.6
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/README.md +0 -1
- package/dist/hls-demo.js +0 -10
- package/dist/hls-demo.js.map +1 -1
- package/dist/hls.js +1169 -2069
- package/dist/hls.js.d.ts +51 -65
- package/dist/hls.js.map +1 -1
- package/dist/hls.light.js +875 -1158
- 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 +709 -993
- 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 +869 -1756
- 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 +20 -20
- package/src/config.ts +2 -3
- package/src/controller/abr-controller.ts +40 -31
- package/src/controller/audio-stream-controller.ts +16 -15
- package/src/controller/audio-track-controller.ts +1 -1
- package/src/controller/base-playlist-controller.ts +8 -20
- package/src/controller/base-stream-controller.ts +33 -149
- package/src/controller/buffer-controller.ts +11 -11
- package/src/controller/cap-level-controller.ts +2 -1
- package/src/controller/cmcd-controller.ts +6 -27
- package/src/controller/content-steering-controller.ts +6 -8
- package/src/controller/eme-controller.ts +22 -9
- package/src/controller/error-controller.ts +8 -6
- package/src/controller/fps-controller.ts +3 -2
- package/src/controller/gap-controller.ts +16 -43
- package/src/controller/latency-controller.ts +11 -9
- package/src/controller/level-controller.ts +18 -12
- package/src/controller/stream-controller.ts +34 -27
- package/src/controller/subtitle-stream-controller.ts +14 -13
- package/src/controller/subtitle-track-controller.ts +3 -5
- package/src/controller/timeline-controller.ts +30 -23
- package/src/crypt/aes-crypto.ts +2 -21
- package/src/crypt/decrypter.ts +18 -32
- package/src/crypt/fast-aes-key.ts +5 -24
- package/src/demux/audio/adts.ts +4 -9
- package/src/demux/sample-aes.ts +0 -2
- package/src/demux/transmuxer-interface.ts +12 -4
- package/src/demux/transmuxer-worker.ts +4 -4
- package/src/demux/transmuxer.ts +3 -16
- package/src/demux/tsdemuxer.ts +37 -71
- package/src/demux/video/avc-video-parser.ts +119 -208
- package/src/demux/video/base-video-parser.ts +2 -134
- package/src/demux/video/exp-golomb.ts +208 -0
- package/src/events.ts +0 -7
- package/src/hls.ts +34 -42
- package/src/loader/fragment-loader.ts +2 -9
- package/src/loader/key-loader.ts +0 -2
- package/src/loader/level-key.ts +9 -10
- package/src/loader/playlist-loader.ts +5 -4
- package/src/remux/mp4-generator.ts +1 -196
- package/src/remux/mp4-remuxer.ts +7 -23
- package/src/task-loop.ts +2 -5
- package/src/types/component-api.ts +0 -2
- package/src/types/demuxer.ts +0 -3
- package/src/types/events.ts +0 -4
- package/src/utils/codecs.ts +4 -33
- package/src/utils/logger.ts +24 -54
- package/src/utils/mp4-tools.ts +6 -4
- package/src/crypt/decrypter-aes-mode.ts +0 -4
- package/src/demux/video/hevc-video-parser.ts +0 -746
- package/src/utils/encryption-methods-util.ts +0 -21
package/package.json
CHANGED
@@ -58,39 +58,39 @@
|
|
58
58
|
"test:func:sauce": "SAUCE=1 UA=safari OS='OS X 10.15' BABEL_ENV=development mocha --require @babel/register tests/functional/auto/setup.js --timeout 40000 --exit",
|
59
59
|
"type-check": "tsc --noEmit",
|
60
60
|
"type-check:watch": "npm run type-check -- --watch",
|
61
|
-
"prepare": "husky"
|
61
|
+
"prepare": "husky install"
|
62
62
|
},
|
63
63
|
"devDependencies": {
|
64
|
-
"@babel/core": "7.23.
|
64
|
+
"@babel/core": "7.23.7",
|
65
65
|
"@babel/helper-module-imports": "7.22.15",
|
66
66
|
"@babel/plugin-proposal-class-properties": "7.18.6",
|
67
67
|
"@babel/plugin-proposal-object-rest-spread": "7.20.7",
|
68
68
|
"@babel/plugin-proposal-optional-chaining": "7.21.0",
|
69
69
|
"@babel/plugin-transform-object-assign": "7.23.3",
|
70
|
-
"@babel/preset-env": "7.23.
|
70
|
+
"@babel/preset-env": "7.23.7",
|
71
71
|
"@babel/preset-typescript": "7.23.3",
|
72
72
|
"@babel/register": "7.23.7",
|
73
|
-
"@microsoft/api-documenter": "7.23.
|
74
|
-
"@microsoft/api-extractor": "7.
|
73
|
+
"@microsoft/api-documenter": "7.23.16",
|
74
|
+
"@microsoft/api-extractor": "7.39.1",
|
75
75
|
"@rollup/plugin-alias": "5.1.0",
|
76
76
|
"@rollup/plugin-babel": "6.0.4",
|
77
77
|
"@rollup/plugin-commonjs": "25.0.7",
|
78
78
|
"@rollup/plugin-node-resolve": "15.2.3",
|
79
79
|
"@rollup/plugin-replace": "5.0.5",
|
80
80
|
"@rollup/plugin-terser": "0.4.4",
|
81
|
-
"@rollup/plugin-typescript": "11.1.
|
82
|
-
"@svta/common-media-library": "0.6.
|
81
|
+
"@rollup/plugin-typescript": "11.1.5",
|
82
|
+
"@svta/common-media-library": "0.6.1",
|
83
83
|
"@types/chai": "4.3.11",
|
84
84
|
"@types/chart.js": "2.9.41",
|
85
85
|
"@types/mocha": "10.0.6",
|
86
86
|
"@types/sinon-chai": "3.2.12",
|
87
|
-
"@typescript-eslint/eslint-plugin": "6.
|
88
|
-
"@typescript-eslint/parser": "6.
|
87
|
+
"@typescript-eslint/eslint-plugin": "6.17.0",
|
88
|
+
"@typescript-eslint/parser": "6.17.0",
|
89
89
|
"babel-loader": "9.1.3",
|
90
90
|
"babel-plugin-transform-remove-console": "6.9.4",
|
91
|
-
"chai": "4.
|
91
|
+
"chai": "4.3.10",
|
92
92
|
"chart.js": "2.9.4",
|
93
|
-
"chromedriver": "
|
93
|
+
"chromedriver": "120.0.1",
|
94
94
|
"doctoc": "2.2.1",
|
95
95
|
"es-check": "7.1.1",
|
96
96
|
"eslint": "8.56.0",
|
@@ -101,7 +101,7 @@
|
|
101
101
|
"eslint-plugin-promise": "6.1.1",
|
102
102
|
"eventemitter3": "5.0.1",
|
103
103
|
"http-server": "14.1.1",
|
104
|
-
"husky": "
|
104
|
+
"husky": "8.0.3",
|
105
105
|
"jsonpack": "1.1.5",
|
106
106
|
"karma": "6.4.2",
|
107
107
|
"karma-chrome-launcher": "3.2.0",
|
@@ -111,24 +111,24 @@
|
|
111
111
|
"karma-rollup-preprocessor": "github:jlmakes/karma-rollup-preprocessor#7a7268d91149307b3cf2888ee4e65ccd079955a3",
|
112
112
|
"karma-sinon-chai": "2.0.2",
|
113
113
|
"karma-sourcemap-loader": "0.4.0",
|
114
|
-
"lint-staged": "15.2.
|
114
|
+
"lint-staged": "15.2.0",
|
115
115
|
"markdown-styles": "3.2.0",
|
116
116
|
"micromatch": "4.0.5",
|
117
117
|
"mocha": "10.2.0",
|
118
118
|
"node-fetch": "3.3.2",
|
119
|
-
"npm-run-
|
120
|
-
"prettier": "3.
|
119
|
+
"npm-run-all": "4.1.5",
|
120
|
+
"prettier": "3.1.1",
|
121
121
|
"promise-polyfill": "8.3.0",
|
122
|
-
"rollup": "4.9.
|
122
|
+
"rollup": "4.9.4",
|
123
123
|
"rollup-plugin-istanbul": "5.0.0",
|
124
124
|
"sauce-connect-launcher": "1.3.2",
|
125
|
-
"selenium-webdriver": "4.
|
126
|
-
"semver": "7.
|
125
|
+
"selenium-webdriver": "4.16.0",
|
126
|
+
"semver": "7.5.4",
|
127
127
|
"sinon": "17.0.1",
|
128
128
|
"sinon-chai": "3.7.0",
|
129
129
|
"typescript": "5.3.3",
|
130
130
|
"url-toolkit": "2.2.5",
|
131
|
-
"wrangler": "3.
|
131
|
+
"wrangler": "3.22.4"
|
132
132
|
},
|
133
|
-
"version": "1.5.6
|
133
|
+
"version": "1.5.6"
|
134
134
|
}
|
package/src/config.ts
CHANGED
@@ -17,10 +17,10 @@ import XhrLoader from './utils/xhr-loader';
|
|
17
17
|
import FetchLoader, { fetchSupported } from './utils/fetch-loader';
|
18
18
|
import Cues from './utils/cues';
|
19
19
|
import { requestMediaKeySystemAccess } from './utils/mediakeys-helper';
|
20
|
+
import { ILogger, logger } from './utils/logger';
|
20
21
|
|
21
22
|
import type Hls from './hls';
|
22
23
|
import type { CuesInterface } from './utils/cues';
|
23
|
-
import type { ILogger } from './utils/logger';
|
24
24
|
import type { MediaKeyFunc, KeySystems } from './utils/mediakeys-helper';
|
25
25
|
import type {
|
26
26
|
FragmentLoaderContext,
|
@@ -558,7 +558,6 @@ function timelineConfig(): TimelineControllerConfig {
|
|
558
558
|
export function mergeConfig(
|
559
559
|
defaultConfig: HlsConfig,
|
560
560
|
userConfig: Partial<HlsConfig>,
|
561
|
-
logger: ILogger,
|
562
561
|
): HlsConfig {
|
563
562
|
if (
|
564
563
|
(userConfig.liveSyncDurationCount ||
|
@@ -665,7 +664,7 @@ function deepCpy(obj: any): any {
|
|
665
664
|
/**
|
666
665
|
* @ignore
|
667
666
|
*/
|
668
|
-
export function enableStreamingMode(config
|
667
|
+
export function enableStreamingMode(config) {
|
669
668
|
const currentLoader = config.loader;
|
670
669
|
if (currentLoader !== FetchLoader && currentLoader !== XhrLoader) {
|
671
670
|
// If a developer has configured their own loader, respect that choice
|
@@ -2,7 +2,7 @@ import EwmaBandWidthEstimator from '../utils/ewma-bandwidth-estimator';
|
|
2
2
|
import { Events } from '../events';
|
3
3
|
import { ErrorDetails } from '../errors';
|
4
4
|
import { PlaylistLevelType } from '../types/loader';
|
5
|
-
import {
|
5
|
+
import { logger } from '../utils/logger';
|
6
6
|
import {
|
7
7
|
SUPPORTED_INFO_DEFAULT,
|
8
8
|
getMediaDecodingInfoPromise,
|
@@ -31,7 +31,7 @@ import type {
|
|
31
31
|
} from '../types/events';
|
32
32
|
import type { AbrComponentAPI } from '../types/component-api';
|
33
33
|
|
34
|
-
class AbrController
|
34
|
+
class AbrController implements AbrComponentAPI {
|
35
35
|
protected hls: Hls;
|
36
36
|
private lastLevelLoadSec: number = 0;
|
37
37
|
private lastLoadedFragLevel: number = -1;
|
@@ -48,7 +48,6 @@ class AbrController extends Logger implements AbrComponentAPI {
|
|
48
48
|
public bwEstimator: EwmaBandWidthEstimator;
|
49
49
|
|
50
50
|
constructor(hls: Hls) {
|
51
|
-
super('abr', hls.logger);
|
52
51
|
this.hls = hls;
|
53
52
|
this.bwEstimator = this.initEstimator();
|
54
53
|
this.registerListeners();
|
@@ -56,7 +55,7 @@ class AbrController extends Logger implements AbrComponentAPI {
|
|
56
55
|
|
57
56
|
public resetEstimator(abrEwmaDefaultEstimate?: number) {
|
58
57
|
if (abrEwmaDefaultEstimate) {
|
59
|
-
|
58
|
+
logger.log(`setting initial bwe to ${abrEwmaDefaultEstimate}`);
|
60
59
|
this.hls.config.abrEwmaDefaultEstimate = abrEwmaDefaultEstimate;
|
61
60
|
}
|
62
61
|
this.firstSelection = -1;
|
@@ -356,7 +355,7 @@ class AbrController extends Logger implements AbrComponentAPI {
|
|
356
355
|
}
|
357
356
|
|
358
357
|
this.clearTimer();
|
359
|
-
|
358
|
+
logger.warn(`[abr] Fragment ${frag.sn}${
|
360
359
|
part ? ' part ' + part.index : ''
|
361
360
|
} of level ${frag.level} is loading too slowly;
|
362
361
|
Time to underbuffer: ${bufferStarvationDelay.toFixed(3)} s
|
@@ -480,8 +479,8 @@ class AbrController extends Logger implements AbrComponentAPI {
|
|
480
479
|
}
|
481
480
|
const firstLevel = this.hls.firstLevel;
|
482
481
|
const clamped = Math.min(Math.max(firstLevel, minAutoLevel), maxAutoLevel);
|
483
|
-
|
484
|
-
`Could not find best starting auto level. Defaulting to first in playlist ${firstLevel} clamped to ${clamped}`,
|
482
|
+
logger.warn(
|
483
|
+
`[abr] Could not find best starting auto level. Defaulting to first in playlist ${firstLevel} clamped to ${clamped}`,
|
485
484
|
);
|
486
485
|
return clamped;
|
487
486
|
}
|
@@ -534,27 +533,20 @@ class AbrController extends Logger implements AbrComponentAPI {
|
|
534
533
|
}
|
535
534
|
|
536
535
|
private getAutoLevelKey(): string {
|
537
|
-
return `${this.getBwEstimate()}_${this.
|
536
|
+
return `${this.getBwEstimate()}_${this.getStarvationDelay().toFixed(2)}`;
|
538
537
|
}
|
539
538
|
|
540
539
|
private getNextABRAutoLevel(): number {
|
541
540
|
const { fragCurrent, partCurrent, hls } = this;
|
542
|
-
const { maxAutoLevel, config, minAutoLevel
|
541
|
+
const { maxAutoLevel, config, minAutoLevel } = hls;
|
543
542
|
const currentFragDuration = partCurrent
|
544
543
|
? partCurrent.duration
|
545
544
|
: fragCurrent
|
546
545
|
? fragCurrent.duration
|
547
546
|
: 0;
|
548
|
-
|
549
|
-
// playbackRate is the absolute value of the playback rate; if media.playbackRate is 0, we use 1 to load as
|
550
|
-
// if we're playing back at the normal rate.
|
551
|
-
const playbackRate =
|
552
|
-
media && media.playbackRate !== 0 ? Math.abs(media.playbackRate) : 1.0;
|
553
547
|
const avgbw = this.getBwEstimate();
|
554
548
|
// bufferStarvationDelay is the wall-clock time left until the playback buffer is exhausted.
|
555
|
-
const
|
556
|
-
const bufferStarvationDelay =
|
557
|
-
(bufferInfo ? bufferInfo.len : 0) / playbackRate;
|
549
|
+
const bufferStarvationDelay = this.getStarvationDelay();
|
558
550
|
|
559
551
|
let bwFactor = config.abrBandWidthFactor;
|
560
552
|
let bwUpFactor = config.abrBandWidthUpFactor;
|
@@ -592,8 +584,8 @@ class AbrController extends Logger implements AbrComponentAPI {
|
|
592
584
|
? Math.min(currentFragDuration, config.maxLoadingDelay)
|
593
585
|
: config.maxLoadingDelay;
|
594
586
|
maxStarvationDelay = maxLoadingDelay - bitrateTestDelay;
|
595
|
-
|
596
|
-
`bitrate test took ${Math.round(
|
587
|
+
logger.info(
|
588
|
+
`[abr] bitrate test took ${Math.round(
|
597
589
|
1000 * bitrateTestDelay,
|
598
590
|
)}ms, set first fragment max fetchDuration to ${Math.round(
|
599
591
|
1000 * maxStarvationDelay,
|
@@ -612,8 +604,8 @@ class AbrController extends Logger implements AbrComponentAPI {
|
|
612
604
|
bwFactor,
|
613
605
|
bwUpFactor,
|
614
606
|
);
|
615
|
-
|
616
|
-
|
607
|
+
logger.info(
|
608
|
+
`[abr] ${
|
617
609
|
bufferStarvationDelay ? 'rebuffering expected' : 'buffer is empty'
|
618
610
|
}, optimal quality level ${bestLevel}`,
|
619
611
|
);
|
@@ -630,6 +622,20 @@ class AbrController extends Logger implements AbrComponentAPI {
|
|
630
622
|
return hls.loadLevel;
|
631
623
|
}
|
632
624
|
|
625
|
+
private getStarvationDelay(): number {
|
626
|
+
const hls = this.hls;
|
627
|
+
const media = hls.media;
|
628
|
+
if (!media) {
|
629
|
+
return Infinity;
|
630
|
+
}
|
631
|
+
// playbackRate is the absolute value of the playback rate; if media.playbackRate is 0, we use 1 to load as
|
632
|
+
// if we're playing back at the normal rate.
|
633
|
+
const playbackRate =
|
634
|
+
media && media.playbackRate !== 0 ? Math.abs(media.playbackRate) : 1.0;
|
635
|
+
const bufferInfo = hls.mainForwardBufferInfo;
|
636
|
+
return (bufferInfo ? bufferInfo.len : 0) / playbackRate;
|
637
|
+
}
|
638
|
+
|
633
639
|
private getBwEstimate(): number {
|
634
640
|
return this.bwEstimator.canEstimate()
|
635
641
|
? this.bwEstimator.getEstimate()
|
@@ -692,7 +698,7 @@ class AbrController extends Logger implements AbrComponentAPI {
|
|
692
698
|
: videoRanges[0];
|
693
699
|
currentFrameRate = minFramerate;
|
694
700
|
currentBw = Math.max(currentBw, minBitrate);
|
695
|
-
|
701
|
+
logger.log(`[abr] picked start tier ${JSON.stringify(startTier)}`);
|
696
702
|
} else {
|
697
703
|
currentCodecSet = level?.codecSet;
|
698
704
|
currentVideoRange = level?.videoRange;
|
@@ -738,23 +744,26 @@ class AbrController extends Logger implements AbrComponentAPI {
|
|
738
744
|
mediaCapabilities,
|
739
745
|
);
|
740
746
|
levelInfo.supportedPromise.then((decodingInfo) => {
|
747
|
+
if (!this.hls) {
|
748
|
+
return;
|
749
|
+
}
|
741
750
|
levelInfo.supportedResult = decodingInfo;
|
742
751
|
const levels = this.hls.levels;
|
743
752
|
const index = levels.indexOf(levelInfo);
|
744
753
|
if (decodingInfo.error) {
|
745
|
-
|
746
|
-
`MediaCapabilities decodingInfo error: "${
|
754
|
+
logger.warn(
|
755
|
+
`[abr] MediaCapabilities decodingInfo error: "${
|
747
756
|
decodingInfo.error
|
748
757
|
}" for level ${index} ${JSON.stringify(decodingInfo)}`,
|
749
758
|
);
|
750
759
|
} else if (!decodingInfo.supported) {
|
751
|
-
|
752
|
-
`Unsupported MediaCapabilities decodingInfo result for level ${index} ${JSON.stringify(
|
760
|
+
logger.warn(
|
761
|
+
`[abr] Unsupported MediaCapabilities decodingInfo result for level ${index} ${JSON.stringify(
|
753
762
|
decodingInfo,
|
754
763
|
)}`,
|
755
764
|
);
|
756
765
|
if (index > -1 && levels.length > 1) {
|
757
|
-
|
766
|
+
logger.log(`[abr] Removing unsupported level ${index}`);
|
758
767
|
this.hls.removeLevel(index);
|
759
768
|
}
|
760
769
|
}
|
@@ -833,8 +842,8 @@ class AbrController extends Logger implements AbrComponentAPI {
|
|
833
842
|
(forcedAutoLevel === -1 || forcedAutoLevel !== loadLevel)
|
834
843
|
) {
|
835
844
|
if (levelsSkipped.length) {
|
836
|
-
|
837
|
-
`Skipped level(s) ${levelsSkipped.join(
|
845
|
+
logger.trace(
|
846
|
+
`[abr] Skipped level(s) ${levelsSkipped.join(
|
838
847
|
',',
|
839
848
|
)} of ${maxAutoLevel} max with CODECS and VIDEO-RANGE:"${
|
840
849
|
levels[levelsSkipped[0]].codecs
|
@@ -843,8 +852,8 @@ class AbrController extends Logger implements AbrComponentAPI {
|
|
843
852
|
}" ${currentVideoRange}`,
|
844
853
|
);
|
845
854
|
}
|
846
|
-
|
847
|
-
`switch candidate:${selectionBaseLevel}->${i} adjustedbw(${Math.round(
|
855
|
+
logger.info(
|
856
|
+
`[abr] switch candidate:${selectionBaseLevel}->${i} adjustedbw(${Math.round(
|
848
857
|
adjustedbw,
|
849
858
|
)})-bitrate=${Math.round(
|
850
859
|
adjustedbw - bitrate,
|
@@ -71,27 +71,30 @@ class AudioStreamController
|
|
71
71
|
hls,
|
72
72
|
fragmentTracker,
|
73
73
|
keyLoader,
|
74
|
-
'audio-stream-controller',
|
74
|
+
'[audio-stream-controller]',
|
75
75
|
PlaylistLevelType.AUDIO,
|
76
76
|
);
|
77
|
-
this.
|
77
|
+
this._registerListeners();
|
78
78
|
}
|
79
79
|
|
80
80
|
protected onHandlerDestroying() {
|
81
|
-
this.
|
81
|
+
this._unregisterListeners();
|
82
82
|
super.onHandlerDestroying();
|
83
83
|
this.mainDetails = null;
|
84
84
|
this.bufferedTrack = null;
|
85
85
|
this.switchingTrack = null;
|
86
86
|
}
|
87
87
|
|
88
|
-
|
89
|
-
super.registerListeners();
|
88
|
+
private _registerListeners() {
|
90
89
|
const { hls } = this;
|
90
|
+
hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
|
91
|
+
hls.on(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
|
92
|
+
hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);
|
91
93
|
hls.on(Events.LEVEL_LOADED, this.onLevelLoaded, this);
|
92
94
|
hls.on(Events.AUDIO_TRACKS_UPDATED, this.onAudioTracksUpdated, this);
|
93
95
|
hls.on(Events.AUDIO_TRACK_SWITCHING, this.onAudioTrackSwitching, this);
|
94
96
|
hls.on(Events.AUDIO_TRACK_LOADED, this.onAudioTrackLoaded, this);
|
97
|
+
hls.on(Events.ERROR, this.onError, this);
|
95
98
|
hls.on(Events.BUFFER_RESET, this.onBufferReset, this);
|
96
99
|
hls.on(Events.BUFFER_CREATED, this.onBufferCreated, this);
|
97
100
|
hls.on(Events.BUFFER_FLUSHING, this.onBufferFlushing, this);
|
@@ -100,16 +103,16 @@ class AudioStreamController
|
|
100
103
|
hls.on(Events.FRAG_BUFFERED, this.onFragBuffered, this);
|
101
104
|
}
|
102
105
|
|
103
|
-
|
106
|
+
private _unregisterListeners() {
|
104
107
|
const { hls } = this;
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
super.unregisterListeners();
|
108
|
+
hls.off(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
|
109
|
+
hls.off(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
|
110
|
+
hls.off(Events.MANIFEST_LOADING, this.onManifestLoading, this);
|
109
111
|
hls.off(Events.LEVEL_LOADED, this.onLevelLoaded, this);
|
110
112
|
hls.off(Events.AUDIO_TRACKS_UPDATED, this.onAudioTracksUpdated, this);
|
111
113
|
hls.off(Events.AUDIO_TRACK_SWITCHING, this.onAudioTrackSwitching, this);
|
112
114
|
hls.off(Events.AUDIO_TRACK_LOADED, this.onAudioTrackLoaded, this);
|
115
|
+
hls.off(Events.ERROR, this.onError, this);
|
113
116
|
hls.off(Events.BUFFER_RESET, this.onBufferReset, this);
|
114
117
|
hls.off(Events.BUFFER_CREATED, this.onBufferCreated, this);
|
115
118
|
hls.off(Events.BUFFER_FLUSHING, this.onBufferFlushing, this);
|
@@ -278,14 +281,12 @@ class AudioStreamController
|
|
278
281
|
const { hls, levels, media, trackId } = this;
|
279
282
|
const config = hls.config;
|
280
283
|
|
281
|
-
// 1. if
|
282
|
-
// 2. if video not attached AND
|
284
|
+
// 1. if video not attached AND
|
283
285
|
// start fragment already requested OR start frag prefetch not enabled
|
284
|
-
//
|
286
|
+
// 2. if tracks or track not loaded and selected
|
285
287
|
// then exit loop
|
286
288
|
// => if media not attached but start frag prefetch is enabled and start frag not requested yet, we will not exit loop
|
287
289
|
if (
|
288
|
-
!this.buffering ||
|
289
290
|
(!media && (this.startFragRequested || !config.startFragPrefetch)) ||
|
290
291
|
!levels?.[trackId]
|
291
292
|
) {
|
@@ -712,7 +713,7 @@ class AudioStreamController
|
|
712
713
|
this.fragBufferedComplete(frag, part);
|
713
714
|
}
|
714
715
|
|
715
|
-
|
716
|
+
private onError(event: Events.ERROR, data: ErrorData) {
|
716
717
|
if (data.fatal) {
|
717
718
|
this.state = State.ERROR;
|
718
719
|
return;
|
@@ -5,7 +5,7 @@ import { computeReloadInterval, mergeDetails } from '../utils/level-helper';
|
|
5
5
|
import { ErrorData } from '../types/events';
|
6
6
|
import { getRetryDelay, isTimeoutError } from '../utils/error-helper';
|
7
7
|
import { NetworkErrorAction } from './error-controller';
|
8
|
-
import {
|
8
|
+
import { logger } from '../utils/logger';
|
9
9
|
import type { LevelDetails } from '../loader/level-details';
|
10
10
|
import type { MediaPlaylist } from '../types/media-playlist';
|
11
11
|
import type {
|
@@ -14,17 +14,17 @@ import type {
|
|
14
14
|
TrackLoadedData,
|
15
15
|
} from '../types/events';
|
16
16
|
|
17
|
-
export default class BasePlaylistController
|
18
|
-
extends Logger
|
19
|
-
implements NetworkComponentAPI
|
20
|
-
{
|
17
|
+
export default class BasePlaylistController implements NetworkComponentAPI {
|
21
18
|
protected hls: Hls;
|
22
19
|
protected timer: number = -1;
|
23
20
|
protected requestScheduled: number = -1;
|
24
21
|
protected canLoad: boolean = false;
|
22
|
+
protected log: (msg: any) => void;
|
23
|
+
protected warn: (msg: any) => void;
|
25
24
|
|
26
25
|
constructor(hls: Hls, logPrefix: string) {
|
27
|
-
|
26
|
+
this.log = logger.log.bind(logger, `${logPrefix}:`);
|
27
|
+
this.warn = logger.warn.bind(logger, `${logPrefix}:`);
|
28
28
|
this.hls = hls;
|
29
29
|
}
|
30
30
|
|
@@ -65,7 +65,7 @@ export default class BasePlaylistController
|
|
65
65
|
try {
|
66
66
|
uri = new self.URL(attr.URI, previous.url).href;
|
67
67
|
} catch (error) {
|
68
|
-
|
68
|
+
logger.warn(
|
69
69
|
`Could not construct new URL for Rendition Report: ${error}`,
|
70
70
|
);
|
71
71
|
uri = attr.URI || '';
|
@@ -192,19 +192,7 @@ export default class BasePlaylistController
|
|
192
192
|
details.targetduration * 1.5,
|
193
193
|
);
|
194
194
|
if (currentGoal > 0) {
|
195
|
-
if (
|
196
|
-
// Omit segment and part directives when the last response was more than 3 target durations ago,
|
197
|
-
this.log(
|
198
|
-
`Playlist last advanced ${lastAdvanced.toFixed(
|
199
|
-
2,
|
200
|
-
)}s ago. Omitting segment and part directives.`,
|
201
|
-
);
|
202
|
-
msn = undefined;
|
203
|
-
part = undefined;
|
204
|
-
} else if (
|
205
|
-
previousDetails?.tuneInGoal &&
|
206
|
-
cdnAge - details.partTarget > previousDetails.tuneInGoal
|
207
|
-
) {
|
195
|
+
if (previousDetails && currentGoal > previousDetails.tuneInGoal) {
|
208
196
|
// If we attempted to get the next or latest playlist update, but currentGoal increased,
|
209
197
|
// then we either can't catchup, or the "age" header cannot be trusted.
|
210
198
|
this.warn(
|