/* * Buffer Controller */ /* eslint-disable */ import Event from '../events'; import EventHandler from '../event-handler'; class BufferController extends EventHandler { constructor(wfs) { super( wfs, Event.MEDIA_ATTACHING, Event.BUFFER_APPENDING, Event.BUFFER_RESET ); this.mediaSource = null; this.media = null; this.pendingTracks = {}; this.sourceBuffer = {}; this.segments = []; this.appended = 0; this._msDuration = null; // Source Buffer listeners this.onsbue = this.onSBUpdateEnd.bind(this); this.browserType = 0; if (navigator.userAgent.toLowerCase().indexOf('firefox') !== -1) { this.browserType = 1; } this.mediaType = 'H264Raw'; this.websocketName = undefined; this.channelName = undefined; this.cameraInfo = {}; } destroy() { EventHandler.prototype.destroy.call(this); } onMediaAttaching(data) { let media = (this.media = data.media); this.mediaType = data.mediaType; this.websocketName = data.websocketName; this.channelName = data.channelName; this.cameraInfo = data.cameraInfo; if (media) { // setup the media source var ms = (this.mediaSource = new MediaSource()); //Media Source listeners this.onmso = this.onMediaSourceOpen.bind(this); this.onmse = this.onMediaSourceEnded.bind(this); this.onmsc = this.onMediaSourceClose.bind(this); ms.addEventListener('sourceopen', this.onmso); ms.addEventListener('sourceended', this.onmse); ms.addEventListener('sourceclose', this.onmsc); // link video and media Source media.src = URL.createObjectURL(ms); } } onMediaDetaching() {} onBufferAppending(data) { if (!this.segments) { this.segments = [data]; } else { this.segments.push(data); } this.doAppending(); } onMediaSourceClose() { console.log('media source closed'); } onMediaSourceEnded() { console.log('media source ended'); } onSBUpdateEnd(event) { // Firefox if (this.browserType === 1) { this.mediaSource.endOfStream(); this.media.play(); } this.appending = false; this.doAppending(); this.updateMediaElementDuration(); } updateMediaElementDuration() {} onMediaSourceOpen() { let mediaSource = this.mediaSource; if (mediaSource) { // once received, don't listen anymore to sourceopen event mediaSource.removeEventListener('sourceopen', this.onmso); } if (this.mediaType === 'FMp4') { this.checkPendingTracks(); } this.wfs.trigger(Event.MEDIA_ATTACHED, { media: this.media, channelName: this.channelName, mediaType: this.mediaType, websocketName: this.websocketName, cameraInfo: this.cameraInfo }); } checkPendingTracks() { this.createSourceBuffers({ tracks: 'video', mimeType: '' }); this.pendingTracks = {}; } onBufferReset(data) { if (this.mediaType === 'H264Raw') { this.createSourceBuffers({ tracks: 'video', mimeType: data.mimeType }); } } createSourceBuffers(tracks) { var sourceBuffer = this.sourceBuffer, mediaSource = this.mediaSource; let mimeType; if (tracks.mimeType === '') { mimeType = 'video/mp4;codecs=avc1.420028'; // avc1.42c01f avc1.42801e avc1.640028 avc1.420028 } else { mimeType = 'video/mp4;codecs=' + tracks.mimeType; } try { let sb = (sourceBuffer['video'] = mediaSource.addSourceBuffer(mimeType)); sb.addEventListener('updateend', this.onsbue); track.buffer = sb; } catch (err) {} this.wfs.trigger(Event.BUFFER_CREATED, { tracks: tracks }); this.media.play(); } doAppending() { var wfs = this.wfs, sourceBuffer = this.sourceBuffer, segments = this.segments; if (Object.keys(sourceBuffer).length) { if (this.media.error) { this.segments = []; console.log( 'trying to append although a media error occured, flush segment and abort' ); return; } if (this.appending) { return; } if (segments && segments.length) { var segment = segments.shift(); try { if (sourceBuffer[segment.type]) { this.parent = segment.parent; sourceBuffer[segment.type].appendBuffer(segment.data); this.appendError = 0; this.appended++; this.appending = true; } else { } } catch (err) { // in case any error occured while appending, put back segment in segments table segments.unshift(segment); var event = { type: ErrorTypes.MEDIA_ERROR }; if (err.code !== 22) { if (this.appendError) { this.appendError++; } else { this.appendError = 1; } event.details = ErrorDetails.BUFFER_APPEND_ERROR; event.frag = this.fragCurrent; if (this.appendError > wfs.config.appendErrorMaxRetry) { segments = []; event.fatal = true; return; } else { event.fatal = false; } } else { this.segments = []; event.details = ErrorDetails.BUFFER_FULL_ERROR; return; } } } } } } export default BufferController;