UNPKG

dashjs

Version:

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

192 lines (165 loc) 7.7 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 MSSFragmentMoofProcessor from './MssFragmentMoofProcessor'; import MSSFragmentMoovProcessor from './MssFragmentMoovProcessor'; import MssEvents from './MssEvents'; // Add specific box processors not provided by codem-isoboxer library function arrayEqual(arr1, arr2) { return (arr1.length === arr2.length) && arr1.every(function (element, index) { return element === arr2[index]; }); } function saioProcessor() { this._procFullBox(); if (this.flags & 1) { this._procField('aux_info_type', 'uint', 32); this._procField('aux_info_type_parameter', 'uint', 32); } this._procField('entry_count', 'uint', 32); this._procFieldArray('offset', this.entry_count, 'uint', (this.version === 1) ? 64 : 32); } function saizProcessor() { this._procFullBox(); if (this.flags & 1) { this._procField('aux_info_type', 'uint', 32); this._procField('aux_info_type_parameter', 'uint', 32); } this._procField('default_sample_info_size', 'uint', 8); this._procField('sample_count', 'uint', 32); if (this.default_sample_info_size === 0) { this._procFieldArray('sample_info_size', this.sample_count, 'uint', 8); } } function sencProcessor() { this._procFullBox(); this._procField('sample_count', 'uint', 32); if (this.flags & 1) { this._procField('IV_size', 'uint', 8); } this._procEntries('entry', this.sample_count, function (entry) { this._procEntryField(entry, 'InitializationVector', 'data', 8); if (this.flags & 2) { this._procEntryField(entry, 'NumberOfEntries', 'uint', 16); this._procSubEntries(entry, 'clearAndCryptedData', entry.NumberOfEntries, function (clearAndCryptedData) { this._procEntryField(clearAndCryptedData, 'BytesOfClearData', 'uint', 16); this._procEntryField(clearAndCryptedData, 'BytesOfEncryptedData', 'uint', 32); }); } }); } function uuidProcessor() { let tfxdUserType = [0x6D, 0x1D, 0x9B, 0x05, 0x42, 0xD5, 0x44, 0xE6, 0x80, 0xE2, 0x14, 0x1D, 0xAF, 0xF7, 0x57, 0xB2]; let tfrfUserType = [0xD4, 0x80, 0x7E, 0xF2, 0xCA, 0x39, 0x46, 0x95, 0x8E, 0x54, 0x26, 0xCB, 0x9E, 0x46, 0xA7, 0x9F]; let sepiffUserType = [0xA2, 0x39, 0x4F, 0x52, 0x5A, 0x9B, 0x4f, 0x14, 0xA2, 0x44, 0x6C, 0x42, 0x7C, 0x64, 0x8D, 0xF4]; if (arrayEqual(this.usertype, tfxdUserType)) { this._procFullBox(); if (this._parsing) { this.type = 'tfxd'; } this._procField('fragment_absolute_time', 'uint', (this.version === 1) ? 64 : 32); this._procField('fragment_duration', 'uint', (this.version === 1) ? 64 : 32); } if (arrayEqual(this.usertype, tfrfUserType)) { this._procFullBox(); if (this._parsing) { this.type = 'tfrf'; } this._procField('fragment_count', 'uint', 8); this._procEntries('entry', this.fragment_count, function (entry) { this._procEntryField(entry, 'fragment_absolute_time', 'uint', (this.version === 1) ? 64 : 32); this._procEntryField(entry, 'fragment_duration', 'uint', (this.version === 1) ? 64 : 32); }); } if (arrayEqual(this.usertype, sepiffUserType)) { if (this._parsing) { this.type = 'sepiff'; } sencProcessor.call(this); } } function MssFragmentProcessor(config) { config = config || {}; const context = this.context; const dashMetrics = config.dashMetrics; const playbackController = config.playbackController; const eventBus = config.eventBus; const protectionController = config.protectionController; const ISOBoxer = config.ISOBoxer; const debug = config.debug; let mssFragmentMoovProcessor, mssFragmentMoofProcessor, instance; function setup() { ISOBoxer.addBoxProcessor('uuid', uuidProcessor); ISOBoxer.addBoxProcessor('saio', saioProcessor); ISOBoxer.addBoxProcessor('saiz', saizProcessor); ISOBoxer.addBoxProcessor('senc', sencProcessor); mssFragmentMoovProcessor = MSSFragmentMoovProcessor(context).create({protectionController: protectionController, constants: config.constants, ISOBoxer: ISOBoxer}); mssFragmentMoofProcessor = MSSFragmentMoofProcessor(context).create({ dashMetrics: dashMetrics, playbackController: playbackController, ISOBoxer: ISOBoxer, eventBus: eventBus, debug: debug, errHandler: config.errHandler }); } function generateMoov(rep) { return mssFragmentMoovProcessor.generateMoov(rep); } function processFragment(e, sp) { if (!e || !e.request || !e.response) { throw new Error('e parameter is missing or malformed'); } let request = e.request; if (request.type === 'MediaSegment') { // it's a MediaSegment, let's convert fragment mssFragmentMoofProcessor.convertFragment(e, sp); } else if (request.type === 'FragmentInfoSegment') { // it's a FragmentInfo, ask relative fragment info controller to handle it eventBus.trigger(MssEvents.FRAGMENT_INFO_LOADING_COMPLETED, { fragmentInfo: e, streamProcessor: sp }); // Change the sender value to stop event to be propagated (fragment info must not be added to buffer) e.sender = null; } } instance = { generateMoov: generateMoov, processFragment: processFragment }; setup(); return instance; } MssFragmentProcessor.__dashjs_factory_name = 'MssFragmentProcessor'; export default dashjs.FactoryMaker.getClassFactory(MssFragmentProcessor); /* jshint ignore:line */