UNPKG

dashjs

Version:

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

53 lines (52 loc) 10.2 kB
'use strict';Object.defineProperty(exports,"__esModule",{value:true});var _XHRLoader=require('./XHRLoader');var _XHRLoader2=_interopRequireDefault(_XHRLoader);var _FetchLoader=require('./FetchLoader');var _FetchLoader2=_interopRequireDefault(_FetchLoader);var _HTTPRequest=require('../vo/metrics/HTTPRequest');var _FactoryMaker=require('../../core/FactoryMaker');var _FactoryMaker2=_interopRequireDefault(_FactoryMaker);var _Errors=require('../../core/errors/Errors');var _Errors2=_interopRequireDefault(_Errors);var _DashJSError=require('../vo/DashJSError');var _DashJSError2=_interopRequireDefault(_DashJSError);function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj};}function _defineProperty(obj,key,value){if(key in obj){Object.defineProperty(obj,key,{value:value,enumerable:true,configurable:true,writable:true});}else{obj[key]=value;}return obj;}/** * 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. *//** * @module HTTPLoader * @ignore * @description Manages download of resources via HTTP. * @param {Object} cfg - dependancies from parent */function HTTPLoader(cfg){cfg=cfg||{};var context=this.context;var errHandler=cfg.errHandler;var dashMetrics=cfg.dashMetrics;var mediaPlayerModel=cfg.mediaPlayerModel;var requestModifier=cfg.requestModifier;var boxParser=cfg.boxParser;var useFetch=cfg.useFetch||false;var instance=void 0,requests=void 0,delayedRequests=void 0,retryRequests=void 0,downloadErrorToRequestTypeMap=void 0;function setup(){var _downloadErrorToReque;requests=[];delayedRequests=[];retryRequests=[];downloadErrorToRequestTypeMap=(_downloadErrorToReque={},_defineProperty(_downloadErrorToReque,_HTTPRequest.HTTPRequest.MPD_TYPE,_Errors2.default.DOWNLOAD_ERROR_ID_MANIFEST_CODE),_defineProperty(_downloadErrorToReque,_HTTPRequest.HTTPRequest.XLINK_EXPANSION_TYPE,_Errors2.default.DOWNLOAD_ERROR_ID_XLINK_CODE),_defineProperty(_downloadErrorToReque,_HTTPRequest.HTTPRequest.INIT_SEGMENT_TYPE,_Errors2.default.DOWNLOAD_ERROR_ID_INITIALIZATION_CODE),_defineProperty(_downloadErrorToReque,_HTTPRequest.HTTPRequest.MEDIA_SEGMENT_TYPE,_Errors2.default.DOWNLOAD_ERROR_ID_CONTENT_CODE),_defineProperty(_downloadErrorToReque,_HTTPRequest.HTTPRequest.INDEX_SEGMENT_TYPE,_Errors2.default.DOWNLOAD_ERROR_ID_CONTENT_CODE),_defineProperty(_downloadErrorToReque,_HTTPRequest.HTTPRequest.BITSTREAM_SWITCHING_SEGMENT_TYPE,_Errors2.default.DOWNLOAD_ERROR_ID_CONTENT_CODE),_defineProperty(_downloadErrorToReque,_HTTPRequest.HTTPRequest.OTHER_TYPE,_Errors2.default.DOWNLOAD_ERROR_ID_CONTENT_CODE),_downloadErrorToReque);}function internalLoad(config,remainingAttempts){var request=config.request;var traces=[];var firstProgress=true;var needFailureReport=true;var requestStartTime=new Date();var lastTraceTime=requestStartTime;var lastTraceReceivedCount=0;var httpRequest=void 0;if(!requestModifier||!dashMetrics||!errHandler){throw new Error('config object is not correct or missing');}var handleLoaded=function handleLoaded(success){needFailureReport=false;request.requestStartDate=requestStartTime;request.requestEndDate=new Date();request.firstByteDate=request.firstByteDate||requestStartTime;if(!request.checkExistenceOnly){dashMetrics.addHttpRequest(request,httpRequest.response?httpRequest.response.responseURL:null,httpRequest.response?httpRequest.response.status:null,httpRequest.response&&httpRequest.response.getAllResponseHeaders?httpRequest.response.getAllResponseHeaders():httpRequest.response?httpRequest.response.responseHeaders:[],success?traces:null);if(request.type===_HTTPRequest.HTTPRequest.MPD_TYPE){dashMetrics.addManifestUpdate(request.type,request.requestStartDate,request.requestEndDate);}}};var onloadend=function onloadend(){if(requests.indexOf(httpRequest)===-1){return;}else{requests.splice(requests.indexOf(httpRequest),1);}if(needFailureReport){handleLoaded(false);if(remainingAttempts>0){remainingAttempts--;var retryRequest={config:config};retryRequests.push(retryRequest);retryRequest.timeout=setTimeout(function(){if(retryRequests.indexOf(retryRequest)===-1){return;}else{retryRequests.splice(retryRequests.indexOf(retryRequest),1);}internalLoad(config,remainingAttempts);},mediaPlayerModel.getRetryIntervalsForType(request.type));}else{errHandler.error(new _DashJSError2.default(downloadErrorToRequestTypeMap[request.type],request.url+' is not available',{request:request,response:httpRequest.response}));if(config.error){config.error(request,'error',httpRequest.response.statusText);}if(config.complete){config.complete(request,httpRequest.response.statusText);}}}};var progress=function progress(event){var currentTime=new Date();if(firstProgress){firstProgress=false;if(!event.lengthComputable||event.lengthComputable&&event.total!==event.loaded){request.firstByteDate=currentTime;}}if(event.lengthComputable){request.bytesLoaded=event.loaded;request.bytesTotal=event.total;}if(!event.noTrace){traces.push({s:lastTraceTime,d:event.time?event.time:currentTime.getTime()-lastTraceTime.getTime(),b:[event.loaded?event.loaded-lastTraceReceivedCount:0]});lastTraceTime=currentTime;lastTraceReceivedCount=event.loaded;}if(config.progress&&event){config.progress(event);}};var onload=function onload(){if(httpRequest.response.status>=200&&httpRequest.response.status<=299){handleLoaded(true);if(config.success){config.success(httpRequest.response.response,httpRequest.response.statusText,httpRequest.response.responseURL);}if(config.complete){config.complete(request,httpRequest.response.statusText);}}};var onabort=function onabort(){if(config.abort){config.abort(request);}};var loader=void 0;if(useFetch&&window.fetch&&request.responseType==='arraybuffer'&&request.type===_HTTPRequest.HTTPRequest.MEDIA_SEGMENT_TYPE){loader=(0,_FetchLoader2.default)(context).create({requestModifier:requestModifier,boxParser:boxParser});}else{loader=(0,_XHRLoader2.default)(context).create({requestModifier:requestModifier});}var modifiedUrl=requestModifier.modifyRequestURL(request.url);var verb=request.checkExistenceOnly?_HTTPRequest.HTTPRequest.HEAD:_HTTPRequest.HTTPRequest.GET;var withCredentials=mediaPlayerModel.getXHRWithCredentialsForType(request.type);httpRequest={url:modifiedUrl,method:verb,withCredentials:withCredentials,request:request,onload:onload,onend:onloadend,onerror:onloadend,progress:progress,onabort:onabort,loader:loader};// Adds the ability to delay single fragment loading time to control buffer. var now=new Date().getTime();if(isNaN(request.delayLoadingTime)||now>=request.delayLoadingTime){// no delay - just send requests.push(httpRequest);loader.load(httpRequest);}else{// delay var delayedRequest={httpRequest:httpRequest};delayedRequests.push(delayedRequest);delayedRequest.delayTimeout=setTimeout(function(){if(delayedRequests.indexOf(delayedRequest)===-1){return;}else{delayedRequests.splice(delayedRequests.indexOf(delayedRequest),1);}try{requestStartTime=new Date();lastTraceTime=requestStartTime;requests.push(delayedRequest.httpRequest);loader.load(delayedRequest.httpRequest);}catch(e){delayedRequest.httpRequest.onerror();}},request.delayLoadingTime-now);}}/** * Initiates a download of the resource described by config.request * @param {Object} config - contains request (FragmentRequest or derived type), and callbacks * @memberof module:HTTPLoader * @instance */function load(config){if(config.request){internalLoad(config,mediaPlayerModel.getRetryAttemptsForType(config.request.type));}else{if(config.error){config.error(config.request,'error');}}}/** * Aborts any inflight downloads * @memberof module:HTTPLoader * @instance */function abort(){retryRequests.forEach(function(t){clearTimeout(t.timeout);// abort request in order to trigger LOADING_ABANDONED event if(t.config.request&&t.config.abort){t.config.abort(t.config.request);}});retryRequests=[];delayedRequests.forEach(function(x){return clearTimeout(x.delayTimeout);});delayedRequests=[];requests.forEach(function(x){// abort will trigger onloadend which we don't want // when deliberately aborting inflight requests - // set them to undefined so they are not called x.onloadend=x.onerror=x.onprogress=undefined;x.loader.abort(x);x.onabort();});requests=[];}instance={load:load,abort:abort};setup();return instance;}HTTPLoader.__dashjs_factory_name='HTTPLoader';var factory=_FactoryMaker2.default.getClassFactory(HTTPLoader);exports.default=factory; //# sourceMappingURL=HTTPLoader.js.map