UNPKG

@l5i/dashjs

Version:

A reference client implementation for the playback of MPEG DASH via Javascript and compliant browsers.

163 lines (145 loc) 7.18 kB
/** * The copyright in this software is being made available under the BSD License, * included below. This software may be subject to other third party and contributor * rights, including patent rights, and no such rights are granted under this license. * * Copyright (c) 2013, Dash Industry Forum. * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * Neither the name of Dash Industry Forum nor the names of its * contributors may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ import FactoryMaker from '../../core/FactoryMaker'; function FragmentedTextBoxParser() { let instance, boxParser; function setConfig(config) { if (!config) return; if (config.boxParser) { boxParser = config.boxParser; } } function getSamplesInfo(ab) { if (!boxParser) { throw new Error('boxParser is undefined'); } if (!ab || ab.byteLength === 0) { return {sampleList: [], lastSequenceNumber: NaN, totalDuration: NaN, numSequences: NaN}; } let isoFile = boxParser.parse(ab); // zero or more moofs let moofBoxes = isoFile.getBoxes('moof'); // exactly one mfhd per moof let mfhdBoxes = isoFile.getBoxes('mfhd'); let sampleDuration, sampleCompositionTimeOffset, sampleCount, sampleSize, sampleDts, sampleList, sample, i, j, k, l, m, n, dataOffset, lastSequenceNumber, numSequences, totalDuration; numSequences = isoFile.getBoxes('moof').length; lastSequenceNumber = mfhdBoxes[mfhdBoxes.length - 1].sequence_number; sampleCount = 0; sampleList = []; let subsIndex = -1; let nextSubsSample = -1; for (l = 0; l < moofBoxes.length; l++) { let moofBox = moofBoxes[l]; // zero or more trafs per moof let trafBoxes = moofBox.getChildBoxes('traf'); for (j = 0; j < trafBoxes.length; j++) { let trafBox = trafBoxes[j]; // exactly one tfhd per traf let tfhdBox = trafBox.getChildBox('tfhd'); // zero or one tfdt per traf let tfdtBox = trafBox.getChildBox('tfdt'); sampleDts = tfdtBox.baseMediaDecodeTime; // zero or more truns per traf let trunBoxes = trafBox.getChildBoxes('trun'); // zero or more subs per traf let subsBoxes = trafBox.getChildBoxes('subs'); for (k = 0; k < trunBoxes.length; k++) { let trunBox = trunBoxes[k]; sampleCount = trunBox.sample_count; dataOffset = (tfhdBox.base_data_offset || 0) + (trunBox.data_offset || 0); for (i = 0; i < sampleCount; i++) { sample = trunBox.samples[i]; sampleDuration = (sample.sample_duration !== undefined) ? sample.sample_duration : tfhdBox.default_sample_duration; sampleSize = (sample.sample_size !== undefined) ? sample.sample_size : tfhdBox.default_sample_size; sampleCompositionTimeOffset = (sample.sample_composition_time_offset !== undefined) ? sample.sample_composition_time_offset : 0; let sampleData = { 'dts': sampleDts, 'cts': (sampleDts + sampleCompositionTimeOffset), 'duration': sampleDuration, 'offset': moofBox.offset + dataOffset, 'size': sampleSize, 'subSizes': [sampleSize] }; if (subsBoxes) { for (m = 0; m < subsBoxes.length; m++) { let subsBox = subsBoxes[m]; if (subsIndex < (subsBox.entry_count - 1) && i > nextSubsSample) { subsIndex++; nextSubsSample += subsBox.entries[subsIndex].sample_delta; } if (i == nextSubsSample) { sampleData.subSizes = []; let entry = subsBox.entries[subsIndex]; for (n = 0; n < entry.subsample_count; n++) { sampleData.subSizes.push(entry.subsamples[n].subsample_size); } } } } sampleList.push(sampleData); dataOffset += sampleSize; sampleDts += sampleDuration; } } totalDuration = sampleDts - tfdtBox.baseMediaDecodeTime; } } return {sampleList: sampleList, lastSequenceNumber: lastSequenceNumber, totalDuration: totalDuration, numSequences: numSequences}; } function getMediaTimescaleFromMoov(ab) { if (!boxParser) { throw new Error('boxParser is undefined'); } let isoFile = boxParser.parse(ab); let mdhdBox = isoFile ? isoFile.getBox('mdhd') : undefined; return mdhdBox ? mdhdBox.timescale : NaN; } instance = { getSamplesInfo: getSamplesInfo, getMediaTimescaleFromMoov: getMediaTimescaleFromMoov, setConfig: setConfig }; return instance; } FragmentedTextBoxParser.__dashjs_factory_name = 'FragmentedTextBoxParser'; export default FactoryMaker.getSingletonFactory(FragmentedTextBoxParser);