/*! @name @videojs/vhs-utils @version 2.3.0 @license MIT */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var toUint8 = function toUint8(bytes) { return bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes && bytes.buffer || bytes, bytes && bytes.byteOffset || 0, bytes && bytes.byteLength || 0); }; var bytesToString = function bytesToString(bytes) { if (!bytes) { return ''; } bytes = Array.prototype.slice.call(bytes); var string = String.fromCharCode.apply(null, toUint8(bytes)); try { return decodeURIComponent(escape(string)); } catch (e) {// if decodeURIComponent/escape fails, we are dealing with partial // or full non string data. Just return the potentially garbled string. } return string; }; var id3Size = function id3Size(bytes, offset) { if (offset === void 0) { offset = 0; } bytes = toUint8(bytes); var returnSize = bytes[offset + 6] << 21 | bytes[offset + 7] << 14 | bytes[offset + 8] << 7 | bytes[offset + 9]; var flags = bytes[offset + 5]; var footerPresent = (flags & 16) >> 4; if (footerPresent) { return returnSize + 20; } return returnSize + 10; }; var getId3Offset = function getId3Offset(bytes, offset) { if (offset === void 0) { offset = 0; } bytes = toUint8(bytes); if (bytes.length - offset < 10 || bytesToString(bytes.subarray(offset, offset + 3)) !== 'ID3') { return offset; } offset += id3Size(bytes, offset); // recursive check for id3 tags as some files // have multiple ID3 tag sections even though // they should not. return getId3Offset(bytes, offset); }; var isLikely = { aac: function aac(bytes) { var offset = getId3Offset(bytes); return bytes.length >= offset + 2 && (bytes[offset] & 0xFF) === 0xFF && (bytes[offset + 1] & 0xE0) === 0xE0 && (bytes[offset + 1] & 0x16) === 0x10; }, mp3: function mp3(bytes) { var offset = getId3Offset(bytes); return bytes.length >= offset + 2 && (bytes[offset] & 0xFF) === 0xFF && (bytes[offset + 1] & 0xE0) === 0xE0 && (bytes[offset + 1] & 0x06) === 0x02; }, webm: function webm(bytes) { return bytes.length >= 4 && (bytes[0] & 0xFF) === 0x1A && (bytes[1] & 0xFF) === 0x45 && (bytes[2] & 0xFF) === 0xDF && (bytes[3] & 0xFF) === 0xA3; }, mp4: function mp4(bytes) { return bytes.length >= 8 && /^(f|s)typ$/.test(bytesToString(bytes.subarray(4, 8))) && // not 3gp data !/^ftyp3g$/.test(bytesToString(bytes.subarray(4, 10))); }, '3gp': function gp(bytes) { return bytes.length >= 10 && /^ftyp3g$/.test(bytesToString(bytes.subarray(4, 10))); }, ts: function ts(bytes) { if (bytes.length < 189 && bytes.length >= 1) { return bytes[0] === 0x47; } var i = 0; // check the first 376 bytes for two matching sync bytes while (i + 188 < bytes.length && i < 188) { if (bytes[i] === 0x47 && bytes[i + 188] === 0x47) { return true; } i += 1; } return false; }, flac: function flac(bytes) { return bytes.length >= 4 && /^fLaC$/.test(bytesToString(bytes.subarray(0, 4))); }, ogg: function ogg(bytes) { return bytes.length >= 4 && /^OggS$/.test(bytesToString(bytes.subarray(0, 4))); } }; // get all the isLikely functions // but make sure 'ts' is at the bottom // as it is the least specific var isLikelyTypes = Object.keys(isLikely) // remove ts .filter(function (t) { return t !== 'ts'; }) // add it back to the bottom .concat('ts'); // make sure we are dealing with uint8 data. isLikelyTypes.forEach(function (type) { var isLikelyFn = isLikely[type]; isLikely[type] = function (bytes) { return isLikelyFn(toUint8(bytes)); }; }); // A useful list of file signatures can be found here // https://en.wikipedia.org/wiki/List_of_file_signatures var detectContainerForBytes = function detectContainerForBytes(bytes) { bytes = toUint8(bytes); for (var i = 0; i < isLikelyTypes.length; i++) { var type = isLikelyTypes[i]; if (isLikely[type](bytes)) { return type; } } return ''; }; // fmp4 is not a container var isLikelyFmp4MediaSegment = function isLikelyFmp4MediaSegment(bytes) { bytes = toUint8(bytes); var i = 0; while (i < bytes.length) { var size = (bytes[i] << 24 | bytes[i + 1] << 16 | bytes[i + 2] << 8 | bytes[i + 3]) >>> 0; var type = bytesToString(bytes.subarray(i + 4, i + 8)); if (type === 'moof') { return true; } if (size === 0 || size + i > bytes.length) { i = bytes.length; } else { i += size; } } return false; }; exports.detectContainerForBytes = detectContainerForBytes; exports.getId3Offset = getId3Offset; exports.id3Size = id3Size; exports.isLikely = isLikely; exports.isLikelyFmp4MediaSegment = isLikelyFmp4MediaSegment;