hls.js 1.5.8-0.canary.10153 → 1.5.8-0.canary.10155

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.
Files changed (41) hide show
  1. package/dist/hls.js +764 -517
  2. package/dist/hls.js.map +1 -1
  3. package/dist/hls.light.js +585 -351
  4. package/dist/hls.light.js.map +1 -1
  5. package/dist/hls.light.min.js +1 -1
  6. package/dist/hls.light.min.js.map +1 -1
  7. package/dist/hls.light.mjs +580 -352
  8. package/dist/hls.light.mjs.map +1 -1
  9. package/dist/hls.min.js +1 -1
  10. package/dist/hls.min.js.map +1 -1
  11. package/dist/hls.mjs +789 -548
  12. package/dist/hls.mjs.map +1 -1
  13. package/dist/hls.worker.js +1 -1
  14. package/dist/hls.worker.js.map +1 -1
  15. package/package.json +1 -1
  16. package/src/controller/base-playlist-controller.ts +7 -2
  17. package/src/controller/cmcd-controller.ts +1 -1
  18. package/src/controller/eme-controller.ts +1 -1
  19. package/src/controller/id3-track-controller.ts +4 -3
  20. package/src/controller/level-controller.ts +1 -1
  21. package/src/demux/audio/aacdemuxer.ts +2 -2
  22. package/src/demux/audio/ac3-demuxer.ts +4 -3
  23. package/src/demux/audio/base-audio-demuxer.ts +16 -14
  24. package/src/demux/audio/mp3demuxer.ts +4 -3
  25. package/src/demux/audio/mpegaudio.ts +1 -1
  26. package/src/demux/mp4demuxer.ts +7 -7
  27. package/src/demux/video/hevc-video-parser.ts +4 -1
  28. package/src/events.ts +1 -1
  29. package/src/exports-named.ts +1 -1
  30. package/src/loader/fragment-loader.ts +1 -1
  31. package/src/loader/key-loader.ts +1 -1
  32. package/src/remux/mp4-remuxer.ts +1 -1
  33. package/src/types/component-api.ts +1 -1
  34. package/src/types/remuxer.ts +1 -1
  35. package/src/utils/fetch-loader.ts +1 -1
  36. package/src/utils/imsc1-ttml-parser.ts +1 -1
  37. package/src/utils/keysystem-util.ts +1 -6
  38. package/src/utils/mp4-tools.ts +1 -1
  39. package/src/utils/utf8-utils.ts +18 -0
  40. package/src/utils/webvtt-parser.ts +1 -1
  41. package/src/demux/id3.ts +0 -411
package/dist/hls.light.js CHANGED
@@ -606,7 +606,7 @@
606
606
  // Some browsers don't allow to use bind on console object anyway
607
607
  // fallback to default if needed
608
608
  try {
609
- newLogger.log("Debug logs enabled for \"" + context + "\" in hls.js version " + "1.5.8-0.canary.10153");
609
+ newLogger.log("Debug logs enabled for \"" + context + "\" in hls.js version " + "1.5.8-0.canary.10155");
610
610
  } catch (e) {
611
611
  /* log fn threw an exception. All logger methods are no-ops. */
612
612
  return createLogger();
@@ -1203,273 +1203,6 @@
1203
1203
  return Uint8Array.prototype.slice ? array.slice(start, end) : new Uint8Array(Array.prototype.slice.call(array, start, end));
1204
1204
  }
1205
1205
 
1206
- // breaking up those two types in order to clarify what is happening in the decoding path.
1207
-
1208
- /**
1209
- * Returns true if an ID3 header can be found at offset in data
1210
- * @param data - The data to search
1211
- * @param offset - The offset at which to start searching
1212
- */
1213
- var isHeader$2 = function isHeader(data, offset) {
1214
- /*
1215
- * http://id3.org/id3v2.3.0
1216
- * [0] = 'I'
1217
- * [1] = 'D'
1218
- * [2] = '3'
1219
- * [3,4] = {Version}
1220
- * [5] = {Flags}
1221
- * [6-9] = {ID3 Size}
1222
- *
1223
- * An ID3v2 tag can be detected with the following pattern:
1224
- * $49 44 33 yy yy xx zz zz zz zz
1225
- * Where yy is less than $FF, xx is the 'flags' byte and zz is less than $80
1226
- */
1227
- if (offset + 10 <= data.length) {
1228
- // look for 'ID3' identifier
1229
- if (data[offset] === 0x49 && data[offset + 1] === 0x44 && data[offset + 2] === 0x33) {
1230
- // check version is within range
1231
- if (data[offset + 3] < 0xff && data[offset + 4] < 0xff) {
1232
- // check size is within range
1233
- if (data[offset + 6] < 0x80 && data[offset + 7] < 0x80 && data[offset + 8] < 0x80 && data[offset + 9] < 0x80) {
1234
- return true;
1235
- }
1236
- }
1237
- }
1238
- }
1239
- return false;
1240
- };
1241
-
1242
- /**
1243
- * Returns true if an ID3 footer can be found at offset in data
1244
- * @param data - The data to search
1245
- * @param offset - The offset at which to start searching
1246
- */
1247
- var isFooter = function isFooter(data, offset) {
1248
- /*
1249
- * The footer is a copy of the header, but with a different identifier
1250
- */
1251
- if (offset + 10 <= data.length) {
1252
- // look for '3DI' identifier
1253
- if (data[offset] === 0x33 && data[offset + 1] === 0x44 && data[offset + 2] === 0x49) {
1254
- // check version is within range
1255
- if (data[offset + 3] < 0xff && data[offset + 4] < 0xff) {
1256
- // check size is within range
1257
- if (data[offset + 6] < 0x80 && data[offset + 7] < 0x80 && data[offset + 8] < 0x80 && data[offset + 9] < 0x80) {
1258
- return true;
1259
- }
1260
- }
1261
- }
1262
- }
1263
- return false;
1264
- };
1265
-
1266
- /**
1267
- * Returns any adjacent ID3 tags found in data starting at offset, as one block of data
1268
- * @param data - The data to search in
1269
- * @param offset - The offset at which to start searching
1270
- * @returns the block of data containing any ID3 tags found
1271
- * or *undefined* if no header is found at the starting offset
1272
- */
1273
- var getID3Data = function getID3Data(data, offset) {
1274
- var front = offset;
1275
- var length = 0;
1276
- while (isHeader$2(data, offset)) {
1277
- // ID3 header is 10 bytes
1278
- length += 10;
1279
- var size = readSize(data, offset + 6);
1280
- length += size;
1281
- if (isFooter(data, offset + 10)) {
1282
- // ID3 footer is 10 bytes
1283
- length += 10;
1284
- }
1285
- offset += length;
1286
- }
1287
- if (length > 0) {
1288
- return data.subarray(front, front + length);
1289
- }
1290
- return undefined;
1291
- };
1292
- var readSize = function readSize(data, offset) {
1293
- var size = 0;
1294
- size = (data[offset] & 0x7f) << 21;
1295
- size |= (data[offset + 1] & 0x7f) << 14;
1296
- size |= (data[offset + 2] & 0x7f) << 7;
1297
- size |= data[offset + 3] & 0x7f;
1298
- return size;
1299
- };
1300
- var canParse$2 = function canParse(data, offset) {
1301
- return isHeader$2(data, offset) && readSize(data, offset + 6) + 10 <= data.length - offset;
1302
- };
1303
-
1304
- /**
1305
- * Searches for the Elementary Stream timestamp found in the ID3 data chunk
1306
- * @param data - Block of data containing one or more ID3 tags
1307
- */
1308
- var getTimeStamp = function getTimeStamp(data) {
1309
- var frames = getID3Frames(data);
1310
- for (var i = 0; i < frames.length; i++) {
1311
- var frame = frames[i];
1312
- if (isTimeStampFrame(frame)) {
1313
- return readTimeStamp(frame);
1314
- }
1315
- }
1316
- return undefined;
1317
- };
1318
-
1319
- /**
1320
- * Returns true if the ID3 frame is an Elementary Stream timestamp frame
1321
- */
1322
- var isTimeStampFrame = function isTimeStampFrame(frame) {
1323
- return frame && frame.key === 'PRIV' && frame.info === 'com.apple.streaming.transportStreamTimestamp';
1324
- };
1325
- var getFrameData = function getFrameData(data) {
1326
- /*
1327
- Frame ID $xx xx xx xx (four characters)
1328
- Size $xx xx xx xx
1329
- Flags $xx xx
1330
- */
1331
- var type = String.fromCharCode(data[0], data[1], data[2], data[3]);
1332
- var size = readSize(data, 4);
1333
-
1334
- // skip frame id, size, and flags
1335
- var offset = 10;
1336
- return {
1337
- type: type,
1338
- size: size,
1339
- data: data.subarray(offset, offset + size)
1340
- };
1341
- };
1342
-
1343
- /**
1344
- * Returns an array of ID3 frames found in all the ID3 tags in the id3Data
1345
- * @param id3Data - The ID3 data containing one or more ID3 tags
1346
- */
1347
- var getID3Frames = function getID3Frames(id3Data) {
1348
- var offset = 0;
1349
- var frames = [];
1350
- while (isHeader$2(id3Data, offset)) {
1351
- var size = readSize(id3Data, offset + 6);
1352
- // skip past ID3 header
1353
- offset += 10;
1354
- var end = offset + size;
1355
- // loop through frames in the ID3 tag
1356
- while (offset + 8 < end) {
1357
- var frameData = getFrameData(id3Data.subarray(offset));
1358
- var frame = decodeFrame(frameData);
1359
- if (frame) {
1360
- frames.push(frame);
1361
- }
1362
-
1363
- // skip frame header and frame data
1364
- offset += frameData.size + 10;
1365
- }
1366
- if (isFooter(id3Data, offset)) {
1367
- offset += 10;
1368
- }
1369
- }
1370
- return frames;
1371
- };
1372
- var decodeFrame = function decodeFrame(frame) {
1373
- if (frame.type === 'PRIV') {
1374
- return decodePrivFrame(frame);
1375
- } else if (frame.type[0] === 'W') {
1376
- return decodeURLFrame(frame);
1377
- }
1378
- return decodeTextFrame(frame);
1379
- };
1380
- var decodePrivFrame = function decodePrivFrame(frame) {
1381
- /*
1382
- Format: <text string>\0<binary data>
1383
- */
1384
- if (frame.size < 2) {
1385
- return undefined;
1386
- }
1387
- var owner = utf8ArrayToStr(frame.data, true);
1388
- var privateData = new Uint8Array(frame.data.subarray(owner.length + 1));
1389
- return {
1390
- key: frame.type,
1391
- info: owner,
1392
- data: privateData.buffer
1393
- };
1394
- };
1395
- var decodeTextFrame = function decodeTextFrame(frame) {
1396
- if (frame.size < 2) {
1397
- return undefined;
1398
- }
1399
- if (frame.type === 'TXXX') {
1400
- /*
1401
- Format:
1402
- [0] = {Text Encoding}
1403
- [1-?] = {Description}\0{Value}
1404
- */
1405
- var index = 1;
1406
- var description = utf8ArrayToStr(frame.data.subarray(index), true);
1407
- index += description.length + 1;
1408
- var value = utf8ArrayToStr(frame.data.subarray(index));
1409
- return {
1410
- key: frame.type,
1411
- info: description,
1412
- data: value
1413
- };
1414
- }
1415
- /*
1416
- Format:
1417
- [0] = {Text Encoding}
1418
- [1-?] = {Value}
1419
- */
1420
- var text = utf8ArrayToStr(frame.data.subarray(1));
1421
- return {
1422
- key: frame.type,
1423
- data: text
1424
- };
1425
- };
1426
- var decodeURLFrame = function decodeURLFrame(frame) {
1427
- if (frame.type === 'WXXX') {
1428
- /*
1429
- Format:
1430
- [0] = {Text Encoding}
1431
- [1-?] = {Description}\0{URL}
1432
- */
1433
- if (frame.size < 2) {
1434
- return undefined;
1435
- }
1436
- var index = 1;
1437
- var description = utf8ArrayToStr(frame.data.subarray(index), true);
1438
- index += description.length + 1;
1439
- var value = utf8ArrayToStr(frame.data.subarray(index));
1440
- return {
1441
- key: frame.type,
1442
- info: description,
1443
- data: value
1444
- };
1445
- }
1446
- /*
1447
- Format:
1448
- [0-?] = {URL}
1449
- */
1450
- var url = utf8ArrayToStr(frame.data);
1451
- return {
1452
- key: frame.type,
1453
- data: url
1454
- };
1455
- };
1456
- var readTimeStamp = function readTimeStamp(timeStampFrame) {
1457
- if (timeStampFrame.data.byteLength === 8) {
1458
- var data = new Uint8Array(timeStampFrame.data);
1459
- // timestamp is 33 bit expressed as a big-endian eight-octet number,
1460
- // with the upper 31 bits set to zero.
1461
- var pts33Bit = data[3] & 0x1;
1462
- var timestamp = (data[4] << 23) + (data[5] << 15) + (data[6] << 7) + data[7];
1463
- timestamp /= 45;
1464
- if (pts33Bit) {
1465
- timestamp += 47721858.84;
1466
- } // 2^32 / 90
1467
-
1468
- return Math.round(timestamp);
1469
- }
1470
- return undefined;
1471
- };
1472
-
1473
1206
  // http://stackoverflow.com/questions/8936984/uint8array-to-string-in-javascript/22373197
1474
1207
  // http://www.onicos.com/staff/iz/amuse/javascript/expert/utf.txt
1475
1208
  /* utf.js - UTF-8 <=> UTF-16 convertion
@@ -1479,19 +1212,29 @@
1479
1212
  * LastModified: Dec 25 1999
1480
1213
  * This library is free. You can redistribute it and/or modify it.
1481
1214
  */
1482
- var utf8ArrayToStr = function utf8ArrayToStr(array, exitOnNull) {
1215
+ /**
1216
+ * Converts a UTF-8 array to a string.
1217
+ *
1218
+ * @param array - The UTF-8 array to convert
1219
+ *
1220
+ * @returns The string
1221
+ *
1222
+ * @group Utils
1223
+ *
1224
+ * @beta
1225
+ */
1226
+ function utf8ArrayToStr(array, exitOnNull) {
1483
1227
  if (exitOnNull === void 0) {
1484
1228
  exitOnNull = false;
1485
1229
  }
1486
- var decoder = getTextDecoder();
1487
- if (decoder) {
1230
+ if (typeof TextDecoder !== 'undefined') {
1231
+ var decoder = new TextDecoder('utf-8');
1488
1232
  var decoded = decoder.decode(array);
1489
1233
  if (exitOnNull) {
1490
1234
  // grab up to the first null
1491
1235
  var idx = decoded.indexOf('\0');
1492
1236
  return idx !== -1 ? decoded.substring(0, idx) : decoded;
1493
1237
  }
1494
-
1495
1238
  // remove any null characters
1496
1239
  return decoded.replace(/\0/g, '');
1497
1240
  }
@@ -1536,18 +1279,6 @@
1536
1279
  }
1537
1280
  }
1538
1281
  return out;
1539
- };
1540
- var decoder;
1541
- function getTextDecoder() {
1542
- // On Play Station 4, TextDecoder is defined but partially implemented.
1543
- // Manual decoding option is preferable
1544
- if (navigator.userAgent.includes('PlayStation 4')) {
1545
- return;
1546
- }
1547
- if (!decoder && typeof self.TextDecoder !== 'undefined') {
1548
- decoder = new self.TextDecoder('utf-8');
1549
- }
1550
- return decoder;
1551
1282
  }
1552
1283
 
1553
1284
  /**
@@ -4075,78 +3806,483 @@
4075
3806
  track.removeCue(track.cues[i]);
4076
3807
  }
4077
3808
  }
4078
- if (mode === 'disabled') {
4079
- track.mode = mode;
3809
+ if (mode === 'disabled') {
3810
+ track.mode = mode;
3811
+ }
3812
+ }
3813
+ function removeCuesInRange(track, start, end, predicate) {
3814
+ var mode = track.mode;
3815
+ if (mode === 'disabled') {
3816
+ track.mode = 'hidden';
3817
+ }
3818
+ if (track.cues && track.cues.length > 0) {
3819
+ var cues = getCuesInRange(track.cues, start, end);
3820
+ for (var i = 0; i < cues.length; i++) {
3821
+ if (!predicate || predicate(cues[i])) {
3822
+ track.removeCue(cues[i]);
3823
+ }
3824
+ }
3825
+ }
3826
+ if (mode === 'disabled') {
3827
+ track.mode = mode;
3828
+ }
3829
+ }
3830
+
3831
+ // Find first cue starting after given time.
3832
+ // Modified version of binary search O(log(n)).
3833
+ function getFirstCueIndexAfterTime(cues, time) {
3834
+ // If first cue starts after time, start there
3835
+ if (time < cues[0].startTime) {
3836
+ return 0;
3837
+ }
3838
+ // If the last cue ends before time there is no overlap
3839
+ var len = cues.length - 1;
3840
+ if (time > cues[len].endTime) {
3841
+ return -1;
3842
+ }
3843
+ var left = 0;
3844
+ var right = len;
3845
+ while (left <= right) {
3846
+ var mid = Math.floor((right + left) / 2);
3847
+ if (time < cues[mid].startTime) {
3848
+ right = mid - 1;
3849
+ } else if (time > cues[mid].startTime && left < len) {
3850
+ left = mid + 1;
3851
+ } else {
3852
+ // If it's not lower or higher, it must be equal.
3853
+ return mid;
3854
+ }
3855
+ }
3856
+ // At this point, left and right have swapped.
3857
+ // No direct match was found, left or right element must be the closest. Check which one has the smallest diff.
3858
+ return cues[left].startTime - time < time - cues[right].startTime ? left : right;
3859
+ }
3860
+ function getCuesInRange(cues, start, end) {
3861
+ var cuesFound = [];
3862
+ var firstCueInRange = getFirstCueIndexAfterTime(cues, start);
3863
+ if (firstCueInRange > -1) {
3864
+ for (var i = firstCueInRange, len = cues.length; i < len; i++) {
3865
+ var _cue = cues[i];
3866
+ if (_cue.startTime >= start && _cue.endTime <= end) {
3867
+ cuesFound.push(_cue);
3868
+ } else if (_cue.startTime > end) {
3869
+ return cuesFound;
3870
+ }
3871
+ }
3872
+ }
3873
+ return cuesFound;
3874
+ }
3875
+
3876
+ var MetadataSchema = {
3877
+ audioId3: "org.id3",
3878
+ dateRange: "com.apple.quicktime.HLS",
3879
+ emsg: "https://aomedia.org/emsg/ID3"
3880
+ };
3881
+
3882
+ /**
3883
+ * Decode an ID3 PRIV frame.
3884
+ *
3885
+ * @param frame - the ID3 PRIV frame
3886
+ *
3887
+ * @returns The decoded ID3 PRIV frame
3888
+ *
3889
+ * @internal
3890
+ *
3891
+ * @group ID3
3892
+ */
3893
+ function decodeId3PrivFrame(frame) {
3894
+ /*
3895
+ Format: <text string>\0<binary data>
3896
+ */
3897
+ if (frame.size < 2) {
3898
+ return undefined;
3899
+ }
3900
+ var owner = utf8ArrayToStr(frame.data, true);
3901
+ var privateData = new Uint8Array(frame.data.subarray(owner.length + 1));
3902
+ return {
3903
+ key: frame.type,
3904
+ info: owner,
3905
+ data: privateData.buffer
3906
+ };
3907
+ }
3908
+
3909
+ /**
3910
+ * Decodes an ID3 text frame
3911
+ *
3912
+ * @param frame - the ID3 text frame
3913
+ *
3914
+ * @returns The decoded ID3 text frame
3915
+ *
3916
+ * @internal
3917
+ *
3918
+ * @group ID3
3919
+ */
3920
+ function decodeId3TextFrame(frame) {
3921
+ if (frame.size < 2) {
3922
+ return undefined;
3923
+ }
3924
+ if (frame.type === 'TXXX') {
3925
+ /*
3926
+ Format:
3927
+ [0] = {Text Encoding}
3928
+ [1-?] = {Description}\0{Value}
3929
+ */
3930
+ var index = 1;
3931
+ var description = utf8ArrayToStr(frame.data.subarray(index), true);
3932
+ index += description.length + 1;
3933
+ var value = utf8ArrayToStr(frame.data.subarray(index));
3934
+ return {
3935
+ key: frame.type,
3936
+ info: description,
3937
+ data: value
3938
+ };
3939
+ }
3940
+ /*
3941
+ Format:
3942
+ [0] = {Text Encoding}
3943
+ [1-?] = {Value}
3944
+ */
3945
+ var text = utf8ArrayToStr(frame.data.subarray(1));
3946
+ return {
3947
+ key: frame.type,
3948
+ info: '',
3949
+ data: text
3950
+ };
3951
+ }
3952
+
3953
+ /**
3954
+ * Decode a URL frame
3955
+ *
3956
+ * @param frame - the ID3 URL frame
3957
+ *
3958
+ * @returns The decoded ID3 URL frame
3959
+ *
3960
+ * @internal
3961
+ *
3962
+ * @group ID3
3963
+ */
3964
+ function decodeId3UrlFrame(frame) {
3965
+ if (frame.type === 'WXXX') {
3966
+ /*
3967
+ Format:
3968
+ [0] = {Text Encoding}
3969
+ [1-?] = {Description}\0{URL}
3970
+ */
3971
+ if (frame.size < 2) {
3972
+ return undefined;
3973
+ }
3974
+ var index = 1;
3975
+ var description = utf8ArrayToStr(frame.data.subarray(index), true);
3976
+ index += description.length + 1;
3977
+ var value = utf8ArrayToStr(frame.data.subarray(index));
3978
+ return {
3979
+ key: frame.type,
3980
+ info: description,
3981
+ data: value
3982
+ };
3983
+ }
3984
+ /*
3985
+ Format:
3986
+ [0-?] = {URL}
3987
+ */
3988
+ var url = utf8ArrayToStr(frame.data);
3989
+ return {
3990
+ key: frame.type,
3991
+ info: '',
3992
+ data: url
3993
+ };
3994
+ }
3995
+
3996
+ function toUint8(data, offset, length) {
3997
+ if (offset === void 0) {
3998
+ offset = 0;
3999
+ }
4000
+ if (length === void 0) {
4001
+ length = Infinity;
4002
+ }
4003
+ return view(data, offset, length, Uint8Array);
4004
+ }
4005
+ function view(data, offset, length, Type) {
4006
+ var buffer = unsafeGetArrayBuffer(data);
4007
+ var bytesPerElement = 1;
4008
+ if ('BYTES_PER_ELEMENT' in Type) {
4009
+ bytesPerElement = Type.BYTES_PER_ELEMENT;
4010
+ }
4011
+ // Absolute end of the |data| view within |buffer|.
4012
+ var dataOffset = isArrayBufferView(data) ? data.byteOffset : 0;
4013
+ var dataEnd = (dataOffset + data.byteLength) / bytesPerElement;
4014
+ // Absolute start of the result within |buffer|.
4015
+ var rawStart = (dataOffset + offset) / bytesPerElement;
4016
+ var start = Math.floor(Math.max(0, Math.min(rawStart, dataEnd)));
4017
+ // Absolute end of the result within |buffer|.
4018
+ var end = Math.floor(Math.min(start + Math.max(length, 0), dataEnd));
4019
+ return new Type(buffer, start, end - start);
4020
+ }
4021
+ function unsafeGetArrayBuffer(view) {
4022
+ if (view instanceof ArrayBuffer) {
4023
+ return view;
4024
+ } else {
4025
+ return view.buffer;
4026
+ }
4027
+ }
4028
+ function isArrayBufferView(obj) {
4029
+ return obj && obj.buffer instanceof ArrayBuffer && obj.byteLength !== undefined && obj.byteOffset !== undefined;
4030
+ }
4031
+
4032
+ function toArrayBuffer(view) {
4033
+ if (view instanceof ArrayBuffer) {
4034
+ return view;
4035
+ } else {
4036
+ if (view.byteOffset == 0 && view.byteLength == view.buffer.byteLength) {
4037
+ // This is a TypedArray over the whole buffer.
4038
+ return view.buffer;
4039
+ }
4040
+ // This is a 'view' on the buffer. Create a new buffer that only contains
4041
+ // the data. Note that since this isn't an ArrayBuffer, the 'new' call
4042
+ // will allocate a new buffer to hold the copy.
4043
+ return new Uint8Array(view).buffer;
4044
+ }
4045
+ }
4046
+
4047
+ function decodeId3ImageFrame(frame) {
4048
+ var metadataFrame = {
4049
+ key: frame.type,
4050
+ description: '',
4051
+ data: '',
4052
+ mimeType: null,
4053
+ pictureType: null
4054
+ };
4055
+ var utf8Encoding = 0x03;
4056
+ if (frame.size < 2) {
4057
+ return undefined;
4058
+ }
4059
+ if (frame.data[0] !== utf8Encoding) {
4060
+ console.log('Ignore frame with unrecognized character ' + 'encoding');
4061
+ return undefined;
4062
+ }
4063
+ var mimeTypeEndIndex = frame.data.subarray(1).indexOf(0);
4064
+ if (mimeTypeEndIndex === -1) {
4065
+ return undefined;
4066
+ }
4067
+ var mimeType = utf8ArrayToStr(toUint8(frame.data, 1, mimeTypeEndIndex));
4068
+ var pictureType = frame.data[2 + mimeTypeEndIndex];
4069
+ var descriptionEndIndex = frame.data.subarray(3 + mimeTypeEndIndex).indexOf(0);
4070
+ if (descriptionEndIndex === -1) {
4071
+ return undefined;
4072
+ }
4073
+ var description = utf8ArrayToStr(toUint8(frame.data, 3 + mimeTypeEndIndex, descriptionEndIndex));
4074
+ var data;
4075
+ if (mimeType === '-->') {
4076
+ data = utf8ArrayToStr(toUint8(frame.data, 4 + mimeTypeEndIndex + descriptionEndIndex));
4077
+ } else {
4078
+ data = toArrayBuffer(frame.data.subarray(4 + mimeTypeEndIndex + descriptionEndIndex));
4080
4079
  }
4080
+ metadataFrame.mimeType = mimeType;
4081
+ metadataFrame.pictureType = pictureType;
4082
+ metadataFrame.description = description;
4083
+ metadataFrame.data = data;
4084
+ return metadataFrame;
4081
4085
  }
4082
- function removeCuesInRange(track, start, end, predicate) {
4083
- var mode = track.mode;
4084
- if (mode === 'disabled') {
4085
- track.mode = 'hidden';
4086
+
4087
+ /**
4088
+ * Decode an ID3 frame.
4089
+ *
4090
+ * @param frame - the ID3 frame
4091
+ *
4092
+ * @returns The decoded ID3 frame
4093
+ *
4094
+ * @internal
4095
+ *
4096
+ * @group ID3
4097
+ */
4098
+ function decodeId3Frame(frame) {
4099
+ if (frame.type === 'PRIV') {
4100
+ return decodeId3PrivFrame(frame);
4101
+ } else if (frame.type[0] === 'W') {
4102
+ return decodeId3UrlFrame(frame);
4103
+ } else if (frame.type === 'APIC') {
4104
+ return decodeId3ImageFrame(frame);
4086
4105
  }
4087
- if (track.cues && track.cues.length > 0) {
4088
- var cues = getCuesInRange(track.cues, start, end);
4089
- for (var i = 0; i < cues.length; i++) {
4090
- if (!predicate || predicate(cues[i])) {
4091
- track.removeCue(cues[i]);
4106
+ return decodeId3TextFrame(frame);
4107
+ }
4108
+
4109
+ /**
4110
+ * Read ID3 size
4111
+ *
4112
+ * @param data - The data to read from
4113
+ * @param offset - The offset at which to start reading
4114
+ *
4115
+ * @returns The size
4116
+ *
4117
+ * @internal
4118
+ *
4119
+ * @group ID3
4120
+ */
4121
+ function readId3Size(data, offset) {
4122
+ var size = 0;
4123
+ size = (data[offset] & 0x7f) << 21;
4124
+ size |= (data[offset + 1] & 0x7f) << 14;
4125
+ size |= (data[offset + 2] & 0x7f) << 7;
4126
+ size |= data[offset + 3] & 0x7f;
4127
+ return size;
4128
+ }
4129
+
4130
+ /**
4131
+ * Returns the data of an ID3 frame.
4132
+ *
4133
+ * @param data - The data to read from
4134
+ *
4135
+ * @returns The data of the ID3 frame
4136
+ *
4137
+ * @internal
4138
+ *
4139
+ * @group ID3
4140
+ */
4141
+ function getId3FrameData(data) {
4142
+ /*
4143
+ Frame ID $xx xx xx xx (four characters)
4144
+ Size $xx xx xx xx
4145
+ Flags $xx xx
4146
+ */
4147
+ var type = String.fromCharCode(data[0], data[1], data[2], data[3]);
4148
+ var size = readId3Size(data, 4);
4149
+ // skip frame id, size, and flags
4150
+ var offset = 10;
4151
+ return {
4152
+ type: type,
4153
+ size: size,
4154
+ data: data.subarray(offset, offset + size)
4155
+ };
4156
+ }
4157
+
4158
+ /**
4159
+ * Returns true if an ID3 footer can be found at offset in data
4160
+ *
4161
+ * @param data - The data to search in
4162
+ * @param offset - The offset at which to start searching
4163
+ *
4164
+ * @returns `true` if an ID3 footer is found
4165
+ *
4166
+ * @internal
4167
+ *
4168
+ * @group ID3
4169
+ */
4170
+ function isId3Footer(data, offset) {
4171
+ /*
4172
+ * The footer is a copy of the header, but with a different identifier
4173
+ */
4174
+ if (offset + 10 <= data.length) {
4175
+ // look for '3DI' identifier
4176
+ if (data[offset] === 0x33 && data[offset + 1] === 0x44 && data[offset + 2] === 0x49) {
4177
+ // check version is within range
4178
+ if (data[offset + 3] < 0xff && data[offset + 4] < 0xff) {
4179
+ // check size is within range
4180
+ if (data[offset + 6] < 0x80 && data[offset + 7] < 0x80 && data[offset + 8] < 0x80 && data[offset + 9] < 0x80) {
4181
+ return true;
4182
+ }
4092
4183
  }
4093
4184
  }
4094
4185
  }
4095
- if (mode === 'disabled') {
4096
- track.mode = mode;
4097
- }
4186
+ return false;
4098
4187
  }
4099
4188
 
4100
- // Find first cue starting after given time.
4101
- // Modified version of binary search O(log(n)).
4102
- function getFirstCueIndexAfterTime(cues, time) {
4103
- // If first cue starts after time, start there
4104
- if (time < cues[0].startTime) {
4105
- return 0;
4106
- }
4107
- // If the last cue ends before time there is no overlap
4108
- var len = cues.length - 1;
4109
- if (time > cues[len].endTime) {
4110
- return -1;
4111
- }
4112
- var left = 0;
4113
- var right = len;
4114
- while (left <= right) {
4115
- var mid = Math.floor((right + left) / 2);
4116
- if (time < cues[mid].startTime) {
4117
- right = mid - 1;
4118
- } else if (time > cues[mid].startTime && left < len) {
4119
- left = mid + 1;
4120
- } else {
4121
- // If it's not lower or higher, it must be equal.
4122
- return mid;
4189
+ /**
4190
+ * Returns true if an ID3 header can be found at offset in data
4191
+ *
4192
+ * @param data - The data to search in
4193
+ * @param offset - The offset at which to start searching
4194
+ *
4195
+ * @returns `true` if an ID3 header is found
4196
+ *
4197
+ * @internal
4198
+ *
4199
+ * @group ID3
4200
+ */
4201
+ function isId3Header(data, offset) {
4202
+ /*
4203
+ * http://id3.org/id3v2.3.0
4204
+ * [0] = 'I'
4205
+ * [1] = 'D'
4206
+ * [2] = '3'
4207
+ * [3,4] = {Version}
4208
+ * [5] = {Flags}
4209
+ * [6-9] = {ID3 Size}
4210
+ *
4211
+ * An ID3v2 tag can be detected with the following pattern:
4212
+ * $49 44 33 yy yy xx zz zz zz zz
4213
+ * Where yy is less than $FF, xx is the 'flags' byte and zz is less than $80
4214
+ */
4215
+ if (offset + 10 <= data.length) {
4216
+ // look for 'ID3' identifier
4217
+ if (data[offset] === 0x49 && data[offset + 1] === 0x44 && data[offset + 2] === 0x33) {
4218
+ // check version is within range
4219
+ if (data[offset + 3] < 0xff && data[offset + 4] < 0xff) {
4220
+ // check size is within range
4221
+ if (data[offset + 6] < 0x80 && data[offset + 7] < 0x80 && data[offset + 8] < 0x80 && data[offset + 9] < 0x80) {
4222
+ return true;
4223
+ }
4224
+ }
4123
4225
  }
4124
4226
  }
4125
- // At this point, left and right have swapped.
4126
- // No direct match was found, left or right element must be the closest. Check which one has the smallest diff.
4127
- return cues[left].startTime - time < time - cues[right].startTime ? left : right;
4227
+ return false;
4128
4228
  }
4129
- function getCuesInRange(cues, start, end) {
4130
- var cuesFound = [];
4131
- var firstCueInRange = getFirstCueIndexAfterTime(cues, start);
4132
- if (firstCueInRange > -1) {
4133
- for (var i = firstCueInRange, len = cues.length; i < len; i++) {
4134
- var _cue = cues[i];
4135
- if (_cue.startTime >= start && _cue.endTime <= end) {
4136
- cuesFound.push(_cue);
4137
- } else if (_cue.startTime > end) {
4138
- return cuesFound;
4229
+
4230
+ var HEADER_FOOTER_SIZE = 10;
4231
+ var FRAME_SIZE = 10;
4232
+ /**
4233
+ * Returns an array of ID3 frames found in all the ID3 tags in the id3Data
4234
+ *
4235
+ * @param id3Data - The ID3 data containing one or more ID3 tags
4236
+ *
4237
+ * @returns Array of ID3 frame objects
4238
+ *
4239
+ * @group ID3
4240
+ *
4241
+ * @beta
4242
+ */
4243
+ function getId3Frames(id3Data) {
4244
+ var offset = 0;
4245
+ var frames = [];
4246
+ while (isId3Header(id3Data, offset)) {
4247
+ var size = readId3Size(id3Data, offset + 6);
4248
+ if (id3Data[offset + 5] >> 6 & 1) {
4249
+ // skip extended header
4250
+ offset += HEADER_FOOTER_SIZE;
4251
+ }
4252
+ // skip past ID3 header
4253
+ offset += HEADER_FOOTER_SIZE;
4254
+ var end = offset + size;
4255
+ // loop through frames in the ID3 tag
4256
+ while (offset + FRAME_SIZE < end) {
4257
+ var frameData = getId3FrameData(id3Data.subarray(offset));
4258
+ var frame = decodeId3Frame(frameData);
4259
+ if (frame) {
4260
+ frames.push(frame);
4139
4261
  }
4262
+ // skip frame header and frame data
4263
+ offset += frameData.size + HEADER_FOOTER_SIZE;
4264
+ }
4265
+ if (isId3Footer(id3Data, offset)) {
4266
+ offset += HEADER_FOOTER_SIZE;
4140
4267
  }
4141
4268
  }
4142
- return cuesFound;
4269
+ return frames;
4143
4270
  }
4144
4271
 
4145
- var MetadataSchema = {
4146
- audioId3: "org.id3",
4147
- dateRange: "com.apple.quicktime.HLS",
4148
- emsg: "https://aomedia.org/emsg/ID3"
4149
- };
4272
+ /**
4273
+ * Returns true if the ID3 frame is an Elementary Stream timestamp frame
4274
+ *
4275
+ * @param frame - the ID3 frame
4276
+ *
4277
+ * @returns `true` if the ID3 frame is an Elementary Stream timestamp frame
4278
+ *
4279
+ * @internal
4280
+ *
4281
+ * @group ID3
4282
+ */
4283
+ function isId3TimestampFrame(frame) {
4284
+ return frame && frame.key === 'PRIV' && frame.info === 'com.apple.streaming.transportStreamTimestamp';
4285
+ }
4150
4286
 
4151
4287
  var MIN_CUE_DURATION = 0.25;
4152
4288
  function getCueClass() {
@@ -4283,7 +4419,7 @@
4283
4419
  if (type === MetadataSchema.emsg && !enableEmsgMetadataCues || !enableID3MetadataCues) {
4284
4420
  continue;
4285
4421
  }
4286
- var frames = getID3Frames(samples[i].data);
4422
+ var frames = getId3Frames(samples[i].data);
4287
4423
  if (frames) {
4288
4424
  var startTime = samples[i].pts;
4289
4425
  var endTime = startTime + samples[i].duration;
@@ -4297,7 +4433,7 @@
4297
4433
  for (var j = 0; j < frames.length; j++) {
4298
4434
  var frame = frames[j];
4299
4435
  // Safari doesn't put the timestamp frame in the TextTrack
4300
- if (!isTimeStampFrame(frame)) {
4436
+ if (!isId3TimestampFrame(frame)) {
4301
4437
  // add a bounds to any unbounded cues
4302
4438
  this.updateId3CueEnds(startTime, type);
4303
4439
  var cue = createCueWithDataFields(Cue, startTime, endTime, frame, type);
@@ -13760,6 +13896,104 @@
13760
13896
  };
13761
13897
  }
13762
13898
 
13899
+ /**
13900
+ * Returns any adjacent ID3 tags found in data starting at offset, as one block of data
13901
+ *
13902
+ * @param data - The data to search in
13903
+ * @param offset - The offset at which to start searching
13904
+ *
13905
+ * @returns The block of data containing any ID3 tags found
13906
+ * or `undefined` if no header is found at the starting offset
13907
+ *
13908
+ * @internal
13909
+ *
13910
+ * @group ID3
13911
+ */
13912
+ function getId3Data(data, offset) {
13913
+ var front = offset;
13914
+ var length = 0;
13915
+ while (isId3Header(data, offset)) {
13916
+ // ID3 header is 10 bytes
13917
+ length += 10;
13918
+ var size = readId3Size(data, offset + 6);
13919
+ length += size;
13920
+ if (isId3Footer(data, offset + 10)) {
13921
+ // ID3 footer is 10 bytes
13922
+ length += 10;
13923
+ }
13924
+ offset += length;
13925
+ }
13926
+ if (length > 0) {
13927
+ return data.subarray(front, front + length);
13928
+ }
13929
+ return undefined;
13930
+ }
13931
+
13932
+ /**
13933
+ * Read a 33 bit timestamp from an ID3 frame.
13934
+ *
13935
+ * @param timeStampFrame - the ID3 frame
13936
+ *
13937
+ * @returns The timestamp
13938
+ *
13939
+ * @internal
13940
+ *
13941
+ * @group ID3
13942
+ */
13943
+ function readId3Timestamp(timeStampFrame) {
13944
+ if (timeStampFrame.data.byteLength === 8) {
13945
+ var data = new Uint8Array(timeStampFrame.data);
13946
+ // timestamp is 33 bit expressed as a big-endian eight-octet number,
13947
+ // with the upper 31 bits set to zero.
13948
+ var pts33Bit = data[3] & 0x1;
13949
+ var timestamp = (data[4] << 23) + (data[5] << 15) + (data[6] << 7) + data[7];
13950
+ timestamp /= 45;
13951
+ if (pts33Bit) {
13952
+ timestamp += 47721858.84;
13953
+ } // 2^32 / 90
13954
+ return Math.round(timestamp);
13955
+ }
13956
+ return undefined;
13957
+ }
13958
+
13959
+ /**
13960
+ * Searches for the Elementary Stream timestamp found in the ID3 data chunk
13961
+ *
13962
+ * @param data - Block of data containing one or more ID3 tags
13963
+ *
13964
+ * @returns The timestamp
13965
+ *
13966
+ * @group ID3
13967
+ *
13968
+ * @beta
13969
+ */
13970
+ function getId3Timestamp(data) {
13971
+ var frames = getId3Frames(data);
13972
+ for (var i = 0; i < frames.length; i++) {
13973
+ var frame = frames[i];
13974
+ if (isId3TimestampFrame(frame)) {
13975
+ return readId3Timestamp(frame);
13976
+ }
13977
+ }
13978
+ return undefined;
13979
+ }
13980
+
13981
+ /**
13982
+ * Checks if the given data contains an ID3 tag.
13983
+ *
13984
+ * @param data - The data to check
13985
+ * @param offset - The offset at which to start checking
13986
+ *
13987
+ * @returns `true` if an ID3 tag is found
13988
+ *
13989
+ * @group ID3
13990
+ *
13991
+ * @beta
13992
+ */
13993
+ function canParseId3(data, offset) {
13994
+ return isId3Header(data, offset) && readId3Size(data, offset + 6) + 10 <= data.length - offset;
13995
+ }
13996
+
13763
13997
  var BaseAudioDemuxer = /*#__PURE__*/function () {
13764
13998
  function BaseAudioDemuxer() {
13765
13999
  this._audioTrack = void 0;
@@ -13803,12 +14037,12 @@
13803
14037
  data = appendUint8Array(this.cachedData, data);
13804
14038
  this.cachedData = null;
13805
14039
  }
13806
- var id3Data = getID3Data(data, 0);
14040
+ var id3Data = getId3Data(data, 0);
13807
14041
  var offset = id3Data ? id3Data.length : 0;
13808
14042
  var lastDataIndex;
13809
14043
  var track = this._audioTrack;
13810
14044
  var id3Track = this._id3Track;
13811
- var timestamp = id3Data ? getTimeStamp(id3Data) : undefined;
14045
+ var timestamp = id3Data ? getId3Timestamp(id3Data) : undefined;
13812
14046
  var length = data.length;
13813
14047
  if (this.basePTS === null || this.frameIndex === 0 && isFiniteNumber(timestamp)) {
13814
14048
  this.basePTS = initPTSFn(timestamp, timeOffset, this.initPTS);
@@ -13839,9 +14073,9 @@
13839
14073
  } else {
13840
14074
  offset = length;
13841
14075
  }
13842
- } else if (canParse$2(data, offset)) {
13843
- // after a ID3.canParse, a call to ID3.getID3Data *should* always returns some data
13844
- id3Data = getID3Data(data, offset);
14076
+ } else if (canParseId3(data, offset)) {
14077
+ // after a canParse, a call to getId3Data *should* always returns some data
14078
+ id3Data = getId3Data(data, offset);
13845
14079
  id3Track.samples.push({
13846
14080
  pts: this.lastPTS,
13847
14081
  dts: this.lastPTS,
@@ -14335,7 +14569,7 @@
14335
14569
  // Look for ADTS header | 1111 1111 | 1111 X00X | where X can be either 0 or 1
14336
14570
  // Layer bits (position 14 and 15) in header should be always 0 for ADTS
14337
14571
  // More info https://wiki.multimedia.cx/index.php?title=ADTS
14338
- var id3Data = getID3Data(data, 0);
14572
+ var id3Data = getId3Data(data, 0);
14339
14573
  var offset = (id3Data == null ? void 0 : id3Data.length) || 0;
14340
14574
  if (probe(data, offset)) {
14341
14575
  return false;
@@ -16093,11 +16327,11 @@
16093
16327
  // Look for MPEG header | 1111 1111 | 111X XYZX | where X can be either 0 or 1 and Y or Z should be 1
16094
16328
  // Layer bits (position 14 and 15) in header should be always different from 0 (Layer I or Layer II or Layer III)
16095
16329
  // More info http://www.mp3-tech.org/programmer/frame_header.html
16096
- var id3Data = getID3Data(data, 0);
16330
+ var id3Data = getId3Data(data, 0);
16097
16331
  var offset = (id3Data == null ? void 0 : id3Data.length) || 0;
16098
16332
 
16099
16333
  // Check for ac-3|ec-3 sync bytes and return false if present
16100
- if (id3Data && data[offset] === 0x0b && data[offset + 1] === 0x77 && getTimeStamp(id3Data) !== undefined &&
16334
+ if (id3Data && data[offset] === 0x0b && data[offset + 1] === 0x77 && getId3Timestamp(id3Data) !== undefined &&
16101
16335
  // check the bsid to confirm ac-3 or ec-3 (not mp3)
16102
16336
  getAudioBSID(data, offset) <= 16) {
16103
16337
  return false;
@@ -21450,7 +21684,7 @@
21450
21684
  * Get the video-dev/hls.js package version.
21451
21685
  */
21452
21686
  function get() {
21453
- return "1.5.8-0.canary.10153";
21687
+ return "1.5.8-0.canary.10155";
21454
21688
  }
21455
21689
  }, {
21456
21690
  key: "Events",