@zenvor/hls.js 1.0.0
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/LICENSE +28 -0
- package/README.md +472 -0
- package/dist/hls-demo.js +26995 -0
- package/dist/hls-demo.js.map +1 -0
- package/dist/hls.d.mts +4204 -0
- package/dist/hls.d.ts +4204 -0
- package/dist/hls.js +40050 -0
- package/dist/hls.js.d.ts +4204 -0
- package/dist/hls.js.map +1 -0
- package/dist/hls.light.js +27145 -0
- package/dist/hls.light.js.map +1 -0
- package/dist/hls.light.min.js +2 -0
- package/dist/hls.light.min.js.map +1 -0
- package/dist/hls.light.mjs +26392 -0
- package/dist/hls.light.mjs.map +1 -0
- package/dist/hls.min.js +2 -0
- package/dist/hls.min.js.map +1 -0
- package/dist/hls.mjs +38956 -0
- package/dist/hls.mjs.map +1 -0
- package/dist/hls.worker.js +2 -0
- package/dist/hls.worker.js.map +1 -0
- package/package.json +143 -0
- package/src/config.ts +794 -0
- package/src/controller/abr-controller.ts +1019 -0
- package/src/controller/algo-data-controller.ts +794 -0
- package/src/controller/audio-stream-controller.ts +1099 -0
- package/src/controller/audio-track-controller.ts +454 -0
- package/src/controller/base-playlist-controller.ts +438 -0
- package/src/controller/base-stream-controller.ts +2526 -0
- package/src/controller/buffer-controller.ts +2015 -0
- package/src/controller/buffer-operation-queue.ts +159 -0
- package/src/controller/cap-level-controller.ts +367 -0
- package/src/controller/cmcd-controller.ts +422 -0
- package/src/controller/content-steering-controller.ts +622 -0
- package/src/controller/eme-controller.ts +1617 -0
- package/src/controller/error-controller.ts +627 -0
- package/src/controller/fps-controller.ts +146 -0
- package/src/controller/fragment-finders.ts +256 -0
- package/src/controller/fragment-tracker.ts +567 -0
- package/src/controller/gap-controller.ts +719 -0
- package/src/controller/id3-track-controller.ts +488 -0
- package/src/controller/interstitial-player.ts +302 -0
- package/src/controller/interstitials-controller.ts +2895 -0
- package/src/controller/interstitials-schedule.ts +698 -0
- package/src/controller/latency-controller.ts +294 -0
- package/src/controller/level-controller.ts +776 -0
- package/src/controller/stream-controller.ts +1597 -0
- package/src/controller/subtitle-stream-controller.ts +508 -0
- package/src/controller/subtitle-track-controller.ts +617 -0
- package/src/controller/timeline-controller.ts +677 -0
- package/src/crypt/aes-crypto.ts +36 -0
- package/src/crypt/aes-decryptor.ts +339 -0
- package/src/crypt/decrypter-aes-mode.ts +4 -0
- package/src/crypt/decrypter.ts +225 -0
- package/src/crypt/fast-aes-key.ts +39 -0
- package/src/define-plugin.d.ts +17 -0
- package/src/demux/audio/aacdemuxer.ts +126 -0
- package/src/demux/audio/ac3-demuxer.ts +170 -0
- package/src/demux/audio/adts.ts +249 -0
- package/src/demux/audio/base-audio-demuxer.ts +205 -0
- package/src/demux/audio/dolby.ts +21 -0
- package/src/demux/audio/mp3demuxer.ts +85 -0
- package/src/demux/audio/mpegaudio.ts +177 -0
- package/src/demux/chunk-cache.ts +42 -0
- package/src/demux/dummy-demuxed-track.ts +13 -0
- package/src/demux/inject-worker.ts +75 -0
- package/src/demux/mp4demuxer.ts +234 -0
- package/src/demux/sample-aes.ts +198 -0
- package/src/demux/transmuxer-interface.ts +449 -0
- package/src/demux/transmuxer-worker.ts +221 -0
- package/src/demux/transmuxer.ts +560 -0
- package/src/demux/tsdemuxer.ts +1256 -0
- package/src/demux/video/avc-video-parser.ts +401 -0
- package/src/demux/video/base-video-parser.ts +198 -0
- package/src/demux/video/exp-golomb.ts +153 -0
- package/src/demux/video/hevc-video-parser.ts +736 -0
- package/src/empty-es.js +5 -0
- package/src/empty.js +3 -0
- package/src/errors.ts +107 -0
- package/src/events.ts +548 -0
- package/src/exports-default.ts +3 -0
- package/src/exports-named.ts +81 -0
- package/src/hls.ts +1613 -0
- package/src/is-supported.ts +54 -0
- package/src/loader/date-range.ts +207 -0
- package/src/loader/fragment-loader.ts +403 -0
- package/src/loader/fragment.ts +487 -0
- package/src/loader/interstitial-asset-list.ts +162 -0
- package/src/loader/interstitial-event.ts +337 -0
- package/src/loader/key-loader.ts +439 -0
- package/src/loader/level-details.ts +203 -0
- package/src/loader/level-key.ts +259 -0
- package/src/loader/load-stats.ts +17 -0
- package/src/loader/m3u8-parser.ts +1072 -0
- package/src/loader/playlist-loader.ts +839 -0
- package/src/polyfills/number.ts +15 -0
- package/src/remux/aac-helper.ts +81 -0
- package/src/remux/mp4-generator.ts +1380 -0
- package/src/remux/mp4-remuxer.ts +1261 -0
- package/src/remux/passthrough-remuxer.ts +434 -0
- package/src/task-loop.ts +130 -0
- package/src/types/algo.ts +44 -0
- package/src/types/buffer.ts +105 -0
- package/src/types/component-api.ts +20 -0
- package/src/types/demuxer.ts +208 -0
- package/src/types/events.ts +574 -0
- package/src/types/fragment-tracker.ts +23 -0
- package/src/types/level.ts +268 -0
- package/src/types/loader.ts +198 -0
- package/src/types/media-playlist.ts +92 -0
- package/src/types/network-details.ts +3 -0
- package/src/types/remuxer.ts +104 -0
- package/src/types/track.ts +12 -0
- package/src/types/transmuxer.ts +46 -0
- package/src/types/tuples.ts +6 -0
- package/src/types/vtt.ts +11 -0
- package/src/utils/arrays.ts +22 -0
- package/src/utils/attr-list.ts +192 -0
- package/src/utils/binary-search.ts +46 -0
- package/src/utils/buffer-helper.ts +173 -0
- package/src/utils/cea-608-parser.ts +1413 -0
- package/src/utils/chunker.ts +41 -0
- package/src/utils/codecs.ts +314 -0
- package/src/utils/cues.ts +96 -0
- package/src/utils/discontinuities.ts +174 -0
- package/src/utils/encryption-methods-util.ts +21 -0
- package/src/utils/error-helper.ts +95 -0
- package/src/utils/event-listener-helper.ts +16 -0
- package/src/utils/ewma-bandwidth-estimator.ts +97 -0
- package/src/utils/ewma.ts +43 -0
- package/src/utils/fetch-loader.ts +331 -0
- package/src/utils/global.ts +2 -0
- package/src/utils/hash.ts +10 -0
- package/src/utils/hdr.ts +67 -0
- package/src/utils/hex.ts +32 -0
- package/src/utils/imsc1-ttml-parser.ts +261 -0
- package/src/utils/keysystem-util.ts +45 -0
- package/src/utils/level-helper.ts +629 -0
- package/src/utils/logger.ts +120 -0
- package/src/utils/media-option-attributes.ts +49 -0
- package/src/utils/mediacapabilities-helper.ts +301 -0
- package/src/utils/mediakeys-helper.ts +210 -0
- package/src/utils/mediasource-helper.ts +37 -0
- package/src/utils/mp4-tools.ts +1473 -0
- package/src/utils/number.ts +3 -0
- package/src/utils/numeric-encoding-utils.ts +26 -0
- package/src/utils/output-filter.ts +46 -0
- package/src/utils/rendition-helper.ts +505 -0
- package/src/utils/safe-json-stringify.ts +22 -0
- package/src/utils/texttrack-utils.ts +164 -0
- package/src/utils/time-ranges.ts +17 -0
- package/src/utils/timescale-conversion.ts +46 -0
- package/src/utils/utf8-utils.ts +18 -0
- package/src/utils/variable-substitution.ts +105 -0
- package/src/utils/vttcue.ts +384 -0
- package/src/utils/vttparser.ts +497 -0
- package/src/utils/webvtt-parser.ts +166 -0
- package/src/utils/xhr-loader.ts +337 -0
- package/src/version.ts +1 -0
|
@@ -0,0 +1,422 @@
|
|
|
1
|
+
import { CmcdObjectType } from '@svta/common-media-library/cmcd/CmcdObjectType';
|
|
2
|
+
import { CmcdStreamingFormat } from '@svta/common-media-library/cmcd/CmcdStreamingFormat';
|
|
3
|
+
import { appendCmcdHeaders } from '@svta/common-media-library/cmcd/appendCmcdHeaders';
|
|
4
|
+
import { appendCmcdQuery } from '@svta/common-media-library/cmcd/appendCmcdQuery';
|
|
5
|
+
import { Events } from '../events';
|
|
6
|
+
import { BufferHelper } from '../utils/buffer-helper';
|
|
7
|
+
import type {
|
|
8
|
+
FragmentLoaderConstructor,
|
|
9
|
+
HlsConfig,
|
|
10
|
+
PlaylistLoaderConstructor,
|
|
11
|
+
} from '../config';
|
|
12
|
+
import type Hls from '../hls';
|
|
13
|
+
import type { Fragment, Part } from '../loader/fragment';
|
|
14
|
+
import type { ExtendedSourceBuffer } from '../types/buffer';
|
|
15
|
+
import type { ComponentAPI } from '../types/component-api';
|
|
16
|
+
import type { BufferCreatedData, MediaAttachedData } from '../types/events';
|
|
17
|
+
import type {
|
|
18
|
+
FragmentLoaderContext,
|
|
19
|
+
Loader,
|
|
20
|
+
LoaderCallbacks,
|
|
21
|
+
LoaderConfiguration,
|
|
22
|
+
LoaderContext,
|
|
23
|
+
PlaylistLoaderContext,
|
|
24
|
+
} from '../types/loader';
|
|
25
|
+
import type { Cmcd } from '@svta/common-media-library/cmcd/Cmcd';
|
|
26
|
+
import type { CmcdEncodeOptions } from '@svta/common-media-library/cmcd/CmcdEncodeOptions';
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Controller to deal with Common Media Client Data (CMCD)
|
|
30
|
+
* @see https://cdn.cta.tech/cta/media/media/resources/standards/pdfs/cta-5004-final.pdf
|
|
31
|
+
*/
|
|
32
|
+
export default class CMCDController implements ComponentAPI {
|
|
33
|
+
private hls: Hls;
|
|
34
|
+
private config: HlsConfig;
|
|
35
|
+
private media?: HTMLMediaElement;
|
|
36
|
+
private sid?: string;
|
|
37
|
+
private cid?: string;
|
|
38
|
+
private useHeaders: boolean = false;
|
|
39
|
+
private includeKeys?: string[];
|
|
40
|
+
private initialized: boolean = false;
|
|
41
|
+
private starved: boolean = false;
|
|
42
|
+
private buffering: boolean = true;
|
|
43
|
+
private audioBuffer?: ExtendedSourceBuffer;
|
|
44
|
+
private videoBuffer?: ExtendedSourceBuffer;
|
|
45
|
+
|
|
46
|
+
constructor(hls: Hls) {
|
|
47
|
+
this.hls = hls;
|
|
48
|
+
const config = (this.config = hls.config);
|
|
49
|
+
const { cmcd } = config;
|
|
50
|
+
|
|
51
|
+
if (cmcd != null) {
|
|
52
|
+
config.pLoader = this.createPlaylistLoader();
|
|
53
|
+
config.fLoader = this.createFragmentLoader();
|
|
54
|
+
|
|
55
|
+
this.sid = cmcd.sessionId || hls.sessionId;
|
|
56
|
+
this.cid = cmcd.contentId;
|
|
57
|
+
this.useHeaders = cmcd.useHeaders === true;
|
|
58
|
+
this.includeKeys = cmcd.includeKeys;
|
|
59
|
+
this.registerListeners();
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
private registerListeners() {
|
|
64
|
+
const hls = this.hls;
|
|
65
|
+
hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
|
|
66
|
+
hls.on(Events.MEDIA_DETACHED, this.onMediaDetached, this);
|
|
67
|
+
hls.on(Events.BUFFER_CREATED, this.onBufferCreated, this);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
private unregisterListeners() {
|
|
71
|
+
const hls = this.hls;
|
|
72
|
+
hls.off(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
|
|
73
|
+
hls.off(Events.MEDIA_DETACHED, this.onMediaDetached, this);
|
|
74
|
+
hls.off(Events.BUFFER_CREATED, this.onBufferCreated, this);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
destroy() {
|
|
78
|
+
this.unregisterListeners();
|
|
79
|
+
this.onMediaDetached();
|
|
80
|
+
|
|
81
|
+
// @ts-ignore
|
|
82
|
+
this.hls = this.config = this.audioBuffer = this.videoBuffer = null;
|
|
83
|
+
// @ts-ignore
|
|
84
|
+
this.onWaiting = this.onPlaying = this.media = null;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
private onMediaAttached(
|
|
88
|
+
event: Events.MEDIA_ATTACHED,
|
|
89
|
+
data: MediaAttachedData,
|
|
90
|
+
) {
|
|
91
|
+
this.media = data.media;
|
|
92
|
+
this.media.addEventListener('waiting', this.onWaiting);
|
|
93
|
+
this.media.addEventListener('playing', this.onPlaying);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
private onMediaDetached() {
|
|
97
|
+
if (!this.media) {
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
this.media.removeEventListener('waiting', this.onWaiting);
|
|
102
|
+
this.media.removeEventListener('playing', this.onPlaying);
|
|
103
|
+
|
|
104
|
+
// @ts-ignore
|
|
105
|
+
this.media = null;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
private onBufferCreated(
|
|
109
|
+
event: Events.BUFFER_CREATED,
|
|
110
|
+
data: BufferCreatedData,
|
|
111
|
+
) {
|
|
112
|
+
this.audioBuffer = data.tracks.audio?.buffer;
|
|
113
|
+
this.videoBuffer = data.tracks.video?.buffer;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
private onWaiting = () => {
|
|
117
|
+
if (this.initialized) {
|
|
118
|
+
this.starved = true;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
this.buffering = true;
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
private onPlaying = () => {
|
|
125
|
+
if (!this.initialized) {
|
|
126
|
+
this.initialized = true;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
this.buffering = false;
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Create baseline CMCD data
|
|
134
|
+
*/
|
|
135
|
+
private createData(): Cmcd {
|
|
136
|
+
return {
|
|
137
|
+
v: 1,
|
|
138
|
+
sf: CmcdStreamingFormat.HLS,
|
|
139
|
+
sid: this.sid,
|
|
140
|
+
cid: this.cid,
|
|
141
|
+
pr: this.media?.playbackRate,
|
|
142
|
+
mtp: this.hls.bandwidthEstimate / 1000,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Apply CMCD data to a request.
|
|
148
|
+
*/
|
|
149
|
+
private apply(context: LoaderContext, data: Cmcd = {}) {
|
|
150
|
+
// apply baseline data
|
|
151
|
+
Object.assign(data, this.createData());
|
|
152
|
+
|
|
153
|
+
const isVideo =
|
|
154
|
+
data.ot === CmcdObjectType.INIT ||
|
|
155
|
+
data.ot === CmcdObjectType.VIDEO ||
|
|
156
|
+
data.ot === CmcdObjectType.MUXED;
|
|
157
|
+
|
|
158
|
+
if (this.starved && isVideo) {
|
|
159
|
+
data.bs = true;
|
|
160
|
+
data.su = true;
|
|
161
|
+
this.starved = false;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
if (data.su == null) {
|
|
165
|
+
data.su = this.buffering;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// TODO: Implement rtp, nrr, dl
|
|
169
|
+
|
|
170
|
+
const { includeKeys } = this;
|
|
171
|
+
if (includeKeys) {
|
|
172
|
+
data = Object.keys(data).reduce((acc, key) => {
|
|
173
|
+
includeKeys.includes(key) && (acc[key] = data[key]);
|
|
174
|
+
return acc;
|
|
175
|
+
}, {});
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const options: CmcdEncodeOptions = { baseUrl: context.url };
|
|
179
|
+
|
|
180
|
+
if (this.useHeaders) {
|
|
181
|
+
if (!context.headers) {
|
|
182
|
+
context.headers = {};
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
appendCmcdHeaders(context.headers, data, options);
|
|
186
|
+
} else {
|
|
187
|
+
context.url = appendCmcdQuery(context.url, data, options);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Apply CMCD data to a manifest request.
|
|
193
|
+
*/
|
|
194
|
+
private applyPlaylistData = (context: PlaylistLoaderContext) => {
|
|
195
|
+
try {
|
|
196
|
+
this.apply(context, {
|
|
197
|
+
ot: CmcdObjectType.MANIFEST,
|
|
198
|
+
su: !this.initialized,
|
|
199
|
+
});
|
|
200
|
+
} catch (error) {
|
|
201
|
+
this.hls.logger.warn('Could not generate manifest CMCD data.', error);
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Apply CMCD data to a segment request
|
|
207
|
+
*/
|
|
208
|
+
private applyFragmentData = (context: FragmentLoaderContext) => {
|
|
209
|
+
try {
|
|
210
|
+
const { frag, part } = context;
|
|
211
|
+
const level = this.hls.levels[frag.level];
|
|
212
|
+
const ot = this.getObjectType(frag);
|
|
213
|
+
const data: Cmcd = { d: (part || frag).duration * 1000, ot };
|
|
214
|
+
|
|
215
|
+
if (
|
|
216
|
+
ot === CmcdObjectType.VIDEO ||
|
|
217
|
+
ot === CmcdObjectType.AUDIO ||
|
|
218
|
+
ot == CmcdObjectType.MUXED
|
|
219
|
+
) {
|
|
220
|
+
data.br = level.bitrate / 1000;
|
|
221
|
+
data.tb = this.getTopBandwidth(ot) / 1000;
|
|
222
|
+
data.bl = this.getBufferLength(ot);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
const next = part ? this.getNextPart(part) : this.getNextFrag(frag);
|
|
226
|
+
|
|
227
|
+
if (next?.url && next.url !== frag.url) {
|
|
228
|
+
data.nor = next.url;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
this.apply(context, data);
|
|
232
|
+
} catch (error) {
|
|
233
|
+
this.hls.logger.warn('Could not generate segment CMCD data.', error);
|
|
234
|
+
}
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
private getNextFrag(fragment: Fragment): Fragment | undefined {
|
|
238
|
+
const levelDetails = this.hls.levels[fragment.level]?.details;
|
|
239
|
+
if (levelDetails) {
|
|
240
|
+
const index = (fragment.sn as number) - levelDetails.startSN;
|
|
241
|
+
return levelDetails.fragments[index + 1];
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
return undefined;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
private getNextPart(part: Part): Part | undefined {
|
|
248
|
+
const { index, fragment } = part;
|
|
249
|
+
const partList = this.hls.levels[fragment.level]?.details?.partList;
|
|
250
|
+
|
|
251
|
+
if (partList) {
|
|
252
|
+
const { sn } = fragment;
|
|
253
|
+
for (let i = partList.length - 1; i >= 0; i--) {
|
|
254
|
+
const p = partList[i];
|
|
255
|
+
if (p.index === index && p.fragment.sn === sn) {
|
|
256
|
+
return partList[i + 1];
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
return undefined;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* The CMCD object type.
|
|
266
|
+
*/
|
|
267
|
+
private getObjectType(fragment: Fragment): CmcdObjectType | undefined {
|
|
268
|
+
const { type } = fragment;
|
|
269
|
+
|
|
270
|
+
if (type === 'subtitle') {
|
|
271
|
+
return CmcdObjectType.TIMED_TEXT;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
if (fragment.sn === 'initSegment') {
|
|
275
|
+
return CmcdObjectType.INIT;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
if (type === 'audio') {
|
|
279
|
+
return CmcdObjectType.AUDIO;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
if (type === 'main') {
|
|
283
|
+
if (!this.hls.audioTracks.length) {
|
|
284
|
+
return CmcdObjectType.MUXED;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
return CmcdObjectType.VIDEO;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
return undefined;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Get the highest bitrate.
|
|
295
|
+
*/
|
|
296
|
+
private getTopBandwidth(type: CmcdObjectType) {
|
|
297
|
+
let bitrate: number = 0;
|
|
298
|
+
let levels;
|
|
299
|
+
const hls = this.hls;
|
|
300
|
+
|
|
301
|
+
if (type === CmcdObjectType.AUDIO) {
|
|
302
|
+
levels = hls.audioTracks;
|
|
303
|
+
} else {
|
|
304
|
+
const max = hls.maxAutoLevel;
|
|
305
|
+
const len = max > -1 ? max + 1 : hls.levels.length;
|
|
306
|
+
levels = hls.levels.slice(0, len);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
levels.forEach((level) => {
|
|
310
|
+
if (level.bitrate > bitrate) {
|
|
311
|
+
bitrate = level.bitrate;
|
|
312
|
+
}
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
return bitrate > 0 ? bitrate : NaN;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Get the buffer length for a media type in milliseconds
|
|
320
|
+
*/
|
|
321
|
+
private getBufferLength(type: CmcdObjectType) {
|
|
322
|
+
const media = this.media;
|
|
323
|
+
const buffer =
|
|
324
|
+
type === CmcdObjectType.AUDIO ? this.audioBuffer : this.videoBuffer;
|
|
325
|
+
|
|
326
|
+
if (!buffer || !media) {
|
|
327
|
+
return NaN;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
const info = BufferHelper.bufferInfo(
|
|
331
|
+
buffer,
|
|
332
|
+
media.currentTime,
|
|
333
|
+
this.config.maxBufferHole,
|
|
334
|
+
);
|
|
335
|
+
|
|
336
|
+
return info.len * 1000;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* Create a playlist loader
|
|
341
|
+
*/
|
|
342
|
+
private createPlaylistLoader(): PlaylistLoaderConstructor | undefined {
|
|
343
|
+
const { pLoader } = this.config;
|
|
344
|
+
const apply = this.applyPlaylistData;
|
|
345
|
+
const Ctor = pLoader || (this.config.loader as PlaylistLoaderConstructor);
|
|
346
|
+
|
|
347
|
+
return class CmcdPlaylistLoader {
|
|
348
|
+
private loader: Loader<PlaylistLoaderContext>;
|
|
349
|
+
|
|
350
|
+
constructor(config: HlsConfig) {
|
|
351
|
+
this.loader = new Ctor(config);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
get stats() {
|
|
355
|
+
return this.loader.stats;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
get context() {
|
|
359
|
+
return this.loader.context;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
destroy() {
|
|
363
|
+
this.loader.destroy();
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
abort() {
|
|
367
|
+
this.loader.abort();
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
load(
|
|
371
|
+
context: PlaylistLoaderContext,
|
|
372
|
+
config: LoaderConfiguration,
|
|
373
|
+
callbacks: LoaderCallbacks<PlaylistLoaderContext>,
|
|
374
|
+
) {
|
|
375
|
+
apply(context);
|
|
376
|
+
this.loader.load(context, config, callbacks);
|
|
377
|
+
}
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* Create a playlist loader
|
|
383
|
+
*/
|
|
384
|
+
private createFragmentLoader(): FragmentLoaderConstructor | undefined {
|
|
385
|
+
const { fLoader } = this.config;
|
|
386
|
+
const apply = this.applyFragmentData;
|
|
387
|
+
const Ctor = fLoader || (this.config.loader as FragmentLoaderConstructor);
|
|
388
|
+
|
|
389
|
+
return class CmcdFragmentLoader {
|
|
390
|
+
private loader: Loader<FragmentLoaderContext>;
|
|
391
|
+
|
|
392
|
+
constructor(config: HlsConfig) {
|
|
393
|
+
this.loader = new Ctor(config);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
get stats() {
|
|
397
|
+
return this.loader.stats;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
get context() {
|
|
401
|
+
return this.loader.context;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
destroy() {
|
|
405
|
+
this.loader.destroy();
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
abort() {
|
|
409
|
+
this.loader.abort();
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
load(
|
|
413
|
+
context: FragmentLoaderContext,
|
|
414
|
+
config: LoaderConfiguration,
|
|
415
|
+
callbacks: LoaderCallbacks<FragmentLoaderContext>,
|
|
416
|
+
) {
|
|
417
|
+
apply(context);
|
|
418
|
+
this.loader.load(context, config, callbacks);
|
|
419
|
+
}
|
|
420
|
+
};
|
|
421
|
+
}
|
|
422
|
+
}
|