hls.js 1.5.12-0.canary.10399 → 1.5.12
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 +2671 -4220
- package/dist/hls.js.d.ts +108 -173
- package/dist/hls.js.map +1 -1
- package/dist/hls.light.js +1955 -2892
- 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 +3402 -4354
- 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 +4445 -6009
- 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 +137 -141
- 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 +82 -215
- package/src/controller/buffer-controller.ts +97 -250
- 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 +2 -2
- package/src/demux/audio/ac3-demuxer.ts +3 -4
- 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/mp4demuxer.ts +7 -7
- package/src/demux/sample-aes.ts +0 -2
- package/src/demux/transmuxer-interface.ts +16 -8
- package/src/demux/transmuxer-worker.ts +4 -4
- package/src/demux/transmuxer.ts +3 -16
- package/src/demux/tsdemuxer.ts +38 -75
- 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/events.ts +1 -8
- package/src/exports-named.ts +1 -1
- package/src/hls.ts +43 -73
- 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 +16 -36
- package/src/remux/passthrough-remuxer.ts +1 -1
- 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/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
@@ -28,8 +28,6 @@ class MP4 {
|
|
28
28
|
MP4.types = {
|
29
29
|
avc1: [], // codingname
|
30
30
|
avcC: [],
|
31
|
-
hvc1: [],
|
32
|
-
hvcC: [],
|
33
31
|
btrt: [],
|
34
32
|
dinf: [],
|
35
33
|
dref: [],
|
@@ -841,10 +839,8 @@ class MP4 {
|
|
841
839
|
return MP4.box(MP4.types.stsd, MP4.STSD, MP4.ac3(track));
|
842
840
|
}
|
843
841
|
return MP4.box(MP4.types.stsd, MP4.STSD, MP4.mp4a(track));
|
844
|
-
} else if (track.segmentCodec === 'avc') {
|
845
|
-
return MP4.box(MP4.types.stsd, MP4.STSD, MP4.avc1(track));
|
846
842
|
} else {
|
847
|
-
return MP4.box(MP4.types.stsd, MP4.STSD, MP4.
|
843
|
+
return MP4.box(MP4.types.stsd, MP4.STSD, MP4.avc1(track));
|
848
844
|
}
|
849
845
|
}
|
850
846
|
|
@@ -1127,197 +1123,6 @@ class MP4 {
|
|
1127
1123
|
const result = appendUint8Array(MP4.FTYP, movie);
|
1128
1124
|
return result;
|
1129
1125
|
}
|
1130
|
-
|
1131
|
-
static hvc1(track) {
|
1132
|
-
const ps = track.params;
|
1133
|
-
const units = [track.vps, track.sps, track.pps];
|
1134
|
-
const NALuLengthSize = 4;
|
1135
|
-
const config = new Uint8Array([
|
1136
|
-
0x01,
|
1137
|
-
(ps.general_profile_space << 6) |
|
1138
|
-
(ps.general_tier_flag ? 32 : 0) |
|
1139
|
-
ps.general_profile_idc,
|
1140
|
-
ps.general_profile_compatibility_flags[0],
|
1141
|
-
ps.general_profile_compatibility_flags[1],
|
1142
|
-
ps.general_profile_compatibility_flags[2],
|
1143
|
-
ps.general_profile_compatibility_flags[3],
|
1144
|
-
ps.general_constraint_indicator_flags[0],
|
1145
|
-
ps.general_constraint_indicator_flags[1],
|
1146
|
-
ps.general_constraint_indicator_flags[2],
|
1147
|
-
ps.general_constraint_indicator_flags[3],
|
1148
|
-
ps.general_constraint_indicator_flags[4],
|
1149
|
-
ps.general_constraint_indicator_flags[5],
|
1150
|
-
ps.general_level_idc,
|
1151
|
-
240 | (ps.min_spatial_segmentation_idc >> 8),
|
1152
|
-
255 & ps.min_spatial_segmentation_idc,
|
1153
|
-
252 | ps.parallelismType,
|
1154
|
-
252 | ps.chroma_format_idc,
|
1155
|
-
248 | ps.bit_depth_luma_minus8,
|
1156
|
-
248 | ps.bit_depth_chroma_minus8,
|
1157
|
-
0x00,
|
1158
|
-
parseInt(ps.frame_rate.fps),
|
1159
|
-
(NALuLengthSize - 1) |
|
1160
|
-
(ps.temporal_id_nested << 2) |
|
1161
|
-
(ps.num_temporal_layers << 3) |
|
1162
|
-
(ps.frame_rate.fixed ? 64 : 0),
|
1163
|
-
units.length,
|
1164
|
-
]);
|
1165
|
-
|
1166
|
-
// compute hvcC size in bytes
|
1167
|
-
let length = config.length;
|
1168
|
-
for (let i = 0; i < units.length; i += 1) {
|
1169
|
-
length += 3;
|
1170
|
-
for (let j = 0; j < units[i].length; j += 1) {
|
1171
|
-
length += 2 + units[i][j].length;
|
1172
|
-
}
|
1173
|
-
}
|
1174
|
-
|
1175
|
-
const hvcC = new Uint8Array(length);
|
1176
|
-
hvcC.set(config, 0);
|
1177
|
-
length = config.length;
|
1178
|
-
// append parameter set units: one vps, one or more sps and pps
|
1179
|
-
const iMax = units.length - 1;
|
1180
|
-
for (let i = 0; i < units.length; i += 1) {
|
1181
|
-
hvcC.set(
|
1182
|
-
new Uint8Array([
|
1183
|
-
(32 + i) | (i === iMax ? 128 : 0),
|
1184
|
-
0x00,
|
1185
|
-
units[i].length,
|
1186
|
-
]),
|
1187
|
-
length,
|
1188
|
-
);
|
1189
|
-
length += 3;
|
1190
|
-
for (let j = 0; j < units[i].length; j += 1) {
|
1191
|
-
hvcC.set(
|
1192
|
-
new Uint8Array([units[i][j].length >> 8, units[i][j].length & 255]),
|
1193
|
-
length,
|
1194
|
-
);
|
1195
|
-
length += 2;
|
1196
|
-
hvcC.set(units[i][j], length);
|
1197
|
-
length += units[i][j].length;
|
1198
|
-
}
|
1199
|
-
}
|
1200
|
-
const hvcc = MP4.box(MP4.types.hvcC, hvcC);
|
1201
|
-
const width = track.width;
|
1202
|
-
const height = track.height;
|
1203
|
-
const hSpacing = track.pixelRatio[0];
|
1204
|
-
const vSpacing = track.pixelRatio[1];
|
1205
|
-
|
1206
|
-
return MP4.box(
|
1207
|
-
MP4.types.hvc1,
|
1208
|
-
new Uint8Array([
|
1209
|
-
0x00,
|
1210
|
-
0x00,
|
1211
|
-
0x00, // reserved
|
1212
|
-
0x00,
|
1213
|
-
0x00,
|
1214
|
-
0x00, // reserved
|
1215
|
-
0x00,
|
1216
|
-
0x01, // data_reference_index
|
1217
|
-
0x00,
|
1218
|
-
0x00, // pre_defined
|
1219
|
-
0x00,
|
1220
|
-
0x00, // reserved
|
1221
|
-
0x00,
|
1222
|
-
0x00,
|
1223
|
-
0x00,
|
1224
|
-
0x00,
|
1225
|
-
0x00,
|
1226
|
-
0x00,
|
1227
|
-
0x00,
|
1228
|
-
0x00,
|
1229
|
-
0x00,
|
1230
|
-
0x00,
|
1231
|
-
0x00,
|
1232
|
-
0x00, // pre_defined
|
1233
|
-
(width >> 8) & 0xff,
|
1234
|
-
width & 0xff, // width
|
1235
|
-
(height >> 8) & 0xff,
|
1236
|
-
height & 0xff, // height
|
1237
|
-
0x00,
|
1238
|
-
0x48,
|
1239
|
-
0x00,
|
1240
|
-
0x00, // horizresolution
|
1241
|
-
0x00,
|
1242
|
-
0x48,
|
1243
|
-
0x00,
|
1244
|
-
0x00, // vertresolution
|
1245
|
-
0x00,
|
1246
|
-
0x00,
|
1247
|
-
0x00,
|
1248
|
-
0x00, // reserved
|
1249
|
-
0x00,
|
1250
|
-
0x01, // frame_count
|
1251
|
-
0x12,
|
1252
|
-
0x64,
|
1253
|
-
0x61,
|
1254
|
-
0x69,
|
1255
|
-
0x6c, // dailymotion/hls.js
|
1256
|
-
0x79,
|
1257
|
-
0x6d,
|
1258
|
-
0x6f,
|
1259
|
-
0x74,
|
1260
|
-
0x69,
|
1261
|
-
0x6f,
|
1262
|
-
0x6e,
|
1263
|
-
0x2f,
|
1264
|
-
0x68,
|
1265
|
-
0x6c,
|
1266
|
-
0x73,
|
1267
|
-
0x2e,
|
1268
|
-
0x6a,
|
1269
|
-
0x73,
|
1270
|
-
0x00,
|
1271
|
-
0x00,
|
1272
|
-
0x00,
|
1273
|
-
0x00,
|
1274
|
-
0x00,
|
1275
|
-
0x00,
|
1276
|
-
0x00,
|
1277
|
-
0x00,
|
1278
|
-
0x00,
|
1279
|
-
0x00,
|
1280
|
-
0x00,
|
1281
|
-
0x00,
|
1282
|
-
0x00, // compressorname
|
1283
|
-
0x00,
|
1284
|
-
0x18, // depth = 24
|
1285
|
-
0x11,
|
1286
|
-
0x11,
|
1287
|
-
]), // pre_defined = -1
|
1288
|
-
hvcc,
|
1289
|
-
MP4.box(
|
1290
|
-
MP4.types.btrt,
|
1291
|
-
new Uint8Array([
|
1292
|
-
0x00,
|
1293
|
-
0x1c,
|
1294
|
-
0x9c,
|
1295
|
-
0x80, // bufferSizeDB
|
1296
|
-
0x00,
|
1297
|
-
0x2d,
|
1298
|
-
0xc6,
|
1299
|
-
0xc0, // maxBitrate
|
1300
|
-
0x00,
|
1301
|
-
0x2d,
|
1302
|
-
0xc6,
|
1303
|
-
0xc0,
|
1304
|
-
]),
|
1305
|
-
), // avgBitrate
|
1306
|
-
MP4.box(
|
1307
|
-
MP4.types.pasp,
|
1308
|
-
new Uint8Array([
|
1309
|
-
hSpacing >> 24, // hSpacing
|
1310
|
-
(hSpacing >> 16) & 0xff,
|
1311
|
-
(hSpacing >> 8) & 0xff,
|
1312
|
-
hSpacing & 0xff,
|
1313
|
-
vSpacing >> 24, // vSpacing
|
1314
|
-
(vSpacing >> 16) & 0xff,
|
1315
|
-
(vSpacing >> 8) & 0xff,
|
1316
|
-
vSpacing & 0xff,
|
1317
|
-
]),
|
1318
|
-
),
|
1319
|
-
);
|
1320
|
-
}
|
1321
1126
|
}
|
1322
1127
|
|
1323
1128
|
export default MP4;
|
package/src/remux/mp4-remuxer.ts
CHANGED
@@ -4,7 +4,7 @@ import type { HlsEventEmitter } from '../events';
|
|
4
4
|
import { Events } from '../events';
|
5
5
|
import { ErrorTypes, ErrorDetails } from '../errors';
|
6
6
|
import { logger } from '../utils/logger';
|
7
|
-
import
|
7
|
+
import {
|
8
8
|
InitSegmentData,
|
9
9
|
Remuxer,
|
10
10
|
RemuxerResult,
|
@@ -29,7 +29,6 @@ import type { TrackSet } from '../types/track';
|
|
29
29
|
import type { SourceBufferName } from '../types/buffer';
|
30
30
|
import type { Fragment } from '../loader/fragment';
|
31
31
|
import type { HlsConfig } from '../config';
|
32
|
-
import type { TypeSupported } from '../utils/codecs';
|
33
32
|
|
34
33
|
const MAX_SILENT_FRAME_DURATION = 10 * 1000; // 10 seconds
|
35
34
|
const AAC_SAMPLES_PER_FRAME = 1024;
|
@@ -42,7 +41,7 @@ let safariWebkitVersion: number | null = null;
|
|
42
41
|
export default class MP4Remuxer implements Remuxer {
|
43
42
|
private observer: HlsEventEmitter;
|
44
43
|
private config: HlsConfig;
|
45
|
-
private typeSupported:
|
44
|
+
private typeSupported: any;
|
46
45
|
private ISGenerated: boolean = false;
|
47
46
|
private _initPTS: RationalTimestamp | null = null;
|
48
47
|
private _initDTS: RationalTimestamp | null = null;
|
@@ -160,18 +159,15 @@ export default class MP4Remuxer implements Remuxer {
|
|
160
159
|
if (this.ISGenerated) {
|
161
160
|
const config = this.videoTrackConfig;
|
162
161
|
if (
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
(!config && enoughVideoSamples) ||
|
169
|
-
(this.nextAudioPts === null && enoughAudioSamples)
|
162
|
+
config &&
|
163
|
+
(videoTrack.width !== config.width ||
|
164
|
+
videoTrack.height !== config.height ||
|
165
|
+
videoTrack.pixelRatio?.[0] !== config.pixelRatio?.[0] ||
|
166
|
+
videoTrack.pixelRatio?.[1] !== config.pixelRatio?.[1])
|
170
167
|
) {
|
171
168
|
this.resetInitSegment();
|
172
169
|
}
|
173
|
-
}
|
174
|
-
if (!this.ISGenerated) {
|
170
|
+
} else {
|
175
171
|
initSegment = this.generateIS(
|
176
172
|
audioTrack,
|
177
173
|
videoTrack,
|
@@ -519,7 +515,7 @@ export default class MP4Remuxer implements Remuxer {
|
|
519
515
|
if (foundHole || foundOverlap) {
|
520
516
|
if (foundHole) {
|
521
517
|
logger.warn(
|
522
|
-
|
518
|
+
`AVC: ${toMsFromMpegTsClock(
|
523
519
|
delta,
|
524
520
|
true,
|
525
521
|
)} ms (${delta}dts) hole between fragments detected at ${timeOffset.toFixed(
|
@@ -528,7 +524,7 @@ export default class MP4Remuxer implements Remuxer {
|
|
528
524
|
);
|
529
525
|
} else {
|
530
526
|
logger.warn(
|
531
|
-
|
527
|
+
`AVC: ${toMsFromMpegTsClock(
|
532
528
|
-delta,
|
533
529
|
true,
|
534
530
|
)} ms (${delta}dts) overlapping between fragments detected at ${timeOffset.toFixed(
|
@@ -547,27 +543,12 @@ export default class MP4Remuxer implements Remuxer {
|
|
547
543
|
inputSamples[0].dts = firstDTS;
|
548
544
|
inputSamples[0].pts = firstPTS;
|
549
545
|
} else {
|
550
|
-
let isPTSOrderRetained = true;
|
551
546
|
for (let i = 0; i < inputSamples.length; i++) {
|
552
|
-
if (inputSamples[i].dts > firstPTS
|
547
|
+
if (inputSamples[i].dts > firstPTS) {
|
553
548
|
break;
|
554
549
|
}
|
555
|
-
|
556
|
-
const prevPTS = inputSamples[i].pts;
|
557
550
|
inputSamples[i].dts -= delta;
|
558
551
|
inputSamples[i].pts -= delta;
|
559
|
-
|
560
|
-
// check to see if this sample's PTS order has changed
|
561
|
-
// relative to the next one
|
562
|
-
if (i < inputSamples.length - 1) {
|
563
|
-
const nextSamplePTS = inputSamples[i + 1].pts;
|
564
|
-
const currentSamplePTS = inputSamples[i].pts;
|
565
|
-
|
566
|
-
const currentOrder = nextSamplePTS <= currentSamplePTS;
|
567
|
-
const prevOrder = nextSamplePTS <= prevPTS;
|
568
|
-
|
569
|
-
isPTSOrderRetained = currentOrder == prevOrder;
|
570
|
-
}
|
571
552
|
}
|
572
553
|
}
|
573
554
|
logger.log(
|
@@ -762,7 +743,7 @@ export default class MP4Remuxer implements Remuxer {
|
|
762
743
|
}
|
763
744
|
}
|
764
745
|
}
|
765
|
-
// next AVC
|
746
|
+
// next AVC sample DTS should be equal to last sample DTS + last sample duration (in PES timescale)
|
766
747
|
mp4SampleDuration =
|
767
748
|
stretchedLastFrame || !mp4SampleDuration
|
768
749
|
? averageSampleDuration
|
@@ -946,7 +927,7 @@ export default class MP4Remuxer implements Remuxer {
|
|
946
927
|
for (let j = 0; j < missing; j++) {
|
947
928
|
const newStamp = Math.max(nextPts as number, 0);
|
948
929
|
let fillFrame = AAC.getSilentFrame(
|
949
|
-
track.
|
930
|
+
track.manifestCodec || track.codec,
|
950
931
|
track.channelCount,
|
951
932
|
);
|
952
933
|
if (!fillFrame) {
|
@@ -1088,16 +1069,15 @@ export default class MP4Remuxer implements Remuxer {
|
|
1088
1069
|
const startDTS: number =
|
1089
1070
|
(nextAudioPts !== null
|
1090
1071
|
? nextAudioPts
|
1091
|
-
:
|
1092
|
-
const endDTS: number =
|
1093
|
-
(videoData.endDTS as number) * inputTimeScale + init90kHz;
|
1072
|
+
: videoData.startDTS * inputTimeScale) + init90kHz;
|
1073
|
+
const endDTS: number = videoData.endDTS * inputTimeScale + init90kHz;
|
1094
1074
|
// one sample's duration value
|
1095
1075
|
const frameDuration: number = scaleFactor * AAC_SAMPLES_PER_FRAME;
|
1096
1076
|
// samples count of this segment's duration
|
1097
1077
|
const nbSamples: number = Math.ceil((endDTS - startDTS) / frameDuration);
|
1098
1078
|
// silent frame
|
1099
1079
|
const silentFrame: Uint8Array | undefined = AAC.getSilentFrame(
|
1100
|
-
track.
|
1080
|
+
track.manifestCodec || track.codec,
|
1101
1081
|
track.channelCount,
|
1102
1082
|
);
|
1103
1083
|
|
@@ -178,7 +178,7 @@ class PassThroughRemuxer implements Remuxer {
|
|
178
178
|
initSegment.initPTS = decodeTime - timeOffset;
|
179
179
|
if (initPTS && initPTS.timescale === 1) {
|
180
180
|
logger.warn(
|
181
|
-
`Adjusting initPTS
|
181
|
+
`Adjusting initPTS by ${initSegment.initPTS - initPTS.baseTime}`,
|
182
182
|
);
|
183
183
|
}
|
184
184
|
this.initPTS = initPTS = {
|
package/src/task-loop.ts
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
import { type ILogger, Logger } from './utils/logger';
|
2
|
-
|
3
1
|
/**
|
4
2
|
* @ignore
|
5
3
|
* Sub-class specialization of EventHandler base class.
|
@@ -29,14 +27,13 @@ import { type ILogger, Logger } from './utils/logger';
|
|
29
27
|
* we are limiting the task execution per call stack to exactly one, but scheduling/post-poning further
|
30
28
|
* task processing on the next main loop iteration (also known as "next tick" in the Node/JS runtime lingo).
|
31
29
|
*/
|
32
|
-
export default class TaskLoop
|
30
|
+
export default class TaskLoop {
|
33
31
|
private readonly _boundTick: () => void;
|
34
32
|
private _tickTimer: number | null = null;
|
35
33
|
private _tickInterval: number | null = null;
|
36
34
|
private _tickCallCount = 0;
|
37
35
|
|
38
|
-
constructor(
|
39
|
-
super(label, logger);
|
36
|
+
constructor() {
|
40
37
|
this._boundTick = this.tick.bind(this);
|
41
38
|
}
|
42
39
|
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import
|
1
|
+
import EwmaBandWidthEstimator from '../utils/ewma-bandwidth-estimator';
|
2
2
|
|
3
3
|
export interface ComponentAPI {
|
4
4
|
destroy(): void;
|
@@ -15,6 +15,4 @@ export interface AbrComponentAPI extends ComponentAPI {
|
|
15
15
|
export interface NetworkComponentAPI extends ComponentAPI {
|
16
16
|
startLoad(startPosition: number): void;
|
17
17
|
stopLoad(): void;
|
18
|
-
pauseBuffering?(): void;
|
19
|
-
resumeBuffering?(): void;
|
20
18
|
}
|
package/src/types/demuxer.ts
CHANGED
@@ -64,7 +64,6 @@ export interface DemuxedAudioTrack extends DemuxedTrack {
|
|
64
64
|
segmentCodec?: string;
|
65
65
|
channelCount?: number;
|
66
66
|
manifestCodec?: string;
|
67
|
-
parsedCodec?: string;
|
68
67
|
samples: AudioSample[];
|
69
68
|
}
|
70
69
|
|
@@ -73,14 +72,12 @@ export interface DemuxedVideoTrackBase extends DemuxedTrack {
|
|
73
72
|
height?: number;
|
74
73
|
pixelRatio?: [number, number];
|
75
74
|
audFound?: boolean;
|
76
|
-
vps?: Uint8Array[];
|
77
75
|
pps?: Uint8Array[];
|
78
76
|
sps?: Uint8Array[];
|
79
77
|
naluState?: number;
|
80
78
|
segmentCodec?: string;
|
81
79
|
manifestCodec?: string;
|
82
80
|
samples: VideoSample[] | Uint8Array;
|
83
|
-
params?: object;
|
84
81
|
}
|
85
82
|
|
86
83
|
export interface DemuxedVideoTrack extends DemuxedVideoTrackBase {
|
package/src/types/events.ts
CHANGED
@@ -1,4 +1,7 @@
|
|
1
|
-
|
1
|
+
// eslint-disable-next-line import/no-duplicates
|
2
|
+
import type { Fragment } from '../loader/fragment';
|
3
|
+
// eslint-disable-next-line import/no-duplicates
|
4
|
+
import type { Part } from '../loader/fragment';
|
2
5
|
import type { LevelDetails } from '../loader/level-details';
|
3
6
|
import type {
|
4
7
|
HdcpLevel,
|
@@ -39,10 +42,6 @@ export interface MediaAttachedData {
|
|
39
42
|
mediaSource?: MediaSource;
|
40
43
|
}
|
41
44
|
|
42
|
-
export interface MediaEndedData {
|
43
|
-
stalled: boolean;
|
44
|
-
}
|
45
|
-
|
46
45
|
export interface BufferCodecsData {
|
47
46
|
video?: Track;
|
48
47
|
audio?: Track;
|
@@ -192,18 +191,6 @@ export interface LevelUpdatedData {
|
|
192
191
|
level: number;
|
193
192
|
}
|
194
193
|
|
195
|
-
export interface AudioTrackUpdatedData {
|
196
|
-
details: LevelDetails;
|
197
|
-
id: number;
|
198
|
-
groupId: string;
|
199
|
-
}
|
200
|
-
|
201
|
-
export interface SubtitleTrackUpdatedData {
|
202
|
-
details: LevelDetails;
|
203
|
-
id: number;
|
204
|
-
groupId: string;
|
205
|
-
}
|
206
|
-
|
207
194
|
export interface LevelPTSUpdatedData {
|
208
195
|
details: LevelDetails;
|
209
196
|
level: Level;
|
@@ -329,8 +316,8 @@ export interface NonNativeTextTracksData {
|
|
329
316
|
}
|
330
317
|
|
331
318
|
export interface InitPTSFoundData {
|
332
|
-
id:
|
333
|
-
frag:
|
319
|
+
id: string;
|
320
|
+
frag: Fragment;
|
334
321
|
initPTS: number;
|
335
322
|
timescale: number;
|
336
323
|
}
|
@@ -1,9 +1,9 @@
|
|
1
|
-
import type {
|
1
|
+
import type { Fragment } from '../loader/fragment';
|
2
2
|
import type { SourceBufferName } from './buffer';
|
3
3
|
import type { FragLoadedData } from './events';
|
4
4
|
|
5
5
|
export interface FragmentEntity {
|
6
|
-
body:
|
6
|
+
body: Fragment;
|
7
7
|
// appendedPTS is the latest buffered presentation time within the fragment's time range.
|
8
8
|
// It is used to determine: which fragment is appended at any given position, and hls.currentLevel.
|
9
9
|
appendedPTS: number | null;
|
@@ -1,7 +1,6 @@
|
|
1
1
|
import type { AttrList } from '../utils/attr-list';
|
2
2
|
import type { LevelDetails } from '../loader/level-details';
|
3
|
-
import type {
|
4
|
-
import type { PlaylistLevelType } from './loader';
|
3
|
+
import type { VideoRange } from './level';
|
5
4
|
|
6
5
|
export type AudioPlaylistType = 'AUDIO';
|
7
6
|
|
@@ -11,16 +10,9 @@ export type SubtitlePlaylistType = 'SUBTITLES' | 'CLOSED-CAPTIONS';
|
|
11
10
|
|
12
11
|
export type MediaPlaylistType = MainPlaylistType | SubtitlePlaylistType;
|
13
12
|
|
14
|
-
export type MediaSelection = {
|
15
|
-
[PlaylistLevelType.MAIN]: Level;
|
16
|
-
[PlaylistLevelType.AUDIO]?: MediaPlaylist;
|
17
|
-
[PlaylistLevelType.SUBTITLE]?: MediaPlaylist;
|
18
|
-
};
|
19
|
-
|
20
13
|
export type VideoSelectionOption = {
|
21
14
|
preferHDR?: boolean;
|
22
15
|
allowedVideoRanges?: Array<VideoRange>;
|
23
|
-
videoCodec?: string;
|
24
16
|
};
|
25
17
|
|
26
18
|
export type AudioSelectionOption = {
|
package/src/types/remuxer.ts
CHANGED
package/src/utils/attr-list.ts
CHANGED
@@ -1,8 +1,3 @@
|
|
1
|
-
import type { LevelDetails } from '../loader/level-details';
|
2
|
-
import type { ParsedMultivariantPlaylist } from '../loader/m3u8-parser';
|
3
|
-
import { logger } from './logger';
|
4
|
-
import { substituteVariables } from './variable-substitution';
|
5
|
-
|
6
1
|
const DECIMAL_RESOLUTION_REGEX = /^(\d+)x(\d+)$/;
|
7
2
|
const ATTR_LIST_REGEX = /(.+?)=(".*?"|.*?)(?:,|$)/g;
|
8
3
|
|
@@ -10,15 +5,9 @@ const ATTR_LIST_REGEX = /(.+?)=(".*?"|.*?)(?:,|$)/g;
|
|
10
5
|
export class AttrList {
|
11
6
|
[key: string]: any;
|
12
7
|
|
13
|
-
constructor(
|
14
|
-
attrs: string | Record<string, any>,
|
15
|
-
parsed?: Pick<
|
16
|
-
ParsedMultivariantPlaylist | LevelDetails,
|
17
|
-
'variableList' | 'hasVariableRefs' | 'playlistParsingError'
|
18
|
-
>,
|
19
|
-
) {
|
8
|
+
constructor(attrs: string | Record<string, any>) {
|
20
9
|
if (typeof attrs === 'string') {
|
21
|
-
attrs = AttrList.parseAttrList(attrs
|
10
|
+
attrs = AttrList.parseAttrList(attrs);
|
22
11
|
}
|
23
12
|
Object.assign(this, attrs);
|
24
13
|
}
|
@@ -74,20 +63,6 @@ export class AttrList {
|
|
74
63
|
return this[attrName];
|
75
64
|
}
|
76
65
|
|
77
|
-
enumeratedStringList<T extends { [key: string]: boolean }>(
|
78
|
-
attrName: string,
|
79
|
-
dict: T,
|
80
|
-
): { [key in keyof T]: boolean } {
|
81
|
-
const attrValue = this[attrName];
|
82
|
-
return (attrValue ? attrValue.split(/[ ,]+/) : []).reduce(
|
83
|
-
(result: { [key in keyof T]: boolean }, identifier: string) => {
|
84
|
-
result[identifier.toLowerCase() as keyof T] = true;
|
85
|
-
return result;
|
86
|
-
},
|
87
|
-
dict,
|
88
|
-
);
|
89
|
-
}
|
90
|
-
|
91
66
|
bool(attrName: string): boolean {
|
92
67
|
return this[attrName] === 'YES';
|
93
68
|
}
|
@@ -109,83 +84,21 @@ export class AttrList {
|
|
109
84
|
};
|
110
85
|
}
|
111
86
|
|
112
|
-
static parseAttrList(
|
113
|
-
|
114
|
-
parsed?: Pick<
|
115
|
-
ParsedMultivariantPlaylist | LevelDetails,
|
116
|
-
'variableList' | 'hasVariableRefs' | 'playlistParsingError'
|
117
|
-
>,
|
118
|
-
): Record<string, string> {
|
119
|
-
let match: RegExpExecArray | null;
|
87
|
+
static parseAttrList(input: string): Record<string, any> {
|
88
|
+
let match;
|
120
89
|
const attrs = {};
|
121
90
|
const quote = '"';
|
122
91
|
ATTR_LIST_REGEX.lastIndex = 0;
|
123
92
|
while ((match = ATTR_LIST_REGEX.exec(input)) !== null) {
|
124
|
-
const name = match[1].trim();
|
125
93
|
let value = match[2];
|
126
|
-
|
94
|
+
|
95
|
+
if (
|
127
96
|
value.indexOf(quote) === 0 &&
|
128
|
-
value.lastIndexOf(quote) === value.length - 1
|
129
|
-
|
130
|
-
if (quotedString) {
|
97
|
+
value.lastIndexOf(quote) === value.length - 1
|
98
|
+
) {
|
131
99
|
value = value.slice(1, -1);
|
132
|
-
} else {
|
133
|
-
switch (name) {
|
134
|
-
case 'IV':
|
135
|
-
case 'SCTE35-CMD':
|
136
|
-
case 'SCTE35-IN':
|
137
|
-
case 'SCTE35-OUT':
|
138
|
-
hexadecimalSequence = true;
|
139
|
-
}
|
140
|
-
}
|
141
|
-
if (parsed && (quotedString || hexadecimalSequence)) {
|
142
|
-
if (__USE_VARIABLE_SUBSTITUTION__) {
|
143
|
-
value = substituteVariables(parsed, value);
|
144
|
-
}
|
145
|
-
} else if (!hexadecimalSequence && !quotedString) {
|
146
|
-
switch (name) {
|
147
|
-
case 'CLOSED-CAPTIONS':
|
148
|
-
if (value === 'NONE') {
|
149
|
-
break;
|
150
|
-
}
|
151
|
-
// falls through
|
152
|
-
case 'ALLOWED-CPC':
|
153
|
-
case 'CLASS':
|
154
|
-
case 'ASSOC-LANGUAGE':
|
155
|
-
case 'AUDIO':
|
156
|
-
case 'BYTERANGE':
|
157
|
-
case 'CHANNELS':
|
158
|
-
case 'CHARACTERISTICS':
|
159
|
-
case 'CODECS':
|
160
|
-
case 'DATA-ID':
|
161
|
-
case 'END-DATE':
|
162
|
-
case 'GROUP-ID':
|
163
|
-
case 'ID':
|
164
|
-
case 'IMPORT':
|
165
|
-
case 'INSTREAM-ID':
|
166
|
-
case 'KEYFORMAT':
|
167
|
-
case 'KEYFORMATVERSIONS':
|
168
|
-
case 'LANGUAGE':
|
169
|
-
case 'NAME':
|
170
|
-
case 'PATHWAY-ID':
|
171
|
-
case 'QUERYPARAM':
|
172
|
-
case 'RECENTLY-REMOVED-DATERANGES':
|
173
|
-
case 'SERVER-URI':
|
174
|
-
case 'STABLE-RENDITION-ID':
|
175
|
-
case 'STABLE-VARIANT-ID':
|
176
|
-
case 'START-DATE':
|
177
|
-
case 'SUBTITLES':
|
178
|
-
case 'SUPPLEMENTAL-CODECS':
|
179
|
-
case 'URI':
|
180
|
-
case 'VALUE':
|
181
|
-
case 'VIDEO':
|
182
|
-
case 'X-ASSET-LIST':
|
183
|
-
case 'X-ASSET-URI':
|
184
|
-
// Since we are not checking tag:attribute combination, just warn rather than ignoring attribute
|
185
|
-
logger.warn(`${input}: attribute ${name} is missing quotes`);
|
186
|
-
// continue;
|
187
|
-
}
|
188
100
|
}
|
101
|
+
const name = match[1].trim();
|
189
102
|
attrs[name] = value;
|
190
103
|
}
|
191
104
|
return attrs;
|