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.
- package/dist/hls.js +764 -517
- package/dist/hls.js.map +1 -1
- package/dist/hls.light.js +585 -351
- 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 +580 -352
- 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 +789 -548
- package/dist/hls.mjs.map +1 -1
- package/dist/hls.worker.js +1 -1
- package/dist/hls.worker.js.map +1 -1
- package/package.json +1 -1
- package/src/controller/base-playlist-controller.ts +7 -2
- package/src/controller/cmcd-controller.ts +1 -1
- package/src/controller/eme-controller.ts +1 -1
- package/src/controller/id3-track-controller.ts +4 -3
- package/src/controller/level-controller.ts +1 -1
- package/src/demux/audio/aacdemuxer.ts +2 -2
- package/src/demux/audio/ac3-demuxer.ts +4 -3
- package/src/demux/audio/base-audio-demuxer.ts +16 -14
- package/src/demux/audio/mp3demuxer.ts +4 -3
- package/src/demux/audio/mpegaudio.ts +1 -1
- package/src/demux/mp4demuxer.ts +7 -7
- package/src/demux/video/hevc-video-parser.ts +4 -1
- package/src/events.ts +1 -1
- package/src/exports-named.ts +1 -1
- package/src/loader/fragment-loader.ts +1 -1
- package/src/loader/key-loader.ts +1 -1
- package/src/remux/mp4-remuxer.ts +1 -1
- package/src/types/component-api.ts +1 -1
- package/src/types/remuxer.ts +1 -1
- package/src/utils/fetch-loader.ts +1 -1
- package/src/utils/imsc1-ttml-parser.ts +1 -1
- package/src/utils/keysystem-util.ts +1 -6
- package/src/utils/mp4-tools.ts +1 -1
- package/src/utils/utf8-utils.ts +18 -0
- package/src/utils/webvtt-parser.ts +1 -1
- package/src/demux/id3.ts +0 -411
package/dist/hls.js
CHANGED
@@ -637,7 +637,7 @@
|
|
637
637
|
// Some browsers don't allow to use bind on console object anyway
|
638
638
|
// fallback to default if needed
|
639
639
|
try {
|
640
|
-
newLogger.log("Debug logs enabled for \"" + context + "\" in hls.js version " + "1.5.8-0.canary.
|
640
|
+
newLogger.log("Debug logs enabled for \"" + context + "\" in hls.js version " + "1.5.8-0.canary.10155");
|
641
641
|
} catch (e) {
|
642
642
|
/* log fn threw an exception. All logger methods are no-ops. */
|
643
643
|
return createLogger();
|
@@ -1209,6 +1209,24 @@
|
|
1209
1209
|
});
|
1210
1210
|
}
|
1211
1211
|
|
1212
|
+
// breaking up those two types in order to clarify what is happening in the decoding path.
|
1213
|
+
|
1214
|
+
// http://stackoverflow.com/questions/8936984/uint8array-to-string-in-javascript/22373197
|
1215
|
+
// http://www.onicos.com/staff/iz/amuse/javascript/expert/utf.txt
|
1216
|
+
/* utf.js - UTF-8 <=> UTF-16 convertion
|
1217
|
+
*
|
1218
|
+
* Copyright (C) 1999 Masanao Izumo <iz@onicos.co.jp>
|
1219
|
+
* Version: 1.0
|
1220
|
+
* LastModified: Dec 25 1999
|
1221
|
+
* This library is free. You can redistribute it and/or modify it.
|
1222
|
+
*/
|
1223
|
+
|
1224
|
+
function strToUtf8array(str) {
|
1225
|
+
return Uint8Array.from(unescape(encodeURIComponent(str)), function (c) {
|
1226
|
+
return c.charCodeAt(0);
|
1227
|
+
});
|
1228
|
+
}
|
1229
|
+
|
1212
1230
|
function getKeyIdBytes(str) {
|
1213
1231
|
var keyIdbytes = strToUtf8array(str).subarray(0, 16);
|
1214
1232
|
var paddedkeyIdbytes = new Uint8Array(16);
|
@@ -1246,11 +1264,6 @@
|
|
1246
1264
|
}
|
1247
1265
|
return keydata;
|
1248
1266
|
}
|
1249
|
-
function strToUtf8array(str) {
|
1250
|
-
return Uint8Array.from(unescape(encodeURIComponent(str)), function (c) {
|
1251
|
-
return c.charCodeAt(0);
|
1252
|
-
});
|
1253
|
-
}
|
1254
1267
|
|
1255
1268
|
var DecrypterAesMode = {
|
1256
1269
|
cbc: 0,
|
@@ -1400,387 +1413,118 @@
|
|
1400
1413
|
return Uint8Array.prototype.slice ? array.slice(start, end) : new Uint8Array(Array.prototype.slice.call(array, start, end));
|
1401
1414
|
}
|
1402
1415
|
|
1403
|
-
//
|
1404
|
-
|
1405
|
-
|
1406
|
-
*
|
1407
|
-
*
|
1408
|
-
*
|
1416
|
+
// http://stackoverflow.com/questions/8936984/uint8array-to-string-in-javascript/22373197
|
1417
|
+
// http://www.onicos.com/staff/iz/amuse/javascript/expert/utf.txt
|
1418
|
+
/* utf.js - UTF-8 <=> UTF-16 convertion
|
1419
|
+
*
|
1420
|
+
* Copyright (C) 1999 Masanao Izumo <iz@onicos.co.jp>
|
1421
|
+
* Version: 1.0
|
1422
|
+
* LastModified: Dec 25 1999
|
1423
|
+
* This library is free. You can redistribute it and/or modify it.
|
1409
1424
|
*/
|
1410
|
-
var isHeader$2 = function isHeader(data, offset) {
|
1411
|
-
/*
|
1412
|
-
* http://id3.org/id3v2.3.0
|
1413
|
-
* [0] = 'I'
|
1414
|
-
* [1] = 'D'
|
1415
|
-
* [2] = '3'
|
1416
|
-
* [3,4] = {Version}
|
1417
|
-
* [5] = {Flags}
|
1418
|
-
* [6-9] = {ID3 Size}
|
1419
|
-
*
|
1420
|
-
* An ID3v2 tag can be detected with the following pattern:
|
1421
|
-
* $49 44 33 yy yy xx zz zz zz zz
|
1422
|
-
* Where yy is less than $FF, xx is the 'flags' byte and zz is less than $80
|
1423
|
-
*/
|
1424
|
-
if (offset + 10 <= data.length) {
|
1425
|
-
// look for 'ID3' identifier
|
1426
|
-
if (data[offset] === 0x49 && data[offset + 1] === 0x44 && data[offset + 2] === 0x33) {
|
1427
|
-
// check version is within range
|
1428
|
-
if (data[offset + 3] < 0xff && data[offset + 4] < 0xff) {
|
1429
|
-
// check size is within range
|
1430
|
-
if (data[offset + 6] < 0x80 && data[offset + 7] < 0x80 && data[offset + 8] < 0x80 && data[offset + 9] < 0x80) {
|
1431
|
-
return true;
|
1432
|
-
}
|
1433
|
-
}
|
1434
|
-
}
|
1435
|
-
}
|
1436
|
-
return false;
|
1437
|
-
};
|
1438
|
-
|
1439
1425
|
/**
|
1440
|
-
*
|
1441
|
-
*
|
1442
|
-
* @param
|
1426
|
+
* Converts a UTF-8 array to a string.
|
1427
|
+
*
|
1428
|
+
* @param array - The UTF-8 array to convert
|
1429
|
+
*
|
1430
|
+
* @returns The string
|
1431
|
+
*
|
1432
|
+
* @group Utils
|
1433
|
+
*
|
1434
|
+
* @beta
|
1443
1435
|
*/
|
1444
|
-
|
1445
|
-
|
1446
|
-
|
1447
|
-
*/
|
1448
|
-
if (offset + 10 <= data.length) {
|
1449
|
-
// look for '3DI' identifier
|
1450
|
-
if (data[offset] === 0x33 && data[offset + 1] === 0x44 && data[offset + 2] === 0x49) {
|
1451
|
-
// check version is within range
|
1452
|
-
if (data[offset + 3] < 0xff && data[offset + 4] < 0xff) {
|
1453
|
-
// check size is within range
|
1454
|
-
if (data[offset + 6] < 0x80 && data[offset + 7] < 0x80 && data[offset + 8] < 0x80 && data[offset + 9] < 0x80) {
|
1455
|
-
return true;
|
1456
|
-
}
|
1457
|
-
}
|
1458
|
-
}
|
1436
|
+
function utf8ArrayToStr(array, exitOnNull) {
|
1437
|
+
if (exitOnNull === void 0) {
|
1438
|
+
exitOnNull = false;
|
1459
1439
|
}
|
1460
|
-
|
1461
|
-
|
1462
|
-
|
1463
|
-
|
1464
|
-
|
1465
|
-
|
1466
|
-
|
1467
|
-
* @returns the block of data containing any ID3 tags found
|
1468
|
-
* or *undefined* if no header is found at the starting offset
|
1469
|
-
*/
|
1470
|
-
var getID3Data = function getID3Data(data, offset) {
|
1471
|
-
var front = offset;
|
1472
|
-
var length = 0;
|
1473
|
-
while (isHeader$2(data, offset)) {
|
1474
|
-
// ID3 header is 10 bytes
|
1475
|
-
length += 10;
|
1476
|
-
var size = readSize(data, offset + 6);
|
1477
|
-
length += size;
|
1478
|
-
if (isFooter(data, offset + 10)) {
|
1479
|
-
// ID3 footer is 10 bytes
|
1480
|
-
length += 10;
|
1440
|
+
if (typeof TextDecoder !== 'undefined') {
|
1441
|
+
var decoder = new TextDecoder('utf-8');
|
1442
|
+
var decoded = decoder.decode(array);
|
1443
|
+
if (exitOnNull) {
|
1444
|
+
// grab up to the first null
|
1445
|
+
var idx = decoded.indexOf('\0');
|
1446
|
+
return idx !== -1 ? decoded.substring(0, idx) : decoded;
|
1481
1447
|
}
|
1482
|
-
|
1483
|
-
|
1484
|
-
if (length > 0) {
|
1485
|
-
return data.subarray(front, front + length);
|
1448
|
+
// remove any null characters
|
1449
|
+
return decoded.replace(/\0/g, '');
|
1486
1450
|
}
|
1487
|
-
|
1488
|
-
|
1489
|
-
|
1490
|
-
var
|
1491
|
-
|
1492
|
-
|
1493
|
-
|
1494
|
-
|
1495
|
-
|
1496
|
-
|
1497
|
-
|
1498
|
-
|
1499
|
-
|
1500
|
-
|
1501
|
-
|
1502
|
-
|
1503
|
-
|
1504
|
-
|
1505
|
-
|
1506
|
-
|
1507
|
-
|
1508
|
-
|
1509
|
-
|
1510
|
-
|
1451
|
+
var len = array.length;
|
1452
|
+
var c;
|
1453
|
+
var char2;
|
1454
|
+
var char3;
|
1455
|
+
var out = '';
|
1456
|
+
var i = 0;
|
1457
|
+
while (i < len) {
|
1458
|
+
c = array[i++];
|
1459
|
+
if (c === 0x00 && exitOnNull) {
|
1460
|
+
return out;
|
1461
|
+
} else if (c === 0x00 || c === 0x03) {
|
1462
|
+
// If the character is 3 (END_OF_TEXT) or 0 (NULL) then skip it
|
1463
|
+
continue;
|
1464
|
+
}
|
1465
|
+
switch (c >> 4) {
|
1466
|
+
case 0:
|
1467
|
+
case 1:
|
1468
|
+
case 2:
|
1469
|
+
case 3:
|
1470
|
+
case 4:
|
1471
|
+
case 5:
|
1472
|
+
case 6:
|
1473
|
+
case 7:
|
1474
|
+
// 0xxxxxxx
|
1475
|
+
out += String.fromCharCode(c);
|
1476
|
+
break;
|
1477
|
+
case 12:
|
1478
|
+
case 13:
|
1479
|
+
// 110x xxxx 10xx xxxx
|
1480
|
+
char2 = array[i++];
|
1481
|
+
out += String.fromCharCode((c & 0x1f) << 6 | char2 & 0x3f);
|
1482
|
+
break;
|
1483
|
+
case 14:
|
1484
|
+
// 1110 xxxx 10xx xxxx 10xx xxxx
|
1485
|
+
char2 = array[i++];
|
1486
|
+
char3 = array[i++];
|
1487
|
+
out += String.fromCharCode((c & 0x0f) << 12 | (char2 & 0x3f) << 6 | (char3 & 0x3f) << 0);
|
1488
|
+
break;
|
1511
1489
|
}
|
1512
1490
|
}
|
1513
|
-
return
|
1514
|
-
}
|
1491
|
+
return out;
|
1492
|
+
}
|
1515
1493
|
|
1516
1494
|
/**
|
1517
|
-
*
|
1495
|
+
* hex dump helper class
|
1518
1496
|
*/
|
1519
|
-
var isTimeStampFrame = function isTimeStampFrame(frame) {
|
1520
|
-
return frame && frame.key === 'PRIV' && frame.info === 'com.apple.streaming.transportStreamTimestamp';
|
1521
|
-
};
|
1522
|
-
var getFrameData = function getFrameData(data) {
|
1523
|
-
/*
|
1524
|
-
Frame ID $xx xx xx xx (four characters)
|
1525
|
-
Size $xx xx xx xx
|
1526
|
-
Flags $xx xx
|
1527
|
-
*/
|
1528
|
-
var type = String.fromCharCode(data[0], data[1], data[2], data[3]);
|
1529
|
-
var size = readSize(data, 4);
|
1530
|
-
|
1531
|
-
// skip frame id, size, and flags
|
1532
|
-
var offset = 10;
|
1533
|
-
return {
|
1534
|
-
type: type,
|
1535
|
-
size: size,
|
1536
|
-
data: data.subarray(offset, offset + size)
|
1537
|
-
};
|
1538
|
-
};
|
1539
1497
|
|
1540
|
-
|
1541
|
-
|
1542
|
-
|
1543
|
-
|
1544
|
-
|
1545
|
-
|
1546
|
-
|
1547
|
-
while (isHeader$2(id3Data, offset)) {
|
1548
|
-
var size = readSize(id3Data, offset + 6);
|
1549
|
-
// skip past ID3 header
|
1550
|
-
offset += 10;
|
1551
|
-
var end = offset + size;
|
1552
|
-
// loop through frames in the ID3 tag
|
1553
|
-
while (offset + 8 < end) {
|
1554
|
-
var frameData = getFrameData(id3Data.subarray(offset));
|
1555
|
-
var frame = decodeFrame(frameData);
|
1556
|
-
if (frame) {
|
1557
|
-
frames.push(frame);
|
1498
|
+
var Hex = {
|
1499
|
+
hexDump: function hexDump(array) {
|
1500
|
+
var str = '';
|
1501
|
+
for (var i = 0; i < array.length; i++) {
|
1502
|
+
var h = array[i].toString(16);
|
1503
|
+
if (h.length < 2) {
|
1504
|
+
h = '0' + h;
|
1558
1505
|
}
|
1559
|
-
|
1560
|
-
// skip frame header and frame data
|
1561
|
-
offset += frameData.size + 10;
|
1562
|
-
}
|
1563
|
-
if (isFooter(id3Data, offset)) {
|
1564
|
-
offset += 10;
|
1506
|
+
str += h;
|
1565
1507
|
}
|
1508
|
+
return str;
|
1566
1509
|
}
|
1567
|
-
return frames;
|
1568
|
-
};
|
1569
|
-
var decodeFrame = function decodeFrame(frame) {
|
1570
|
-
if (frame.type === 'PRIV') {
|
1571
|
-
return decodePrivFrame(frame);
|
1572
|
-
} else if (frame.type[0] === 'W') {
|
1573
|
-
return decodeURLFrame(frame);
|
1574
|
-
}
|
1575
|
-
return decodeTextFrame(frame);
|
1576
1510
|
};
|
1577
|
-
|
1578
|
-
|
1579
|
-
|
1580
|
-
|
1581
|
-
|
1582
|
-
|
1583
|
-
|
1584
|
-
|
1585
|
-
|
1586
|
-
|
1587
|
-
|
1588
|
-
|
1589
|
-
|
1590
|
-
|
1591
|
-
|
1592
|
-
|
1593
|
-
|
1594
|
-
return undefined;
|
1595
|
-
}
|
1596
|
-
if (frame.type === 'TXXX') {
|
1597
|
-
/*
|
1598
|
-
Format:
|
1599
|
-
[0] = {Text Encoding}
|
1600
|
-
[1-?] = {Description}\0{Value}
|
1601
|
-
*/
|
1602
|
-
var index = 1;
|
1603
|
-
var description = utf8ArrayToStr(frame.data.subarray(index), true);
|
1604
|
-
index += description.length + 1;
|
1605
|
-
var value = utf8ArrayToStr(frame.data.subarray(index));
|
1606
|
-
return {
|
1607
|
-
key: frame.type,
|
1608
|
-
info: description,
|
1609
|
-
data: value
|
1610
|
-
};
|
1611
|
-
}
|
1612
|
-
/*
|
1613
|
-
Format:
|
1614
|
-
[0] = {Text Encoding}
|
1615
|
-
[1-?] = {Value}
|
1616
|
-
*/
|
1617
|
-
var text = utf8ArrayToStr(frame.data.subarray(1));
|
1618
|
-
return {
|
1619
|
-
key: frame.type,
|
1620
|
-
data: text
|
1621
|
-
};
|
1622
|
-
};
|
1623
|
-
var decodeURLFrame = function decodeURLFrame(frame) {
|
1624
|
-
if (frame.type === 'WXXX') {
|
1625
|
-
/*
|
1626
|
-
Format:
|
1627
|
-
[0] = {Text Encoding}
|
1628
|
-
[1-?] = {Description}\0{URL}
|
1629
|
-
*/
|
1630
|
-
if (frame.size < 2) {
|
1631
|
-
return undefined;
|
1632
|
-
}
|
1633
|
-
var index = 1;
|
1634
|
-
var description = utf8ArrayToStr(frame.data.subarray(index), true);
|
1635
|
-
index += description.length + 1;
|
1636
|
-
var value = utf8ArrayToStr(frame.data.subarray(index));
|
1637
|
-
return {
|
1638
|
-
key: frame.type,
|
1639
|
-
info: description,
|
1640
|
-
data: value
|
1641
|
-
};
|
1642
|
-
}
|
1643
|
-
/*
|
1644
|
-
Format:
|
1645
|
-
[0-?] = {URL}
|
1646
|
-
*/
|
1647
|
-
var url = utf8ArrayToStr(frame.data);
|
1648
|
-
return {
|
1649
|
-
key: frame.type,
|
1650
|
-
data: url
|
1651
|
-
};
|
1652
|
-
};
|
1653
|
-
var readTimeStamp = function readTimeStamp(timeStampFrame) {
|
1654
|
-
if (timeStampFrame.data.byteLength === 8) {
|
1655
|
-
var data = new Uint8Array(timeStampFrame.data);
|
1656
|
-
// timestamp is 33 bit expressed as a big-endian eight-octet number,
|
1657
|
-
// with the upper 31 bits set to zero.
|
1658
|
-
var pts33Bit = data[3] & 0x1;
|
1659
|
-
var timestamp = (data[4] << 23) + (data[5] << 15) + (data[6] << 7) + data[7];
|
1660
|
-
timestamp /= 45;
|
1661
|
-
if (pts33Bit) {
|
1662
|
-
timestamp += 47721858.84;
|
1663
|
-
} // 2^32 / 90
|
1664
|
-
|
1665
|
-
return Math.round(timestamp);
|
1666
|
-
}
|
1667
|
-
return undefined;
|
1668
|
-
};
|
1669
|
-
|
1670
|
-
// http://stackoverflow.com/questions/8936984/uint8array-to-string-in-javascript/22373197
|
1671
|
-
// http://www.onicos.com/staff/iz/amuse/javascript/expert/utf.txt
|
1672
|
-
/* utf.js - UTF-8 <=> UTF-16 convertion
|
1673
|
-
*
|
1674
|
-
* Copyright (C) 1999 Masanao Izumo <iz@onicos.co.jp>
|
1675
|
-
* Version: 1.0
|
1676
|
-
* LastModified: Dec 25 1999
|
1677
|
-
* This library is free. You can redistribute it and/or modify it.
|
1678
|
-
*/
|
1679
|
-
var utf8ArrayToStr = function utf8ArrayToStr(array, exitOnNull) {
|
1680
|
-
if (exitOnNull === void 0) {
|
1681
|
-
exitOnNull = false;
|
1682
|
-
}
|
1683
|
-
var decoder = getTextDecoder();
|
1684
|
-
if (decoder) {
|
1685
|
-
var decoded = decoder.decode(array);
|
1686
|
-
if (exitOnNull) {
|
1687
|
-
// grab up to the first null
|
1688
|
-
var idx = decoded.indexOf('\0');
|
1689
|
-
return idx !== -1 ? decoded.substring(0, idx) : decoded;
|
1690
|
-
}
|
1691
|
-
|
1692
|
-
// remove any null characters
|
1693
|
-
return decoded.replace(/\0/g, '');
|
1694
|
-
}
|
1695
|
-
var len = array.length;
|
1696
|
-
var c;
|
1697
|
-
var char2;
|
1698
|
-
var char3;
|
1699
|
-
var out = '';
|
1700
|
-
var i = 0;
|
1701
|
-
while (i < len) {
|
1702
|
-
c = array[i++];
|
1703
|
-
if (c === 0x00 && exitOnNull) {
|
1704
|
-
return out;
|
1705
|
-
} else if (c === 0x00 || c === 0x03) {
|
1706
|
-
// If the character is 3 (END_OF_TEXT) or 0 (NULL) then skip it
|
1707
|
-
continue;
|
1708
|
-
}
|
1709
|
-
switch (c >> 4) {
|
1710
|
-
case 0:
|
1711
|
-
case 1:
|
1712
|
-
case 2:
|
1713
|
-
case 3:
|
1714
|
-
case 4:
|
1715
|
-
case 5:
|
1716
|
-
case 6:
|
1717
|
-
case 7:
|
1718
|
-
// 0xxxxxxx
|
1719
|
-
out += String.fromCharCode(c);
|
1720
|
-
break;
|
1721
|
-
case 12:
|
1722
|
-
case 13:
|
1723
|
-
// 110x xxxx 10xx xxxx
|
1724
|
-
char2 = array[i++];
|
1725
|
-
out += String.fromCharCode((c & 0x1f) << 6 | char2 & 0x3f);
|
1726
|
-
break;
|
1727
|
-
case 14:
|
1728
|
-
// 1110 xxxx 10xx xxxx 10xx xxxx
|
1729
|
-
char2 = array[i++];
|
1730
|
-
char3 = array[i++];
|
1731
|
-
out += String.fromCharCode((c & 0x0f) << 12 | (char2 & 0x3f) << 6 | (char3 & 0x3f) << 0);
|
1732
|
-
break;
|
1733
|
-
}
|
1734
|
-
}
|
1735
|
-
return out;
|
1736
|
-
};
|
1737
|
-
var decoder;
|
1738
|
-
function getTextDecoder() {
|
1739
|
-
// On Play Station 4, TextDecoder is defined but partially implemented.
|
1740
|
-
// Manual decoding option is preferable
|
1741
|
-
if (navigator.userAgent.includes('PlayStation 4')) {
|
1742
|
-
return;
|
1743
|
-
}
|
1744
|
-
if (!decoder && typeof self.TextDecoder !== 'undefined') {
|
1745
|
-
decoder = new self.TextDecoder('utf-8');
|
1746
|
-
}
|
1747
|
-
return decoder;
|
1748
|
-
}
|
1749
|
-
|
1750
|
-
/**
|
1751
|
-
* hex dump helper class
|
1752
|
-
*/
|
1753
|
-
|
1754
|
-
var Hex = {
|
1755
|
-
hexDump: function hexDump(array) {
|
1756
|
-
var str = '';
|
1757
|
-
for (var i = 0; i < array.length; i++) {
|
1758
|
-
var h = array[i].toString(16);
|
1759
|
-
if (h.length < 2) {
|
1760
|
-
h = '0' + h;
|
1761
|
-
}
|
1762
|
-
str += h;
|
1763
|
-
}
|
1764
|
-
return str;
|
1765
|
-
}
|
1766
|
-
};
|
1767
|
-
|
1768
|
-
var UINT32_MAX$1 = Math.pow(2, 32) - 1;
|
1769
|
-
var push = [].push;
|
1770
|
-
|
1771
|
-
// We are using fixed track IDs for driving the MP4 remuxer
|
1772
|
-
// instead of following the TS PIDs.
|
1773
|
-
// There is no reason not to do this and some browsers/SourceBuffer-demuxers
|
1774
|
-
// may not like if there are TrackID "switches"
|
1775
|
-
// See https://github.com/video-dev/hls.js/issues/1331
|
1776
|
-
// Here we are mapping our internal track types to constant MP4 track IDs
|
1777
|
-
// With MSE currently one can only have one track of each, and we are muxing
|
1778
|
-
// whatever video/audio rendition in them.
|
1779
|
-
var RemuxerTrackIdConfig = {
|
1780
|
-
video: 1,
|
1781
|
-
audio: 2,
|
1782
|
-
id3: 3,
|
1783
|
-
text: 4
|
1511
|
+
|
1512
|
+
var UINT32_MAX$1 = Math.pow(2, 32) - 1;
|
1513
|
+
var push = [].push;
|
1514
|
+
|
1515
|
+
// We are using fixed track IDs for driving the MP4 remuxer
|
1516
|
+
// instead of following the TS PIDs.
|
1517
|
+
// There is no reason not to do this and some browsers/SourceBuffer-demuxers
|
1518
|
+
// may not like if there are TrackID "switches"
|
1519
|
+
// See https://github.com/video-dev/hls.js/issues/1331
|
1520
|
+
// Here we are mapping our internal track types to constant MP4 track IDs
|
1521
|
+
// With MSE currently one can only have one track of each, and we are muxing
|
1522
|
+
// whatever video/audio rendition in them.
|
1523
|
+
var RemuxerTrackIdConfig = {
|
1524
|
+
video: 1,
|
1525
|
+
audio: 2,
|
1526
|
+
id3: 3,
|
1527
|
+
text: 4
|
1784
1528
|
};
|
1785
1529
|
function bin2str(data) {
|
1786
1530
|
return String.fromCharCode.apply(null, data);
|
@@ -4637,42 +4381,551 @@
|
|
4637
4381
|
return mid;
|
4638
4382
|
}
|
4639
4383
|
}
|
4640
|
-
// At this point, left and right have swapped.
|
4641
|
-
// No direct match was found, left or right element must be the closest. Check which one has the smallest diff.
|
4642
|
-
return cues[left].startTime - time < time - cues[right].startTime ? left : right;
|
4384
|
+
// At this point, left and right have swapped.
|
4385
|
+
// No direct match was found, left or right element must be the closest. Check which one has the smallest diff.
|
4386
|
+
return cues[left].startTime - time < time - cues[right].startTime ? left : right;
|
4387
|
+
}
|
4388
|
+
function getCuesInRange(cues, start, end) {
|
4389
|
+
var cuesFound = [];
|
4390
|
+
var firstCueInRange = getFirstCueIndexAfterTime(cues, start);
|
4391
|
+
if (firstCueInRange > -1) {
|
4392
|
+
for (var i = firstCueInRange, len = cues.length; i < len; i++) {
|
4393
|
+
var _cue = cues[i];
|
4394
|
+
if (_cue.startTime >= start && _cue.endTime <= end) {
|
4395
|
+
cuesFound.push(_cue);
|
4396
|
+
} else if (_cue.startTime > end) {
|
4397
|
+
return cuesFound;
|
4398
|
+
}
|
4399
|
+
}
|
4400
|
+
}
|
4401
|
+
return cuesFound;
|
4402
|
+
}
|
4403
|
+
function filterSubtitleTracks(textTrackList) {
|
4404
|
+
var tracks = [];
|
4405
|
+
for (var i = 0; i < textTrackList.length; i++) {
|
4406
|
+
var track = textTrackList[i];
|
4407
|
+
// Edge adds a track without a label; we don't want to use it
|
4408
|
+
if ((track.kind === 'subtitles' || track.kind === 'captions') && track.label) {
|
4409
|
+
tracks.push(textTrackList[i]);
|
4410
|
+
}
|
4411
|
+
}
|
4412
|
+
return tracks;
|
4413
|
+
}
|
4414
|
+
|
4415
|
+
var MetadataSchema = {
|
4416
|
+
audioId3: "org.id3",
|
4417
|
+
dateRange: "com.apple.quicktime.HLS",
|
4418
|
+
emsg: "https://aomedia.org/emsg/ID3"
|
4419
|
+
};
|
4420
|
+
|
4421
|
+
/**
|
4422
|
+
* Decode an ID3 PRIV frame.
|
4423
|
+
*
|
4424
|
+
* @param frame - the ID3 PRIV frame
|
4425
|
+
*
|
4426
|
+
* @returns The decoded ID3 PRIV frame
|
4427
|
+
*
|
4428
|
+
* @internal
|
4429
|
+
*
|
4430
|
+
* @group ID3
|
4431
|
+
*/
|
4432
|
+
function decodeId3PrivFrame(frame) {
|
4433
|
+
/*
|
4434
|
+
Format: <text string>\0<binary data>
|
4435
|
+
*/
|
4436
|
+
if (frame.size < 2) {
|
4437
|
+
return undefined;
|
4438
|
+
}
|
4439
|
+
var owner = utf8ArrayToStr(frame.data, true);
|
4440
|
+
var privateData = new Uint8Array(frame.data.subarray(owner.length + 1));
|
4441
|
+
return {
|
4442
|
+
key: frame.type,
|
4443
|
+
info: owner,
|
4444
|
+
data: privateData.buffer
|
4445
|
+
};
|
4446
|
+
}
|
4447
|
+
|
4448
|
+
/**
|
4449
|
+
* Decodes an ID3 text frame
|
4450
|
+
*
|
4451
|
+
* @param frame - the ID3 text frame
|
4452
|
+
*
|
4453
|
+
* @returns The decoded ID3 text frame
|
4454
|
+
*
|
4455
|
+
* @internal
|
4456
|
+
*
|
4457
|
+
* @group ID3
|
4458
|
+
*/
|
4459
|
+
function decodeId3TextFrame(frame) {
|
4460
|
+
if (frame.size < 2) {
|
4461
|
+
return undefined;
|
4462
|
+
}
|
4463
|
+
if (frame.type === 'TXXX') {
|
4464
|
+
/*
|
4465
|
+
Format:
|
4466
|
+
[0] = {Text Encoding}
|
4467
|
+
[1-?] = {Description}\0{Value}
|
4468
|
+
*/
|
4469
|
+
var index = 1;
|
4470
|
+
var description = utf8ArrayToStr(frame.data.subarray(index), true);
|
4471
|
+
index += description.length + 1;
|
4472
|
+
var value = utf8ArrayToStr(frame.data.subarray(index));
|
4473
|
+
return {
|
4474
|
+
key: frame.type,
|
4475
|
+
info: description,
|
4476
|
+
data: value
|
4477
|
+
};
|
4478
|
+
}
|
4479
|
+
/*
|
4480
|
+
Format:
|
4481
|
+
[0] = {Text Encoding}
|
4482
|
+
[1-?] = {Value}
|
4483
|
+
*/
|
4484
|
+
var text = utf8ArrayToStr(frame.data.subarray(1));
|
4485
|
+
return {
|
4486
|
+
key: frame.type,
|
4487
|
+
info: '',
|
4488
|
+
data: text
|
4489
|
+
};
|
4490
|
+
}
|
4491
|
+
|
4492
|
+
/**
|
4493
|
+
* Decode a URL frame
|
4494
|
+
*
|
4495
|
+
* @param frame - the ID3 URL frame
|
4496
|
+
*
|
4497
|
+
* @returns The decoded ID3 URL frame
|
4498
|
+
*
|
4499
|
+
* @internal
|
4500
|
+
*
|
4501
|
+
* @group ID3
|
4502
|
+
*/
|
4503
|
+
function decodeId3UrlFrame(frame) {
|
4504
|
+
if (frame.type === 'WXXX') {
|
4505
|
+
/*
|
4506
|
+
Format:
|
4507
|
+
[0] = {Text Encoding}
|
4508
|
+
[1-?] = {Description}\0{URL}
|
4509
|
+
*/
|
4510
|
+
if (frame.size < 2) {
|
4511
|
+
return undefined;
|
4512
|
+
}
|
4513
|
+
var index = 1;
|
4514
|
+
var description = utf8ArrayToStr(frame.data.subarray(index), true);
|
4515
|
+
index += description.length + 1;
|
4516
|
+
var value = utf8ArrayToStr(frame.data.subarray(index));
|
4517
|
+
return {
|
4518
|
+
key: frame.type,
|
4519
|
+
info: description,
|
4520
|
+
data: value
|
4521
|
+
};
|
4522
|
+
}
|
4523
|
+
/*
|
4524
|
+
Format:
|
4525
|
+
[0-?] = {URL}
|
4526
|
+
*/
|
4527
|
+
var url = utf8ArrayToStr(frame.data);
|
4528
|
+
return {
|
4529
|
+
key: frame.type,
|
4530
|
+
info: '',
|
4531
|
+
data: url
|
4532
|
+
};
|
4533
|
+
}
|
4534
|
+
|
4535
|
+
function toUint8(data, offset, length) {
|
4536
|
+
if (offset === void 0) {
|
4537
|
+
offset = 0;
|
4538
|
+
}
|
4539
|
+
if (length === void 0) {
|
4540
|
+
length = Infinity;
|
4541
|
+
}
|
4542
|
+
return view(data, offset, length, Uint8Array);
|
4543
|
+
}
|
4544
|
+
function view(data, offset, length, Type) {
|
4545
|
+
var buffer = unsafeGetArrayBuffer(data);
|
4546
|
+
var bytesPerElement = 1;
|
4547
|
+
if ('BYTES_PER_ELEMENT' in Type) {
|
4548
|
+
bytesPerElement = Type.BYTES_PER_ELEMENT;
|
4549
|
+
}
|
4550
|
+
// Absolute end of the |data| view within |buffer|.
|
4551
|
+
var dataOffset = isArrayBufferView(data) ? data.byteOffset : 0;
|
4552
|
+
var dataEnd = (dataOffset + data.byteLength) / bytesPerElement;
|
4553
|
+
// Absolute start of the result within |buffer|.
|
4554
|
+
var rawStart = (dataOffset + offset) / bytesPerElement;
|
4555
|
+
var start = Math.floor(Math.max(0, Math.min(rawStart, dataEnd)));
|
4556
|
+
// Absolute end of the result within |buffer|.
|
4557
|
+
var end = Math.floor(Math.min(start + Math.max(length, 0), dataEnd));
|
4558
|
+
return new Type(buffer, start, end - start);
|
4559
|
+
}
|
4560
|
+
function unsafeGetArrayBuffer(view) {
|
4561
|
+
if (view instanceof ArrayBuffer) {
|
4562
|
+
return view;
|
4563
|
+
} else {
|
4564
|
+
return view.buffer;
|
4565
|
+
}
|
4566
|
+
}
|
4567
|
+
function isArrayBufferView(obj) {
|
4568
|
+
return obj && obj.buffer instanceof ArrayBuffer && obj.byteLength !== undefined && obj.byteOffset !== undefined;
|
4569
|
+
}
|
4570
|
+
|
4571
|
+
function toArrayBuffer(view) {
|
4572
|
+
if (view instanceof ArrayBuffer) {
|
4573
|
+
return view;
|
4574
|
+
} else {
|
4575
|
+
if (view.byteOffset == 0 && view.byteLength == view.buffer.byteLength) {
|
4576
|
+
// This is a TypedArray over the whole buffer.
|
4577
|
+
return view.buffer;
|
4578
|
+
}
|
4579
|
+
// This is a 'view' on the buffer. Create a new buffer that only contains
|
4580
|
+
// the data. Note that since this isn't an ArrayBuffer, the 'new' call
|
4581
|
+
// will allocate a new buffer to hold the copy.
|
4582
|
+
return new Uint8Array(view).buffer;
|
4583
|
+
}
|
4584
|
+
}
|
4585
|
+
|
4586
|
+
/**
|
4587
|
+
* Encodes binary data to base64
|
4588
|
+
*
|
4589
|
+
* @param binary - The binary data to encode
|
4590
|
+
* @returns The base64 encoded string
|
4591
|
+
*
|
4592
|
+
* @group Utils
|
4593
|
+
*
|
4594
|
+
* @beta
|
4595
|
+
*/
|
4596
|
+
function base64encode(binary) {
|
4597
|
+
return btoa(String.fromCharCode.apply(String, binary));
|
4598
|
+
}
|
4599
|
+
|
4600
|
+
/**
|
4601
|
+
* This implements the rounding procedure described in step 2 of the "Serializing a Decimal" specification.
|
4602
|
+
* This rounding style is known as "even rounding", "banker's rounding", or "commercial rounding".
|
4603
|
+
*
|
4604
|
+
* @param value - The value to round
|
4605
|
+
* @param precision - The number of decimal places to round to
|
4606
|
+
* @returns The rounded value
|
4607
|
+
*
|
4608
|
+
* @group Utils
|
4609
|
+
*
|
4610
|
+
* @beta
|
4611
|
+
*/
|
4612
|
+
function roundToEven(value, precision) {
|
4613
|
+
if (value < 0) {
|
4614
|
+
return -roundToEven(-value, precision);
|
4615
|
+
}
|
4616
|
+
var decimalShift = Math.pow(10, precision);
|
4617
|
+
var isEquidistant = Math.abs(value * decimalShift % 1 - 0.5) < Number.EPSILON;
|
4618
|
+
if (isEquidistant) {
|
4619
|
+
// If the tail of the decimal place is 'equidistant' we round to the nearest even value
|
4620
|
+
var flooredValue = Math.floor(value * decimalShift);
|
4621
|
+
return (flooredValue % 2 === 0 ? flooredValue : flooredValue + 1) / decimalShift;
|
4622
|
+
} else {
|
4623
|
+
// Otherwise, proceed as normal
|
4624
|
+
return Math.round(value * decimalShift) / decimalShift;
|
4625
|
+
}
|
4626
|
+
}
|
4627
|
+
|
4628
|
+
/**
|
4629
|
+
* Constructs a relative path from a URL.
|
4630
|
+
*
|
4631
|
+
* @param url - The destination URL
|
4632
|
+
* @param base - The base URL
|
4633
|
+
* @returns The relative path
|
4634
|
+
*
|
4635
|
+
* @group Utils
|
4636
|
+
*
|
4637
|
+
* @beta
|
4638
|
+
*/
|
4639
|
+
function urlToRelativePath(url, base) {
|
4640
|
+
var to = new URL(url);
|
4641
|
+
var from = new URL(base);
|
4642
|
+
if (to.origin !== from.origin) {
|
4643
|
+
return url;
|
4644
|
+
}
|
4645
|
+
var toPath = to.pathname.split('/').slice(1);
|
4646
|
+
var fromPath = from.pathname.split('/').slice(1, -1);
|
4647
|
+
// remove common parents
|
4648
|
+
while (toPath[0] === fromPath[0]) {
|
4649
|
+
toPath.shift();
|
4650
|
+
fromPath.shift();
|
4651
|
+
}
|
4652
|
+
// add back paths
|
4653
|
+
while (fromPath.length) {
|
4654
|
+
fromPath.shift();
|
4655
|
+
toPath.unshift('..');
|
4656
|
+
}
|
4657
|
+
return toPath.join('/');
|
4658
|
+
}
|
4659
|
+
|
4660
|
+
/**
|
4661
|
+
* Generate a random v4 UUID
|
4662
|
+
*
|
4663
|
+
* @returns A random v4 UUID
|
4664
|
+
*
|
4665
|
+
* @group Utils
|
4666
|
+
*
|
4667
|
+
* @beta
|
4668
|
+
*/
|
4669
|
+
function uuid() {
|
4670
|
+
try {
|
4671
|
+
return crypto.randomUUID();
|
4672
|
+
} catch (error) {
|
4673
|
+
try {
|
4674
|
+
var url = URL.createObjectURL(new Blob());
|
4675
|
+
var _uuid = url.toString();
|
4676
|
+
URL.revokeObjectURL(url);
|
4677
|
+
return _uuid.slice(_uuid.lastIndexOf('/') + 1);
|
4678
|
+
} catch (error) {
|
4679
|
+
var dt = new Date().getTime();
|
4680
|
+
var _uuid2 = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
|
4681
|
+
var r = (dt + Math.random() * 16) % 16 | 0;
|
4682
|
+
dt = Math.floor(dt / 16);
|
4683
|
+
return (c == 'x' ? r : r & 0x3 | 0x8).toString(16);
|
4684
|
+
});
|
4685
|
+
return _uuid2;
|
4686
|
+
}
|
4687
|
+
}
|
4688
|
+
}
|
4689
|
+
|
4690
|
+
function decodeId3ImageFrame(frame) {
|
4691
|
+
var metadataFrame = {
|
4692
|
+
key: frame.type,
|
4693
|
+
description: '',
|
4694
|
+
data: '',
|
4695
|
+
mimeType: null,
|
4696
|
+
pictureType: null
|
4697
|
+
};
|
4698
|
+
var utf8Encoding = 0x03;
|
4699
|
+
if (frame.size < 2) {
|
4700
|
+
return undefined;
|
4701
|
+
}
|
4702
|
+
if (frame.data[0] !== utf8Encoding) {
|
4703
|
+
console.log('Ignore frame with unrecognized character ' + 'encoding');
|
4704
|
+
return undefined;
|
4705
|
+
}
|
4706
|
+
var mimeTypeEndIndex = frame.data.subarray(1).indexOf(0);
|
4707
|
+
if (mimeTypeEndIndex === -1) {
|
4708
|
+
return undefined;
|
4709
|
+
}
|
4710
|
+
var mimeType = utf8ArrayToStr(toUint8(frame.data, 1, mimeTypeEndIndex));
|
4711
|
+
var pictureType = frame.data[2 + mimeTypeEndIndex];
|
4712
|
+
var descriptionEndIndex = frame.data.subarray(3 + mimeTypeEndIndex).indexOf(0);
|
4713
|
+
if (descriptionEndIndex === -1) {
|
4714
|
+
return undefined;
|
4715
|
+
}
|
4716
|
+
var description = utf8ArrayToStr(toUint8(frame.data, 3 + mimeTypeEndIndex, descriptionEndIndex));
|
4717
|
+
var data;
|
4718
|
+
if (mimeType === '-->') {
|
4719
|
+
data = utf8ArrayToStr(toUint8(frame.data, 4 + mimeTypeEndIndex + descriptionEndIndex));
|
4720
|
+
} else {
|
4721
|
+
data = toArrayBuffer(frame.data.subarray(4 + mimeTypeEndIndex + descriptionEndIndex));
|
4722
|
+
}
|
4723
|
+
metadataFrame.mimeType = mimeType;
|
4724
|
+
metadataFrame.pictureType = pictureType;
|
4725
|
+
metadataFrame.description = description;
|
4726
|
+
metadataFrame.data = data;
|
4727
|
+
return metadataFrame;
|
4728
|
+
}
|
4729
|
+
|
4730
|
+
/**
|
4731
|
+
* Decode an ID3 frame.
|
4732
|
+
*
|
4733
|
+
* @param frame - the ID3 frame
|
4734
|
+
*
|
4735
|
+
* @returns The decoded ID3 frame
|
4736
|
+
*
|
4737
|
+
* @internal
|
4738
|
+
*
|
4739
|
+
* @group ID3
|
4740
|
+
*/
|
4741
|
+
function decodeId3Frame(frame) {
|
4742
|
+
if (frame.type === 'PRIV') {
|
4743
|
+
return decodeId3PrivFrame(frame);
|
4744
|
+
} else if (frame.type[0] === 'W') {
|
4745
|
+
return decodeId3UrlFrame(frame);
|
4746
|
+
} else if (frame.type === 'APIC') {
|
4747
|
+
return decodeId3ImageFrame(frame);
|
4748
|
+
}
|
4749
|
+
return decodeId3TextFrame(frame);
|
4750
|
+
}
|
4751
|
+
|
4752
|
+
/**
|
4753
|
+
* Read ID3 size
|
4754
|
+
*
|
4755
|
+
* @param data - The data to read from
|
4756
|
+
* @param offset - The offset at which to start reading
|
4757
|
+
*
|
4758
|
+
* @returns The size
|
4759
|
+
*
|
4760
|
+
* @internal
|
4761
|
+
*
|
4762
|
+
* @group ID3
|
4763
|
+
*/
|
4764
|
+
function readId3Size(data, offset) {
|
4765
|
+
var size = 0;
|
4766
|
+
size = (data[offset] & 0x7f) << 21;
|
4767
|
+
size |= (data[offset + 1] & 0x7f) << 14;
|
4768
|
+
size |= (data[offset + 2] & 0x7f) << 7;
|
4769
|
+
size |= data[offset + 3] & 0x7f;
|
4770
|
+
return size;
|
4771
|
+
}
|
4772
|
+
|
4773
|
+
/**
|
4774
|
+
* Returns the data of an ID3 frame.
|
4775
|
+
*
|
4776
|
+
* @param data - The data to read from
|
4777
|
+
*
|
4778
|
+
* @returns The data of the ID3 frame
|
4779
|
+
*
|
4780
|
+
* @internal
|
4781
|
+
*
|
4782
|
+
* @group ID3
|
4783
|
+
*/
|
4784
|
+
function getId3FrameData(data) {
|
4785
|
+
/*
|
4786
|
+
Frame ID $xx xx xx xx (four characters)
|
4787
|
+
Size $xx xx xx xx
|
4788
|
+
Flags $xx xx
|
4789
|
+
*/
|
4790
|
+
var type = String.fromCharCode(data[0], data[1], data[2], data[3]);
|
4791
|
+
var size = readId3Size(data, 4);
|
4792
|
+
// skip frame id, size, and flags
|
4793
|
+
var offset = 10;
|
4794
|
+
return {
|
4795
|
+
type: type,
|
4796
|
+
size: size,
|
4797
|
+
data: data.subarray(offset, offset + size)
|
4798
|
+
};
|
4799
|
+
}
|
4800
|
+
|
4801
|
+
/**
|
4802
|
+
* Returns true if an ID3 footer can be found at offset in data
|
4803
|
+
*
|
4804
|
+
* @param data - The data to search in
|
4805
|
+
* @param offset - The offset at which to start searching
|
4806
|
+
*
|
4807
|
+
* @returns `true` if an ID3 footer is found
|
4808
|
+
*
|
4809
|
+
* @internal
|
4810
|
+
*
|
4811
|
+
* @group ID3
|
4812
|
+
*/
|
4813
|
+
function isId3Footer(data, offset) {
|
4814
|
+
/*
|
4815
|
+
* The footer is a copy of the header, but with a different identifier
|
4816
|
+
*/
|
4817
|
+
if (offset + 10 <= data.length) {
|
4818
|
+
// look for '3DI' identifier
|
4819
|
+
if (data[offset] === 0x33 && data[offset + 1] === 0x44 && data[offset + 2] === 0x49) {
|
4820
|
+
// check version is within range
|
4821
|
+
if (data[offset + 3] < 0xff && data[offset + 4] < 0xff) {
|
4822
|
+
// check size is within range
|
4823
|
+
if (data[offset + 6] < 0x80 && data[offset + 7] < 0x80 && data[offset + 8] < 0x80 && data[offset + 9] < 0x80) {
|
4824
|
+
return true;
|
4825
|
+
}
|
4826
|
+
}
|
4827
|
+
}
|
4828
|
+
}
|
4829
|
+
return false;
|
4830
|
+
}
|
4831
|
+
|
4832
|
+
/**
|
4833
|
+
* Returns true if an ID3 header can be found at offset in data
|
4834
|
+
*
|
4835
|
+
* @param data - The data to search in
|
4836
|
+
* @param offset - The offset at which to start searching
|
4837
|
+
*
|
4838
|
+
* @returns `true` if an ID3 header is found
|
4839
|
+
*
|
4840
|
+
* @internal
|
4841
|
+
*
|
4842
|
+
* @group ID3
|
4843
|
+
*/
|
4844
|
+
function isId3Header(data, offset) {
|
4845
|
+
/*
|
4846
|
+
* http://id3.org/id3v2.3.0
|
4847
|
+
* [0] = 'I'
|
4848
|
+
* [1] = 'D'
|
4849
|
+
* [2] = '3'
|
4850
|
+
* [3,4] = {Version}
|
4851
|
+
* [5] = {Flags}
|
4852
|
+
* [6-9] = {ID3 Size}
|
4853
|
+
*
|
4854
|
+
* An ID3v2 tag can be detected with the following pattern:
|
4855
|
+
* $49 44 33 yy yy xx zz zz zz zz
|
4856
|
+
* Where yy is less than $FF, xx is the 'flags' byte and zz is less than $80
|
4857
|
+
*/
|
4858
|
+
if (offset + 10 <= data.length) {
|
4859
|
+
// look for 'ID3' identifier
|
4860
|
+
if (data[offset] === 0x49 && data[offset + 1] === 0x44 && data[offset + 2] === 0x33) {
|
4861
|
+
// check version is within range
|
4862
|
+
if (data[offset + 3] < 0xff && data[offset + 4] < 0xff) {
|
4863
|
+
// check size is within range
|
4864
|
+
if (data[offset + 6] < 0x80 && data[offset + 7] < 0x80 && data[offset + 8] < 0x80 && data[offset + 9] < 0x80) {
|
4865
|
+
return true;
|
4866
|
+
}
|
4867
|
+
}
|
4868
|
+
}
|
4869
|
+
}
|
4870
|
+
return false;
|
4643
4871
|
}
|
4644
|
-
|
4645
|
-
|
4646
|
-
|
4647
|
-
|
4648
|
-
|
4649
|
-
|
4650
|
-
|
4651
|
-
|
4652
|
-
|
4653
|
-
|
4872
|
+
|
4873
|
+
var HEADER_FOOTER_SIZE = 10;
|
4874
|
+
var FRAME_SIZE = 10;
|
4875
|
+
/**
|
4876
|
+
* Returns an array of ID3 frames found in all the ID3 tags in the id3Data
|
4877
|
+
*
|
4878
|
+
* @param id3Data - The ID3 data containing one or more ID3 tags
|
4879
|
+
*
|
4880
|
+
* @returns Array of ID3 frame objects
|
4881
|
+
*
|
4882
|
+
* @group ID3
|
4883
|
+
*
|
4884
|
+
* @beta
|
4885
|
+
*/
|
4886
|
+
function getId3Frames(id3Data) {
|
4887
|
+
var offset = 0;
|
4888
|
+
var frames = [];
|
4889
|
+
while (isId3Header(id3Data, offset)) {
|
4890
|
+
var size = readId3Size(id3Data, offset + 6);
|
4891
|
+
if (id3Data[offset + 5] >> 6 & 1) {
|
4892
|
+
// skip extended header
|
4893
|
+
offset += HEADER_FOOTER_SIZE;
|
4894
|
+
}
|
4895
|
+
// skip past ID3 header
|
4896
|
+
offset += HEADER_FOOTER_SIZE;
|
4897
|
+
var end = offset + size;
|
4898
|
+
// loop through frames in the ID3 tag
|
4899
|
+
while (offset + FRAME_SIZE < end) {
|
4900
|
+
var frameData = getId3FrameData(id3Data.subarray(offset));
|
4901
|
+
var frame = decodeId3Frame(frameData);
|
4902
|
+
if (frame) {
|
4903
|
+
frames.push(frame);
|
4654
4904
|
}
|
4905
|
+
// skip frame header and frame data
|
4906
|
+
offset += frameData.size + HEADER_FOOTER_SIZE;
|
4655
4907
|
}
|
4656
|
-
|
4657
|
-
|
4658
|
-
}
|
4659
|
-
function filterSubtitleTracks(textTrackList) {
|
4660
|
-
var tracks = [];
|
4661
|
-
for (var i = 0; i < textTrackList.length; i++) {
|
4662
|
-
var track = textTrackList[i];
|
4663
|
-
// Edge adds a track without a label; we don't want to use it
|
4664
|
-
if ((track.kind === 'subtitles' || track.kind === 'captions') && track.label) {
|
4665
|
-
tracks.push(textTrackList[i]);
|
4908
|
+
if (isId3Footer(id3Data, offset)) {
|
4909
|
+
offset += HEADER_FOOTER_SIZE;
|
4666
4910
|
}
|
4667
4911
|
}
|
4668
|
-
return
|
4912
|
+
return frames;
|
4669
4913
|
}
|
4670
4914
|
|
4671
|
-
|
4672
|
-
|
4673
|
-
|
4674
|
-
|
4675
|
-
|
4915
|
+
/**
|
4916
|
+
* Returns true if the ID3 frame is an Elementary Stream timestamp frame
|
4917
|
+
*
|
4918
|
+
* @param frame - the ID3 frame
|
4919
|
+
*
|
4920
|
+
* @returns `true` if the ID3 frame is an Elementary Stream timestamp frame
|
4921
|
+
*
|
4922
|
+
* @internal
|
4923
|
+
*
|
4924
|
+
* @group ID3
|
4925
|
+
*/
|
4926
|
+
function isId3TimestampFrame(frame) {
|
4927
|
+
return frame && frame.key === 'PRIV' && frame.info === 'com.apple.streaming.transportStreamTimestamp';
|
4928
|
+
}
|
4676
4929
|
|
4677
4930
|
var MIN_CUE_DURATION = 0.25;
|
4678
4931
|
function getCueClass() {
|
@@ -4809,7 +5062,7 @@
|
|
4809
5062
|
if (type === MetadataSchema.emsg && !enableEmsgMetadataCues || !enableID3MetadataCues) {
|
4810
5063
|
continue;
|
4811
5064
|
}
|
4812
|
-
var frames =
|
5065
|
+
var frames = getId3Frames(samples[i].data);
|
4813
5066
|
if (frames) {
|
4814
5067
|
var startTime = samples[i].pts;
|
4815
5068
|
var endTime = startTime + samples[i].duration;
|
@@ -4823,7 +5076,7 @@
|
|
4823
5076
|
for (var j = 0; j < frames.length; j++) {
|
4824
5077
|
var frame = frames[j];
|
4825
5078
|
// Safari doesn't put the timestamp frame in the TextTrack
|
4826
|
-
if (!
|
5079
|
+
if (!isId3TimestampFrame(frame)) {
|
4827
5080
|
// add a bounds to any unbounded cues
|
4828
5081
|
this.updateId3CueEnds(startTime, type);
|
4829
5082
|
var cue = createCueWithDataFields(Cue, startTime, endTime, frame, type);
|
@@ -10900,6 +11153,104 @@
|
|
10900
11153
|
};
|
10901
11154
|
}
|
10902
11155
|
|
11156
|
+
/**
|
11157
|
+
* Returns any adjacent ID3 tags found in data starting at offset, as one block of data
|
11158
|
+
*
|
11159
|
+
* @param data - The data to search in
|
11160
|
+
* @param offset - The offset at which to start searching
|
11161
|
+
*
|
11162
|
+
* @returns The block of data containing any ID3 tags found
|
11163
|
+
* or `undefined` if no header is found at the starting offset
|
11164
|
+
*
|
11165
|
+
* @internal
|
11166
|
+
*
|
11167
|
+
* @group ID3
|
11168
|
+
*/
|
11169
|
+
function getId3Data(data, offset) {
|
11170
|
+
var front = offset;
|
11171
|
+
var length = 0;
|
11172
|
+
while (isId3Header(data, offset)) {
|
11173
|
+
// ID3 header is 10 bytes
|
11174
|
+
length += 10;
|
11175
|
+
var size = readId3Size(data, offset + 6);
|
11176
|
+
length += size;
|
11177
|
+
if (isId3Footer(data, offset + 10)) {
|
11178
|
+
// ID3 footer is 10 bytes
|
11179
|
+
length += 10;
|
11180
|
+
}
|
11181
|
+
offset += length;
|
11182
|
+
}
|
11183
|
+
if (length > 0) {
|
11184
|
+
return data.subarray(front, front + length);
|
11185
|
+
}
|
11186
|
+
return undefined;
|
11187
|
+
}
|
11188
|
+
|
11189
|
+
/**
|
11190
|
+
* Read a 33 bit timestamp from an ID3 frame.
|
11191
|
+
*
|
11192
|
+
* @param timeStampFrame - the ID3 frame
|
11193
|
+
*
|
11194
|
+
* @returns The timestamp
|
11195
|
+
*
|
11196
|
+
* @internal
|
11197
|
+
*
|
11198
|
+
* @group ID3
|
11199
|
+
*/
|
11200
|
+
function readId3Timestamp(timeStampFrame) {
|
11201
|
+
if (timeStampFrame.data.byteLength === 8) {
|
11202
|
+
var data = new Uint8Array(timeStampFrame.data);
|
11203
|
+
// timestamp is 33 bit expressed as a big-endian eight-octet number,
|
11204
|
+
// with the upper 31 bits set to zero.
|
11205
|
+
var pts33Bit = data[3] & 0x1;
|
11206
|
+
var timestamp = (data[4] << 23) + (data[5] << 15) + (data[6] << 7) + data[7];
|
11207
|
+
timestamp /= 45;
|
11208
|
+
if (pts33Bit) {
|
11209
|
+
timestamp += 47721858.84;
|
11210
|
+
} // 2^32 / 90
|
11211
|
+
return Math.round(timestamp);
|
11212
|
+
}
|
11213
|
+
return undefined;
|
11214
|
+
}
|
11215
|
+
|
11216
|
+
/**
|
11217
|
+
* Searches for the Elementary Stream timestamp found in the ID3 data chunk
|
11218
|
+
*
|
11219
|
+
* @param data - Block of data containing one or more ID3 tags
|
11220
|
+
*
|
11221
|
+
* @returns The timestamp
|
11222
|
+
*
|
11223
|
+
* @group ID3
|
11224
|
+
*
|
11225
|
+
* @beta
|
11226
|
+
*/
|
11227
|
+
function getId3Timestamp(data) {
|
11228
|
+
var frames = getId3Frames(data);
|
11229
|
+
for (var i = 0; i < frames.length; i++) {
|
11230
|
+
var frame = frames[i];
|
11231
|
+
if (isId3TimestampFrame(frame)) {
|
11232
|
+
return readId3Timestamp(frame);
|
11233
|
+
}
|
11234
|
+
}
|
11235
|
+
return undefined;
|
11236
|
+
}
|
11237
|
+
|
11238
|
+
/**
|
11239
|
+
* Checks if the given data contains an ID3 tag.
|
11240
|
+
*
|
11241
|
+
* @param data - The data to check
|
11242
|
+
* @param offset - The offset at which to start checking
|
11243
|
+
*
|
11244
|
+
* @returns `true` if an ID3 tag is found
|
11245
|
+
*
|
11246
|
+
* @group ID3
|
11247
|
+
*
|
11248
|
+
* @beta
|
11249
|
+
*/
|
11250
|
+
function canParseId3(data, offset) {
|
11251
|
+
return isId3Header(data, offset) && readId3Size(data, offset + 6) + 10 <= data.length - offset;
|
11252
|
+
}
|
11253
|
+
|
10903
11254
|
var BaseAudioDemuxer = /*#__PURE__*/function () {
|
10904
11255
|
function BaseAudioDemuxer() {
|
10905
11256
|
this._audioTrack = void 0;
|
@@ -10943,12 +11294,12 @@
|
|
10943
11294
|
data = appendUint8Array(this.cachedData, data);
|
10944
11295
|
this.cachedData = null;
|
10945
11296
|
}
|
10946
|
-
var id3Data =
|
11297
|
+
var id3Data = getId3Data(data, 0);
|
10947
11298
|
var offset = id3Data ? id3Data.length : 0;
|
10948
11299
|
var lastDataIndex;
|
10949
11300
|
var track = this._audioTrack;
|
10950
11301
|
var id3Track = this._id3Track;
|
10951
|
-
var timestamp = id3Data ?
|
11302
|
+
var timestamp = id3Data ? getId3Timestamp(id3Data) : undefined;
|
10952
11303
|
var length = data.length;
|
10953
11304
|
if (this.basePTS === null || this.frameIndex === 0 && isFiniteNumber(timestamp)) {
|
10954
11305
|
this.basePTS = initPTSFn(timestamp, timeOffset, this.initPTS);
|
@@ -10979,9 +11330,9 @@
|
|
10979
11330
|
} else {
|
10980
11331
|
offset = length;
|
10981
11332
|
}
|
10982
|
-
} else if (
|
10983
|
-
// after a
|
10984
|
-
id3Data =
|
11333
|
+
} else if (canParseId3(data, offset)) {
|
11334
|
+
// after a canParse, a call to getId3Data *should* always returns some data
|
11335
|
+
id3Data = getId3Data(data, offset);
|
10985
11336
|
id3Track.samples.push({
|
10986
11337
|
pts: this.lastPTS,
|
10987
11338
|
dts: this.lastPTS,
|
@@ -11475,7 +11826,7 @@
|
|
11475
11826
|
// Look for ADTS header | 1111 1111 | 1111 X00X | where X can be either 0 or 1
|
11476
11827
|
// Layer bits (position 14 and 15) in header should be always 0 for ADTS
|
11477
11828
|
// More info https://wiki.multimedia.cx/index.php?title=ADTS
|
11478
|
-
var id3Data =
|
11829
|
+
var id3Data = getId3Data(data, 0);
|
11479
11830
|
var offset = (id3Data == null ? void 0 : id3Data.length) || 0;
|
11480
11831
|
if (probe(data, offset)) {
|
11481
11832
|
return false;
|
@@ -11698,14 +12049,14 @@
|
|
11698
12049
|
if (!data) {
|
11699
12050
|
return false;
|
11700
12051
|
}
|
11701
|
-
var id3Data =
|
12052
|
+
var id3Data = getId3Data(data, 0);
|
11702
12053
|
if (!id3Data) {
|
11703
12054
|
return false;
|
11704
12055
|
}
|
11705
12056
|
|
11706
12057
|
// look for the ac-3 sync bytes
|
11707
12058
|
var offset = id3Data.length;
|
11708
|
-
if (data[offset] === 0x0b && data[offset + 1] === 0x77 &&
|
12059
|
+
if (data[offset] === 0x0b && data[offset + 1] === 0x77 && getId3Timestamp(id3Data) !== undefined &&
|
11709
12060
|
// check the bsid to confirm ac-3
|
11710
12061
|
getAudioBSID(data, offset) < 16) {
|
11711
12062
|
return true;
|
@@ -14002,11 +14353,11 @@
|
|
14002
14353
|
// Look for MPEG header | 1111 1111 | 111X XYZX | where X can be either 0 or 1 and Y or Z should be 1
|
14003
14354
|
// Layer bits (position 14 and 15) in header should be always different from 0 (Layer I or Layer II or Layer III)
|
14004
14355
|
// More info http://www.mp3-tech.org/programmer/frame_header.html
|
14005
|
-
var id3Data =
|
14356
|
+
var id3Data = getId3Data(data, 0);
|
14006
14357
|
var offset = (id3Data == null ? void 0 : id3Data.length) || 0;
|
14007
14358
|
|
14008
14359
|
// Check for ac-3|ec-3 sync bytes and return false if present
|
14009
|
-
if (id3Data && data[offset] === 0x0b && data[offset + 1] === 0x77 &&
|
14360
|
+
if (id3Data && data[offset] === 0x0b && data[offset + 1] === 0x77 && getId3Timestamp(id3Data) !== undefined &&
|
14010
14361
|
// check the bsid to confirm ac-3 or ec-3 (not mp3)
|
14011
14362
|
getAudioBSID(data, offset) <= 16) {
|
14012
14363
|
return false;
|
@@ -24531,20 +24882,6 @@
|
|
24531
24882
|
return value ? '?1' : '?0';
|
24532
24883
|
}
|
24533
24884
|
|
24534
|
-
/**
|
24535
|
-
* Encodes binary data to base64
|
24536
|
-
*
|
24537
|
-
* @param binary - The binary data to encode
|
24538
|
-
* @returns The base64 encoded string
|
24539
|
-
*
|
24540
|
-
* @group Utils
|
24541
|
-
*
|
24542
|
-
* @beta
|
24543
|
-
*/
|
24544
|
-
function base64encode(binary) {
|
24545
|
-
return btoa(String.fromCharCode.apply(String, binary));
|
24546
|
-
}
|
24547
|
-
|
24548
24885
|
var BYTES = 'Byte Sequence';
|
24549
24886
|
|
24550
24887
|
// 4.1.8. Serializing a Byte Sequence
|
@@ -24621,34 +24958,6 @@
|
|
24621
24958
|
return "@" + serializeInteger(value.getTime() / 1000);
|
24622
24959
|
}
|
24623
24960
|
|
24624
|
-
/**
|
24625
|
-
* This implements the rounding procedure described in step 2 of the "Serializing a Decimal" specification.
|
24626
|
-
* This rounding style is known as "even rounding", "banker's rounding", or "commercial rounding".
|
24627
|
-
*
|
24628
|
-
* @param value - The value to round
|
24629
|
-
* @param precision - The number of decimal places to round to
|
24630
|
-
* @returns The rounded value
|
24631
|
-
*
|
24632
|
-
* @group Utils
|
24633
|
-
*
|
24634
|
-
* @beta
|
24635
|
-
*/
|
24636
|
-
function roundToEven(value, precision) {
|
24637
|
-
if (value < 0) {
|
24638
|
-
return -roundToEven(-value, precision);
|
24639
|
-
}
|
24640
|
-
var decimalShift = Math.pow(10, precision);
|
24641
|
-
var isEquidistant = Math.abs(value * decimalShift % 1 - 0.5) < Number.EPSILON;
|
24642
|
-
if (isEquidistant) {
|
24643
|
-
// If the tail of the decimal place is 'equidistant' we round to the nearest even value
|
24644
|
-
var flooredValue = Math.floor(value * decimalShift);
|
24645
|
-
return (flooredValue % 2 === 0 ? flooredValue : flooredValue + 1) / decimalShift;
|
24646
|
-
} else {
|
24647
|
-
// Otherwise, proceed as normal
|
24648
|
-
return Math.round(value * decimalShift) / decimalShift;
|
24649
|
-
}
|
24650
|
-
}
|
24651
|
-
|
24652
24961
|
var DECIMAL = 'Decimal';
|
24653
24962
|
|
24654
24963
|
// 4.1.5. Serializing a Decimal
|
@@ -25040,38 +25349,6 @@
|
|
25040
25349
|
return value != null && value !== '' && value !== false;
|
25041
25350
|
};
|
25042
25351
|
|
25043
|
-
/**
|
25044
|
-
* Constructs a relative path from a URL.
|
25045
|
-
*
|
25046
|
-
* @param url - The destination URL
|
25047
|
-
* @param base - The base URL
|
25048
|
-
* @returns The relative path
|
25049
|
-
*
|
25050
|
-
* @group Utils
|
25051
|
-
*
|
25052
|
-
* @beta
|
25053
|
-
*/
|
25054
|
-
function urlToRelativePath(url, base) {
|
25055
|
-
var to = new URL(url);
|
25056
|
-
var from = new URL(base);
|
25057
|
-
if (to.origin !== from.origin) {
|
25058
|
-
return url;
|
25059
|
-
}
|
25060
|
-
var toPath = to.pathname.split('/').slice(1);
|
25061
|
-
var fromPath = from.pathname.split('/').slice(1, -1);
|
25062
|
-
// remove common parents
|
25063
|
-
while (toPath[0] === fromPath[0]) {
|
25064
|
-
toPath.shift();
|
25065
|
-
fromPath.shift();
|
25066
|
-
}
|
25067
|
-
// add back paths
|
25068
|
-
while (fromPath.length) {
|
25069
|
-
fromPath.shift();
|
25070
|
-
toPath.unshift('..');
|
25071
|
-
}
|
25072
|
-
return toPath.join('/');
|
25073
|
-
}
|
25074
|
-
|
25075
25352
|
var toRounded = function toRounded(value) {
|
25076
25353
|
return Math.round(value);
|
25077
25354
|
};
|
@@ -25315,36 +25592,6 @@
|
|
25315
25592
|
return "" + url + separator + query;
|
25316
25593
|
}
|
25317
25594
|
|
25318
|
-
/**
|
25319
|
-
* Generate a random v4 UUID
|
25320
|
-
*
|
25321
|
-
* @returns A random v4 UUID
|
25322
|
-
*
|
25323
|
-
* @group Utils
|
25324
|
-
*
|
25325
|
-
* @beta
|
25326
|
-
*/
|
25327
|
-
function uuid() {
|
25328
|
-
try {
|
25329
|
-
return crypto.randomUUID();
|
25330
|
-
} catch (error) {
|
25331
|
-
try {
|
25332
|
-
var url = URL.createObjectURL(new Blob());
|
25333
|
-
var _uuid = url.toString();
|
25334
|
-
URL.revokeObjectURL(url);
|
25335
|
-
return _uuid.slice(_uuid.lastIndexOf('/') + 1);
|
25336
|
-
} catch (error) {
|
25337
|
-
var dt = new Date().getTime();
|
25338
|
-
var _uuid2 = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
|
25339
|
-
var r = (dt + Math.random() * 16) % 16 | 0;
|
25340
|
-
dt = Math.floor(dt / 16);
|
25341
|
-
return (c == 'x' ? r : r & 0x3 | 0x8).toString(16);
|
25342
|
-
});
|
25343
|
-
return _uuid2;
|
25344
|
-
}
|
25345
|
-
}
|
25346
|
-
}
|
25347
|
-
|
25348
25595
|
/**
|
25349
25596
|
* Controller to deal with Common Media Client Data (CMCD)
|
25350
25597
|
* @see https://cdn.cta.tech/cta/media/media/resources/standards/pdfs/cta-5004-final.pdf
|
@@ -30211,7 +30458,7 @@
|
|
30211
30458
|
* Get the video-dev/hls.js package version.
|
30212
30459
|
*/
|
30213
30460
|
function get() {
|
30214
|
-
return "1.5.8-0.canary.
|
30461
|
+
return "1.5.8-0.canary.10155";
|
30215
30462
|
}
|
30216
30463
|
}, {
|
30217
30464
|
key: "Events",
|