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
@@ -1,15 +1,12 @@
|
|
1
1
|
import type { ParsedVideoSample } from '../tsdemuxer';
|
2
|
-
import
|
2
|
+
import {
|
3
3
|
DemuxedVideoTrack,
|
4
|
-
DemuxedUserdataTrack,
|
5
4
|
VideoSample,
|
6
5
|
VideoSampleUnit,
|
7
6
|
} from '../../types/demuxer';
|
8
|
-
import type { PES } from '../tsdemuxer';
|
9
7
|
import { logger } from '../../utils/logger';
|
10
|
-
import { appendUint8Array } from '../../utils/mp4-tools';
|
11
8
|
|
12
|
-
|
9
|
+
class BaseVideoParser {
|
13
10
|
protected VideoSample: ParsedVideoSample | null = null;
|
14
11
|
|
15
12
|
protected createVideoSample(
|
@@ -72,135 +69,6 @@ abstract class BaseVideoParser {
|
|
72
69
|
);
|
73
70
|
}
|
74
71
|
}
|
75
|
-
|
76
|
-
abstract parsePES(
|
77
|
-
track: DemuxedVideoTrack,
|
78
|
-
textTrack: DemuxedUserdataTrack,
|
79
|
-
pes: PES,
|
80
|
-
last: boolean,
|
81
|
-
duration: number,
|
82
|
-
);
|
83
|
-
|
84
|
-
protected abstract getNALuType(data: Uint8Array, offset: number): number;
|
85
|
-
|
86
|
-
protected parseNALu(
|
87
|
-
track: DemuxedVideoTrack,
|
88
|
-
array: Uint8Array,
|
89
|
-
): Array<{
|
90
|
-
data: Uint8Array;
|
91
|
-
type: number;
|
92
|
-
state?: number;
|
93
|
-
}> {
|
94
|
-
const len = array.byteLength;
|
95
|
-
let state = track.naluState || 0;
|
96
|
-
const lastState = state;
|
97
|
-
const units: VideoSampleUnit[] = [];
|
98
|
-
let i = 0;
|
99
|
-
let value: number;
|
100
|
-
let overflow: number;
|
101
|
-
let unitType: number;
|
102
|
-
let lastUnitStart = -1;
|
103
|
-
let lastUnitType: number = 0;
|
104
|
-
// logger.log('PES:' + Hex.hexDump(array));
|
105
|
-
|
106
|
-
if (state === -1) {
|
107
|
-
// special use case where we found 3 or 4-byte start codes exactly at the end of previous PES packet
|
108
|
-
lastUnitStart = 0;
|
109
|
-
// NALu type is value read from offset 0
|
110
|
-
lastUnitType = this.getNALuType(array, 0);
|
111
|
-
state = 0;
|
112
|
-
i = 1;
|
113
|
-
}
|
114
|
-
|
115
|
-
while (i < len) {
|
116
|
-
value = array[i++];
|
117
|
-
// optimization. state 0 and 1 are the predominant case. let's handle them outside of the switch/case
|
118
|
-
if (!state) {
|
119
|
-
state = value ? 0 : 1;
|
120
|
-
continue;
|
121
|
-
}
|
122
|
-
if (state === 1) {
|
123
|
-
state = value ? 0 : 2;
|
124
|
-
continue;
|
125
|
-
}
|
126
|
-
// here we have state either equal to 2 or 3
|
127
|
-
if (!value) {
|
128
|
-
state = 3;
|
129
|
-
} else if (value === 1) {
|
130
|
-
overflow = i - state - 1;
|
131
|
-
if (lastUnitStart >= 0) {
|
132
|
-
const unit: VideoSampleUnit = {
|
133
|
-
data: array.subarray(lastUnitStart, overflow),
|
134
|
-
type: lastUnitType,
|
135
|
-
};
|
136
|
-
// logger.log('pushing NALU, type/size:' + unit.type + '/' + unit.data.byteLength);
|
137
|
-
units.push(unit);
|
138
|
-
} else {
|
139
|
-
// lastUnitStart is undefined => this is the first start code found in this PES packet
|
140
|
-
// first check if start code delimiter is overlapping between 2 PES packets,
|
141
|
-
// ie it started in last packet (lastState not zero)
|
142
|
-
// and ended at the beginning of this PES packet (i <= 4 - lastState)
|
143
|
-
const lastUnit = this.getLastNalUnit(track.samples);
|
144
|
-
if (lastUnit) {
|
145
|
-
if (lastState && i <= 4 - lastState) {
|
146
|
-
// start delimiter overlapping between PES packets
|
147
|
-
// strip start delimiter bytes from the end of last NAL unit
|
148
|
-
// check if lastUnit had a state different from zero
|
149
|
-
if (lastUnit.state) {
|
150
|
-
// strip last bytes
|
151
|
-
lastUnit.data = lastUnit.data.subarray(
|
152
|
-
0,
|
153
|
-
lastUnit.data.byteLength - lastState,
|
154
|
-
);
|
155
|
-
}
|
156
|
-
}
|
157
|
-
// If NAL units are not starting right at the beginning of the PES packet, push preceding data into previous NAL unit.
|
158
|
-
|
159
|
-
if (overflow > 0) {
|
160
|
-
// logger.log('first NALU found with overflow:' + overflow);
|
161
|
-
lastUnit.data = appendUint8Array(
|
162
|
-
lastUnit.data,
|
163
|
-
array.subarray(0, overflow),
|
164
|
-
);
|
165
|
-
lastUnit.state = 0;
|
166
|
-
}
|
167
|
-
}
|
168
|
-
}
|
169
|
-
// check if we can read unit type
|
170
|
-
if (i < len) {
|
171
|
-
unitType = this.getNALuType(array, i);
|
172
|
-
// logger.log('find NALU @ offset:' + i + ',type:' + unitType);
|
173
|
-
lastUnitStart = i;
|
174
|
-
lastUnitType = unitType;
|
175
|
-
state = 0;
|
176
|
-
} else {
|
177
|
-
// not enough byte to read unit type. let's read it on next PES parsing
|
178
|
-
state = -1;
|
179
|
-
}
|
180
|
-
} else {
|
181
|
-
state = 0;
|
182
|
-
}
|
183
|
-
}
|
184
|
-
if (lastUnitStart >= 0 && state >= 0) {
|
185
|
-
const unit: VideoSampleUnit = {
|
186
|
-
data: array.subarray(lastUnitStart, len),
|
187
|
-
type: lastUnitType,
|
188
|
-
state: state,
|
189
|
-
};
|
190
|
-
units.push(unit);
|
191
|
-
// logger.log('pushing NALU, type/size/state:' + unit.type + '/' + unit.data.byteLength + '/' + state);
|
192
|
-
}
|
193
|
-
// no NALu found
|
194
|
-
if (units.length === 0) {
|
195
|
-
// append pes.data to previous NAL unit
|
196
|
-
const lastUnit = this.getLastNalUnit(track.samples);
|
197
|
-
if (lastUnit) {
|
198
|
-
lastUnit.data = appendUint8Array(lastUnit.data, array);
|
199
|
-
}
|
200
|
-
}
|
201
|
-
track.naluState = state;
|
202
|
-
return units;
|
203
|
-
}
|
204
72
|
}
|
205
73
|
|
206
74
|
export default BaseVideoParser;
|
@@ -148,6 +148,214 @@ class ExpGolomb {
|
|
148
148
|
readUInt(): number {
|
149
149
|
return this.readBits(32);
|
150
150
|
}
|
151
|
+
|
152
|
+
/**
|
153
|
+
* Advance the ExpGolomb decoder past a scaling list. The scaling
|
154
|
+
* list is optionally transmitted as part of a sequence parameter
|
155
|
+
* set and is not relevant to transmuxing.
|
156
|
+
* @param count the number of entries in this scaling list
|
157
|
+
* @see Recommendation ITU-T H.264, Section 7.3.2.1.1.1
|
158
|
+
*/
|
159
|
+
skipScalingList(count: number): void {
|
160
|
+
let lastScale = 8;
|
161
|
+
let nextScale = 8;
|
162
|
+
let deltaScale;
|
163
|
+
for (let j = 0; j < count; j++) {
|
164
|
+
if (nextScale !== 0) {
|
165
|
+
deltaScale = this.readEG();
|
166
|
+
nextScale = (lastScale + deltaScale + 256) % 256;
|
167
|
+
}
|
168
|
+
lastScale = nextScale === 0 ? lastScale : nextScale;
|
169
|
+
}
|
170
|
+
}
|
171
|
+
|
172
|
+
/**
|
173
|
+
* Read a sequence parameter set and return some interesting video
|
174
|
+
* properties. A sequence parameter set is the H264 metadata that
|
175
|
+
* describes the properties of upcoming video frames.
|
176
|
+
* @returns an object with configuration parsed from the
|
177
|
+
* sequence parameter set, including the dimensions of the
|
178
|
+
* associated video frames.
|
179
|
+
*/
|
180
|
+
readSPS(): {
|
181
|
+
width: number;
|
182
|
+
height: number;
|
183
|
+
pixelRatio: [number, number];
|
184
|
+
} {
|
185
|
+
let frameCropLeftOffset = 0;
|
186
|
+
let frameCropRightOffset = 0;
|
187
|
+
let frameCropTopOffset = 0;
|
188
|
+
let frameCropBottomOffset = 0;
|
189
|
+
let numRefFramesInPicOrderCntCycle;
|
190
|
+
let scalingListCount;
|
191
|
+
let i;
|
192
|
+
const readUByte = this.readUByte.bind(this);
|
193
|
+
const readBits = this.readBits.bind(this);
|
194
|
+
const readUEG = this.readUEG.bind(this);
|
195
|
+
const readBoolean = this.readBoolean.bind(this);
|
196
|
+
const skipBits = this.skipBits.bind(this);
|
197
|
+
const skipEG = this.skipEG.bind(this);
|
198
|
+
const skipUEG = this.skipUEG.bind(this);
|
199
|
+
const skipScalingList = this.skipScalingList.bind(this);
|
200
|
+
|
201
|
+
readUByte();
|
202
|
+
const profileIdc = readUByte(); // profile_idc
|
203
|
+
readBits(5); // profileCompat constraint_set[0-4]_flag, u(5)
|
204
|
+
skipBits(3); // reserved_zero_3bits u(3),
|
205
|
+
readUByte(); // level_idc u(8)
|
206
|
+
skipUEG(); // seq_parameter_set_id
|
207
|
+
// some profiles have more optional data we don't need
|
208
|
+
if (
|
209
|
+
profileIdc === 100 ||
|
210
|
+
profileIdc === 110 ||
|
211
|
+
profileIdc === 122 ||
|
212
|
+
profileIdc === 244 ||
|
213
|
+
profileIdc === 44 ||
|
214
|
+
profileIdc === 83 ||
|
215
|
+
profileIdc === 86 ||
|
216
|
+
profileIdc === 118 ||
|
217
|
+
profileIdc === 128
|
218
|
+
) {
|
219
|
+
const chromaFormatIdc = readUEG();
|
220
|
+
if (chromaFormatIdc === 3) {
|
221
|
+
skipBits(1);
|
222
|
+
} // separate_colour_plane_flag
|
223
|
+
|
224
|
+
skipUEG(); // bit_depth_luma_minus8
|
225
|
+
skipUEG(); // bit_depth_chroma_minus8
|
226
|
+
skipBits(1); // qpprime_y_zero_transform_bypass_flag
|
227
|
+
if (readBoolean()) {
|
228
|
+
// seq_scaling_matrix_present_flag
|
229
|
+
scalingListCount = chromaFormatIdc !== 3 ? 8 : 12;
|
230
|
+
for (i = 0; i < scalingListCount; i++) {
|
231
|
+
if (readBoolean()) {
|
232
|
+
// seq_scaling_list_present_flag[ i ]
|
233
|
+
if (i < 6) {
|
234
|
+
skipScalingList(16);
|
235
|
+
} else {
|
236
|
+
skipScalingList(64);
|
237
|
+
}
|
238
|
+
}
|
239
|
+
}
|
240
|
+
}
|
241
|
+
}
|
242
|
+
skipUEG(); // log2_max_frame_num_minus4
|
243
|
+
const picOrderCntType = readUEG();
|
244
|
+
if (picOrderCntType === 0) {
|
245
|
+
readUEG(); // log2_max_pic_order_cnt_lsb_minus4
|
246
|
+
} else if (picOrderCntType === 1) {
|
247
|
+
skipBits(1); // delta_pic_order_always_zero_flag
|
248
|
+
skipEG(); // offset_for_non_ref_pic
|
249
|
+
skipEG(); // offset_for_top_to_bottom_field
|
250
|
+
numRefFramesInPicOrderCntCycle = readUEG();
|
251
|
+
for (i = 0; i < numRefFramesInPicOrderCntCycle; i++) {
|
252
|
+
skipEG();
|
253
|
+
} // offset_for_ref_frame[ i ]
|
254
|
+
}
|
255
|
+
skipUEG(); // max_num_ref_frames
|
256
|
+
skipBits(1); // gaps_in_frame_num_value_allowed_flag
|
257
|
+
const picWidthInMbsMinus1 = readUEG();
|
258
|
+
const picHeightInMapUnitsMinus1 = readUEG();
|
259
|
+
const frameMbsOnlyFlag = readBits(1);
|
260
|
+
if (frameMbsOnlyFlag === 0) {
|
261
|
+
skipBits(1);
|
262
|
+
} // mb_adaptive_frame_field_flag
|
263
|
+
|
264
|
+
skipBits(1); // direct_8x8_inference_flag
|
265
|
+
if (readBoolean()) {
|
266
|
+
// frame_cropping_flag
|
267
|
+
frameCropLeftOffset = readUEG();
|
268
|
+
frameCropRightOffset = readUEG();
|
269
|
+
frameCropTopOffset = readUEG();
|
270
|
+
frameCropBottomOffset = readUEG();
|
271
|
+
}
|
272
|
+
let pixelRatio: [number, number] = [1, 1];
|
273
|
+
if (readBoolean()) {
|
274
|
+
// vui_parameters_present_flag
|
275
|
+
if (readBoolean()) {
|
276
|
+
// aspect_ratio_info_present_flag
|
277
|
+
const aspectRatioIdc = readUByte();
|
278
|
+
switch (aspectRatioIdc) {
|
279
|
+
case 1:
|
280
|
+
pixelRatio = [1, 1];
|
281
|
+
break;
|
282
|
+
case 2:
|
283
|
+
pixelRatio = [12, 11];
|
284
|
+
break;
|
285
|
+
case 3:
|
286
|
+
pixelRatio = [10, 11];
|
287
|
+
break;
|
288
|
+
case 4:
|
289
|
+
pixelRatio = [16, 11];
|
290
|
+
break;
|
291
|
+
case 5:
|
292
|
+
pixelRatio = [40, 33];
|
293
|
+
break;
|
294
|
+
case 6:
|
295
|
+
pixelRatio = [24, 11];
|
296
|
+
break;
|
297
|
+
case 7:
|
298
|
+
pixelRatio = [20, 11];
|
299
|
+
break;
|
300
|
+
case 8:
|
301
|
+
pixelRatio = [32, 11];
|
302
|
+
break;
|
303
|
+
case 9:
|
304
|
+
pixelRatio = [80, 33];
|
305
|
+
break;
|
306
|
+
case 10:
|
307
|
+
pixelRatio = [18, 11];
|
308
|
+
break;
|
309
|
+
case 11:
|
310
|
+
pixelRatio = [15, 11];
|
311
|
+
break;
|
312
|
+
case 12:
|
313
|
+
pixelRatio = [64, 33];
|
314
|
+
break;
|
315
|
+
case 13:
|
316
|
+
pixelRatio = [160, 99];
|
317
|
+
break;
|
318
|
+
case 14:
|
319
|
+
pixelRatio = [4, 3];
|
320
|
+
break;
|
321
|
+
case 15:
|
322
|
+
pixelRatio = [3, 2];
|
323
|
+
break;
|
324
|
+
case 16:
|
325
|
+
pixelRatio = [2, 1];
|
326
|
+
break;
|
327
|
+
case 255: {
|
328
|
+
pixelRatio = [
|
329
|
+
(readUByte() << 8) | readUByte(),
|
330
|
+
(readUByte() << 8) | readUByte(),
|
331
|
+
];
|
332
|
+
break;
|
333
|
+
}
|
334
|
+
}
|
335
|
+
}
|
336
|
+
}
|
337
|
+
return {
|
338
|
+
width: Math.ceil(
|
339
|
+
(picWidthInMbsMinus1 + 1) * 16 -
|
340
|
+
frameCropLeftOffset * 2 -
|
341
|
+
frameCropRightOffset * 2,
|
342
|
+
),
|
343
|
+
height:
|
344
|
+
(2 - frameMbsOnlyFlag) * (picHeightInMapUnitsMinus1 + 1) * 16 -
|
345
|
+
(frameMbsOnlyFlag ? 2 : 4) *
|
346
|
+
(frameCropTopOffset + frameCropBottomOffset),
|
347
|
+
pixelRatio: pixelRatio,
|
348
|
+
};
|
349
|
+
}
|
350
|
+
|
351
|
+
readSliceType() {
|
352
|
+
// skip NALu type
|
353
|
+
this.readUByte();
|
354
|
+
// discard first_mb_in_slice
|
355
|
+
this.readUEG();
|
356
|
+
// return slice_type
|
357
|
+
return this.readUEG();
|
358
|
+
}
|
151
359
|
}
|
152
360
|
|
153
361
|
export default ExpGolomb;
|
package/src/events.ts
CHANGED
@@ -3,7 +3,6 @@ import {
|
|
3
3
|
ManifestLoadingData,
|
4
4
|
MediaAttachedData,
|
5
5
|
MediaAttachingData,
|
6
|
-
MediaEndedData,
|
7
6
|
LevelLoadingData,
|
8
7
|
LevelLoadedData,
|
9
8
|
ManifestParsedData,
|
@@ -61,8 +60,6 @@ export enum Events {
|
|
61
60
|
MEDIA_DETACHING = 'hlsMediaDetaching',
|
62
61
|
// Fired when MediaSource has been detached from media element
|
63
62
|
MEDIA_DETACHED = 'hlsMediaDetached',
|
64
|
-
// Fired when HTMLMediaElement dispatches "ended" event, or stalls at end of VOD program
|
65
|
-
MEDIA_ENDED = 'hlsMediaEnded',
|
66
63
|
// Fired when the buffer is going to be reset
|
67
64
|
BUFFER_RESET = 'hlsBufferReset',
|
68
65
|
// Fired when we know about the codecs that we need buffers for to push into - data: {tracks : { container, codec, levelCodec, initSegment, metadata }}
|
@@ -187,10 +184,6 @@ export interface HlsListeners {
|
|
187
184
|
) => void;
|
188
185
|
[Events.MEDIA_DETACHING]: (event: Events.MEDIA_DETACHING) => void;
|
189
186
|
[Events.MEDIA_DETACHED]: (event: Events.MEDIA_DETACHED) => void;
|
190
|
-
[Events.MEDIA_ENDED]: (
|
191
|
-
event: Events.MEDIA_ENDED,
|
192
|
-
data: MediaEndedData,
|
193
|
-
) => void;
|
194
187
|
[Events.BUFFER_RESET]: (event: Events.BUFFER_RESET) => void;
|
195
188
|
[Events.BUFFER_CODECS]: (
|
196
189
|
event: Events.BUFFER_CODECS,
|
package/src/hls.ts
CHANGED
@@ -8,7 +8,7 @@ import KeyLoader from './loader/key-loader';
|
|
8
8
|
import StreamController from './controller/stream-controller';
|
9
9
|
import { isMSESupported, isSupported } from './is-supported';
|
10
10
|
import { getMediaSource } from './utils/mediasource-helper';
|
11
|
-
import {
|
11
|
+
import { logger, enableLogs } from './utils/logger';
|
12
12
|
import { enableStreamingMode, hlsDefaultConfig, mergeConfig } from './config';
|
13
13
|
import { EventEmitter } from 'eventemitter3';
|
14
14
|
import { Events } from './events';
|
@@ -59,13 +59,9 @@ export default class Hls implements HlsEventEmitter {
|
|
59
59
|
*/
|
60
60
|
public readonly userConfig: Partial<HlsConfig>;
|
61
61
|
|
62
|
-
/**
|
63
|
-
* The logger functions used by this player instance, configured on player instantiation.
|
64
|
-
*/
|
65
|
-
public readonly logger: ILogger;
|
66
|
-
|
67
62
|
private coreComponents: ComponentAPI[];
|
68
63
|
private networkControllers: NetworkComponentAPI[];
|
64
|
+
private started: boolean = false;
|
69
65
|
private _emitter: HlsEventEmitter = new EventEmitter();
|
70
66
|
private _autoLevelCapping: number = -1;
|
71
67
|
private _maxHdcpLevel: HdcpLevel = null;
|
@@ -146,19 +142,12 @@ export default class Hls implements HlsEventEmitter {
|
|
146
142
|
* @param userConfig - Configuration options applied over `Hls.DefaultConfig`
|
147
143
|
*/
|
148
144
|
constructor(userConfig: Partial<HlsConfig> = {}) {
|
149
|
-
|
150
|
-
|
151
|
-
'Hls instance',
|
152
|
-
));
|
153
|
-
const config = (this.config = mergeConfig(
|
154
|
-
Hls.DefaultConfig,
|
155
|
-
userConfig,
|
156
|
-
logger,
|
157
|
-
));
|
145
|
+
enableLogs(userConfig.debug || false, 'Hls instance');
|
146
|
+
const config = (this.config = mergeConfig(Hls.DefaultConfig, userConfig));
|
158
147
|
this.userConfig = userConfig;
|
159
148
|
|
160
149
|
if (config.progressive) {
|
161
|
-
enableStreamingMode(config
|
150
|
+
enableStreamingMode(config);
|
162
151
|
}
|
163
152
|
|
164
153
|
// core controllers and network loaders
|
@@ -331,7 +320,7 @@ export default class Hls implements HlsEventEmitter {
|
|
331
320
|
try {
|
332
321
|
return this.emit(event, event, eventObject);
|
333
322
|
} catch (error) {
|
334
|
-
|
323
|
+
logger.error(
|
335
324
|
'An internal error happened while handling event ' +
|
336
325
|
event +
|
337
326
|
'. Error message: "' +
|
@@ -365,7 +354,7 @@ export default class Hls implements HlsEventEmitter {
|
|
365
354
|
* Dispose of the instance
|
366
355
|
*/
|
367
356
|
destroy() {
|
368
|
-
|
357
|
+
logger.log('destroy');
|
369
358
|
this.trigger(Events.DESTROYING, undefined);
|
370
359
|
this.detachMedia();
|
371
360
|
this.removeAllListeners();
|
@@ -388,7 +377,7 @@ export default class Hls implements HlsEventEmitter {
|
|
388
377
|
* Attaches Hls.js to a media element
|
389
378
|
*/
|
390
379
|
attachMedia(media: HTMLMediaElement) {
|
391
|
-
|
380
|
+
logger.log('attachMedia');
|
392
381
|
this._media = media;
|
393
382
|
this.trigger(Events.MEDIA_ATTACHING, { media: media });
|
394
383
|
}
|
@@ -397,7 +386,7 @@ export default class Hls implements HlsEventEmitter {
|
|
397
386
|
* Detach Hls.js from the media
|
398
387
|
*/
|
399
388
|
detachMedia() {
|
400
|
-
|
389
|
+
logger.log('detachMedia');
|
401
390
|
this.trigger(Events.MEDIA_DETACHING, undefined);
|
402
391
|
this._media = null;
|
403
392
|
}
|
@@ -418,7 +407,7 @@ export default class Hls implements HlsEventEmitter {
|
|
418
407
|
));
|
419
408
|
this._autoLevelCapping = -1;
|
420
409
|
this._maxHdcpLevel = null;
|
421
|
-
|
410
|
+
logger.log(`loadSource:${loadingSource}`);
|
422
411
|
if (
|
423
412
|
media &&
|
424
413
|
loadedSource &&
|
@@ -439,7 +428,8 @@ export default class Hls implements HlsEventEmitter {
|
|
439
428
|
* Defaults to -1 (None: starts from earliest point)
|
440
429
|
*/
|
441
430
|
startLoad(startPosition: number = -1) {
|
442
|
-
|
431
|
+
logger.log(`startLoad(${startPosition})`);
|
432
|
+
this.started = true;
|
443
433
|
this.networkControllers.forEach((controller) => {
|
444
434
|
controller.startLoad(startPosition);
|
445
435
|
});
|
@@ -449,31 +439,34 @@ export default class Hls implements HlsEventEmitter {
|
|
449
439
|
* Stop loading of any stream data.
|
450
440
|
*/
|
451
441
|
stopLoad() {
|
452
|
-
|
442
|
+
logger.log('stopLoad');
|
443
|
+
this.started = false;
|
453
444
|
this.networkControllers.forEach((controller) => {
|
454
445
|
controller.stopLoad();
|
455
446
|
});
|
456
447
|
}
|
457
448
|
|
458
449
|
/**
|
459
|
-
* Resumes stream controller segment loading
|
450
|
+
* Resumes stream controller segment loading if previously started.
|
460
451
|
*/
|
461
452
|
resumeBuffering() {
|
462
|
-
this.
|
463
|
-
|
464
|
-
controller
|
465
|
-
|
466
|
-
|
453
|
+
if (this.started) {
|
454
|
+
this.networkControllers.forEach((controller) => {
|
455
|
+
if ('fragmentLoader' in controller) {
|
456
|
+
controller.startLoad(-1);
|
457
|
+
}
|
458
|
+
});
|
459
|
+
}
|
467
460
|
}
|
468
461
|
|
469
462
|
/**
|
470
|
-
*
|
463
|
+
* Stops stream controller segment loading without changing 'started' state like stopLoad().
|
471
464
|
* This allows for media buffering to be paused without interupting playlist loading.
|
472
465
|
*/
|
473
466
|
pauseBuffering() {
|
474
467
|
this.networkControllers.forEach((controller) => {
|
475
|
-
if (controller
|
476
|
-
controller.
|
468
|
+
if ('fragmentLoader' in controller) {
|
469
|
+
controller.stopLoad();
|
477
470
|
}
|
478
471
|
});
|
479
472
|
}
|
@@ -482,7 +475,7 @@ export default class Hls implements HlsEventEmitter {
|
|
482
475
|
* Swap through possible audio codecs in the stream (for example to switch from stereo to 5.1)
|
483
476
|
*/
|
484
477
|
swapAudioCodec() {
|
485
|
-
|
478
|
+
logger.log('swapAudioCodec');
|
486
479
|
this.streamController.swapAudioCodec();
|
487
480
|
}
|
488
481
|
|
@@ -493,7 +486,7 @@ export default class Hls implements HlsEventEmitter {
|
|
493
486
|
* Automatic recovery of media-errors by this process is configurable.
|
494
487
|
*/
|
495
488
|
recoverMediaError() {
|
496
|
-
|
489
|
+
logger.log('recoverMediaError');
|
497
490
|
const media = this._media;
|
498
491
|
this.detachMedia();
|
499
492
|
if (media) {
|
@@ -524,7 +517,7 @@ export default class Hls implements HlsEventEmitter {
|
|
524
517
|
* Set quality level index immediately. This will flush the current buffer to replace the quality asap. That means playback will interrupt at least shortly to re-buffer and re-sync eventually. Set to -1 for automatic level selection.
|
525
518
|
*/
|
526
519
|
set currentLevel(newLevel: number) {
|
527
|
-
|
520
|
+
logger.log(`set currentLevel:${newLevel}`);
|
528
521
|
this.levelController.manualLevel = newLevel;
|
529
522
|
this.streamController.immediateLevelSwitch();
|
530
523
|
}
|
@@ -543,7 +536,7 @@ export default class Hls implements HlsEventEmitter {
|
|
543
536
|
* @param newLevel - Pass -1 for automatic level selection
|
544
537
|
*/
|
545
538
|
set nextLevel(newLevel: number) {
|
546
|
-
|
539
|
+
logger.log(`set nextLevel:${newLevel}`);
|
547
540
|
this.levelController.manualLevel = newLevel;
|
548
541
|
this.streamController.nextLevelSwitch();
|
549
542
|
}
|
@@ -562,7 +555,7 @@ export default class Hls implements HlsEventEmitter {
|
|
562
555
|
* @param newLevel - Pass -1 for automatic level selection
|
563
556
|
*/
|
564
557
|
set loadLevel(newLevel: number) {
|
565
|
-
|
558
|
+
logger.log(`set loadLevel:${newLevel}`);
|
566
559
|
this.levelController.manualLevel = newLevel;
|
567
560
|
}
|
568
561
|
|
@@ -593,7 +586,7 @@ export default class Hls implements HlsEventEmitter {
|
|
593
586
|
* Sets "first-level", see getter.
|
594
587
|
*/
|
595
588
|
set firstLevel(newLevel: number) {
|
596
|
-
|
589
|
+
logger.log(`set firstLevel:${newLevel}`);
|
597
590
|
this.levelController.firstLevel = newLevel;
|
598
591
|
}
|
599
592
|
|
@@ -618,7 +611,7 @@ export default class Hls implements HlsEventEmitter {
|
|
618
611
|
* (determined from download of first segment)
|
619
612
|
*/
|
620
613
|
set startLevel(newLevel: number) {
|
621
|
-
|
614
|
+
logger.log(`set startLevel:${newLevel}`);
|
622
615
|
// if not in automatic start level detection, ensure startLevel is greater than minAutoLevel
|
623
616
|
if (newLevel !== -1) {
|
624
617
|
newLevel = Math.max(newLevel, this.minAutoLevel);
|
@@ -693,7 +686,7 @@ export default class Hls implements HlsEventEmitter {
|
|
693
686
|
*/
|
694
687
|
set autoLevelCapping(newLevel: number) {
|
695
688
|
if (this._autoLevelCapping !== newLevel) {
|
696
|
-
|
689
|
+
logger.log(`set autoLevelCapping:${newLevel}`);
|
697
690
|
this._autoLevelCapping = newLevel;
|
698
691
|
this.levelController.checkMaxAutoUpdated();
|
699
692
|
}
|
@@ -1039,7 +1032,7 @@ export type {
|
|
1039
1032
|
TSDemuxerConfig,
|
1040
1033
|
} from './config';
|
1041
1034
|
export type { MediaKeySessionContext } from './controller/eme-controller';
|
1042
|
-
export type { ILogger
|
1035
|
+
export type { ILogger } from './utils/logger';
|
1043
1036
|
export type {
|
1044
1037
|
PathwayClone,
|
1045
1038
|
SteeringManifest,
|
@@ -1154,7 +1147,6 @@ export type {
|
|
1154
1147
|
ManifestParsedData,
|
1155
1148
|
MediaAttachedData,
|
1156
1149
|
MediaAttachingData,
|
1157
|
-
MediaEndedData,
|
1158
1150
|
NonNativeTextTrack,
|
1159
1151
|
NonNativeTextTracksData,
|
1160
1152
|
SteeringManifestLoadedData,
|
@@ -336,11 +336,8 @@ function createLoaderContext(
|
|
336
336
|
if (Number.isFinite(start) && Number.isFinite(end)) {
|
337
337
|
let byteRangeStart = start;
|
338
338
|
let byteRangeEnd = end;
|
339
|
-
if (
|
340
|
-
|
341
|
-
isMethodFullSegmentAesCbc(frag.decryptdata?.method)
|
342
|
-
) {
|
343
|
-
// MAP segment encrypted with method 'AES-128' or 'AES-256' (cbc), when served with HTTP Range,
|
339
|
+
if (frag.sn === 'initSegment' && frag.decryptdata?.method === 'AES-128') {
|
340
|
+
// MAP segment encrypted with method 'AES-128', when served with HTTP Range,
|
344
341
|
// has the unencrypted size specified in the range.
|
345
342
|
// Ref: https://tools.ietf.org/html/draft-pantos-hls-rfc8216bis-08#section-6.3.6
|
346
343
|
const fragmentLen = end - start;
|
@@ -375,10 +372,6 @@ function createGapLoadError(frag: Fragment, part?: Part): LoadError {
|
|
375
372
|
return new LoadError(errorData);
|
376
373
|
}
|
377
374
|
|
378
|
-
function isMethodFullSegmentAesCbc(method) {
|
379
|
-
return method === 'AES-128' || method === 'AES-256';
|
380
|
-
}
|
381
|
-
|
382
375
|
export class LoadError extends Error {
|
383
376
|
public readonly data: FragLoadFailResult;
|
384
377
|
constructor(data: FragLoadFailResult) {
|
package/src/loader/key-loader.ts
CHANGED
@@ -194,8 +194,6 @@ export default class KeyLoader implements ComponentAPI {
|
|
194
194
|
}
|
195
195
|
return this.loadKeyEME(keyInfo, frag);
|
196
196
|
case 'AES-128':
|
197
|
-
case 'AES-256':
|
198
|
-
case 'AES-256-CTR':
|
199
197
|
return this.loadKeyHTTP(keyInfo, frag);
|
200
198
|
default:
|
201
199
|
return Promise.reject(
|