hls.js 1.5.6 → 1.5.7-0.canary.10015
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 +1 -0
- package/dist/hls-demo.js +10 -0
- package/dist/hls-demo.js.map +1 -1
- package/dist/hls.js +2077 -1166
- package/dist/hls.js.d.ts +65 -50
- package/dist/hls.js.map +1 -1
- package/dist/hls.light.js +1149 -858
- 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 +985 -695
- 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 +1758 -862
- 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 +21 -21
- package/src/config.ts +3 -2
- package/src/controller/abr-controller.ts +21 -20
- package/src/controller/audio-stream-controller.ts +15 -16
- package/src/controller/audio-track-controller.ts +1 -1
- package/src/controller/base-playlist-controller.ts +20 -8
- package/src/controller/base-stream-controller.ts +149 -33
- package/src/controller/buffer-controller.ts +11 -11
- package/src/controller/cap-level-controller.ts +1 -2
- package/src/controller/cmcd-controller.ts +27 -6
- package/src/controller/content-steering-controller.ts +8 -6
- package/src/controller/eme-controller.ts +9 -22
- package/src/controller/error-controller.ts +6 -8
- package/src/controller/fps-controller.ts +2 -3
- package/src/controller/gap-controller.ts +43 -16
- package/src/controller/latency-controller.ts +9 -11
- package/src/controller/level-controller.ts +12 -18
- package/src/controller/stream-controller.ts +24 -31
- package/src/controller/subtitle-stream-controller.ts +13 -14
- package/src/controller/subtitle-track-controller.ts +5 -3
- package/src/controller/timeline-controller.ts +23 -30
- package/src/crypt/aes-crypto.ts +21 -2
- package/src/crypt/decrypter-aes-mode.ts +4 -0
- package/src/crypt/decrypter.ts +32 -18
- package/src/crypt/fast-aes-key.ts +24 -5
- package/src/demux/audio/adts.ts +9 -4
- package/src/demux/sample-aes.ts +2 -0
- package/src/demux/transmuxer-interface.ts +4 -12
- package/src/demux/transmuxer-worker.ts +4 -4
- package/src/demux/transmuxer.ts +16 -3
- package/src/demux/tsdemuxer.ts +71 -37
- package/src/demux/video/avc-video-parser.ts +208 -119
- package/src/demux/video/base-video-parser.ts +134 -2
- package/src/demux/video/exp-golomb.ts +0 -208
- package/src/demux/video/hevc-video-parser.ts +746 -0
- package/src/events.ts +7 -0
- package/src/hls.ts +42 -34
- package/src/loader/fragment-loader.ts +9 -2
- package/src/loader/key-loader.ts +2 -0
- package/src/loader/level-key.ts +10 -9
- package/src/loader/playlist-loader.ts +4 -5
- package/src/remux/mp4-generator.ts +196 -1
- package/src/remux/mp4-remuxer.ts +23 -7
- package/src/task-loop.ts +5 -2
- package/src/types/component-api.ts +2 -0
- package/src/types/demuxer.ts +3 -0
- package/src/types/events.ts +4 -0
- package/src/utils/codecs.ts +33 -4
- package/src/utils/encryption-methods-util.ts +21 -0
- package/src/utils/logger.ts +54 -24
- package/src/utils/mp4-tools.ts +3 -1
package/src/task-loop.ts
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
import { type ILogger, Logger } from './utils/logger';
|
2
|
+
|
1
3
|
/**
|
2
4
|
* @ignore
|
3
5
|
* Sub-class specialization of EventHandler base class.
|
@@ -27,13 +29,14 @@
|
|
27
29
|
* we are limiting the task execution per call stack to exactly one, but scheduling/post-poning further
|
28
30
|
* task processing on the next main loop iteration (also known as "next tick" in the Node/JS runtime lingo).
|
29
31
|
*/
|
30
|
-
export default class TaskLoop {
|
32
|
+
export default class TaskLoop extends Logger {
|
31
33
|
private readonly _boundTick: () => void;
|
32
34
|
private _tickTimer: number | null = null;
|
33
35
|
private _tickInterval: number | null = null;
|
34
36
|
private _tickCallCount = 0;
|
35
37
|
|
36
|
-
constructor() {
|
38
|
+
constructor(label: string, logger: ILogger) {
|
39
|
+
super(label, logger);
|
37
40
|
this._boundTick = this.tick.bind(this);
|
38
41
|
}
|
39
42
|
|
package/src/types/demuxer.ts
CHANGED
@@ -64,6 +64,7 @@ export interface DemuxedAudioTrack extends DemuxedTrack {
|
|
64
64
|
segmentCodec?: string;
|
65
65
|
channelCount?: number;
|
66
66
|
manifestCodec?: string;
|
67
|
+
parsedCodec?: string;
|
67
68
|
samples: AudioSample[];
|
68
69
|
}
|
69
70
|
|
@@ -72,12 +73,14 @@ export interface DemuxedVideoTrackBase extends DemuxedTrack {
|
|
72
73
|
height?: number;
|
73
74
|
pixelRatio?: [number, number];
|
74
75
|
audFound?: boolean;
|
76
|
+
vps?: Uint8Array[];
|
75
77
|
pps?: Uint8Array[];
|
76
78
|
sps?: Uint8Array[];
|
77
79
|
naluState?: number;
|
78
80
|
segmentCodec?: string;
|
79
81
|
manifestCodec?: string;
|
80
82
|
samples: VideoSample[] | Uint8Array;
|
83
|
+
params?: object;
|
81
84
|
}
|
82
85
|
|
83
86
|
export interface DemuxedVideoTrack extends DemuxedVideoTrackBase {
|
package/src/types/events.ts
CHANGED
package/src/utils/codecs.ts
CHANGED
@@ -147,12 +147,15 @@ function getCodecCompatibleNameLower(
|
|
147
147
|
return CODEC_COMPATIBLE_NAMES[lowerCaseCodec]!;
|
148
148
|
}
|
149
149
|
|
150
|
-
// Idealy fLaC and Opus would be first (spec-compliant) but
|
151
|
-
// some browsers will report that fLaC is supported then fail.
|
152
|
-
// see: https://bugs.chromium.org/p/chromium/issues/detail?id=1422728
|
153
150
|
const codecsToCheck = {
|
151
|
+
// Idealy fLaC and Opus would be first (spec-compliant) but
|
152
|
+
// some browsers will report that fLaC is supported then fail.
|
153
|
+
// see: https://bugs.chromium.org/p/chromium/issues/detail?id=1422728
|
154
154
|
flac: ['flac', 'fLaC', 'FLAC'],
|
155
155
|
opus: ['opus', 'Opus'],
|
156
|
+
// Replace audio codec info if browser does not support mp4a.40.34,
|
157
|
+
// and demuxer can fallback to 'audio/mpeg' or 'audio/mp4;codecs="mp3"'
|
158
|
+
'mp4a.40.34': ['mp3'],
|
156
159
|
}[lowerCaseCodec];
|
157
160
|
|
158
161
|
for (let i = 0; i < codecsToCheck.length; i++) {
|
@@ -165,13 +168,18 @@ function getCodecCompatibleNameLower(
|
|
165
168
|
) {
|
166
169
|
CODEC_COMPATIBLE_NAMES[lowerCaseCodec] = codecsToCheck[i];
|
167
170
|
return codecsToCheck[i];
|
171
|
+
} else if (
|
172
|
+
codecsToCheck[i] === 'mp3' &&
|
173
|
+
getMediaSource(preferManagedMediaSource)?.isTypeSupported('audio/mpeg')
|
174
|
+
) {
|
175
|
+
return '';
|
168
176
|
}
|
169
177
|
}
|
170
178
|
|
171
179
|
return lowerCaseCodec;
|
172
180
|
}
|
173
181
|
|
174
|
-
const AUDIO_CODEC_REGEXP = /flac|opus/i;
|
182
|
+
const AUDIO_CODEC_REGEXP = /flac|opus|mp4a\.40\.34/i;
|
175
183
|
export function getCodecCompatibleName(
|
176
184
|
codec: string,
|
177
185
|
preferManagedMediaSource = true,
|
@@ -209,3 +217,24 @@ export function convertAVC1ToAVCOTI(codec: string) {
|
|
209
217
|
}
|
210
218
|
return codec;
|
211
219
|
}
|
220
|
+
|
221
|
+
export interface TypeSupported {
|
222
|
+
mpeg: boolean;
|
223
|
+
mp3: boolean;
|
224
|
+
ac3: boolean;
|
225
|
+
}
|
226
|
+
|
227
|
+
export function getM2TSSupportedAudioTypes(
|
228
|
+
preferManagedMediaSource: boolean,
|
229
|
+
): TypeSupported {
|
230
|
+
const MediaSource = getMediaSource(preferManagedMediaSource) || {
|
231
|
+
isTypeSupported: () => false,
|
232
|
+
};
|
233
|
+
return {
|
234
|
+
mpeg: MediaSource.isTypeSupported('audio/mpeg'),
|
235
|
+
mp3: MediaSource.isTypeSupported('audio/mp4; codecs="mp3"'),
|
236
|
+
ac3: __USE_M2TS_ADVANCED_CODECS__
|
237
|
+
? MediaSource.isTypeSupported('audio/mp4; codecs="ac-3"')
|
238
|
+
: false,
|
239
|
+
};
|
240
|
+
}
|
@@ -0,0 +1,21 @@
|
|
1
|
+
import { DecrypterAesMode } from '../crypt/decrypter-aes-mode';
|
2
|
+
|
3
|
+
export function isFullSegmentEncryption(method: string): boolean {
|
4
|
+
return (
|
5
|
+
method === 'AES-128' || method === 'AES-256' || method === 'AES-256-CTR'
|
6
|
+
);
|
7
|
+
}
|
8
|
+
|
9
|
+
export function getAesModeFromFullSegmentMethod(
|
10
|
+
method: string,
|
11
|
+
): DecrypterAesMode {
|
12
|
+
switch (method) {
|
13
|
+
case 'AES-128':
|
14
|
+
case 'AES-256':
|
15
|
+
return DecrypterAesMode.cbc;
|
16
|
+
case 'AES-256-CTR':
|
17
|
+
return DecrypterAesMode.ctr;
|
18
|
+
default:
|
19
|
+
throw new Error(`invalid full segment method ${method}`);
|
20
|
+
}
|
21
|
+
}
|
package/src/utils/logger.ts
CHANGED
@@ -11,6 +11,25 @@ export interface ILogger {
|
|
11
11
|
error: ILogFunction;
|
12
12
|
}
|
13
13
|
|
14
|
+
export class Logger implements ILogger {
|
15
|
+
trace: ILogFunction;
|
16
|
+
debug: ILogFunction;
|
17
|
+
log: ILogFunction;
|
18
|
+
warn: ILogFunction;
|
19
|
+
info: ILogFunction;
|
20
|
+
error: ILogFunction;
|
21
|
+
|
22
|
+
constructor(label: string, logger: ILogger) {
|
23
|
+
const lb = `[${label}]:`;
|
24
|
+
this.trace = noop;
|
25
|
+
this.debug = logger.debug.bind(null, lb);
|
26
|
+
this.log = logger.log.bind(null, lb);
|
27
|
+
this.warn = logger.warn.bind(null, lb);
|
28
|
+
this.info = logger.info.bind(null, lb);
|
29
|
+
this.error = logger.error.bind(null, lb);
|
30
|
+
}
|
31
|
+
}
|
32
|
+
|
14
33
|
const noop: ILogFunction = function () {};
|
15
34
|
|
16
35
|
const fakeLogger: ILogger = {
|
@@ -22,7 +41,9 @@ const fakeLogger: ILogger = {
|
|
22
41
|
error: noop,
|
23
42
|
};
|
24
43
|
|
25
|
-
|
44
|
+
function createLogger() {
|
45
|
+
return Object.assign({}, fakeLogger);
|
46
|
+
}
|
26
47
|
|
27
48
|
// let lastCallTime;
|
28
49
|
// function formatMsgWithTimeInfo(type, msg) {
|
@@ -33,33 +54,37 @@ let exportedLogger: ILogger = fakeLogger;
|
|
33
54
|
// return msg;
|
34
55
|
// }
|
35
56
|
|
36
|
-
function consolePrintFn(type: string): ILogFunction {
|
57
|
+
function consolePrintFn(type: string, id: string | undefined): ILogFunction {
|
37
58
|
const func: ILogFunction = self.console[type];
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
return noop;
|
59
|
+
return func
|
60
|
+
? func.bind(self.console, `${id ? '[' + id + '] ' : ''}[${type}] >`)
|
61
|
+
: noop;
|
42
62
|
}
|
43
63
|
|
44
|
-
function
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
});
|
64
|
+
function getLoggerFn(
|
65
|
+
key: string,
|
66
|
+
debugConfig: boolean | Partial<ILogger>,
|
67
|
+
id: string | undefined,
|
68
|
+
): ILogFunction {
|
69
|
+
return debugConfig[key]
|
70
|
+
? debugConfig[key].bind(debugConfig)
|
71
|
+
: consolePrintFn(key, id);
|
53
72
|
}
|
54
73
|
|
55
|
-
|
74
|
+
const exportedLogger: ILogger = createLogger();
|
75
|
+
|
76
|
+
export function enableLogs(
|
77
|
+
debugConfig: boolean | ILogger,
|
78
|
+
context: string,
|
79
|
+
id?: string | undefined,
|
80
|
+
): ILogger {
|
56
81
|
// check that console is available
|
82
|
+
const newLogger = createLogger();
|
57
83
|
if (
|
58
84
|
(typeof console === 'object' && debugConfig === true) ||
|
59
85
|
typeof debugConfig === 'object'
|
60
86
|
) {
|
61
|
-
|
62
|
-
debugConfig,
|
87
|
+
const keys: (keyof ILogger)[] = [
|
63
88
|
// Remove out from list here to hard-disable a log-level
|
64
89
|
// 'trace',
|
65
90
|
'debug',
|
@@ -67,19 +92,24 @@ export function enableLogs(debugConfig: boolean | ILogger, id: string): void {
|
|
67
92
|
'info',
|
68
93
|
'warn',
|
69
94
|
'error',
|
70
|
-
|
95
|
+
];
|
96
|
+
keys.forEach((key) => {
|
97
|
+
newLogger[key] = getLoggerFn(key, debugConfig, id);
|
98
|
+
});
|
71
99
|
// Some browsers don't allow to use bind on console object anyway
|
72
100
|
// fallback to default if needed
|
73
101
|
try {
|
74
|
-
|
75
|
-
`Debug logs enabled for "${
|
102
|
+
newLogger.log(
|
103
|
+
`Debug logs enabled for "${context}" in hls.js version ${__VERSION__}`,
|
76
104
|
);
|
77
105
|
} catch (e) {
|
78
|
-
|
106
|
+
/* log fn threw an exception. All logger methods are no-ops. */
|
107
|
+
return createLogger();
|
79
108
|
}
|
80
|
-
} else {
|
81
|
-
exportedLogger = fakeLogger;
|
82
109
|
}
|
110
|
+
// global exported logger uses the log methods from last call to `enableLogs`
|
111
|
+
Object.assign(exportedLogger, newLogger);
|
112
|
+
return newLogger;
|
83
113
|
}
|
84
114
|
|
85
115
|
export const logger: ILogger = exportedLogger;
|
package/src/utils/mp4-tools.ts
CHANGED
@@ -478,7 +478,9 @@ function parseStsd(stsd: Uint8Array): { codec: string; encrypted: boolean } {
|
|
478
478
|
|
479
479
|
function skipBERInteger(bytes: Uint8Array, i: number): number {
|
480
480
|
const limit = i + 5;
|
481
|
-
while (bytes[i++] & 0x80 && i < limit) {
|
481
|
+
while (bytes[i++] & 0x80 && i < limit) {
|
482
|
+
/* do nothing */
|
483
|
+
}
|
482
484
|
return i;
|
483
485
|
}
|
484
486
|
|