| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581 | 
							- "use strict";
 
- Object.defineProperty(exports, "__esModule", {
 
-   value: true
 
- });
 
- exports.parseMediaInfo = exports.parseTracks = exports.addSampleDescription = exports.buildFrameTable = exports.findNamedBox = exports.findBox = exports.parseDescriptors = void 0;
 
- var _byteHelpers = require("./byte-helpers.js");
 
- var _codecHelpers = require("./codec-helpers.js");
 
- var _opusHelpers = require("./opus-helpers.js");
 
- var normalizePath = function normalizePath(path) {
 
-   if (typeof path === 'string') {
 
-     return (0, _byteHelpers.stringToBytes)(path);
 
-   }
 
-   if (typeof path === 'number') {
 
-     return path;
 
-   }
 
-   return path;
 
- };
 
- var normalizePaths = function normalizePaths(paths) {
 
-   if (!Array.isArray(paths)) {
 
-     return [normalizePath(paths)];
 
-   }
 
-   return paths.map(function (p) {
 
-     return normalizePath(p);
 
-   });
 
- };
 
- var DESCRIPTORS;
 
- var parseDescriptors = function parseDescriptors(bytes) {
 
-   bytes = (0, _byteHelpers.toUint8)(bytes);
 
-   var results = [];
 
-   var i = 0;
 
-   while (bytes.length > i) {
 
-     var tag = bytes[i];
 
-     var size = 0;
 
-     var headerSize = 0; // tag
 
-     headerSize++;
 
-     var byte = bytes[headerSize]; // first byte
 
-     headerSize++;
 
-     while (byte & 0x80) {
 
-       size = (byte & 0x7F) << 7;
 
-       byte = bytes[headerSize];
 
-       headerSize++;
 
-     }
 
-     size += byte & 0x7F;
 
-     for (var z = 0; z < DESCRIPTORS.length; z++) {
 
-       var _DESCRIPTORS$z = DESCRIPTORS[z],
 
-           id = _DESCRIPTORS$z.id,
 
-           parser = _DESCRIPTORS$z.parser;
 
-       if (tag === id) {
 
-         results.push(parser(bytes.subarray(headerSize, headerSize + size)));
 
-         break;
 
-       }
 
-     }
 
-     i += size + headerSize;
 
-   }
 
-   return results;
 
- };
 
- exports.parseDescriptors = parseDescriptors;
 
- DESCRIPTORS = [{
 
-   id: 0x03,
 
-   parser: function parser(bytes) {
 
-     var desc = {
 
-       tag: 0x03,
 
-       id: bytes[0] << 8 | bytes[1],
 
-       flags: bytes[2],
 
-       size: 3,
 
-       dependsOnEsId: 0,
 
-       ocrEsId: 0,
 
-       descriptors: [],
 
-       url: ''
 
-     }; // depends on es id
 
-     if (desc.flags & 0x80) {
 
-       desc.dependsOnEsId = bytes[desc.size] << 8 | bytes[desc.size + 1];
 
-       desc.size += 2;
 
-     } // url
 
-     if (desc.flags & 0x40) {
 
-       var len = bytes[desc.size];
 
-       desc.url = (0, _byteHelpers.bytesToString)(bytes.subarray(desc.size + 1, desc.size + 1 + len));
 
-       desc.size += len;
 
-     } // ocr es id
 
-     if (desc.flags & 0x20) {
 
-       desc.ocrEsId = bytes[desc.size] << 8 | bytes[desc.size + 1];
 
-       desc.size += 2;
 
-     }
 
-     desc.descriptors = parseDescriptors(bytes.subarray(desc.size)) || [];
 
-     return desc;
 
-   }
 
- }, {
 
-   id: 0x04,
 
-   parser: function parser(bytes) {
 
-     // DecoderConfigDescriptor
 
-     var desc = {
 
-       tag: 0x04,
 
-       oti: bytes[0],
 
-       streamType: bytes[1],
 
-       bufferSize: bytes[2] << 16 | bytes[3] << 8 | bytes[4],
 
-       maxBitrate: bytes[5] << 24 | bytes[6] << 16 | bytes[7] << 8 | bytes[8],
 
-       avgBitrate: bytes[9] << 24 | bytes[10] << 16 | bytes[11] << 8 | bytes[12],
 
-       descriptors: parseDescriptors(bytes.subarray(13))
 
-     };
 
-     return desc;
 
-   }
 
- }, {
 
-   id: 0x05,
 
-   parser: function parser(bytes) {
 
-     // DecoderSpecificInfo
 
-     return {
 
-       tag: 0x05,
 
-       bytes: bytes
 
-     };
 
-   }
 
- }, {
 
-   id: 0x06,
 
-   parser: function parser(bytes) {
 
-     // SLConfigDescriptor
 
-     return {
 
-       tag: 0x06,
 
-       bytes: bytes
 
-     };
 
-   }
 
- }];
 
- /**
 
-  * find any number of boxes by name given a path to it in an iso bmff
 
-  * such as mp4.
 
-  *
 
-  * @param {TypedArray} bytes
 
-  *        bytes for the iso bmff to search for boxes in
 
-  *
 
-  * @param {Uint8Array[]|string[]|string|Uint8Array} name
 
-  *        An array of paths or a single path representing the name
 
-  *        of boxes to search through in bytes. Paths may be
 
-  *        uint8 (character codes) or strings.
 
-  *
 
-  * @param {boolean} [complete=false]
 
-  *        Should we search only for complete boxes on the final path.
 
-  *        This is very useful when you do not want to get back partial boxes
 
-  *        in the case of streaming files.
 
-  *
 
-  * @return {Uint8Array[]}
 
-  *         An array of the end paths that we found.
 
-  */
 
- var findBox = function findBox(bytes, paths, complete) {
 
-   if (complete === void 0) {
 
-     complete = false;
 
-   }
 
-   paths = normalizePaths(paths);
 
-   bytes = (0, _byteHelpers.toUint8)(bytes);
 
-   var results = [];
 
-   if (!paths.length) {
 
-     // short-circuit the search for empty paths
 
-     return results;
 
-   }
 
-   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 = bytes.subarray(i + 4, i + 8); // invalid box format.
 
-     if (size === 0) {
 
-       break;
 
-     }
 
-     var end = i + size;
 
-     if (end > bytes.length) {
 
-       // this box is bigger than the number of bytes we have
 
-       // and complete is set, we cannot find any more boxes.
 
-       if (complete) {
 
-         break;
 
-       }
 
-       end = bytes.length;
 
-     }
 
-     var data = bytes.subarray(i + 8, end);
 
-     if ((0, _byteHelpers.bytesMatch)(type, paths[0])) {
 
-       if (paths.length === 1) {
 
-         // this is the end of the path and we've found the box we were
 
-         // looking for
 
-         results.push(data);
 
-       } else {
 
-         // recursively search for the next box along the path
 
-         results.push.apply(results, findBox(data, paths.slice(1), complete));
 
-       }
 
-     }
 
-     i = end;
 
-   } // we've finished searching all of bytes
 
-   return results;
 
- };
 
- /**
 
-  * Search for a single matching box by name in an iso bmff format like
 
-  * mp4. This function is useful for finding codec boxes which
 
-  * can be placed arbitrarily in sample descriptions depending
 
-  * on the version of the file or file type.
 
-  *
 
-  * @param {TypedArray} bytes
 
-  *        bytes for the iso bmff to search for boxes in
 
-  *
 
-  * @param {string|Uint8Array} name
 
-  *        The name of the box to find.
 
-  *
 
-  * @return {Uint8Array[]}
 
-  *         a subarray of bytes representing the name boxed we found.
 
-  */
 
- exports.findBox = findBox;
 
- var findNamedBox = function findNamedBox(bytes, name) {
 
-   name = normalizePath(name);
 
-   if (!name.length) {
 
-     // short-circuit the search for empty paths
 
-     return bytes.subarray(bytes.length);
 
-   }
 
-   var i = 0;
 
-   while (i < bytes.length) {
 
-     if ((0, _byteHelpers.bytesMatch)(bytes.subarray(i, i + name.length), name)) {
 
-       var size = (bytes[i - 4] << 24 | bytes[i - 3] << 16 | bytes[i - 2] << 8 | bytes[i - 1]) >>> 0;
 
-       var end = size > 1 ? i + size : bytes.byteLength;
 
-       return bytes.subarray(i + 4, end);
 
-     }
 
-     i++;
 
-   } // we've finished searching all of bytes
 
-   return bytes.subarray(bytes.length);
 
- };
 
- exports.findNamedBox = findNamedBox;
 
- var parseSamples = function parseSamples(data, entrySize, parseEntry) {
 
-   if (entrySize === void 0) {
 
-     entrySize = 4;
 
-   }
 
-   if (parseEntry === void 0) {
 
-     parseEntry = function parseEntry(d) {
 
-       return (0, _byteHelpers.bytesToNumber)(d);
 
-     };
 
-   }
 
-   var entries = [];
 
-   if (!data || !data.length) {
 
-     return entries;
 
-   }
 
-   var entryCount = (0, _byteHelpers.bytesToNumber)(data.subarray(4, 8));
 
-   for (var i = 8; entryCount; i += entrySize, entryCount--) {
 
-     entries.push(parseEntry(data.subarray(i, i + entrySize)));
 
-   }
 
-   return entries;
 
- };
 
- var buildFrameTable = function buildFrameTable(stbl, timescale) {
 
-   var keySamples = parseSamples(findBox(stbl, ['stss'])[0]);
 
-   var chunkOffsets = parseSamples(findBox(stbl, ['stco'])[0]);
 
-   var timeToSamples = parseSamples(findBox(stbl, ['stts'])[0], 8, function (entry) {
 
-     return {
 
-       sampleCount: (0, _byteHelpers.bytesToNumber)(entry.subarray(0, 4)),
 
-       sampleDelta: (0, _byteHelpers.bytesToNumber)(entry.subarray(4, 8))
 
-     };
 
-   });
 
-   var samplesToChunks = parseSamples(findBox(stbl, ['stsc'])[0], 12, function (entry) {
 
-     return {
 
-       firstChunk: (0, _byteHelpers.bytesToNumber)(entry.subarray(0, 4)),
 
-       samplesPerChunk: (0, _byteHelpers.bytesToNumber)(entry.subarray(4, 8)),
 
-       sampleDescriptionIndex: (0, _byteHelpers.bytesToNumber)(entry.subarray(8, 12))
 
-     };
 
-   });
 
-   var stsz = findBox(stbl, ['stsz'])[0]; // stsz starts with a 4 byte sampleSize which we don't need
 
-   var sampleSizes = parseSamples(stsz && stsz.length && stsz.subarray(4) || null);
 
-   var frames = [];
 
-   for (var chunkIndex = 0; chunkIndex < chunkOffsets.length; chunkIndex++) {
 
-     var samplesInChunk = void 0;
 
-     for (var i = 0; i < samplesToChunks.length; i++) {
 
-       var sampleToChunk = samplesToChunks[i];
 
-       var isThisOne = chunkIndex + 1 >= sampleToChunk.firstChunk && (i + 1 >= samplesToChunks.length || chunkIndex + 1 < samplesToChunks[i + 1].firstChunk);
 
-       if (isThisOne) {
 
-         samplesInChunk = sampleToChunk.samplesPerChunk;
 
-         break;
 
-       }
 
-     }
 
-     var chunkOffset = chunkOffsets[chunkIndex];
 
-     for (var _i = 0; _i < samplesInChunk; _i++) {
 
-       var frameEnd = sampleSizes[frames.length]; // if we don't have key samples every frame is a keyframe
 
-       var keyframe = !keySamples.length;
 
-       if (keySamples.length && keySamples.indexOf(frames.length + 1) !== -1) {
 
-         keyframe = true;
 
-       }
 
-       var frame = {
 
-         keyframe: keyframe,
 
-         start: chunkOffset,
 
-         end: chunkOffset + frameEnd
 
-       };
 
-       for (var k = 0; k < timeToSamples.length; k++) {
 
-         var _timeToSamples$k = timeToSamples[k],
 
-             sampleCount = _timeToSamples$k.sampleCount,
 
-             sampleDelta = _timeToSamples$k.sampleDelta;
 
-         if (frames.length <= sampleCount) {
 
-           // ms to ns
 
-           var lastTimestamp = frames.length ? frames[frames.length - 1].timestamp : 0;
 
-           frame.timestamp = lastTimestamp + sampleDelta / timescale * 1000;
 
-           frame.duration = sampleDelta;
 
-           break;
 
-         }
 
-       }
 
-       frames.push(frame);
 
-       chunkOffset += frameEnd;
 
-     }
 
-   }
 
-   return frames;
 
- };
 
- exports.buildFrameTable = buildFrameTable;
 
- var addSampleDescription = function addSampleDescription(track, bytes) {
 
-   var codec = (0, _byteHelpers.bytesToString)(bytes.subarray(0, 4));
 
-   if (track.type === 'video') {
 
-     track.info = track.info || {};
 
-     track.info.width = bytes[28] << 8 | bytes[29];
 
-     track.info.height = bytes[30] << 8 | bytes[31];
 
-   } else if (track.type === 'audio') {
 
-     track.info = track.info || {};
 
-     track.info.channels = bytes[20] << 8 | bytes[21];
 
-     track.info.bitDepth = bytes[22] << 8 | bytes[23];
 
-     track.info.sampleRate = bytes[28] << 8 | bytes[29];
 
-   }
 
-   if (codec === 'avc1') {
 
-     var avcC = findNamedBox(bytes, 'avcC'); // AVCDecoderConfigurationRecord
 
-     codec += "." + (0, _codecHelpers.getAvcCodec)(avcC);
 
-     track.info.avcC = avcC; // TODO: do we need to parse all this?
 
-     /* {
 
-       configurationVersion: avcC[0],
 
-       profile: avcC[1],
 
-       profileCompatibility: avcC[2],
 
-       level: avcC[3],
 
-       lengthSizeMinusOne: avcC[4] & 0x3
 
-     };
 
-      let spsNalUnitCount = avcC[5] & 0x1F;
 
-     const spsNalUnits = track.info.avc.spsNalUnits = [];
 
-      // past spsNalUnitCount
 
-     let offset = 6;
 
-      while (spsNalUnitCount--) {
 
-       const nalLen = avcC[offset] << 8 | avcC[offset + 1];
 
-        spsNalUnits.push(avcC.subarray(offset + 2, offset + 2 + nalLen));
 
-        offset += nalLen + 2;
 
-     }
 
-     let ppsNalUnitCount = avcC[offset];
 
-     const ppsNalUnits = track.info.avc.ppsNalUnits = [];
 
-      // past ppsNalUnitCount
 
-     offset += 1;
 
-      while (ppsNalUnitCount--) {
 
-       const nalLen = avcC[offset] << 8 | avcC[offset + 1];
 
-        ppsNalUnits.push(avcC.subarray(offset + 2, offset + 2 + nalLen));
 
-        offset += nalLen + 2;
 
-     }*/
 
-     // HEVCDecoderConfigurationRecord
 
-   } else if (codec === 'hvc1' || codec === 'hev1') {
 
-     codec += "." + (0, _codecHelpers.getHvcCodec)(findNamedBox(bytes, 'hvcC'));
 
-   } else if (codec === 'mp4a' || codec === 'mp4v') {
 
-     var esds = findNamedBox(bytes, 'esds');
 
-     var esDescriptor = parseDescriptors(esds.subarray(4))[0];
 
-     var decoderConfig = esDescriptor && esDescriptor.descriptors.filter(function (_ref) {
 
-       var tag = _ref.tag;
 
-       return tag === 0x04;
 
-     })[0];
 
-     if (decoderConfig) {
 
-       // most codecs do not have a further '.'
 
-       // such as 0xa5 for ac-3 and 0xa6 for e-ac-3
 
-       codec += '.' + (0, _byteHelpers.toHexString)(decoderConfig.oti);
 
-       if (decoderConfig.oti === 0x40) {
 
-         codec += '.' + (decoderConfig.descriptors[0].bytes[0] >> 3).toString();
 
-       } else if (decoderConfig.oti === 0x20) {
 
-         codec += '.' + decoderConfig.descriptors[0].bytes[4].toString();
 
-       } else if (decoderConfig.oti === 0xdd) {
 
-         codec = 'vorbis';
 
-       }
 
-     } else if (track.type === 'audio') {
 
-       codec += '.40.2';
 
-     } else {
 
-       codec += '.20.9';
 
-     }
 
-   } else if (codec === 'av01') {
 
-     // AV1DecoderConfigurationRecord
 
-     codec += "." + (0, _codecHelpers.getAv1Codec)(findNamedBox(bytes, 'av1C'));
 
-   } else if (codec === 'vp09') {
 
-     // VPCodecConfigurationRecord
 
-     var vpcC = findNamedBox(bytes, 'vpcC'); // https://www.webmproject.org/vp9/mp4/
 
-     var profile = vpcC[0];
 
-     var level = vpcC[1];
 
-     var bitDepth = vpcC[2] >> 4;
 
-     var chromaSubsampling = (vpcC[2] & 0x0F) >> 1;
 
-     var videoFullRangeFlag = (vpcC[2] & 0x0F) >> 3;
 
-     var colourPrimaries = vpcC[3];
 
-     var transferCharacteristics = vpcC[4];
 
-     var matrixCoefficients = vpcC[5];
 
-     codec += "." + (0, _byteHelpers.padStart)(profile, 2, '0');
 
-     codec += "." + (0, _byteHelpers.padStart)(level, 2, '0');
 
-     codec += "." + (0, _byteHelpers.padStart)(bitDepth, 2, '0');
 
-     codec += "." + (0, _byteHelpers.padStart)(chromaSubsampling, 2, '0');
 
-     codec += "." + (0, _byteHelpers.padStart)(colourPrimaries, 2, '0');
 
-     codec += "." + (0, _byteHelpers.padStart)(transferCharacteristics, 2, '0');
 
-     codec += "." + (0, _byteHelpers.padStart)(matrixCoefficients, 2, '0');
 
-     codec += "." + (0, _byteHelpers.padStart)(videoFullRangeFlag, 2, '0');
 
-   } else if (codec === 'theo') {
 
-     codec = 'theora';
 
-   } else if (codec === 'spex') {
 
-     codec = 'speex';
 
-   } else if (codec === '.mp3') {
 
-     codec = 'mp4a.40.34';
 
-   } else if (codec === 'msVo') {
 
-     codec = 'vorbis';
 
-   } else if (codec === 'Opus') {
 
-     codec = 'opus';
 
-     var dOps = findNamedBox(bytes, 'dOps');
 
-     track.info.opus = (0, _opusHelpers.parseOpusHead)(dOps); // TODO: should this go into the webm code??
 
-     // Firefox requires a codecDelay for opus playback
 
-     // see https://bugzilla.mozilla.org/show_bug.cgi?id=1276238
 
-     track.info.codecDelay = 6500000;
 
-   } else {
 
-     codec = codec.toLowerCase();
 
-   }
 
-   /* eslint-enable */
 
-   // flac, ac-3, ec-3, opus
 
-   track.codec = codec;
 
- };
 
- exports.addSampleDescription = addSampleDescription;
 
- var parseTracks = function parseTracks(bytes, frameTable) {
 
-   if (frameTable === void 0) {
 
-     frameTable = true;
 
-   }
 
-   bytes = (0, _byteHelpers.toUint8)(bytes);
 
-   var traks = findBox(bytes, ['moov', 'trak'], true);
 
-   var tracks = [];
 
-   traks.forEach(function (trak) {
 
-     var track = {
 
-       bytes: trak
 
-     };
 
-     var mdia = findBox(trak, ['mdia'])[0];
 
-     var hdlr = findBox(mdia, ['hdlr'])[0];
 
-     var trakType = (0, _byteHelpers.bytesToString)(hdlr.subarray(8, 12));
 
-     if (trakType === 'soun') {
 
-       track.type = 'audio';
 
-     } else if (trakType === 'vide') {
 
-       track.type = 'video';
 
-     } else {
 
-       track.type = trakType;
 
-     }
 
-     var tkhd = findBox(trak, ['tkhd'])[0];
 
-     if (tkhd) {
 
-       var view = new DataView(tkhd.buffer, tkhd.byteOffset, tkhd.byteLength);
 
-       var tkhdVersion = view.getUint8(0);
 
-       track.number = tkhdVersion === 0 ? view.getUint32(12) : view.getUint32(20);
 
-     }
 
-     var mdhd = findBox(mdia, ['mdhd'])[0];
 
-     if (mdhd) {
 
-       // mdhd is a FullBox, meaning it will have its own version as the first byte
 
-       var version = mdhd[0];
 
-       var index = version === 0 ? 12 : 20;
 
-       track.timescale = (mdhd[index] << 24 | mdhd[index + 1] << 16 | mdhd[index + 2] << 8 | mdhd[index + 3]) >>> 0;
 
-     }
 
-     var stbl = findBox(mdia, ['minf', 'stbl'])[0];
 
-     var stsd = findBox(stbl, ['stsd'])[0];
 
-     var descriptionCount = (0, _byteHelpers.bytesToNumber)(stsd.subarray(4, 8));
 
-     var offset = 8; // add codec and codec info
 
-     while (descriptionCount--) {
 
-       var len = (0, _byteHelpers.bytesToNumber)(stsd.subarray(offset, offset + 4));
 
-       var sampleDescriptor = stsd.subarray(offset + 4, offset + 4 + len);
 
-       addSampleDescription(track, sampleDescriptor);
 
-       offset += 4 + len;
 
-     }
 
-     if (frameTable) {
 
-       track.frameTable = buildFrameTable(stbl, track.timescale);
 
-     } // codec has no sub parameters
 
-     tracks.push(track);
 
-   });
 
-   return tracks;
 
- };
 
- exports.parseTracks = parseTracks;
 
- var parseMediaInfo = function parseMediaInfo(bytes) {
 
-   var mvhd = findBox(bytes, ['moov', 'mvhd'], true)[0];
 
-   if (!mvhd || !mvhd.length) {
 
-     return;
 
-   }
 
-   var info = {}; // ms to ns
 
-   // mvhd v1 has 8 byte duration and other fields too
 
-   if (mvhd[0] === 1) {
 
-     info.timestampScale = (0, _byteHelpers.bytesToNumber)(mvhd.subarray(20, 24));
 
-     info.duration = (0, _byteHelpers.bytesToNumber)(mvhd.subarray(24, 32));
 
-   } else {
 
-     info.timestampScale = (0, _byteHelpers.bytesToNumber)(mvhd.subarray(12, 16));
 
-     info.duration = (0, _byteHelpers.bytesToNumber)(mvhd.subarray(16, 20));
 
-   }
 
-   info.bytes = mvhd;
 
-   return info;
 
- };
 
- exports.parseMediaInfo = parseMediaInfo;
 
 
  |