hls.js 1.5.2-0.canary.9966 → 1.5.2-0.canary.9970
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 +52 -32
- package/dist/hls.js.d.ts +7 -3
- package/dist/hls.js.map +1 -1
- package/dist/hls.light.js +46 -27
- 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 +49 -29
- 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 +55 -34
- 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 +3 -2
- package/src/controller/audio-stream-controller.ts +5 -3
- package/src/controller/base-stream-controller.ts +9 -0
- package/src/controller/buffer-controller.ts +1 -0
- package/src/controller/stream-controller.ts +3 -2
- package/src/controller/subtitle-stream-controller.ts +1 -1
- package/src/hls.ts +9 -14
- package/src/types/component-api.ts +2 -0
- package/src/utils/mp4-tools.ts +28 -9
package/package.json
CHANGED
@@ -871,8 +871,9 @@ class AbrController extends Logger implements AbrComponentAPI {
|
|
871
871
|
}
|
872
872
|
|
873
873
|
public set nextAutoLevel(nextLevel: number) {
|
874
|
-
const
|
875
|
-
|
874
|
+
const { maxAutoLevel, minAutoLevel } = this.hls;
|
875
|
+
const value = Math.min(Math.max(nextLevel, minAutoLevel), maxAutoLevel);
|
876
|
+
if (this._nextAutoLevel !== value) {
|
876
877
|
this.nextAutoLevelKey = '';
|
877
878
|
this._nextAutoLevel = value;
|
878
879
|
}
|
@@ -278,12 +278,14 @@ class AudioStreamController
|
|
278
278
|
const { hls, levels, media, trackId } = this;
|
279
279
|
const config = hls.config;
|
280
280
|
|
281
|
-
// 1. if
|
281
|
+
// 1. if buffering is suspended
|
282
|
+
// 2. if video not attached AND
|
282
283
|
// start fragment already requested OR start frag prefetch not enabled
|
283
|
-
//
|
284
|
+
// 3. if tracks or track not loaded and selected
|
284
285
|
// then exit loop
|
285
286
|
// => if media not attached but start frag prefetch is enabled and start frag not requested yet, we will not exit loop
|
286
287
|
if (
|
288
|
+
!this.buffering ||
|
287
289
|
(!media && (this.startFragRequested || !config.startFragPrefetch)) ||
|
288
290
|
!levels?.[trackId]
|
289
291
|
) {
|
@@ -552,7 +554,7 @@ class AudioStreamController
|
|
552
554
|
|
553
555
|
// compute start position if we are aligned with the main playlist
|
554
556
|
if (!this.startFragRequested && (this.mainDetails || !newDetails.live)) {
|
555
|
-
this.setStartPosition(
|
557
|
+
this.setStartPosition(this.mainDetails || newDetails, sliding);
|
556
558
|
}
|
557
559
|
// only switch back to IDLE state if we were waiting for track to start downloading a new fragment
|
558
560
|
if (
|
@@ -100,6 +100,7 @@ export default class BaseStreamController
|
|
100
100
|
protected startFragRequested: boolean = false;
|
101
101
|
protected decrypter: Decrypter;
|
102
102
|
protected initPTS: RationalTimestamp[] = [];
|
103
|
+
protected buffering: boolean = true;
|
103
104
|
|
104
105
|
constructor(
|
105
106
|
hls: Hls,
|
@@ -161,6 +162,14 @@ export default class BaseStreamController
|
|
161
162
|
this.state = State.STOPPED;
|
162
163
|
}
|
163
164
|
|
165
|
+
public pauseBuffering() {
|
166
|
+
this.buffering = false;
|
167
|
+
}
|
168
|
+
|
169
|
+
public resumeBuffering() {
|
170
|
+
this.buffering = true;
|
171
|
+
}
|
172
|
+
|
164
173
|
protected _streamEnded(
|
165
174
|
bufferInfo: BufferInfo,
|
166
175
|
levelDetails: LevelDetails,
|
@@ -134,7 +134,8 @@ export default class StreamController
|
|
134
134
|
}
|
135
135
|
// set new level to playlist loader : this will trigger start level load
|
136
136
|
// hls.nextLoadLevel remains until it is set to a new value or until a new frag is successfully loaded
|
137
|
-
|
137
|
+
hls.nextLoadLevel = startLevel;
|
138
|
+
this.level = hls.loadLevel;
|
138
139
|
this.loadedmetadata = false;
|
139
140
|
}
|
140
141
|
// if startPosition undefined but lastCurrentTime set, set startPosition to last currentTime
|
@@ -231,7 +232,7 @@ export default class StreamController
|
|
231
232
|
return;
|
232
233
|
}
|
233
234
|
|
234
|
-
if (!levels?.[level]) {
|
235
|
+
if (!this.buffering || !levels?.[level]) {
|
235
236
|
return;
|
236
237
|
}
|
237
238
|
|
@@ -318,7 +318,7 @@ export class SubtitleStreamController
|
|
318
318
|
this.levelLastLoaded = track;
|
319
319
|
|
320
320
|
if (!this.startFragRequested && (this.mainDetails || !newDetails.live)) {
|
321
|
-
this.setStartPosition(
|
321
|
+
this.setStartPosition(this.mainDetails || newDetails, sliding);
|
322
322
|
}
|
323
323
|
|
324
324
|
// trigger handler right now
|
package/src/hls.ts
CHANGED
@@ -66,7 +66,6 @@ export default class Hls implements HlsEventEmitter {
|
|
66
66
|
|
67
67
|
private coreComponents: ComponentAPI[];
|
68
68
|
private networkControllers: NetworkComponentAPI[];
|
69
|
-
private started: boolean = false;
|
70
69
|
private _emitter: HlsEventEmitter = new EventEmitter();
|
71
70
|
private _autoLevelCapping: number = -1;
|
72
71
|
private _maxHdcpLevel: HdcpLevel = null;
|
@@ -441,7 +440,6 @@ export default class Hls implements HlsEventEmitter {
|
|
441
440
|
*/
|
442
441
|
startLoad(startPosition: number = -1) {
|
443
442
|
this.logger.log(`startLoad(${startPosition})`);
|
444
|
-
this.started = true;
|
445
443
|
this.networkControllers.forEach((controller) => {
|
446
444
|
controller.startLoad(startPosition);
|
447
445
|
});
|
@@ -452,33 +450,30 @@ export default class Hls implements HlsEventEmitter {
|
|
452
450
|
*/
|
453
451
|
stopLoad() {
|
454
452
|
this.logger.log('stopLoad');
|
455
|
-
this.started = false;
|
456
453
|
this.networkControllers.forEach((controller) => {
|
457
454
|
controller.stopLoad();
|
458
455
|
});
|
459
456
|
}
|
460
457
|
|
461
458
|
/**
|
462
|
-
* Resumes stream controller segment loading
|
459
|
+
* Resumes stream controller segment loading after `pauseBuffering` has been called.
|
463
460
|
*/
|
464
461
|
resumeBuffering() {
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
});
|
471
|
-
}
|
462
|
+
this.networkControllers.forEach((controller) => {
|
463
|
+
if (controller.resumeBuffering) {
|
464
|
+
controller.resumeBuffering();
|
465
|
+
}
|
466
|
+
});
|
472
467
|
}
|
473
468
|
|
474
469
|
/**
|
475
|
-
*
|
470
|
+
* Prevents stream controller from loading new segments until `resumeBuffering` is called.
|
476
471
|
* This allows for media buffering to be paused without interupting playlist loading.
|
477
472
|
*/
|
478
473
|
pauseBuffering() {
|
479
474
|
this.networkControllers.forEach((controller) => {
|
480
|
-
if (
|
481
|
-
controller.
|
475
|
+
if (controller.pauseBuffering) {
|
476
|
+
controller.pauseBuffering();
|
482
477
|
}
|
483
478
|
});
|
484
479
|
}
|
package/src/utils/mp4-tools.ts
CHANGED
@@ -38,6 +38,13 @@ export function readUint32(buffer: Uint8Array, offset: number): number {
|
|
38
38
|
return val < 0 ? 4294967296 + val : val;
|
39
39
|
}
|
40
40
|
|
41
|
+
export function readUint64(buffer: Uint8Array, offset: number) {
|
42
|
+
let result = readUint32(buffer, offset);
|
43
|
+
result *= Math.pow(2, 32);
|
44
|
+
result += readUint32(buffer, offset + 4);
|
45
|
+
return result;
|
46
|
+
}
|
47
|
+
|
41
48
|
export function readSint32(buffer: Uint8Array, offset: number): number {
|
42
49
|
return (
|
43
50
|
(buffer[offset] << 24) |
|
@@ -125,15 +132,15 @@ export function parseSegmentIndex(sidx: Uint8Array): SidxInfo | null {
|
|
125
132
|
const timescale = readUint32(sidx, index);
|
126
133
|
index += 4;
|
127
134
|
|
128
|
-
|
129
|
-
|
130
|
-
const earliestPresentationTime = 0;
|
131
|
-
const firstOffset = 0;
|
135
|
+
let earliestPresentationTime = 0;
|
136
|
+
let firstOffset = 0;
|
132
137
|
|
133
138
|
if (version === 0) {
|
134
|
-
index +=
|
139
|
+
earliestPresentationTime = readUint32(sidx, (index += 4));
|
140
|
+
firstOffset = readUint32(sidx, (index += 4));
|
135
141
|
} else {
|
136
|
-
index +=
|
142
|
+
earliestPresentationTime = readUint64(sidx, (index += 8));
|
143
|
+
firstOffset = readUint64(sidx, (index += 8));
|
137
144
|
}
|
138
145
|
|
139
146
|
// skip reserved
|
@@ -677,19 +684,31 @@ export function getDuration(data: Uint8Array, initData: InitData) {
|
|
677
684
|
}
|
678
685
|
if (videoDuration === 0 && audioDuration === 0) {
|
679
686
|
// If duration samples are not available in the traf use sidx subsegment_duration
|
687
|
+
let sidxMinStart = Infinity;
|
688
|
+
let sidxMaxEnd = 0;
|
680
689
|
let sidxDuration = 0;
|
681
690
|
const sidxs = findBox(data, ['sidx']);
|
682
691
|
for (let i = 0; i < sidxs.length; i++) {
|
683
692
|
const sidx = parseSegmentIndex(sidxs[i]);
|
684
693
|
if (sidx?.references) {
|
685
|
-
|
694
|
+
sidxMinStart = Math.min(
|
695
|
+
sidxMinStart,
|
696
|
+
sidx.earliestPresentationTime / sidx.timescale,
|
697
|
+
);
|
698
|
+
const subSegmentDuration = sidx.references.reduce(
|
686
699
|
(dur, ref) => dur + ref.info.duration || 0,
|
687
700
|
0,
|
688
701
|
);
|
702
|
+
sidxMaxEnd = Math.max(
|
703
|
+
sidxMaxEnd,
|
704
|
+
subSegmentDuration + sidx.earliestPresentationTime / sidx.timescale,
|
705
|
+
);
|
706
|
+
sidxDuration = sidxMaxEnd - sidxMinStart;
|
689
707
|
}
|
690
708
|
}
|
691
|
-
|
692
|
-
|
709
|
+
if (sidxDuration && Number.isFinite(sidxDuration)) {
|
710
|
+
return sidxDuration;
|
711
|
+
}
|
693
712
|
}
|
694
713
|
if (videoDuration) {
|
695
714
|
return videoDuration;
|