1 line
13 KiB
JavaScript
1 line
13 KiB
JavaScript
define(["exports","../utils/logger.js","./mp4-generator.js","./aac-silent.js","../../browser.js","../core/media-segment-info.js","../utils/exception.js"],function(_exports,_logger,_mp4Generator,_aacSilent,_browser,_mediaSegmentInfo,_exception){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0;var MP4Remuxer=function(){function MP4Remuxer(config){babelHelpers.classCallCheck(this,MP4Remuxer),this.TAG="MP4Remuxer",this._config=config,this._isLive=!0===config.isLive,this._dtsBase=-1,this._dtsBaseInited=!1,this._audioDtsBase=1/0,this._videoDtsBase=1/0,this._audioNextDts=void 0,this._videoNextDts=void 0,this._audioStashedLastSample=null,this._videoStashedLastSample=null,this._audioMeta=null,this._videoMeta=null,this._audioSegmentInfoList=new _mediaSegmentInfo.MediaSegmentInfoList("audio"),this._videoSegmentInfoList=new _mediaSegmentInfo.MediaSegmentInfoList("video"),this._onInitSegment=null,this._onMediaSegment=null,this._forceFirstIDR=_browser.default.chrome&&((config=navigator.userAgent.match(/Chrome\/(\d+)/i))?parseInt(config[1]):0)<=50,this._fillSilentAfterSeek=_browser.default.edge,this._mp3UseMpegAudio=!_browser.default.firefox,this._fillAudioTimestampGap=this._config.fixAudioTimestampGap}return babelHelpers.createClass(MP4Remuxer,[{key:"destroy",value:function(){this._dtsBase=-1,this._dtsBaseInited=!1,this._audioMeta=null,this._videoMeta=null,this._audioSegmentInfoList.clear(),this._audioSegmentInfoList=null,this._videoSegmentInfoList.clear(),this._videoSegmentInfoList=null,this._onInitSegment=null,this._onMediaSegment=null}},{key:"bindDataSource",value:function(producer){return producer.onDataAvailable=this.remux.bind(this),producer.onTrackMetadata=this._onTrackMetadataReceived.bind(this),this}},{key:"onInitSegment",get:function(){return this._onInitSegment},set:function(callback){this._onInitSegment=callback}},{key:"onMediaSegment",get:function(){return this._onMediaSegment},set:function(callback){this._onMediaSegment=callback}},{key:"insertDiscontinuity",value:function(){this._audioNextDts=this._videoNextDts=void 0}},{key:"seek",value:function(originalDts){this._audioStashedLastSample=null,this._videoStashedLastSample=null,this._videoSegmentInfoList.clear(),this._audioSegmentInfoList.clear()}},{key:"remux",value:function(audioTrack,videoTrack){if(!this._onMediaSegment)throw new _exception.IllegalStateException("MP4Remuxer: onMediaSegment callback must be specificed!");this._dtsBaseInited||this._calculateDtsBase(audioTrack,videoTrack),this._remuxVideo(videoTrack),this._remuxAudio(audioTrack)}},{key:"_onTrackMetadataReceived",value:function(type,metadata){var metabox=null,container="mp4",codec=metadata.codec;if("audio"===type)metabox="mp3"===(this._audioMeta=metadata).codec&&this._mp3UseMpegAudio?(container="mpeg",codec="",new Uint8Array):_mp4Generator.default.initSegment([metadata]);else{if("video"!==type)return;this._videoMeta=metadata,metabox=_mp4Generator.default.initSegment([metadata])}if(!this._onInitSegment)throw new _exception.IllegalStateException("MP4Remuxer: onInitSegment callback must be specified!");this._onInitSegment(type,{type:type,data:metabox.buffer,codec:codec,container:"".concat(type,"/").concat(container),mediaDuration:metadata.duration})}},{key:"_calculateDtsBase",value:function(audioTrack,videoTrack){this._dtsBaseInited||(audioTrack.samples&&audioTrack.samples.length&&(this._audioDtsBase=audioTrack.samples[0].dts),videoTrack.samples&&videoTrack.samples.length&&(this._videoDtsBase=videoTrack.samples[0].dts),this._dtsBase=Math.min(this._audioDtsBase,this._videoDtsBase),this._dtsBaseInited=!0)}},{key:"flushStashedSamples",value:function(){var videoSample=this._videoStashedLastSample,audioSample=this._audioStashedLastSample,videoTrack={type:"video",id:1,sequenceNumber:0,samples:[],length:0},videoSample=(null!=videoSample&&(videoTrack.samples.push(videoSample),videoTrack.length=videoSample.length),{type:"audio",id:2,sequenceNumber:0,samples:[],length:0});null!=audioSample&&(videoSample.samples.push(audioSample),videoSample.length=audioSample.length),this._videoStashedLastSample=null,this._audioStashedLastSample=null,this._remuxVideo(videoTrack,!0),this._remuxAudio(videoSample,!0)}},{key:"_remuxAudio",value:function(audioTrack,force){if(null!=this._audioMeta){var samples=audioTrack.samples,firstDts=-1,refSampleDuration=this._audioMeta.refSampleDuration,mpegRawTrack="mp3"===this._audioMeta.codec&&this._mp3UseMpegAudio,firstSegmentAfterSeek=this._dtsBaseInited&&void 0===this._audioNextDts,insertPrefixSilentFrame=!1;if(samples&&0!==samples.length&&(1!==samples.length||force)){for(var dtsCorrection,offset=0,mdatbox=null,mdatBytes=0,mdatBytes=mpegRawTrack?(offset=0,audioTrack.length):(offset=8)+audioTrack.length,lastSample=null,force=(1<samples.length&&(mdatBytes-=(lastSample=samples.pop()).length),null!=this._audioStashedLastSample&&(force=this._audioStashedLastSample,this._audioStashedLastSample=null,samples.unshift(force),mdatBytes+=force.length),null!=lastSample&&(this._audioStashedLastSample=lastSample),samples[0].dts-this._dtsBase),mp4Samples=(this._audioNextDts?dtsCorrection=force-this._audioNextDts:this._audioSegmentInfoList.isEmpty()?(dtsCorrection=0,this._fillSilentAfterSeek&&!this._videoSegmentInfoList.isEmpty()&&"mp3"!==this._audioMeta.originalCodec&&(insertPrefixSilentFrame=!0)):dtsCorrection=null!=(_lastSample=this._audioSegmentInfoList.getLastSampleBefore(force))?(distance=force-(_lastSample.originalDts+_lastSample.duration),force-(_lastSample.dts+_lastSample.duration+(distance=distance<=3?0:distance))):0,insertPrefixSilentFrame&&(_lastSample=force-dtsCorrection,null!=(distance=this._videoSegmentInfoList.getLastSegmentBefore(force))&&distance.beginDts<_lastSample?(force=_aacSilent.default.getSilentFrame(this._audioMeta.originalCodec,this._audioMeta.channelCount))&&(dts=distance.beginDts,_lastSample=_lastSample-distance.beginDts,_logger.default.v(this.TAG,"InsertPrefixSilentAudio: dts: ".concat(dts,", duration: ").concat(_lastSample)),samples.unshift({unit:force,dts:dts,pts:dts}),mdatBytes+=force.byteLength):insertPrefixSilentFrame=!1),[]),i=0;i<samples.length;i++){var _sample=samples[i],unit=_sample.unit,originalDts=_sample.dts-this._dtsBase,_dts=originalDts-dtsCorrection,sampleDuration=(-1===firstDts&&(firstDts=_dts),0),needFillSilentFrames=!1,silentFrames=null;if(1.5*refSampleDuration<(sampleDuration=i!==samples.length-1?samples[i+1].dts-this._dtsBase-dtsCorrection-_dts:null!=lastSample?lastSample.dts-this._dtsBase-dtsCorrection-_dts:1<=mp4Samples.length?mp4Samples[mp4Samples.length-1].duration:Math.floor(refSampleDuration))&&"mp3"!==this._audioMeta.codec&&this._fillAudioTimestampGap&&!_browser.default.safari){var needFillSilentFrames=!0,delta=Math.abs(sampleDuration-refSampleDuration),frameCount=Math.ceil(delta/refSampleDuration),currentDts=_dts+refSampleDuration,_silentUnit=(_logger.default.w(this.TAG,"Large audio timestamp gap detected, may cause AV sync to drift. Silent frames will be generated to avoid unsync.\n"+"dts: ".concat(_dts+sampleDuration," ms, expected: ").concat(_dts+Math.round(refSampleDuration)," ms, ")+"delta: ".concat(Math.round(delta)," ms, generate: ").concat(frameCount," frames")),_aacSilent.default.getSilentFrame(this._audioMeta.originalCodec,this._audioMeta.channelCount));null==_silentUnit&&(_logger.default.w(this.TAG,"Unable to generate silent frame for "+"".concat(this._audioMeta.originalCodec," with ").concat(this._audioMeta.channelCount," channels, repeat last frame")),_silentUnit=unit);for(var silentFrames=[],j=0;j<frameCount;j++){var intDts=Math.round(currentDts),previousFrame=(0<silentFrames.length&&((previousFrame=silentFrames[silentFrames.length-1]).duration=intDts-previousFrame.dts),{dts:intDts,pts:intDts,cts:0,unit:_silentUnit,size:_silentUnit.byteLength,duration:0,originalDts:originalDts,flags:{isLeading:0,dependsOn:1,isDependedOn:0,hasRedundancy:0}});silentFrames.push(previousFrame),mdatBytes+=previousFrame.size,currentDts+=refSampleDuration}delta=silentFrames[silentFrames.length-1];delta.duration=_dts+sampleDuration-delta.dts,sampleDuration=Math.round(refSampleDuration)}mp4Samples.push({dts:_dts,pts:_dts,cts:0,unit:_sample.unit,size:_sample.unit.byteLength,duration:sampleDuration,originalDts:originalDts,flags:{isLeading:0,dependsOn:1,isDependedOn:0,hasRedundancy:0}}),needFillSilentFrames&&mp4Samples.push.apply(mp4Samples,silentFrames)}mpegRawTrack?mdatbox=new Uint8Array(mdatBytes):((mdatbox=new Uint8Array(mdatBytes))[0]=mdatBytes>>>24&255,mdatbox[1]=mdatBytes>>>16&255,mdatbox[2]=mdatBytes>>>8&255,mdatbox[3]=255&mdatBytes,mdatbox.set(_mp4Generator.default.types.mdat,4));for(var _i=0;_i<mp4Samples.length;_i++){var _unit=mp4Samples[_i].unit;mdatbox.set(_unit,offset),offset+=_unit.byteLength}var distance=mp4Samples[mp4Samples.length-1],_lastSample=distance.dts+distance.duration,dts=(this._audioNextDts=_lastSample,new _mediaSegmentInfo.MediaSegmentInfo),force=(dts.beginDts=firstDts,dts.endDts=_lastSample,dts.beginPts=firstDts,dts.endPts=_lastSample,dts.originalBeginDts=mp4Samples[0].originalDts,dts.originalEndDts=distance.originalDts+distance.duration,dts.firstSample=new _mediaSegmentInfo.SampleInfo(mp4Samples[0].dts,mp4Samples[0].pts,mp4Samples[0].duration,mp4Samples[0].originalDts,!1),dts.lastSample=new _mediaSegmentInfo.SampleInfo(distance.dts,distance.pts,distance.duration,distance.originalDts,!1),this._isLive||this._audioSegmentInfoList.append(dts),audioTrack.samples=mp4Samples,audioTrack.sequenceNumber++,null),force=mpegRawTrack?new Uint8Array:_mp4Generator.default.moof(audioTrack.sequenceNumber,firstDts,audioTrack),insertPrefixSilentFrame=(audioTrack.samples=[],audioTrack.length=0,{type:"audio",data:this._mergeBoxes(force,mdatbox).buffer,sampleCount:mp4Samples.length,info:dts});mpegRawTrack&&firstSegmentAfterSeek&&(insertPrefixSilentFrame.timestampOffset=firstDts),this._onMediaSegment("audio",insertPrefixSilentFrame)}}}},{key:"_remuxVideo",value:function(videoTrack,force){if(null!=this._videoMeta){var track=videoTrack,samples=track.samples,firstDts=-1,firstPts=-1;if(samples&&0!==samples.length&&(1!==samples.length||force)){for(var dtsCorrection,offset=8,mdatbox=null,force=8+videoTrack.length,lastSample=null,videoTrack=(1<samples.length&&(force-=(lastSample=samples.pop()).length),null!=this._videoStashedLastSample&&(videoTrack=this._videoStashedLastSample,this._videoStashedLastSample=null,samples.unshift(videoTrack),force+=videoTrack.length),null!=lastSample&&(this._videoStashedLastSample=lastSample),samples[0].dts-this._dtsBase),info=(dtsCorrection=this._videoNextDts?videoTrack-this._videoNextDts:!this._videoSegmentInfoList.isEmpty()&&null!=(_lastSample2=this._videoSegmentInfoList.getLastSampleBefore(videoTrack))?(distance=videoTrack-(_lastSample2.originalDts+_lastSample2.duration),videoTrack-(_lastSample2.dts+_lastSample2.duration+(distance=distance<=3?0:distance))):0,new _mediaSegmentInfo.MediaSegmentInfo),mp4Samples=[],i=0;i<samples.length;i++){var syncPoint,_sample2=samples[i],originalDts=_sample2.dts-this._dtsBase,isKeyframe=_sample2.isKeyframe,dts=originalDts-dtsCorrection,cts=_sample2.cts,pts=dts+cts,sampleDuration=(-1===firstDts&&(firstDts=dts,firstPts=pts),0);sampleDuration=i!==samples.length-1?samples[i+1].dts-this._dtsBase-dtsCorrection-dts:null!=lastSample?lastSample.dts-this._dtsBase-dtsCorrection-dts:1<=mp4Samples.length?mp4Samples[mp4Samples.length-1].duration:Math.floor(this._videoMeta.refSampleDuration),isKeyframe&&((syncPoint=new _mediaSegmentInfo.SampleInfo(dts,pts,sampleDuration,_sample2.dts,!0)).fileposition=_sample2.fileposition,info.appendSyncPoint(syncPoint)),mp4Samples.push({dts:dts,pts:pts,cts:cts,units:_sample2.units,size:_sample2.length,isKeyframe:isKeyframe,duration:sampleDuration,originalDts:originalDts,flags:{isLeading:0,dependsOn:isKeyframe?2:1,isDependedOn:isKeyframe?1:0,hasRedundancy:0,isNonSync:isKeyframe?0:1}})}(mdatbox=new Uint8Array(force))[0]=force>>>24&255,mdatbox[1]=force>>>16&255,mdatbox[2]=force>>>8&255,mdatbox[3]=255&force,mdatbox.set(_mp4Generator.default.types.mdat,4);for(var _i2=0;_i2<mp4Samples.length;_i2++)for(var units=mp4Samples[_i2].units;units.length;){var data=units.shift().data;mdatbox.set(data,offset),offset+=data.byteLength}var videoTrack=mp4Samples[mp4Samples.length-1],_lastSample2=videoTrack.dts+videoTrack.duration,distance=videoTrack.pts+videoTrack.duration,_lastSample2=(this._videoNextDts=_lastSample2,info.beginDts=firstDts,info.endDts=_lastSample2,info.beginPts=firstPts,info.endPts=distance,info.originalBeginDts=mp4Samples[0].originalDts,info.originalEndDts=videoTrack.originalDts+videoTrack.duration,info.firstSample=new _mediaSegmentInfo.SampleInfo(mp4Samples[0].dts,mp4Samples[0].pts,mp4Samples[0].duration,mp4Samples[0].originalDts,mp4Samples[0].isKeyframe),info.lastSample=new _mediaSegmentInfo.SampleInfo(videoTrack.dts,videoTrack.pts,videoTrack.duration,videoTrack.originalDts,videoTrack.isKeyframe),this._isLive||this._videoSegmentInfoList.append(info),track.samples=mp4Samples,track.sequenceNumber++,this._forceFirstIDR&&((force=mp4Samples[0].flags).dependsOn=2,force.isNonSync=0),_mp4Generator.default.moof(track.sequenceNumber,firstDts,track));track.samples=[],track.length=0,this._onMediaSegment("video",{type:"video",data:this._mergeBoxes(_lastSample2,mdatbox).buffer,sampleCount:mp4Samples.length,info:info})}}}},{key:"_mergeBoxes",value:function(moof,mdat){var result=new Uint8Array(moof.byteLength+mdat.byteLength);return result.set(moof,0),result.set(mdat,moof.byteLength),result}}]),MP4Remuxer}();_exports.default=MP4Remuxer}); |