hls.js 1.5.14-0.canary.10515 → 1.5.14
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 +3 -4
- package/dist/hls-demo.js +38 -41
- package/dist/hls-demo.js.map +1 -1
- package/dist/hls.js +2903 -4542
- package/dist/hls.js.d.ts +112 -186
- package/dist/hls.js.map +1 -1
- package/dist/hls.light.js +2284 -3295
- 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 +1804 -2817
- 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 +4652 -6293
- 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 +38 -38
- package/src/config.ts +2 -5
- package/src/controller/abr-controller.ts +25 -39
- package/src/controller/audio-stream-controller.ts +136 -156
- package/src/controller/audio-track-controller.ts +1 -1
- package/src/controller/base-playlist-controller.ts +10 -27
- package/src/controller/base-stream-controller.ts +107 -263
- package/src/controller/buffer-controller.ts +98 -252
- package/src/controller/buffer-operation-queue.ts +19 -16
- package/src/controller/cap-level-controller.ts +2 -3
- package/src/controller/cmcd-controller.ts +14 -51
- package/src/controller/content-steering-controller.ts +15 -29
- package/src/controller/eme-controller.ts +23 -10
- package/src/controller/error-controller.ts +22 -28
- package/src/controller/fps-controller.ts +3 -8
- package/src/controller/fragment-finders.ts +16 -44
- package/src/controller/fragment-tracker.ts +25 -58
- package/src/controller/gap-controller.ts +16 -43
- package/src/controller/id3-track-controller.ts +35 -45
- package/src/controller/latency-controller.ts +13 -18
- package/src/controller/level-controller.ts +19 -37
- package/src/controller/stream-controller.ts +83 -100
- package/src/controller/subtitle-stream-controller.ts +47 -35
- package/src/controller/subtitle-track-controller.ts +3 -5
- package/src/controller/timeline-controller.ts +22 -20
- package/src/crypt/aes-crypto.ts +2 -21
- package/src/crypt/decrypter.ts +16 -32
- package/src/crypt/fast-aes-key.ts +5 -28
- package/src/demux/audio/aacdemuxer.ts +5 -5
- package/src/demux/audio/ac3-demuxer.ts +4 -5
- package/src/demux/audio/adts.ts +4 -9
- package/src/demux/audio/base-audio-demuxer.ts +14 -16
- package/src/demux/audio/mp3demuxer.ts +3 -4
- package/src/demux/audio/mpegaudio.ts +1 -1
- package/src/demux/id3.ts +411 -0
- package/src/demux/inject-worker.ts +4 -38
- package/src/demux/mp4demuxer.ts +7 -7
- package/src/demux/sample-aes.ts +0 -2
- package/src/demux/transmuxer-interface.ts +83 -106
- package/src/demux/transmuxer-worker.ts +77 -111
- package/src/demux/transmuxer.ts +22 -46
- package/src/demux/tsdemuxer.ts +62 -122
- package/src/demux/video/avc-video-parser.ts +121 -210
- package/src/demux/video/base-video-parser.ts +2 -135
- package/src/demux/video/exp-golomb.ts +208 -0
- package/src/errors.ts +0 -2
- package/src/events.ts +1 -8
- package/src/exports-named.ts +1 -1
- package/src/hls.ts +48 -97
- package/src/loader/date-range.ts +5 -71
- package/src/loader/fragment-loader.ts +21 -23
- package/src/loader/fragment.ts +4 -8
- package/src/loader/key-loader.ts +1 -3
- package/src/loader/level-details.ts +6 -6
- package/src/loader/level-key.ts +9 -10
- package/src/loader/m3u8-parser.ts +144 -138
- package/src/loader/playlist-loader.ts +7 -5
- package/src/remux/mp4-generator.ts +1 -196
- package/src/remux/mp4-remuxer.ts +84 -55
- package/src/remux/passthrough-remuxer.ts +8 -23
- package/src/task-loop.ts +2 -5
- package/src/types/component-api.ts +1 -3
- package/src/types/demuxer.ts +0 -3
- package/src/types/events.ts +6 -19
- package/src/types/fragment-tracker.ts +2 -2
- package/src/types/general.ts +6 -0
- package/src/types/media-playlist.ts +1 -9
- package/src/types/remuxer.ts +1 -1
- package/src/utils/attr-list.ts +9 -96
- package/src/utils/buffer-helper.ts +31 -12
- package/src/utils/cea-608-parser.ts +3 -1
- package/src/utils/codecs.ts +5 -34
- package/src/utils/discontinuities.ts +47 -21
- package/src/utils/fetch-loader.ts +1 -1
- package/src/utils/hdr.ts +7 -4
- package/src/utils/imsc1-ttml-parser.ts +1 -1
- package/src/utils/keysystem-util.ts +6 -1
- package/src/utils/level-helper.ts +44 -71
- package/src/utils/logger.ts +23 -58
- package/src/utils/mp4-tools.ts +3 -5
- package/src/utils/rendition-helper.ts +74 -100
- package/src/utils/variable-substitution.ts +19 -0
- package/src/utils/webvtt-parser.ts +12 -2
- package/src/crypt/decrypter-aes-mode.ts +0 -4
- package/src/demux/video/hevc-video-parser.ts +0 -749
- package/src/utils/encryption-methods-util.ts +0 -21
- package/src/utils/hash.ts +0 -10
- package/src/utils/utf8-utils.ts +0 -18
- package/src/version.ts +0 -1
@@ -1,4 +1,4 @@
|
|
1
|
-
import
|
1
|
+
import {
|
2
2
|
ManifestLoadedData,
|
3
3
|
ManifestParsedData,
|
4
4
|
LevelLoadedData,
|
@@ -27,6 +27,8 @@ import type Hls from '../hls';
|
|
27
27
|
import type { HlsUrlParameters, LevelParsed } from '../types/level';
|
28
28
|
import type { MediaPlaylist } from '../types/media-playlist';
|
29
29
|
|
30
|
+
let chromeOrFirefox: boolean;
|
31
|
+
|
30
32
|
export default class LevelController extends BasePlaylistController {
|
31
33
|
private _levels: Level[] = [];
|
32
34
|
private _firstLevel: number = -1;
|
@@ -43,7 +45,7 @@ export default class LevelController extends BasePlaylistController {
|
|
43
45
|
hls: Hls,
|
44
46
|
contentSteeringController: ContentSteeringController | null,
|
45
47
|
) {
|
46
|
-
super(hls, 'level-controller');
|
48
|
+
super(hls, '[level-controller]');
|
47
49
|
this.steering = contentSteeringController;
|
48
50
|
this._registerListeners();
|
49
51
|
}
|
@@ -117,12 +119,22 @@ export default class LevelController extends BasePlaylistController {
|
|
117
119
|
|
118
120
|
data.levels.forEach((levelParsed: LevelParsed) => {
|
119
121
|
const attributes = levelParsed.attrs;
|
122
|
+
|
123
|
+
// erase audio codec info if browser does not support mp4a.40.34.
|
124
|
+
// demuxer will autodetect codec and fallback to mpeg/audio
|
120
125
|
let { audioCodec, videoCodec } = levelParsed;
|
126
|
+
if (audioCodec?.indexOf('mp4a.40.34') !== -1) {
|
127
|
+
chromeOrFirefox ||= /chrome|firefox/i.test(navigator.userAgent);
|
128
|
+
if (chromeOrFirefox) {
|
129
|
+
levelParsed.audioCodec = audioCodec = undefined;
|
130
|
+
}
|
131
|
+
}
|
132
|
+
|
121
133
|
if (audioCodec) {
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
134
|
+
levelParsed.audioCodec = audioCodec = getCodecCompatibleName(
|
135
|
+
audioCodec,
|
136
|
+
preferManagedMediaSource,
|
137
|
+
);
|
126
138
|
}
|
127
139
|
|
128
140
|
if (videoCodec?.indexOf('avc1') === 0) {
|
@@ -509,30 +521,6 @@ export default class LevelController extends BasePlaylistController {
|
|
509
521
|
this._startLevel = newLevel;
|
510
522
|
}
|
511
523
|
|
512
|
-
get pathwayPriority(): string[] | null {
|
513
|
-
if (this.steering) {
|
514
|
-
return this.steering.pathwayPriority;
|
515
|
-
}
|
516
|
-
|
517
|
-
return null;
|
518
|
-
}
|
519
|
-
|
520
|
-
set pathwayPriority(pathwayPriority: string[]) {
|
521
|
-
if (this.steering) {
|
522
|
-
const pathwaysList = this.steering.pathways();
|
523
|
-
const filteredPathwayPriority = pathwayPriority.filter((pathwayId) => {
|
524
|
-
return pathwaysList.indexOf(pathwayId) !== -1;
|
525
|
-
});
|
526
|
-
if (pathwayPriority.length < 1) {
|
527
|
-
this.warn(
|
528
|
-
`pathwayPriority ${pathwayPriority} should contain at least one pathway from list: ${pathwaysList}`,
|
529
|
-
);
|
530
|
-
return;
|
531
|
-
}
|
532
|
-
this.steering.pathwayPriority = filteredPathwayPriority;
|
533
|
-
}
|
534
|
-
}
|
535
|
-
|
536
524
|
protected onError(event: Events.ERROR, data: ErrorData) {
|
537
525
|
if (data.fatal || !data.context) {
|
538
526
|
return;
|
@@ -584,13 +572,7 @@ export default class LevelController extends BasePlaylistController {
|
|
584
572
|
if (curLevel.fragmentError === 0) {
|
585
573
|
curLevel.loadError = 0;
|
586
574
|
}
|
587
|
-
|
588
|
-
let previousDetails = curLevel.details;
|
589
|
-
if (previousDetails === data.details && previousDetails.advanced) {
|
590
|
-
previousDetails = undefined;
|
591
|
-
}
|
592
|
-
|
593
|
-
this.playlistLoaded(level, data, previousDetails);
|
575
|
+
this.playlistLoaded(level, data, curLevel.details);
|
594
576
|
} else if (data.deliveryDirectives?.skip) {
|
595
577
|
// received a delta playlist update that cannot be merged
|
596
578
|
details.deltaUpdateFailed = true;
|
@@ -2,14 +2,9 @@ import BaseStreamController, { State } from './base-stream-controller';
|
|
2
2
|
import { changeTypeSupported } from '../is-supported';
|
3
3
|
import { Events } from '../events';
|
4
4
|
import { BufferHelper, BufferInfo } from '../utils/buffer-helper';
|
5
|
-
import { findFragmentByPTS } from './fragment-finders';
|
6
5
|
import { FragmentState } from './fragment-tracker';
|
7
6
|
import { PlaylistContextType, PlaylistLevelType } from '../types/loader';
|
8
|
-
import {
|
9
|
-
ElementaryStreamTypes,
|
10
|
-
Fragment,
|
11
|
-
MediaFragment,
|
12
|
-
} from '../loader/fragment';
|
7
|
+
import { ElementaryStreamTypes, Fragment } from '../loader/fragment';
|
13
8
|
import TransmuxerInterface from '../demux/transmuxer-interface';
|
14
9
|
import { ChunkMetadata } from '../types/transmuxer';
|
15
10
|
import GapController, { MAX_START_GAP_JUMP } from './gap-controller';
|
@@ -17,15 +12,15 @@ import { ErrorDetails } from '../errors';
|
|
17
12
|
import type { NetworkComponentAPI } from '../types/component-api';
|
18
13
|
import type Hls from '../hls';
|
19
14
|
import type { Level } from '../types/level';
|
15
|
+
import type { LevelDetails } from '../loader/level-details';
|
20
16
|
import type { FragmentTracker } from './fragment-tracker';
|
21
17
|
import type KeyLoader from '../loader/key-loader';
|
22
18
|
import type { TransmuxerResult } from '../types/transmuxer';
|
23
|
-
import type {
|
19
|
+
import type { TrackSet } from '../types/track';
|
24
20
|
import type { SourceBufferName } from '../types/buffer';
|
25
21
|
import type {
|
26
22
|
AudioTrackSwitchedData,
|
27
23
|
AudioTrackSwitchingData,
|
28
|
-
BufferCodecsData,
|
29
24
|
BufferCreatedData,
|
30
25
|
BufferEOSData,
|
31
26
|
BufferFlushedData,
|
@@ -54,6 +49,8 @@ export default class StreamController
|
|
54
49
|
private altAudio: boolean = false;
|
55
50
|
private audioOnly: boolean = false;
|
56
51
|
private fragPlaying: Fragment | null = null;
|
52
|
+
private onvplaying: EventListener | null = null;
|
53
|
+
private onvseeked: EventListener | null = null;
|
57
54
|
private fragLastKbps: number = 0;
|
58
55
|
private couldBacktrack: boolean = false;
|
59
56
|
private backtrackFragment: Fragment | null = null;
|
@@ -69,15 +66,17 @@ export default class StreamController
|
|
69
66
|
hls,
|
70
67
|
fragmentTracker,
|
71
68
|
keyLoader,
|
72
|
-
'stream-controller',
|
69
|
+
'[stream-controller]',
|
73
70
|
PlaylistLevelType.MAIN,
|
74
71
|
);
|
75
|
-
this.
|
72
|
+
this._registerListeners();
|
76
73
|
}
|
77
74
|
|
78
|
-
|
79
|
-
super.registerListeners();
|
75
|
+
private _registerListeners() {
|
80
76
|
const { hls } = this;
|
77
|
+
hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
|
78
|
+
hls.on(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
|
79
|
+
hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);
|
81
80
|
hls.on(Events.MANIFEST_PARSED, this.onManifestParsed, this);
|
82
81
|
hls.on(Events.LEVEL_LOADING, this.onLevelLoading, this);
|
83
82
|
hls.on(Events.LEVEL_LOADED, this.onLevelLoaded, this);
|
@@ -86,6 +85,7 @@ export default class StreamController
|
|
86
85
|
this.onFragLoadEmergencyAborted,
|
87
86
|
this,
|
88
87
|
);
|
88
|
+
hls.on(Events.ERROR, this.onError, this);
|
89
89
|
hls.on(Events.AUDIO_TRACK_SWITCHING, this.onAudioTrackSwitching, this);
|
90
90
|
hls.on(Events.AUDIO_TRACK_SWITCHED, this.onAudioTrackSwitched, this);
|
91
91
|
hls.on(Events.BUFFER_CREATED, this.onBufferCreated, this);
|
@@ -94,9 +94,11 @@ export default class StreamController
|
|
94
94
|
hls.on(Events.FRAG_BUFFERED, this.onFragBuffered, this);
|
95
95
|
}
|
96
96
|
|
97
|
-
protected
|
98
|
-
super.unregisterListeners();
|
97
|
+
protected _unregisterListeners() {
|
99
98
|
const { hls } = this;
|
99
|
+
hls.off(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
|
100
|
+
hls.off(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
|
101
|
+
hls.off(Events.MANIFEST_LOADING, this.onManifestLoading, this);
|
100
102
|
hls.off(Events.MANIFEST_PARSED, this.onManifestParsed, this);
|
101
103
|
hls.off(Events.LEVEL_LOADED, this.onLevelLoaded, this);
|
102
104
|
hls.off(
|
@@ -104,6 +106,7 @@ export default class StreamController
|
|
104
106
|
this.onFragLoadEmergencyAborted,
|
105
107
|
this,
|
106
108
|
);
|
109
|
+
hls.off(Events.ERROR, this.onError, this);
|
107
110
|
hls.off(Events.AUDIO_TRACK_SWITCHING, this.onAudioTrackSwitching, this);
|
108
111
|
hls.off(Events.AUDIO_TRACK_SWITCHED, this.onAudioTrackSwitched, this);
|
109
112
|
hls.off(Events.BUFFER_CREATED, this.onBufferCreated, this);
|
@@ -113,9 +116,7 @@ export default class StreamController
|
|
113
116
|
}
|
114
117
|
|
115
118
|
protected onHandlerDestroying() {
|
116
|
-
|
117
|
-
this.onMediaPlaying = this.onMediaSeeked = null;
|
118
|
-
this.unregisterListeners();
|
119
|
+
this._unregisterListeners();
|
119
120
|
super.onHandlerDestroying();
|
120
121
|
}
|
121
122
|
|
@@ -219,9 +220,6 @@ export default class StreamController
|
|
219
220
|
}
|
220
221
|
|
221
222
|
private doTickIdle() {
|
222
|
-
if (!this.buffering) {
|
223
|
-
return;
|
224
|
-
}
|
225
223
|
const { hls, levelLastLoaded, levels, media } = this;
|
226
224
|
|
227
225
|
// if start level not parsed yet OR
|
@@ -365,6 +363,7 @@ export default class StreamController
|
|
365
363
|
) {
|
366
364
|
// Check if fragment is not loaded
|
367
365
|
const fragState = this.fragmentTracker.getState(frag);
|
366
|
+
this.fragCurrent = frag;
|
368
367
|
if (
|
369
368
|
fragState === FragmentState.NOT_LOADED ||
|
370
369
|
fragState === FragmentState.PARTIAL
|
@@ -377,6 +376,7 @@ export default class StreamController
|
|
377
376
|
);
|
378
377
|
this._loadBitrateTestFrag(frag, level);
|
379
378
|
} else {
|
379
|
+
this.startFragRequested = true;
|
380
380
|
super.loadFragment(frag, level, targetBufferTime);
|
381
381
|
}
|
382
382
|
} else {
|
@@ -516,8 +516,10 @@ export default class StreamController
|
|
516
516
|
) {
|
517
517
|
super.onMediaAttached(event, data);
|
518
518
|
const media = data.media;
|
519
|
-
|
520
|
-
|
519
|
+
this.onvplaying = this.onMediaPlaying.bind(this);
|
520
|
+
this.onvseeked = this.onMediaSeeked.bind(this);
|
521
|
+
media.addEventListener('playing', this.onvplaying as EventListener);
|
522
|
+
media.addEventListener('seeked', this.onvseeked as EventListener);
|
521
523
|
this.gapController = new GapController(
|
522
524
|
this.config,
|
523
525
|
media,
|
@@ -528,11 +530,12 @@ export default class StreamController
|
|
528
530
|
|
529
531
|
protected onMediaDetaching() {
|
530
532
|
const { media } = this;
|
531
|
-
if (media) {
|
532
|
-
media.removeEventListener('playing', this.
|
533
|
-
media.removeEventListener('seeked', this.
|
533
|
+
if (media && this.onvplaying && this.onvseeked) {
|
534
|
+
media.removeEventListener('playing', this.onvplaying);
|
535
|
+
media.removeEventListener('seeked', this.onvseeked);
|
536
|
+
this.onvplaying = this.onvseeked = null;
|
537
|
+
this.videoBuffer = null;
|
534
538
|
}
|
535
|
-
this.videoBuffer = null;
|
536
539
|
this.fragPlaying = null;
|
537
540
|
if (this.gapController) {
|
538
541
|
this.gapController.destroy();
|
@@ -541,12 +544,12 @@ export default class StreamController
|
|
541
544
|
super.onMediaDetaching();
|
542
545
|
}
|
543
546
|
|
544
|
-
private onMediaPlaying
|
547
|
+
private onMediaPlaying() {
|
545
548
|
// tick to speed up FRAG_CHANGED triggering
|
546
549
|
this.tick();
|
547
|
-
}
|
550
|
+
}
|
548
551
|
|
549
|
-
private onMediaSeeked
|
552
|
+
private onMediaSeeked() {
|
550
553
|
const media = this.media;
|
551
554
|
const currentTime = media ? media.currentTime : null;
|
552
555
|
if (Number.isFinite(currentTime)) {
|
@@ -566,17 +569,21 @@ export default class StreamController
|
|
566
569
|
|
567
570
|
// tick to speed up FRAG_CHANGED triggering
|
568
571
|
this.tick();
|
569
|
-
}
|
572
|
+
}
|
570
573
|
|
571
|
-
|
572
|
-
super.onManifestLoading();
|
574
|
+
private onManifestLoading() {
|
573
575
|
// reset buffer on manifest loading
|
574
576
|
this.log('Trigger BUFFER_RESET');
|
575
577
|
this.hls.trigger(Events.BUFFER_RESET, undefined);
|
578
|
+
this.fragmentTracker.removeAllFragments();
|
576
579
|
this.couldBacktrack = false;
|
577
|
-
this.fragLastKbps = 0;
|
578
|
-
this.
|
579
|
-
|
580
|
+
this.startPosition = this.lastCurrentTime = this.fragLastKbps = 0;
|
581
|
+
this.levels =
|
582
|
+
this.fragPlaying =
|
583
|
+
this.backtrackFragment =
|
584
|
+
this.levelLastLoaded =
|
585
|
+
null;
|
586
|
+
this.altAudio = this.audioOnly = this.startFragRequested = false;
|
580
587
|
}
|
581
588
|
|
582
589
|
private onManifestParsed(
|
@@ -690,8 +697,7 @@ export default class StreamController
|
|
690
697
|
}
|
691
698
|
|
692
699
|
protected _handleFragmentLoadProgress(data: FragLoadedData) {
|
693
|
-
const frag = data
|
694
|
-
const { part, payload } = data;
|
700
|
+
const { frag, part, payload } = data;
|
695
701
|
const { levels } = this;
|
696
702
|
if (!levels) {
|
697
703
|
this.warn(
|
@@ -700,7 +706,7 @@ export default class StreamController
|
|
700
706
|
return;
|
701
707
|
}
|
702
708
|
const currentLevel = levels[frag.level];
|
703
|
-
const details = currentLevel.details;
|
709
|
+
const details = currentLevel.details as LevelDetails;
|
704
710
|
if (!details) {
|
705
711
|
this.warn(
|
706
712
|
`Dropping fragment ${frag.sn} of level ${frag.level} after level details were reset`,
|
@@ -729,7 +735,7 @@ export default class StreamController
|
|
729
735
|
const partial = partIndex !== -1;
|
730
736
|
const chunkMeta = new ChunkMetadata(
|
731
737
|
frag.level,
|
732
|
-
frag.sn,
|
738
|
+
frag.sn as number,
|
733
739
|
frag.stats.chunkCount,
|
734
740
|
payload.byteLength,
|
735
741
|
partIndex,
|
@@ -873,12 +879,12 @@ export default class StreamController
|
|
873
879
|
(8 * stats.total) / (stats.buffering.end - stats.loading.first),
|
874
880
|
);
|
875
881
|
if (frag.sn !== 'initSegment') {
|
876
|
-
this.fragPrevious = frag
|
882
|
+
this.fragPrevious = frag;
|
877
883
|
}
|
878
884
|
this.fragBufferedComplete(frag, part);
|
879
885
|
}
|
880
886
|
|
881
|
-
|
887
|
+
private onError(event: Events.ERROR, data: ErrorData) {
|
882
888
|
if (data.fatal) {
|
883
889
|
this.state = State.ERROR;
|
884
890
|
return;
|
@@ -936,10 +942,8 @@ export default class StreamController
|
|
936
942
|
|
937
943
|
if (this.loadedmetadata || !BufferHelper.getBuffered(media).length) {
|
938
944
|
// Resolve gaps using the main buffer, whose ranges are the intersections of the A/V sourcebuffers
|
939
|
-
const
|
940
|
-
|
941
|
-
const levelDetails = this.getLevelDetails();
|
942
|
-
gapController.poll(this.lastCurrentTime, activeFrag, levelDetails, state);
|
945
|
+
const activeFrag = this.state !== State.IDLE ? this.fragCurrent : null;
|
946
|
+
gapController.poll(this.lastCurrentTime, activeFrag);
|
943
947
|
}
|
944
948
|
|
945
949
|
this.lastCurrentTime = media.currentTime;
|
@@ -951,7 +955,7 @@ export default class StreamController
|
|
951
955
|
// in that case, reset startFragRequested flag
|
952
956
|
if (!this.loadedmetadata) {
|
953
957
|
this.startFragRequested = false;
|
954
|
-
this.nextLoadPosition = this.
|
958
|
+
this.nextLoadPosition = this.startPosition;
|
955
959
|
}
|
956
960
|
this.tickImmediate();
|
957
961
|
}
|
@@ -1063,7 +1067,7 @@ export default class StreamController
|
|
1063
1067
|
}
|
1064
1068
|
|
1065
1069
|
private _handleTransmuxComplete(transmuxResult: TransmuxerResult) {
|
1066
|
-
const id =
|
1070
|
+
const id = 'main';
|
1067
1071
|
const { hls } = this;
|
1068
1072
|
const { remuxResult, chunkMeta } = transmuxResult;
|
1069
1073
|
|
@@ -1113,7 +1117,7 @@ export default class StreamController
|
|
1113
1117
|
}
|
1114
1118
|
|
1115
1119
|
// Avoid buffering if backtracking this fragment
|
1116
|
-
if (video && details) {
|
1120
|
+
if (video && details && frag.sn !== 'initSegment') {
|
1117
1121
|
const prevFrag = details.fragments[frag.sn - 1 - details.startSN];
|
1118
1122
|
const isFirstFragment = frag.sn === details.startSN;
|
1119
1123
|
const isFirstInDiscontinuity = !prevFrag || frag.cc > prevFrag.cc;
|
@@ -1303,7 +1307,6 @@ export default class StreamController
|
|
1303
1307
|
currentLevel.audioCodec || ''
|
1304
1308
|
}/${audio.codec}]`,
|
1305
1309
|
);
|
1306
|
-
delete tracks.audiovideo;
|
1307
1310
|
}
|
1308
1311
|
if (video) {
|
1309
1312
|
video.levelCodec = currentLevel.videoCodec;
|
@@ -1315,34 +1318,28 @@ export default class StreamController
|
|
1315
1318
|
video.codec
|
1316
1319
|
}]`,
|
1317
1320
|
);
|
1318
|
-
delete tracks.audiovideo;
|
1319
1321
|
}
|
1320
1322
|
if (audiovideo) {
|
1321
1323
|
this.log(
|
1322
1324
|
`Init audiovideo buffer, container:${audiovideo.container}, codecs[level/parsed]=[${currentLevel.codecs}/${audiovideo.codec}]`,
|
1323
1325
|
);
|
1324
|
-
delete tracks.video;
|
1325
|
-
delete tracks.audio;
|
1326
|
-
}
|
1327
|
-
const trackTypes = Object.keys(tracks);
|
1328
|
-
if (trackTypes.length) {
|
1329
|
-
this.hls.trigger(Events.BUFFER_CODECS, tracks as BufferCodecsData);
|
1330
|
-
// loop through tracks that are going to be provided to bufferController
|
1331
|
-
trackTypes.forEach((trackName) => {
|
1332
|
-
const track = tracks[trackName] as Track;
|
1333
|
-
const initSegment = track.initSegment;
|
1334
|
-
if (initSegment?.byteLength) {
|
1335
|
-
this.hls.trigger(Events.BUFFER_APPENDING, {
|
1336
|
-
type: trackName as SourceBufferName,
|
1337
|
-
data: initSegment,
|
1338
|
-
frag,
|
1339
|
-
part: null,
|
1340
|
-
chunkMeta,
|
1341
|
-
parent: frag.type,
|
1342
|
-
});
|
1343
|
-
}
|
1344
|
-
});
|
1345
1326
|
}
|
1327
|
+
this.hls.trigger(Events.BUFFER_CODECS, tracks);
|
1328
|
+
// loop through tracks that are going to be provided to bufferController
|
1329
|
+
Object.keys(tracks).forEach((trackName) => {
|
1330
|
+
const track = tracks[trackName];
|
1331
|
+
const initSegment = track.initSegment;
|
1332
|
+
if (initSegment?.byteLength) {
|
1333
|
+
this.hls.trigger(Events.BUFFER_APPENDING, {
|
1334
|
+
type: trackName as SourceBufferName,
|
1335
|
+
data: initSegment,
|
1336
|
+
frag,
|
1337
|
+
part: null,
|
1338
|
+
chunkMeta,
|
1339
|
+
parent: frag.type,
|
1340
|
+
});
|
1341
|
+
}
|
1342
|
+
});
|
1346
1343
|
// trigger handler right now
|
1347
1344
|
this.tickImmediate();
|
1348
1345
|
}
|
@@ -1354,15 +1351,6 @@ export default class StreamController
|
|
1354
1351
|
);
|
1355
1352
|
}
|
1356
1353
|
|
1357
|
-
public get maxBufferLength(): number {
|
1358
|
-
const { levels, level } = this;
|
1359
|
-
const levelInfo = levels?.[level];
|
1360
|
-
if (!levelInfo) {
|
1361
|
-
return this.config.maxBufferLength;
|
1362
|
-
}
|
1363
|
-
return this.getMaxBufferLength(levelInfo.maxBitrate);
|
1364
|
-
}
|
1365
|
-
|
1366
1354
|
private backtrack(frag: Fragment) {
|
1367
1355
|
this.couldBacktrack = true;
|
1368
1356
|
// Causes findFragments to backtrack through fragments to find the keyframe
|
@@ -1427,31 +1415,26 @@ export default class StreamController
|
|
1427
1415
|
}
|
1428
1416
|
|
1429
1417
|
get currentFrag(): Fragment | null {
|
1430
|
-
|
1431
|
-
|
1432
|
-
|
1433
|
-
const currentTime = this.media?.currentTime || this.lastCurrentTime;
|
1434
|
-
if (Number.isFinite(currentTime)) {
|
1435
|
-
return this.getAppendedFrag(currentTime);
|
1418
|
+
const media = this.media;
|
1419
|
+
if (media) {
|
1420
|
+
return this.fragPlaying || this.getAppendedFrag(media.currentTime);
|
1436
1421
|
}
|
1437
1422
|
return null;
|
1438
1423
|
}
|
1439
1424
|
|
1440
1425
|
get currentProgramDateTime(): Date | null {
|
1441
|
-
const
|
1442
|
-
if (
|
1443
|
-
const
|
1444
|
-
const frag =
|
1445
|
-
|
1446
|
-
|
1447
|
-
|
1448
|
-
|
1449
|
-
|
1450
|
-
const
|
1451
|
-
|
1452
|
-
|
1453
|
-
return new Date(epocMs);
|
1454
|
-
}
|
1426
|
+
const media = this.media;
|
1427
|
+
if (media) {
|
1428
|
+
const currentTime = media.currentTime;
|
1429
|
+
const frag = this.currentFrag;
|
1430
|
+
if (
|
1431
|
+
frag &&
|
1432
|
+
Number.isFinite(currentTime) &&
|
1433
|
+
Number.isFinite(frag.programDateTime)
|
1434
|
+
) {
|
1435
|
+
const epocMs =
|
1436
|
+
(frag.programDateTime as number) + (currentTime - frag.start) * 1000;
|
1437
|
+
return new Date(epocMs);
|
1455
1438
|
}
|
1456
1439
|
}
|
1457
1440
|
return null;
|