hls.js 1.5.8-0.canary.10153 → 1.5.8-0.canary.10154
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 +579 -351
- 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 +788 -547
- 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/eme-controller.ts +1 -1
- package/src/controller/id3-track-controller.ts +4 -3
- 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 +8 -6
- package/src/demux/audio/mp3demuxer.ts +4 -3
- 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.light.mjs
CHANGED
@@ -512,7 +512,7 @@ function enableLogs(debugConfig, context, id) {
|
|
512
512
|
// Some browsers don't allow to use bind on console object anyway
|
513
513
|
// fallback to default if needed
|
514
514
|
try {
|
515
|
-
newLogger.log(`Debug logs enabled for "${context}" in hls.js version ${"1.5.8-0.canary.
|
515
|
+
newLogger.log(`Debug logs enabled for "${context}" in hls.js version ${"1.5.8-0.canary.10154"}`);
|
516
516
|
} catch (e) {
|
517
517
|
/* log fn threw an exception. All logger methods are no-ops. */
|
518
518
|
return createLogger();
|
@@ -1049,273 +1049,6 @@ function sliceUint8(array, start, end) {
|
|
1049
1049
|
return Uint8Array.prototype.slice ? array.slice(start, end) : new Uint8Array(Array.prototype.slice.call(array, start, end));
|
1050
1050
|
}
|
1051
1051
|
|
1052
|
-
// breaking up those two types in order to clarify what is happening in the decoding path.
|
1053
|
-
|
1054
|
-
/**
|
1055
|
-
* Returns true if an ID3 header can be found at offset in data
|
1056
|
-
* @param data - The data to search
|
1057
|
-
* @param offset - The offset at which to start searching
|
1058
|
-
*/
|
1059
|
-
const isHeader$2 = (data, offset) => {
|
1060
|
-
/*
|
1061
|
-
* http://id3.org/id3v2.3.0
|
1062
|
-
* [0] = 'I'
|
1063
|
-
* [1] = 'D'
|
1064
|
-
* [2] = '3'
|
1065
|
-
* [3,4] = {Version}
|
1066
|
-
* [5] = {Flags}
|
1067
|
-
* [6-9] = {ID3 Size}
|
1068
|
-
*
|
1069
|
-
* An ID3v2 tag can be detected with the following pattern:
|
1070
|
-
* $49 44 33 yy yy xx zz zz zz zz
|
1071
|
-
* Where yy is less than $FF, xx is the 'flags' byte and zz is less than $80
|
1072
|
-
*/
|
1073
|
-
if (offset + 10 <= data.length) {
|
1074
|
-
// look for 'ID3' identifier
|
1075
|
-
if (data[offset] === 0x49 && data[offset + 1] === 0x44 && data[offset + 2] === 0x33) {
|
1076
|
-
// check version is within range
|
1077
|
-
if (data[offset + 3] < 0xff && data[offset + 4] < 0xff) {
|
1078
|
-
// check size is within range
|
1079
|
-
if (data[offset + 6] < 0x80 && data[offset + 7] < 0x80 && data[offset + 8] < 0x80 && data[offset + 9] < 0x80) {
|
1080
|
-
return true;
|
1081
|
-
}
|
1082
|
-
}
|
1083
|
-
}
|
1084
|
-
}
|
1085
|
-
return false;
|
1086
|
-
};
|
1087
|
-
|
1088
|
-
/**
|
1089
|
-
* Returns true if an ID3 footer can be found at offset in data
|
1090
|
-
* @param data - The data to search
|
1091
|
-
* @param offset - The offset at which to start searching
|
1092
|
-
*/
|
1093
|
-
const isFooter = (data, offset) => {
|
1094
|
-
/*
|
1095
|
-
* The footer is a copy of the header, but with a different identifier
|
1096
|
-
*/
|
1097
|
-
if (offset + 10 <= data.length) {
|
1098
|
-
// look for '3DI' identifier
|
1099
|
-
if (data[offset] === 0x33 && data[offset + 1] === 0x44 && data[offset + 2] === 0x49) {
|
1100
|
-
// check version is within range
|
1101
|
-
if (data[offset + 3] < 0xff && data[offset + 4] < 0xff) {
|
1102
|
-
// check size is within range
|
1103
|
-
if (data[offset + 6] < 0x80 && data[offset + 7] < 0x80 && data[offset + 8] < 0x80 && data[offset + 9] < 0x80) {
|
1104
|
-
return true;
|
1105
|
-
}
|
1106
|
-
}
|
1107
|
-
}
|
1108
|
-
}
|
1109
|
-
return false;
|
1110
|
-
};
|
1111
|
-
|
1112
|
-
/**
|
1113
|
-
* Returns any adjacent ID3 tags found in data starting at offset, as one block of data
|
1114
|
-
* @param data - The data to search in
|
1115
|
-
* @param offset - The offset at which to start searching
|
1116
|
-
* @returns the block of data containing any ID3 tags found
|
1117
|
-
* or *undefined* if no header is found at the starting offset
|
1118
|
-
*/
|
1119
|
-
const getID3Data = (data, offset) => {
|
1120
|
-
const front = offset;
|
1121
|
-
let length = 0;
|
1122
|
-
while (isHeader$2(data, offset)) {
|
1123
|
-
// ID3 header is 10 bytes
|
1124
|
-
length += 10;
|
1125
|
-
const size = readSize(data, offset + 6);
|
1126
|
-
length += size;
|
1127
|
-
if (isFooter(data, offset + 10)) {
|
1128
|
-
// ID3 footer is 10 bytes
|
1129
|
-
length += 10;
|
1130
|
-
}
|
1131
|
-
offset += length;
|
1132
|
-
}
|
1133
|
-
if (length > 0) {
|
1134
|
-
return data.subarray(front, front + length);
|
1135
|
-
}
|
1136
|
-
return undefined;
|
1137
|
-
};
|
1138
|
-
const readSize = (data, offset) => {
|
1139
|
-
let size = 0;
|
1140
|
-
size = (data[offset] & 0x7f) << 21;
|
1141
|
-
size |= (data[offset + 1] & 0x7f) << 14;
|
1142
|
-
size |= (data[offset + 2] & 0x7f) << 7;
|
1143
|
-
size |= data[offset + 3] & 0x7f;
|
1144
|
-
return size;
|
1145
|
-
};
|
1146
|
-
const canParse$2 = (data, offset) => {
|
1147
|
-
return isHeader$2(data, offset) && readSize(data, offset + 6) + 10 <= data.length - offset;
|
1148
|
-
};
|
1149
|
-
|
1150
|
-
/**
|
1151
|
-
* Searches for the Elementary Stream timestamp found in the ID3 data chunk
|
1152
|
-
* @param data - Block of data containing one or more ID3 tags
|
1153
|
-
*/
|
1154
|
-
const getTimeStamp = data => {
|
1155
|
-
const frames = getID3Frames(data);
|
1156
|
-
for (let i = 0; i < frames.length; i++) {
|
1157
|
-
const frame = frames[i];
|
1158
|
-
if (isTimeStampFrame(frame)) {
|
1159
|
-
return readTimeStamp(frame);
|
1160
|
-
}
|
1161
|
-
}
|
1162
|
-
return undefined;
|
1163
|
-
};
|
1164
|
-
|
1165
|
-
/**
|
1166
|
-
* Returns true if the ID3 frame is an Elementary Stream timestamp frame
|
1167
|
-
*/
|
1168
|
-
const isTimeStampFrame = frame => {
|
1169
|
-
return frame && frame.key === 'PRIV' && frame.info === 'com.apple.streaming.transportStreamTimestamp';
|
1170
|
-
};
|
1171
|
-
const getFrameData = data => {
|
1172
|
-
/*
|
1173
|
-
Frame ID $xx xx xx xx (four characters)
|
1174
|
-
Size $xx xx xx xx
|
1175
|
-
Flags $xx xx
|
1176
|
-
*/
|
1177
|
-
const type = String.fromCharCode(data[0], data[1], data[2], data[3]);
|
1178
|
-
const size = readSize(data, 4);
|
1179
|
-
|
1180
|
-
// skip frame id, size, and flags
|
1181
|
-
const offset = 10;
|
1182
|
-
return {
|
1183
|
-
type,
|
1184
|
-
size,
|
1185
|
-
data: data.subarray(offset, offset + size)
|
1186
|
-
};
|
1187
|
-
};
|
1188
|
-
|
1189
|
-
/**
|
1190
|
-
* Returns an array of ID3 frames found in all the ID3 tags in the id3Data
|
1191
|
-
* @param id3Data - The ID3 data containing one or more ID3 tags
|
1192
|
-
*/
|
1193
|
-
const getID3Frames = id3Data => {
|
1194
|
-
let offset = 0;
|
1195
|
-
const frames = [];
|
1196
|
-
while (isHeader$2(id3Data, offset)) {
|
1197
|
-
const size = readSize(id3Data, offset + 6);
|
1198
|
-
// skip past ID3 header
|
1199
|
-
offset += 10;
|
1200
|
-
const end = offset + size;
|
1201
|
-
// loop through frames in the ID3 tag
|
1202
|
-
while (offset + 8 < end) {
|
1203
|
-
const frameData = getFrameData(id3Data.subarray(offset));
|
1204
|
-
const frame = decodeFrame(frameData);
|
1205
|
-
if (frame) {
|
1206
|
-
frames.push(frame);
|
1207
|
-
}
|
1208
|
-
|
1209
|
-
// skip frame header and frame data
|
1210
|
-
offset += frameData.size + 10;
|
1211
|
-
}
|
1212
|
-
if (isFooter(id3Data, offset)) {
|
1213
|
-
offset += 10;
|
1214
|
-
}
|
1215
|
-
}
|
1216
|
-
return frames;
|
1217
|
-
};
|
1218
|
-
const decodeFrame = frame => {
|
1219
|
-
if (frame.type === 'PRIV') {
|
1220
|
-
return decodePrivFrame(frame);
|
1221
|
-
} else if (frame.type[0] === 'W') {
|
1222
|
-
return decodeURLFrame(frame);
|
1223
|
-
}
|
1224
|
-
return decodeTextFrame(frame);
|
1225
|
-
};
|
1226
|
-
const decodePrivFrame = frame => {
|
1227
|
-
/*
|
1228
|
-
Format: <text string>\0<binary data>
|
1229
|
-
*/
|
1230
|
-
if (frame.size < 2) {
|
1231
|
-
return undefined;
|
1232
|
-
}
|
1233
|
-
const owner = utf8ArrayToStr(frame.data, true);
|
1234
|
-
const privateData = new Uint8Array(frame.data.subarray(owner.length + 1));
|
1235
|
-
return {
|
1236
|
-
key: frame.type,
|
1237
|
-
info: owner,
|
1238
|
-
data: privateData.buffer
|
1239
|
-
};
|
1240
|
-
};
|
1241
|
-
const decodeTextFrame = frame => {
|
1242
|
-
if (frame.size < 2) {
|
1243
|
-
return undefined;
|
1244
|
-
}
|
1245
|
-
if (frame.type === 'TXXX') {
|
1246
|
-
/*
|
1247
|
-
Format:
|
1248
|
-
[0] = {Text Encoding}
|
1249
|
-
[1-?] = {Description}\0{Value}
|
1250
|
-
*/
|
1251
|
-
let index = 1;
|
1252
|
-
const description = utf8ArrayToStr(frame.data.subarray(index), true);
|
1253
|
-
index += description.length + 1;
|
1254
|
-
const value = utf8ArrayToStr(frame.data.subarray(index));
|
1255
|
-
return {
|
1256
|
-
key: frame.type,
|
1257
|
-
info: description,
|
1258
|
-
data: value
|
1259
|
-
};
|
1260
|
-
}
|
1261
|
-
/*
|
1262
|
-
Format:
|
1263
|
-
[0] = {Text Encoding}
|
1264
|
-
[1-?] = {Value}
|
1265
|
-
*/
|
1266
|
-
const text = utf8ArrayToStr(frame.data.subarray(1));
|
1267
|
-
return {
|
1268
|
-
key: frame.type,
|
1269
|
-
data: text
|
1270
|
-
};
|
1271
|
-
};
|
1272
|
-
const decodeURLFrame = frame => {
|
1273
|
-
if (frame.type === 'WXXX') {
|
1274
|
-
/*
|
1275
|
-
Format:
|
1276
|
-
[0] = {Text Encoding}
|
1277
|
-
[1-?] = {Description}\0{URL}
|
1278
|
-
*/
|
1279
|
-
if (frame.size < 2) {
|
1280
|
-
return undefined;
|
1281
|
-
}
|
1282
|
-
let index = 1;
|
1283
|
-
const description = utf8ArrayToStr(frame.data.subarray(index), true);
|
1284
|
-
index += description.length + 1;
|
1285
|
-
const value = utf8ArrayToStr(frame.data.subarray(index));
|
1286
|
-
return {
|
1287
|
-
key: frame.type,
|
1288
|
-
info: description,
|
1289
|
-
data: value
|
1290
|
-
};
|
1291
|
-
}
|
1292
|
-
/*
|
1293
|
-
Format:
|
1294
|
-
[0-?] = {URL}
|
1295
|
-
*/
|
1296
|
-
const url = utf8ArrayToStr(frame.data);
|
1297
|
-
return {
|
1298
|
-
key: frame.type,
|
1299
|
-
data: url
|
1300
|
-
};
|
1301
|
-
};
|
1302
|
-
const readTimeStamp = timeStampFrame => {
|
1303
|
-
if (timeStampFrame.data.byteLength === 8) {
|
1304
|
-
const data = new Uint8Array(timeStampFrame.data);
|
1305
|
-
// timestamp is 33 bit expressed as a big-endian eight-octet number,
|
1306
|
-
// with the upper 31 bits set to zero.
|
1307
|
-
const pts33Bit = data[3] & 0x1;
|
1308
|
-
let timestamp = (data[4] << 23) + (data[5] << 15) + (data[6] << 7) + data[7];
|
1309
|
-
timestamp /= 45;
|
1310
|
-
if (pts33Bit) {
|
1311
|
-
timestamp += 47721858.84;
|
1312
|
-
} // 2^32 / 90
|
1313
|
-
|
1314
|
-
return Math.round(timestamp);
|
1315
|
-
}
|
1316
|
-
return undefined;
|
1317
|
-
};
|
1318
|
-
|
1319
1052
|
// http://stackoverflow.com/questions/8936984/uint8array-to-string-in-javascript/22373197
|
1320
1053
|
// http://www.onicos.com/staff/iz/amuse/javascript/expert/utf.txt
|
1321
1054
|
/* utf.js - UTF-8 <=> UTF-16 convertion
|
@@ -1325,16 +1058,26 @@ const readTimeStamp = timeStampFrame => {
|
|
1325
1058
|
* LastModified: Dec 25 1999
|
1326
1059
|
* This library is free. You can redistribute it and/or modify it.
|
1327
1060
|
*/
|
1328
|
-
|
1329
|
-
|
1330
|
-
|
1061
|
+
/**
|
1062
|
+
* Converts a UTF-8 array to a string.
|
1063
|
+
*
|
1064
|
+
* @param array - The UTF-8 array to convert
|
1065
|
+
*
|
1066
|
+
* @returns The string
|
1067
|
+
*
|
1068
|
+
* @group Utils
|
1069
|
+
*
|
1070
|
+
* @beta
|
1071
|
+
*/
|
1072
|
+
function utf8ArrayToStr(array, exitOnNull = false) {
|
1073
|
+
if (typeof TextDecoder !== 'undefined') {
|
1074
|
+
const decoder = new TextDecoder('utf-8');
|
1331
1075
|
const decoded = decoder.decode(array);
|
1332
1076
|
if (exitOnNull) {
|
1333
1077
|
// grab up to the first null
|
1334
1078
|
const idx = decoded.indexOf('\0');
|
1335
1079
|
return idx !== -1 ? decoded.substring(0, idx) : decoded;
|
1336
1080
|
}
|
1337
|
-
|
1338
1081
|
// remove any null characters
|
1339
1082
|
return decoded.replace(/\0/g, '');
|
1340
1083
|
}
|
@@ -1379,18 +1122,6 @@ const utf8ArrayToStr = (array, exitOnNull = false) => {
|
|
1379
1122
|
}
|
1380
1123
|
}
|
1381
1124
|
return out;
|
1382
|
-
};
|
1383
|
-
let decoder;
|
1384
|
-
function getTextDecoder() {
|
1385
|
-
// On Play Station 4, TextDecoder is defined but partially implemented.
|
1386
|
-
// Manual decoding option is preferable
|
1387
|
-
if (navigator.userAgent.includes('PlayStation 4')) {
|
1388
|
-
return;
|
1389
|
-
}
|
1390
|
-
if (!decoder && typeof self.TextDecoder !== 'undefined') {
|
1391
|
-
decoder = new self.TextDecoder('utf-8');
|
1392
|
-
}
|
1393
|
-
return decoder;
|
1394
1125
|
}
|
1395
1126
|
|
1396
1127
|
/**
|
@@ -3885,78 +3616,477 @@ function clearCurrentCues(track) {
|
|
3885
3616
|
track.removeCue(track.cues[i]);
|
3886
3617
|
}
|
3887
3618
|
}
|
3888
|
-
if (mode === 'disabled') {
|
3889
|
-
track.mode = mode;
|
3619
|
+
if (mode === 'disabled') {
|
3620
|
+
track.mode = mode;
|
3621
|
+
}
|
3622
|
+
}
|
3623
|
+
function removeCuesInRange(track, start, end, predicate) {
|
3624
|
+
const mode = track.mode;
|
3625
|
+
if (mode === 'disabled') {
|
3626
|
+
track.mode = 'hidden';
|
3627
|
+
}
|
3628
|
+
if (track.cues && track.cues.length > 0) {
|
3629
|
+
const cues = getCuesInRange(track.cues, start, end);
|
3630
|
+
for (let i = 0; i < cues.length; i++) {
|
3631
|
+
if (!predicate || predicate(cues[i])) {
|
3632
|
+
track.removeCue(cues[i]);
|
3633
|
+
}
|
3634
|
+
}
|
3635
|
+
}
|
3636
|
+
if (mode === 'disabled') {
|
3637
|
+
track.mode = mode;
|
3638
|
+
}
|
3639
|
+
}
|
3640
|
+
|
3641
|
+
// Find first cue starting after given time.
|
3642
|
+
// Modified version of binary search O(log(n)).
|
3643
|
+
function getFirstCueIndexAfterTime(cues, time) {
|
3644
|
+
// If first cue starts after time, start there
|
3645
|
+
if (time < cues[0].startTime) {
|
3646
|
+
return 0;
|
3647
|
+
}
|
3648
|
+
// If the last cue ends before time there is no overlap
|
3649
|
+
const len = cues.length - 1;
|
3650
|
+
if (time > cues[len].endTime) {
|
3651
|
+
return -1;
|
3652
|
+
}
|
3653
|
+
let left = 0;
|
3654
|
+
let right = len;
|
3655
|
+
while (left <= right) {
|
3656
|
+
const mid = Math.floor((right + left) / 2);
|
3657
|
+
if (time < cues[mid].startTime) {
|
3658
|
+
right = mid - 1;
|
3659
|
+
} else if (time > cues[mid].startTime && left < len) {
|
3660
|
+
left = mid + 1;
|
3661
|
+
} else {
|
3662
|
+
// If it's not lower or higher, it must be equal.
|
3663
|
+
return mid;
|
3664
|
+
}
|
3665
|
+
}
|
3666
|
+
// At this point, left and right have swapped.
|
3667
|
+
// No direct match was found, left or right element must be the closest. Check which one has the smallest diff.
|
3668
|
+
return cues[left].startTime - time < time - cues[right].startTime ? left : right;
|
3669
|
+
}
|
3670
|
+
function getCuesInRange(cues, start, end) {
|
3671
|
+
const cuesFound = [];
|
3672
|
+
const firstCueInRange = getFirstCueIndexAfterTime(cues, start);
|
3673
|
+
if (firstCueInRange > -1) {
|
3674
|
+
for (let i = firstCueInRange, len = cues.length; i < len; i++) {
|
3675
|
+
const cue = cues[i];
|
3676
|
+
if (cue.startTime >= start && cue.endTime <= end) {
|
3677
|
+
cuesFound.push(cue);
|
3678
|
+
} else if (cue.startTime > end) {
|
3679
|
+
return cuesFound;
|
3680
|
+
}
|
3681
|
+
}
|
3682
|
+
}
|
3683
|
+
return cuesFound;
|
3684
|
+
}
|
3685
|
+
|
3686
|
+
var MetadataSchema = {
|
3687
|
+
audioId3: "org.id3",
|
3688
|
+
dateRange: "com.apple.quicktime.HLS",
|
3689
|
+
emsg: "https://aomedia.org/emsg/ID3"
|
3690
|
+
};
|
3691
|
+
|
3692
|
+
/**
|
3693
|
+
* Decode an ID3 PRIV frame.
|
3694
|
+
*
|
3695
|
+
* @param frame - the ID3 PRIV frame
|
3696
|
+
*
|
3697
|
+
* @returns The decoded ID3 PRIV frame
|
3698
|
+
*
|
3699
|
+
* @internal
|
3700
|
+
*
|
3701
|
+
* @group ID3
|
3702
|
+
*/
|
3703
|
+
function decodeId3PrivFrame(frame) {
|
3704
|
+
/*
|
3705
|
+
Format: <text string>\0<binary data>
|
3706
|
+
*/
|
3707
|
+
if (frame.size < 2) {
|
3708
|
+
return undefined;
|
3709
|
+
}
|
3710
|
+
const owner = utf8ArrayToStr(frame.data, true);
|
3711
|
+
const privateData = new Uint8Array(frame.data.subarray(owner.length + 1));
|
3712
|
+
return {
|
3713
|
+
key: frame.type,
|
3714
|
+
info: owner,
|
3715
|
+
data: privateData.buffer
|
3716
|
+
};
|
3717
|
+
}
|
3718
|
+
|
3719
|
+
/**
|
3720
|
+
* Decodes an ID3 text frame
|
3721
|
+
*
|
3722
|
+
* @param frame - the ID3 text frame
|
3723
|
+
*
|
3724
|
+
* @returns The decoded ID3 text frame
|
3725
|
+
*
|
3726
|
+
* @internal
|
3727
|
+
*
|
3728
|
+
* @group ID3
|
3729
|
+
*/
|
3730
|
+
function decodeId3TextFrame(frame) {
|
3731
|
+
if (frame.size < 2) {
|
3732
|
+
return undefined;
|
3733
|
+
}
|
3734
|
+
if (frame.type === 'TXXX') {
|
3735
|
+
/*
|
3736
|
+
Format:
|
3737
|
+
[0] = {Text Encoding}
|
3738
|
+
[1-?] = {Description}\0{Value}
|
3739
|
+
*/
|
3740
|
+
let index = 1;
|
3741
|
+
const description = utf8ArrayToStr(frame.data.subarray(index), true);
|
3742
|
+
index += description.length + 1;
|
3743
|
+
const value = utf8ArrayToStr(frame.data.subarray(index));
|
3744
|
+
return {
|
3745
|
+
key: frame.type,
|
3746
|
+
info: description,
|
3747
|
+
data: value
|
3748
|
+
};
|
3749
|
+
}
|
3750
|
+
/*
|
3751
|
+
Format:
|
3752
|
+
[0] = {Text Encoding}
|
3753
|
+
[1-?] = {Value}
|
3754
|
+
*/
|
3755
|
+
const text = utf8ArrayToStr(frame.data.subarray(1));
|
3756
|
+
return {
|
3757
|
+
key: frame.type,
|
3758
|
+
info: '',
|
3759
|
+
data: text
|
3760
|
+
};
|
3761
|
+
}
|
3762
|
+
|
3763
|
+
/**
|
3764
|
+
* Decode a URL frame
|
3765
|
+
*
|
3766
|
+
* @param frame - the ID3 URL frame
|
3767
|
+
*
|
3768
|
+
* @returns The decoded ID3 URL frame
|
3769
|
+
*
|
3770
|
+
* @internal
|
3771
|
+
*
|
3772
|
+
* @group ID3
|
3773
|
+
*/
|
3774
|
+
function decodeId3UrlFrame(frame) {
|
3775
|
+
if (frame.type === 'WXXX') {
|
3776
|
+
/*
|
3777
|
+
Format:
|
3778
|
+
[0] = {Text Encoding}
|
3779
|
+
[1-?] = {Description}\0{URL}
|
3780
|
+
*/
|
3781
|
+
if (frame.size < 2) {
|
3782
|
+
return undefined;
|
3783
|
+
}
|
3784
|
+
let index = 1;
|
3785
|
+
const description = utf8ArrayToStr(frame.data.subarray(index), true);
|
3786
|
+
index += description.length + 1;
|
3787
|
+
const value = utf8ArrayToStr(frame.data.subarray(index));
|
3788
|
+
return {
|
3789
|
+
key: frame.type,
|
3790
|
+
info: description,
|
3791
|
+
data: value
|
3792
|
+
};
|
3793
|
+
}
|
3794
|
+
/*
|
3795
|
+
Format:
|
3796
|
+
[0-?] = {URL}
|
3797
|
+
*/
|
3798
|
+
const url = utf8ArrayToStr(frame.data);
|
3799
|
+
return {
|
3800
|
+
key: frame.type,
|
3801
|
+
info: '',
|
3802
|
+
data: url
|
3803
|
+
};
|
3804
|
+
}
|
3805
|
+
|
3806
|
+
function toUint8(data, offset = 0, length = Infinity) {
|
3807
|
+
return view(data, offset, length, Uint8Array);
|
3808
|
+
}
|
3809
|
+
function view(data, offset, length, Type) {
|
3810
|
+
const buffer = unsafeGetArrayBuffer(data);
|
3811
|
+
let bytesPerElement = 1;
|
3812
|
+
if ('BYTES_PER_ELEMENT' in Type) {
|
3813
|
+
bytesPerElement = Type.BYTES_PER_ELEMENT;
|
3814
|
+
}
|
3815
|
+
// Absolute end of the |data| view within |buffer|.
|
3816
|
+
const dataOffset = isArrayBufferView(data) ? data.byteOffset : 0;
|
3817
|
+
const dataEnd = (dataOffset + data.byteLength) / bytesPerElement;
|
3818
|
+
// Absolute start of the result within |buffer|.
|
3819
|
+
const rawStart = (dataOffset + offset) / bytesPerElement;
|
3820
|
+
const start = Math.floor(Math.max(0, Math.min(rawStart, dataEnd)));
|
3821
|
+
// Absolute end of the result within |buffer|.
|
3822
|
+
const end = Math.floor(Math.min(start + Math.max(length, 0), dataEnd));
|
3823
|
+
return new Type(buffer, start, end - start);
|
3824
|
+
}
|
3825
|
+
function unsafeGetArrayBuffer(view) {
|
3826
|
+
if (view instanceof ArrayBuffer) {
|
3827
|
+
return view;
|
3828
|
+
} else {
|
3829
|
+
return view.buffer;
|
3830
|
+
}
|
3831
|
+
}
|
3832
|
+
function isArrayBufferView(obj) {
|
3833
|
+
return obj && obj.buffer instanceof ArrayBuffer && obj.byteLength !== undefined && obj.byteOffset !== undefined;
|
3834
|
+
}
|
3835
|
+
|
3836
|
+
function toArrayBuffer(view) {
|
3837
|
+
if (view instanceof ArrayBuffer) {
|
3838
|
+
return view;
|
3839
|
+
} else {
|
3840
|
+
if (view.byteOffset == 0 && view.byteLength == view.buffer.byteLength) {
|
3841
|
+
// This is a TypedArray over the whole buffer.
|
3842
|
+
return view.buffer;
|
3843
|
+
}
|
3844
|
+
// This is a 'view' on the buffer. Create a new buffer that only contains
|
3845
|
+
// the data. Note that since this isn't an ArrayBuffer, the 'new' call
|
3846
|
+
// will allocate a new buffer to hold the copy.
|
3847
|
+
return new Uint8Array(view).buffer;
|
3848
|
+
}
|
3849
|
+
}
|
3850
|
+
|
3851
|
+
function decodeId3ImageFrame(frame) {
|
3852
|
+
const metadataFrame = {
|
3853
|
+
key: frame.type,
|
3854
|
+
description: '',
|
3855
|
+
data: '',
|
3856
|
+
mimeType: null,
|
3857
|
+
pictureType: null
|
3858
|
+
};
|
3859
|
+
const utf8Encoding = 0x03;
|
3860
|
+
if (frame.size < 2) {
|
3861
|
+
return undefined;
|
3862
|
+
}
|
3863
|
+
if (frame.data[0] !== utf8Encoding) {
|
3864
|
+
console.log('Ignore frame with unrecognized character ' + 'encoding');
|
3865
|
+
return undefined;
|
3866
|
+
}
|
3867
|
+
const mimeTypeEndIndex = frame.data.subarray(1).indexOf(0);
|
3868
|
+
if (mimeTypeEndIndex === -1) {
|
3869
|
+
return undefined;
|
3870
|
+
}
|
3871
|
+
const mimeType = utf8ArrayToStr(toUint8(frame.data, 1, mimeTypeEndIndex));
|
3872
|
+
const pictureType = frame.data[2 + mimeTypeEndIndex];
|
3873
|
+
const descriptionEndIndex = frame.data.subarray(3 + mimeTypeEndIndex).indexOf(0);
|
3874
|
+
if (descriptionEndIndex === -1) {
|
3875
|
+
return undefined;
|
3876
|
+
}
|
3877
|
+
const description = utf8ArrayToStr(toUint8(frame.data, 3 + mimeTypeEndIndex, descriptionEndIndex));
|
3878
|
+
let data;
|
3879
|
+
if (mimeType === '-->') {
|
3880
|
+
data = utf8ArrayToStr(toUint8(frame.data, 4 + mimeTypeEndIndex + descriptionEndIndex));
|
3881
|
+
} else {
|
3882
|
+
data = toArrayBuffer(frame.data.subarray(4 + mimeTypeEndIndex + descriptionEndIndex));
|
3890
3883
|
}
|
3884
|
+
metadataFrame.mimeType = mimeType;
|
3885
|
+
metadataFrame.pictureType = pictureType;
|
3886
|
+
metadataFrame.description = description;
|
3887
|
+
metadataFrame.data = data;
|
3888
|
+
return metadataFrame;
|
3891
3889
|
}
|
3892
|
-
|
3893
|
-
|
3894
|
-
|
3895
|
-
|
3890
|
+
|
3891
|
+
/**
|
3892
|
+
* Decode an ID3 frame.
|
3893
|
+
*
|
3894
|
+
* @param frame - the ID3 frame
|
3895
|
+
*
|
3896
|
+
* @returns The decoded ID3 frame
|
3897
|
+
*
|
3898
|
+
* @internal
|
3899
|
+
*
|
3900
|
+
* @group ID3
|
3901
|
+
*/
|
3902
|
+
function decodeId3Frame(frame) {
|
3903
|
+
if (frame.type === 'PRIV') {
|
3904
|
+
return decodeId3PrivFrame(frame);
|
3905
|
+
} else if (frame.type[0] === 'W') {
|
3906
|
+
return decodeId3UrlFrame(frame);
|
3907
|
+
} else if (frame.type === 'APIC') {
|
3908
|
+
return decodeId3ImageFrame(frame);
|
3896
3909
|
}
|
3897
|
-
|
3898
|
-
|
3899
|
-
|
3900
|
-
|
3901
|
-
|
3910
|
+
return decodeId3TextFrame(frame);
|
3911
|
+
}
|
3912
|
+
|
3913
|
+
/**
|
3914
|
+
* Read ID3 size
|
3915
|
+
*
|
3916
|
+
* @param data - The data to read from
|
3917
|
+
* @param offset - The offset at which to start reading
|
3918
|
+
*
|
3919
|
+
* @returns The size
|
3920
|
+
*
|
3921
|
+
* @internal
|
3922
|
+
*
|
3923
|
+
* @group ID3
|
3924
|
+
*/
|
3925
|
+
function readId3Size(data, offset) {
|
3926
|
+
let size = 0;
|
3927
|
+
size = (data[offset] & 0x7f) << 21;
|
3928
|
+
size |= (data[offset + 1] & 0x7f) << 14;
|
3929
|
+
size |= (data[offset + 2] & 0x7f) << 7;
|
3930
|
+
size |= data[offset + 3] & 0x7f;
|
3931
|
+
return size;
|
3932
|
+
}
|
3933
|
+
|
3934
|
+
/**
|
3935
|
+
* Returns the data of an ID3 frame.
|
3936
|
+
*
|
3937
|
+
* @param data - The data to read from
|
3938
|
+
*
|
3939
|
+
* @returns The data of the ID3 frame
|
3940
|
+
*
|
3941
|
+
* @internal
|
3942
|
+
*
|
3943
|
+
* @group ID3
|
3944
|
+
*/
|
3945
|
+
function getId3FrameData(data) {
|
3946
|
+
/*
|
3947
|
+
Frame ID $xx xx xx xx (four characters)
|
3948
|
+
Size $xx xx xx xx
|
3949
|
+
Flags $xx xx
|
3950
|
+
*/
|
3951
|
+
const type = String.fromCharCode(data[0], data[1], data[2], data[3]);
|
3952
|
+
const size = readId3Size(data, 4);
|
3953
|
+
// skip frame id, size, and flags
|
3954
|
+
const offset = 10;
|
3955
|
+
return {
|
3956
|
+
type,
|
3957
|
+
size,
|
3958
|
+
data: data.subarray(offset, offset + size)
|
3959
|
+
};
|
3960
|
+
}
|
3961
|
+
|
3962
|
+
/**
|
3963
|
+
* Returns true if an ID3 footer can be found at offset in data
|
3964
|
+
*
|
3965
|
+
* @param data - The data to search in
|
3966
|
+
* @param offset - The offset at which to start searching
|
3967
|
+
*
|
3968
|
+
* @returns `true` if an ID3 footer is found
|
3969
|
+
*
|
3970
|
+
* @internal
|
3971
|
+
*
|
3972
|
+
* @group ID3
|
3973
|
+
*/
|
3974
|
+
function isId3Footer(data, offset) {
|
3975
|
+
/*
|
3976
|
+
* The footer is a copy of the header, but with a different identifier
|
3977
|
+
*/
|
3978
|
+
if (offset + 10 <= data.length) {
|
3979
|
+
// look for '3DI' identifier
|
3980
|
+
if (data[offset] === 0x33 && data[offset + 1] === 0x44 && data[offset + 2] === 0x49) {
|
3981
|
+
// check version is within range
|
3982
|
+
if (data[offset + 3] < 0xff && data[offset + 4] < 0xff) {
|
3983
|
+
// check size is within range
|
3984
|
+
if (data[offset + 6] < 0x80 && data[offset + 7] < 0x80 && data[offset + 8] < 0x80 && data[offset + 9] < 0x80) {
|
3985
|
+
return true;
|
3986
|
+
}
|
3902
3987
|
}
|
3903
3988
|
}
|
3904
3989
|
}
|
3905
|
-
|
3906
|
-
track.mode = mode;
|
3907
|
-
}
|
3990
|
+
return false;
|
3908
3991
|
}
|
3909
3992
|
|
3910
|
-
|
3911
|
-
|
3912
|
-
|
3913
|
-
|
3914
|
-
|
3915
|
-
|
3916
|
-
|
3917
|
-
|
3918
|
-
|
3919
|
-
|
3920
|
-
|
3921
|
-
|
3922
|
-
|
3923
|
-
|
3924
|
-
|
3925
|
-
|
3926
|
-
|
3927
|
-
|
3928
|
-
|
3929
|
-
|
3930
|
-
|
3931
|
-
|
3932
|
-
|
3993
|
+
/**
|
3994
|
+
* Returns true if an ID3 header can be found at offset in data
|
3995
|
+
*
|
3996
|
+
* @param data - The data to search in
|
3997
|
+
* @param offset - The offset at which to start searching
|
3998
|
+
*
|
3999
|
+
* @returns `true` if an ID3 header is found
|
4000
|
+
*
|
4001
|
+
* @internal
|
4002
|
+
*
|
4003
|
+
* @group ID3
|
4004
|
+
*/
|
4005
|
+
function isId3Header(data, offset) {
|
4006
|
+
/*
|
4007
|
+
* http://id3.org/id3v2.3.0
|
4008
|
+
* [0] = 'I'
|
4009
|
+
* [1] = 'D'
|
4010
|
+
* [2] = '3'
|
4011
|
+
* [3,4] = {Version}
|
4012
|
+
* [5] = {Flags}
|
4013
|
+
* [6-9] = {ID3 Size}
|
4014
|
+
*
|
4015
|
+
* An ID3v2 tag can be detected with the following pattern:
|
4016
|
+
* $49 44 33 yy yy xx zz zz zz zz
|
4017
|
+
* Where yy is less than $FF, xx is the 'flags' byte and zz is less than $80
|
4018
|
+
*/
|
4019
|
+
if (offset + 10 <= data.length) {
|
4020
|
+
// look for 'ID3' identifier
|
4021
|
+
if (data[offset] === 0x49 && data[offset + 1] === 0x44 && data[offset + 2] === 0x33) {
|
4022
|
+
// check version is within range
|
4023
|
+
if (data[offset + 3] < 0xff && data[offset + 4] < 0xff) {
|
4024
|
+
// check size is within range
|
4025
|
+
if (data[offset + 6] < 0x80 && data[offset + 7] < 0x80 && data[offset + 8] < 0x80 && data[offset + 9] < 0x80) {
|
4026
|
+
return true;
|
4027
|
+
}
|
4028
|
+
}
|
3933
4029
|
}
|
3934
4030
|
}
|
3935
|
-
|
3936
|
-
// No direct match was found, left or right element must be the closest. Check which one has the smallest diff.
|
3937
|
-
return cues[left].startTime - time < time - cues[right].startTime ? left : right;
|
4031
|
+
return false;
|
3938
4032
|
}
|
3939
|
-
|
3940
|
-
|
3941
|
-
|
3942
|
-
|
3943
|
-
|
3944
|
-
|
3945
|
-
|
3946
|
-
|
3947
|
-
|
3948
|
-
|
4033
|
+
|
4034
|
+
const HEADER_FOOTER_SIZE = 10;
|
4035
|
+
const FRAME_SIZE = 10;
|
4036
|
+
/**
|
4037
|
+
* Returns an array of ID3 frames found in all the ID3 tags in the id3Data
|
4038
|
+
*
|
4039
|
+
* @param id3Data - The ID3 data containing one or more ID3 tags
|
4040
|
+
*
|
4041
|
+
* @returns Array of ID3 frame objects
|
4042
|
+
*
|
4043
|
+
* @group ID3
|
4044
|
+
*
|
4045
|
+
* @beta
|
4046
|
+
*/
|
4047
|
+
function getId3Frames(id3Data) {
|
4048
|
+
let offset = 0;
|
4049
|
+
const frames = [];
|
4050
|
+
while (isId3Header(id3Data, offset)) {
|
4051
|
+
const size = readId3Size(id3Data, offset + 6);
|
4052
|
+
if (id3Data[offset + 5] >> 6 & 1) {
|
4053
|
+
// skip extended header
|
4054
|
+
offset += HEADER_FOOTER_SIZE;
|
4055
|
+
}
|
4056
|
+
// skip past ID3 header
|
4057
|
+
offset += HEADER_FOOTER_SIZE;
|
4058
|
+
const end = offset + size;
|
4059
|
+
// loop through frames in the ID3 tag
|
4060
|
+
while (offset + FRAME_SIZE < end) {
|
4061
|
+
const frameData = getId3FrameData(id3Data.subarray(offset));
|
4062
|
+
const frame = decodeId3Frame(frameData);
|
4063
|
+
if (frame) {
|
4064
|
+
frames.push(frame);
|
3949
4065
|
}
|
4066
|
+
// skip frame header and frame data
|
4067
|
+
offset += frameData.size + HEADER_FOOTER_SIZE;
|
4068
|
+
}
|
4069
|
+
if (isId3Footer(id3Data, offset)) {
|
4070
|
+
offset += HEADER_FOOTER_SIZE;
|
3950
4071
|
}
|
3951
4072
|
}
|
3952
|
-
return
|
4073
|
+
return frames;
|
3953
4074
|
}
|
3954
4075
|
|
3955
|
-
|
3956
|
-
|
3957
|
-
|
3958
|
-
|
3959
|
-
|
4076
|
+
/**
|
4077
|
+
* Returns true if the ID3 frame is an Elementary Stream timestamp frame
|
4078
|
+
*
|
4079
|
+
* @param frame - the ID3 frame
|
4080
|
+
*
|
4081
|
+
* @returns `true` if the ID3 frame is an Elementary Stream timestamp frame
|
4082
|
+
*
|
4083
|
+
* @internal
|
4084
|
+
*
|
4085
|
+
* @group ID3
|
4086
|
+
*/
|
4087
|
+
function isId3TimestampFrame(frame) {
|
4088
|
+
return frame && frame.key === 'PRIV' && frame.info === 'com.apple.streaming.transportStreamTimestamp';
|
4089
|
+
}
|
3960
4090
|
|
3961
4091
|
const MIN_CUE_DURATION = 0.25;
|
3962
4092
|
function getCueClass() {
|
@@ -4102,7 +4232,7 @@ class ID3TrackController {
|
|
4102
4232
|
if (type === MetadataSchema.emsg && !enableEmsgMetadataCues || !enableID3MetadataCues) {
|
4103
4233
|
continue;
|
4104
4234
|
}
|
4105
|
-
const frames =
|
4235
|
+
const frames = getId3Frames(samples[i].data);
|
4106
4236
|
if (frames) {
|
4107
4237
|
const startTime = samples[i].pts;
|
4108
4238
|
let endTime = startTime + samples[i].duration;
|
@@ -4116,7 +4246,7 @@ class ID3TrackController {
|
|
4116
4246
|
for (let j = 0; j < frames.length; j++) {
|
4117
4247
|
const frame = frames[j];
|
4118
4248
|
// Safari doesn't put the timestamp frame in the TextTrack
|
4119
|
-
if (!
|
4249
|
+
if (!isId3TimestampFrame(frame)) {
|
4120
4250
|
// add a bounds to any unbounded cues
|
4121
4251
|
this.updateId3CueEnds(startTime, type);
|
4122
4252
|
const cue = createCueWithDataFields(Cue, startTime, endTime, frame, type);
|
@@ -13465,6 +13595,104 @@ function dummyTrack(type = '', inputTimeScale = 90000) {
|
|
13465
13595
|
};
|
13466
13596
|
}
|
13467
13597
|
|
13598
|
+
/**
|
13599
|
+
* Returns any adjacent ID3 tags found in data starting at offset, as one block of data
|
13600
|
+
*
|
13601
|
+
* @param data - The data to search in
|
13602
|
+
* @param offset - The offset at which to start searching
|
13603
|
+
*
|
13604
|
+
* @returns The block of data containing any ID3 tags found
|
13605
|
+
* or `undefined` if no header is found at the starting offset
|
13606
|
+
*
|
13607
|
+
* @internal
|
13608
|
+
*
|
13609
|
+
* @group ID3
|
13610
|
+
*/
|
13611
|
+
function getId3Data(data, offset) {
|
13612
|
+
const front = offset;
|
13613
|
+
let length = 0;
|
13614
|
+
while (isId3Header(data, offset)) {
|
13615
|
+
// ID3 header is 10 bytes
|
13616
|
+
length += 10;
|
13617
|
+
const size = readId3Size(data, offset + 6);
|
13618
|
+
length += size;
|
13619
|
+
if (isId3Footer(data, offset + 10)) {
|
13620
|
+
// ID3 footer is 10 bytes
|
13621
|
+
length += 10;
|
13622
|
+
}
|
13623
|
+
offset += length;
|
13624
|
+
}
|
13625
|
+
if (length > 0) {
|
13626
|
+
return data.subarray(front, front + length);
|
13627
|
+
}
|
13628
|
+
return undefined;
|
13629
|
+
}
|
13630
|
+
|
13631
|
+
/**
|
13632
|
+
* Read a 33 bit timestamp from an ID3 frame.
|
13633
|
+
*
|
13634
|
+
* @param timeStampFrame - the ID3 frame
|
13635
|
+
*
|
13636
|
+
* @returns The timestamp
|
13637
|
+
*
|
13638
|
+
* @internal
|
13639
|
+
*
|
13640
|
+
* @group ID3
|
13641
|
+
*/
|
13642
|
+
function readId3Timestamp(timeStampFrame) {
|
13643
|
+
if (timeStampFrame.data.byteLength === 8) {
|
13644
|
+
const data = new Uint8Array(timeStampFrame.data);
|
13645
|
+
// timestamp is 33 bit expressed as a big-endian eight-octet number,
|
13646
|
+
// with the upper 31 bits set to zero.
|
13647
|
+
const pts33Bit = data[3] & 0x1;
|
13648
|
+
let timestamp = (data[4] << 23) + (data[5] << 15) + (data[6] << 7) + data[7];
|
13649
|
+
timestamp /= 45;
|
13650
|
+
if (pts33Bit) {
|
13651
|
+
timestamp += 47721858.84;
|
13652
|
+
} // 2^32 / 90
|
13653
|
+
return Math.round(timestamp);
|
13654
|
+
}
|
13655
|
+
return undefined;
|
13656
|
+
}
|
13657
|
+
|
13658
|
+
/**
|
13659
|
+
* Searches for the Elementary Stream timestamp found in the ID3 data chunk
|
13660
|
+
*
|
13661
|
+
* @param data - Block of data containing one or more ID3 tags
|
13662
|
+
*
|
13663
|
+
* @returns The timestamp
|
13664
|
+
*
|
13665
|
+
* @group ID3
|
13666
|
+
*
|
13667
|
+
* @beta
|
13668
|
+
*/
|
13669
|
+
function getId3Timestamp(data) {
|
13670
|
+
const frames = getId3Frames(data);
|
13671
|
+
for (let i = 0; i < frames.length; i++) {
|
13672
|
+
const frame = frames[i];
|
13673
|
+
if (isId3TimestampFrame(frame)) {
|
13674
|
+
return readId3Timestamp(frame);
|
13675
|
+
}
|
13676
|
+
}
|
13677
|
+
return undefined;
|
13678
|
+
}
|
13679
|
+
|
13680
|
+
/**
|
13681
|
+
* Checks if the given data contains an ID3 tag.
|
13682
|
+
*
|
13683
|
+
* @param data - The data to check
|
13684
|
+
* @param offset - The offset at which to start checking
|
13685
|
+
*
|
13686
|
+
* @returns `true` if an ID3 tag is found
|
13687
|
+
*
|
13688
|
+
* @group ID3
|
13689
|
+
*
|
13690
|
+
* @beta
|
13691
|
+
*/
|
13692
|
+
function canParseId3(data, offset) {
|
13693
|
+
return isId3Header(data, offset) && readId3Size(data, offset + 6) + 10 <= data.length - offset;
|
13694
|
+
}
|
13695
|
+
|
13468
13696
|
class BaseAudioDemuxer {
|
13469
13697
|
constructor() {
|
13470
13698
|
this._audioTrack = void 0;
|
@@ -13506,12 +13734,12 @@ class BaseAudioDemuxer {
|
|
13506
13734
|
data = appendUint8Array(this.cachedData, data);
|
13507
13735
|
this.cachedData = null;
|
13508
13736
|
}
|
13509
|
-
let id3Data =
|
13737
|
+
let id3Data = getId3Data(data, 0);
|
13510
13738
|
let offset = id3Data ? id3Data.length : 0;
|
13511
13739
|
let lastDataIndex;
|
13512
13740
|
const track = this._audioTrack;
|
13513
13741
|
const id3Track = this._id3Track;
|
13514
|
-
const timestamp = id3Data ?
|
13742
|
+
const timestamp = id3Data ? getId3Timestamp(id3Data) : undefined;
|
13515
13743
|
const length = data.length;
|
13516
13744
|
if (this.basePTS === null || this.frameIndex === 0 && isFiniteNumber(timestamp)) {
|
13517
13745
|
this.basePTS = initPTSFn(timestamp, timeOffset, this.initPTS);
|
@@ -13542,9 +13770,9 @@ class BaseAudioDemuxer {
|
|
13542
13770
|
} else {
|
13543
13771
|
offset = length;
|
13544
13772
|
}
|
13545
|
-
} else if (
|
13546
|
-
// after a
|
13547
|
-
id3Data =
|
13773
|
+
} else if (canParseId3(data, offset)) {
|
13774
|
+
// after a canParse, a call to getId3Data *should* always returns some data
|
13775
|
+
id3Data = getId3Data(data, offset);
|
13548
13776
|
id3Track.samples.push({
|
13549
13777
|
pts: this.lastPTS,
|
13550
13778
|
dts: this.lastPTS,
|
@@ -14038,7 +14266,7 @@ class AACDemuxer extends BaseAudioDemuxer {
|
|
14038
14266
|
// Look for ADTS header | 1111 1111 | 1111 X00X | where X can be either 0 or 1
|
14039
14267
|
// Layer bits (position 14 and 15) in header should be always 0 for ADTS
|
14040
14268
|
// More info https://wiki.multimedia.cx/index.php?title=ADTS
|
14041
|
-
const id3Data =
|
14269
|
+
const id3Data = getId3Data(data, 0);
|
14042
14270
|
let offset = (id3Data == null ? void 0 : id3Data.length) || 0;
|
14043
14271
|
if (probe(data, offset)) {
|
14044
14272
|
return false;
|
@@ -15765,11 +15993,11 @@ class MP3Demuxer extends BaseAudioDemuxer {
|
|
15765
15993
|
// Look for MPEG header | 1111 1111 | 111X XYZX | where X can be either 0 or 1 and Y or Z should be 1
|
15766
15994
|
// Layer bits (position 14 and 15) in header should be always different from 0 (Layer I or Layer II or Layer III)
|
15767
15995
|
// More info http://www.mp3-tech.org/programmer/frame_header.html
|
15768
|
-
const id3Data =
|
15996
|
+
const id3Data = getId3Data(data, 0);
|
15769
15997
|
let offset = (id3Data == null ? void 0 : id3Data.length) || 0;
|
15770
15998
|
|
15771
15999
|
// Check for ac-3|ec-3 sync bytes and return false if present
|
15772
|
-
if (id3Data && data[offset] === 0x0b && data[offset + 1] === 0x77 &&
|
16000
|
+
if (id3Data && data[offset] === 0x0b && data[offset + 1] === 0x77 && getId3Timestamp(id3Data) !== undefined &&
|
15773
16001
|
// check the bsid to confirm ac-3 or ec-3 (not mp3)
|
15774
16002
|
getAudioBSID(data, offset) <= 16) {
|
15775
16003
|
return false;
|
@@ -20127,7 +20355,7 @@ class Hls {
|
|
20127
20355
|
* Get the video-dev/hls.js package version.
|
20128
20356
|
*/
|
20129
20357
|
static get version() {
|
20130
|
-
return "1.5.8-0.canary.
|
20358
|
+
return "1.5.8-0.canary.10154";
|
20131
20359
|
}
|
20132
20360
|
|
20133
20361
|
/**
|