From 40e7625ca813db68bf9e87ff0cc243f33c229c10 Mon Sep 17 00:00:00 2001 From: John Bartos Date: Tue, 17 Apr 2018 11:08:21 -0400 Subject: [PATCH] Curly brace ESLint rule changes (#1672) * Always require curly braces and disallow single-line conditionals * Apply lint rules to eslintrc --- .eslintrc.js | 115 ++++++----- src/config.js | 3 +- src/controller/abr-controller.js | 19 +- src/controller/audio-stream-controller.js | 73 ++++--- src/controller/audio-track-controller.js | 9 +- src/controller/buffer-controller.js | 37 ++-- src/controller/cap-level-controller.js | 15 +- src/controller/eme-controller.js | 12 +- src/controller/fps-controller.js | 6 +- src/controller/id3-track-controller.js | 3 +- src/controller/level-controller.js | 43 +++-- src/controller/stream-controller.js | 189 ++++++++++++------- src/controller/subtitle-stream-controller.js | 25 ++- src/controller/subtitle-track-controller.js | 37 ++-- src/controller/timeline-controller.js | 38 ++-- src/crypt/aes-decryptor.js | 29 +-- src/crypt/decrypter.js | 3 +- src/demux/aacdemuxer.js | 3 +- src/demux/adts.js | 9 +- src/demux/demuxer-inline.js | 9 +- src/demux/demuxer.js | 16 +- src/demux/exp-golomb.js | 36 ++-- src/demux/id3.js | 39 ++-- src/demux/mp4demuxer.js | 29 ++- src/demux/mpegaudio.js | 12 +- src/demux/sample-aes.js | 27 ++- src/demux/tsdemuxer.js | 125 +++++++----- src/event-handler.js | 6 +- src/helper/aac.js | 13 +- src/helper/buffer-helper.js | 14 +- src/helper/fragment-tracker.js | 16 +- src/helper/level-helper.js | 34 ++-- src/helper/mediakeys-helper.js | 5 +- src/helper/mediasource-helper.js | 3 +- src/hls.js | 50 +++-- src/loader/fragment-loader.js | 9 +- src/loader/fragment.js | 18 +- src/loader/key-loader.js | 9 +- src/loader/level-key.js | 3 +- src/loader/m3u8-parser.js | 27 ++- src/loader/playlist-loader.js | 17 +- src/remux/dummy-remuxer.js | 3 +- src/remux/mp4-generator.js | 20 +- src/remux/mp4-remuxer.js | 55 ++++-- src/remux/passthrough-remuxer.js | 6 +- src/task-loop.js | 3 +- src/utils/attr-list.js | 21 ++- src/utils/binary-search.js | 7 +- src/utils/cea-608-parser.js | 173 ++++++++++------- src/utils/cues.js | 13 +- src/utils/discontinuities.js | 10 +- src/utils/fetch-loader.js | 20 +- src/utils/hex.js | 3 +- src/utils/logger.js | 3 +- src/utils/output-filter.js | 6 +- src/utils/texttrack-utils.js | 3 +- src/utils/time-ranges.js | 3 +- src/utils/vttcue.js | 50 +++-- src/utils/vttparser.js | 80 +++++--- src/utils/webvtt-parser.js | 17 +- src/utils/xhr-loader.js | 18 +- tests/functional/auto/setup.js | 37 ++-- tests/functional/auto/testbench.js | 15 +- tests/test-streams.js | 3 +- tests/unit/events.js | 3 +- tests/unit/loader/playlist-loader.js | 6 +- tests/unit/utils/binary-search.js | 5 +- 67 files changed, 1128 insertions(+), 640 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index f31395b91c1..041861db3b8 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,64 +1,63 @@ module.exports = { - "env": { - "browser": true, - "commonjs": true, - "es6": true, + 'env': { + 'browser': true, + 'commonjs': true, + 'es6': true }, - "globals": { + 'globals': { // Allowed globals - "console": true, - //"MediaSource": true, - "performance": true, - "crypto": true, - "fetch": true, - "Request": true, - "Headers": true, - "escape": true, + 'console': true, + // "MediaSource": true, + 'performance': true, + 'crypto': true, + 'fetch': true, + 'Request': true, + 'Headers': true, + 'escape': true, // Compile-time defines - "__VERSION__": true, - "__USE_SUBTITLES__": true, - "__USE_ALT_AUDIO__": true, - "__USE_EME_DRM__": true + '__VERSION__': true, + '__USE_SUBTITLES__': true, + '__USE_ALT_AUDIO__': true, + '__USE_EME_DRM__': true }, // see https://standardjs.com/ // see https://github.com/standard/eslint-config-standard - "extends": [ - "eslint:recommended", - "standard" + 'extends': [ + 'eslint:recommended', + 'standard' ], - "parserOptions": { - "sourceType": "module" + 'parserOptions': { + 'sourceType': 'module' }, - "rules": { + 'rules': { // our basic style rules - "semi": [ - "error", - "always" + 'semi': [ + 'error', + 'always' ], - "indent": [ - "error", + 'indent': [ + 'error', 2 ], - "quotes": [ - "error", - "single" + 'quotes': [ + 'error', + 'single' ], - "linebreak-style": [ - "error", - "unix" + 'linebreak-style': [ + 'error', + 'unix' ], // spacing - "space-infix-ops": 2, - "space-unary-ops": [2, {"words": true, "nonwords": false}], - "space-in-parens": ["error", "never"], - "keyword-spacing": [2, {"before": true, "after": true}], + 'space-infix-ops': 2, + 'space-unary-ops': [2, { 'words': true, 'nonwords': false }], + 'space-in-parens': ['error', 'never'], + 'keyword-spacing': [2, { 'before': true, 'after': true }], // enforce litteral objects on multiple lines - "block-spacing": "error", - "curly": ["error", "multi-or-nest", "consistent"], - "object-curly-spacing": ["error", "always"], - "brace-style": ["error", "1tbs", { "allowSingleLine": true }], - + 'block-spacing': 'error', + 'curly': 2, + 'object-curly-spacing': ['error', 'always'], + 'brace-style': ['error', '1tbs', { 'allowSingleLine': false }], // limit code block and line length /* @@ -75,23 +74,23 @@ module.exports = { // (warnings for now) // forbid "one var" style, enforce one declaration per variable - "one-var": [ + 'one-var': [ 1, - "never" + 'never' ], - "standard/no-callback-literal": 1, - "import/first": 1, - "no-var": 1, - "no-empty": 1, - "no-mixed-operators": 1, - "no-unused-vars": 1, - "no-console": 1, - "no-fallthrough": 1, - "no-case-declarations": 1, - "no-irregular-whitespace": 1, - "no-self-assign": 1, - "new-cap": 1, - "no-undefined": 1 + 'standard/no-callback-literal': 1, + 'import/first': 1, + 'no-var': 1, + 'no-empty': 1, + 'no-mixed-operators': 1, + 'no-unused-vars': 1, + 'no-console': 1, + 'no-fallthrough': 1, + 'no-case-declarations': 1, + 'no-irregular-whitespace': 1, + 'no-self-assign': 1, + 'new-cap': 1, + 'no-undefined': 1 } }; diff --git a/src/config.js b/src/config.js index 17d15c47cec..a406a1f5800 100644 --- a/src/config.js +++ b/src/config.js @@ -111,5 +111,6 @@ if (__USE_ALT_AUDIO__) { hlsDefaultConfig.audioTrackController = AudioTrackController; } -if (__USE_EME_DRM__) +if (__USE_EME_DRM__) { hlsDefaultConfig.emeController = EMEController; +} diff --git a/src/controller/abr-controller.js b/src/controller/abr-controller.js index 1719cd44dc3..f59e7ba2322 100644 --- a/src/controller/abr-controller.js +++ b/src/controller/abr-controller.js @@ -33,8 +33,9 @@ class AbrController extends EventHandler { onFragLoading (data) { let frag = data.frag; if (frag.type === 'main') { - if (!this.timer) + if (!this.timer) { this.timer = setInterval(this.onCheck, 100); + } // lazy init of bw Estimator, rationale is that we use different params for Live/VoD // so we need to wait for stream manifest / playlist type to instantiate it. @@ -170,10 +171,11 @@ class AbrController extends EventHandler { this._bwEstimator.sample(fragLoadingProcessingMs, stats.loaded); stats.bwEstimate = this._bwEstimator.getEstimate(); // if fragment has been loaded to perform a bitrate test, (hls.startLevel = -1), store bitrate test delay duration - if (frag.bitrateTest) + if (frag.bitrateTest) { this.bitrateTestDelay = fragLoadingProcessingMs / 1000; - else + } else { this.bitrateTestDelay = 0; + } } } @@ -199,14 +201,16 @@ class AbrController extends EventHandler { const forcedAutoLevel = this._nextAutoLevel; const bwEstimator = this._bwEstimator; // in case next auto level has been forced, and bw not available or not reliable, return forced value - if (forcedAutoLevel !== -1 && (!bwEstimator || !bwEstimator.canEstimate())) + if (forcedAutoLevel !== -1 && (!bwEstimator || !bwEstimator.canEstimate())) { return forcedAutoLevel; + } // compute next level using ABR logic let nextABRAutoLevel = this._nextABRAutoLevel; // if forced auto level has been defined, use it to cap ABR computed quality level - if (forcedAutoLevel !== -1) + if (forcedAutoLevel !== -1) { nextABRAutoLevel = Math.min(forcedAutoLevel, nextABRAutoLevel); + } return nextABRAutoLevel; } @@ -268,10 +272,11 @@ class AbrController extends EventHandler { // consider only 80% of the available bandwidth, but if we are switching up, // be even more conservative (70%) to avoid overestimating and immediately // switching back. - if (i <= currentLevel) + if (i <= currentLevel) { adjustedbw = bwFactor * currentBw; - else + } else { adjustedbw = bwUpFactor * currentBw; + } const bitrate = levels[i].realBitrate ? Math.max(levels[i].realBitrate, levels[i].bitrate) : levels[i].bitrate, fetchDuration = bitrate * avgDuration / adjustedbw; diff --git a/src/controller/audio-stream-controller.js b/src/controller/audio-stream-controller.js index 45517af7754..05b586e2b63 100644 --- a/src/controller/audio-stream-controller.js +++ b/src/controller/audio-stream-controller.js @@ -81,8 +81,9 @@ class AudioStreamController extends TaskLoop { // If we are waiting we need to demux/remux the waiting frag // With the new initPTS - if (this.state === State.WAITING_INIT_PTS) + if (this.state === State.WAITING_INIT_PTS) { this.tick(); + } } } @@ -110,8 +111,9 @@ class AudioStreamController extends TaskLoop { stopLoad () { let frag = this.fragCurrent; if (frag) { - if (frag.loader) + if (frag.loader) { frag.loader.abort(); + } this.fragmentTracker.removeFragment(frag); this.fragCurrent = null; @@ -153,16 +155,18 @@ class AudioStreamController extends TaskLoop { case State.IDLE: const tracks = this.tracks; // audio tracks not received => exit loop - if (!tracks) + if (!tracks) { break; + } // if video not attached AND // start fragment already requested OR start frag prefetch disable // exit loop // => if media not attached but start frag prefetch is enabled and start frag not requested yet, we will not exit loop if (!this.media && - (this.startFragRequested || !config.startFragPrefetch)) + (this.startFragRequested || !config.startFragPrefetch)) { break; + } // determine next candidate fragment to be loaded, based on current position and // end of buffer position @@ -171,8 +175,9 @@ class AudioStreamController extends TaskLoop { pos = this.media.currentTime; } else { pos = this.nextLoadPosition; - if (pos === undefined) + if (pos === undefined) { break; + } } let media = this.mediaBuffer ? this.mediaBuffer : this.media, videoBuffer = this.videoBuffer ? this.videoBuffer : this.media, @@ -278,24 +283,27 @@ class AudioStreamController extends TaskLoop { // logger.log(`level/sn/start/end/bufEnd:${level}/${candidate.sn}/${candidate.start}/${(candidate.start+candidate.duration)}/${bufferEnd}`); // Set the lookup tolerance to be small enough to detect the current segment - ensures we don't skip over very small segments let candidateLookupTolerance = Math.min(maxFragLookUpTolerance, candidate.duration); - if ((candidate.start + candidate.duration - candidateLookupTolerance) <= bufferEnd) + if ((candidate.start + candidate.duration - candidateLookupTolerance) <= bufferEnd) { return 1; - // if maxFragLookUpTolerance will have negative value then don't return -1 for first element - else if (candidate.start - candidateLookupTolerance > bufferEnd && candidate.start) + } else if (candidate.start - candidateLookupTolerance > bufferEnd && candidate.start) { + // if maxFragLookUpTolerance will have negative value then don't return -1 for first element return -1; + } return 0; }; if (bufferEnd < end) { - if (bufferEnd > end - maxFragLookUpTolerance) + if (bufferEnd > end - maxFragLookUpTolerance) { maxFragLookUpTolerance = 0; + } // Prefer the next fragment if it's within tolerance - if (fragNext && !fragmentWithinToleranceTest(fragNext)) + if (fragNext && !fragmentWithinToleranceTest(fragNext)) { foundFrag = fragNext; - else + } else { foundFrag = BinarySearch.search(fragments, fragmentWithinToleranceTest); + } } else { // reach end of playlist foundFrag = fragments[fragLen - 1]; @@ -327,8 +335,9 @@ class AudioStreamController extends TaskLoop { if (audioSwitch || this.fragmentTracker.getState(frag) === FragmentState.NOT_LOADED) { this.fragCurrent = frag; this.startFragRequested = true; - if (!isNaN(frag.sn)) + if (!isNaN(frag.sn)) { this.nextLoadPosition = frag.start + frag.duration; + } hls.trigger(Event.FRAG_LOADING, { frag }); this.state = State.FRAG_LOADING; @@ -340,8 +349,9 @@ class AudioStreamController extends TaskLoop { case State.WAITING_TRACK: track = this.tracks[this.trackId]; // check if playlist is already loaded - if (track && track.details) + if (track && track.details) { this.state = State.IDLE; + } break; case State.FRAG_LOADING_WAITING_RETRY: @@ -357,8 +367,9 @@ class AudioStreamController extends TaskLoop { break; case State.WAITING_INIT_PTS: const videoTrackCC = this.videoTrackCC; - if (this.initPTS[videoTrackCC] === undefined) + if (this.initPTS[videoTrackCC] === undefined) { break; + } // Ensure we don't get stuck in the WAITING_INIT_PTS state if the waiting frag CC doesn't match any initPTS const waitingFrag = this.waitingFragment; @@ -399,8 +410,9 @@ class AudioStreamController extends TaskLoop { media.addEventListener('seeking', this.onvseeking); media.addEventListener('ended', this.onvended); let config = this.config; - if (this.tracks && config.autoStartLoad) + if (this.tracks && config.autoStartLoad) { this.startLoad(config.startPosition); + } } onMediaDetaching () { @@ -426,8 +438,9 @@ class AudioStreamController extends TaskLoop { // switch to IDLE state to check for potential new fragment this.state = State.IDLE; } - if (this.media) + if (this.media) { this.lastCurrentTime = this.media.currentTime; + } // tick to speed up processing this.tick(); @@ -488,10 +501,11 @@ class AudioStreamController extends TaskLoop { sliding = newDetails.fragments[0].start; // TODO // this.liveSyncPosition = this.computeLivePosition(sliding, curDetails); - if (newDetails.PTSKnown) + if (newDetails.PTSKnown) { logger.log(`live audio playlist sliding:${sliding.toFixed(3)}`); - else + } else { logger.log('live audio playlist - outdated PTS, unknown sliding'); + } } else { newDetails.PTSKnown = false; logger.log('live audio playlist - first load, unknown sliding'); @@ -517,8 +531,9 @@ class AudioStreamController extends TaskLoop { this.nextLoadPosition = this.startPosition; } // only switch batck to IDLE state if we were waiting for track to start downloading a new fragment - if (this.state === State.WAITING_TRACK) + if (this.state === State.WAITING_TRACK) { this.state = State.IDLE; + } // trigger handler right now this.tick(); @@ -558,8 +573,9 @@ class AudioStreamController extends TaskLoop { this.state = State.PARSING; // transmux the MPEG-TS data to ISO-BMFF segments this.appended = false; - if (!this.demuxer) + if (!this.demuxer) { this.demuxer = new Demuxer(this.hls, 'audio'); + } // Check if we have video initPTS // If not we need to wait for it @@ -592,8 +608,9 @@ class AudioStreamController extends TaskLoop { let tracks = data.tracks, track; // delete any video track found on audio demuxer - if (tracks.video) + if (tracks.video) { delete tracks.video; + } // include levelCodec in audio and video tracks track = tracks.audio; @@ -675,8 +692,9 @@ class AudioStreamController extends TaskLoop { if (!this.audioSwitch) { [data.data1, data.data2].forEach(buffer => { - if (buffer && buffer.length) + if (buffer && buffer.length) { pendingData.push({ type: data.type, data: buffer, parent: 'audio', content: 'data' }); + } }); if (!appendOnBufferFlush && pendingData.length) { pendingData.forEach(appendObj => { @@ -723,8 +741,9 @@ class AudioStreamController extends TaskLoop { this.mediaBuffer = audioTrack.buffer; this.loadedmetadata = true; } - if (data.tracks.video) + if (data.tracks.video) { this.videoBuffer = data.tracks.video.buffer; + } } onBufferAppended (data) { @@ -761,18 +780,20 @@ class AudioStreamController extends TaskLoop { onError (data) { let frag = data.frag; // don't handle frag error not related to audio fragment - if (frag && frag.type !== 'audio') + if (frag && frag.type !== 'audio') { return; + } switch (data.details) { case ErrorDetails.FRAG_LOAD_ERROR: case ErrorDetails.FRAG_LOAD_TIMEOUT: if (!data.fatal) { let loadError = this.fragLoadError; - if (loadError) + if (loadError) { loadError++; - else + } else { loadError = 1; + } let config = this.config; if (loadError <= config.fragLoadingMaxRetry) { diff --git a/src/controller/audio-track-controller.js b/src/controller/audio-track-controller.js index fc99862421c..58c72f9e9f2 100644 --- a/src/controller/audio-track-controller.js +++ b/src/controller/audio-track-controller.js @@ -33,8 +33,9 @@ class AudioTrackController extends EventHandler { this.ticks++; if (this.ticks === 1) { this.doTick(); - if (this.ticks > 1) + if (this.ticks > 1) { setTimeout(this.tick, 1); + } this.ticks = 0; } @@ -45,8 +46,9 @@ class AudioTrackController extends EventHandler { } onError (data) { - if (data.fatal && data.type === ErrorTypes.NETWORK_ERROR) + if (data.fatal && data.type === ErrorTypes.NETWORK_ERROR) { this.cleanTimer(); + } } onManifestLoading () { @@ -105,8 +107,9 @@ class AudioTrackController extends EventHandler { /** select an audio track, based on its index in audio track lists**/ set audioTrack (audioTrackId) { - if (this.trackId !== audioTrackId || this.tracks[audioTrackId].details === undefined) + if (this.trackId !== audioTrackId || this.tracks[audioTrackId].details === undefined) { this.setAudioTrackInternal(audioTrackId); + } } setAudioTrackInternal (newId) { diff --git a/src/controller/buffer-controller.js b/src/controller/buffer-controller.js index 42451284460..c2e906283c9 100644 --- a/src/controller/buffer-controller.js +++ b/src/controller/buffer-controller.js @@ -207,11 +207,13 @@ class BufferController extends EventHandler { delete this.audioTimestampOffset; } - if (this._needsFlush) + if (this._needsFlush) { this.doFlush(); + } - if (this._needsEos) + if (this._needsEos) { this.checkEos(); + } this.appending = false; let parent = this.parent; @@ -221,13 +223,15 @@ class BufferController extends EventHandler { // this.sourceBuffer is better to use than media.buffered as it is closer to the PTS data from the fragments let timeRanges = {}; const sourceBuffer = this.sourceBuffer; - for (let streamType in sourceBuffer) + for (let streamType in sourceBuffer) { timeRanges[streamType] = sourceBuffer[streamType].buffered; + } this.hls.trigger(Event.BUFFER_APPENDED, { parent, pending, timeRanges }); // don't append in flushing mode - if (!this._needsFlush) + if (!this._needsFlush) { this.doAppending(); + } this.updateMediaElementDuration(); } @@ -298,10 +302,11 @@ class BufferController extends EventHandler { onBufferAppending (data) { if (!this._needsFlush) { - if (!this.segments) + if (!this.segments) { this.segments = [ data ]; - else + } else { this.segments.push(data); + } this.doAppending(); } @@ -339,8 +344,9 @@ class BufferController extends EventHandler { } for (let type in sb) { let sbobj = sb[type]; - if (!sbobj.ended) + if (!sbobj.ended) { return; + } if (sbobj.updating) { this._needsEos = true; @@ -386,8 +392,9 @@ class BufferController extends EventHandler { !this.mediaSource || !this.sourceBuffer || this.media.readyState === 0 || - this.mediaSource.readyState !== 'open') + this.mediaSource.readyState !== 'open') { return; + } for (let type in this.sourceBuffer) { if (this.sourceBuffer[type].updating === true) { @@ -398,8 +405,9 @@ class BufferController extends EventHandler { duration = this.media.duration; // initialise to the value that the media source is reporting - if (this._msDuration === null) + if (this._msDuration === null) { this._msDuration = this.mediaSource.duration; + } if (this._live === true && config.liveDurationInfinity === true) { // Override duration to Infinity @@ -439,8 +447,9 @@ class BufferController extends EventHandler { let appended = 0; let sourceBuffer = this.sourceBuffer; try { - for (let type in sourceBuffer) + for (let type in sourceBuffer) { appended += sourceBuffer[type].buffered.length; + } } catch (error) { // error could be thrown while accessing buffered, in case sourcebuffer has already been removed from MediaSource // this is harmess at this stage, catch this to avoid reporting an internal exception @@ -492,10 +501,11 @@ class BufferController extends EventHandler { segments.unshift(segment); let event = { type: ErrorTypes.MEDIA_ERROR, parent: segment.parent }; if (err.code !== 22) { - if (this.appendError) + if (this.appendError) { this.appendError++; - else + } else { this.appendError = 1; + } event.details = ErrorDetails.BUFFER_APPEND_ERROR; /* with UHD content, we could get loop of quota exceeded error until @@ -537,8 +547,9 @@ class BufferController extends EventHandler { for (let type in sourceBuffer) { // check if sourcebuffer type is defined (typeIn): if yes, let's only flush this one // if no, let's flush all sourcebuffers - if (typeIn && type !== typeIn) + if (typeIn && type !== typeIn) { continue; + } sb = sourceBuffer[type]; // we are going to flush buffer, mark source buffer as 'not ended' diff --git a/src/controller/cap-level-controller.js b/src/controller/cap-level-controller.js index 6c73679c80c..d10dd77098c 100644 --- a/src/controller/cap-level-controller.js +++ b/src/controller/cap-level-controller.js @@ -17,15 +17,17 @@ class CapLevelController extends EventHandler { if (this.hls.config.capLevelToPlayerSize) { this.media = this.restrictedLevels = null; this.autoLevelCapping = Number.POSITIVE_INFINITY; - if (this.timer) + if (this.timer) { this.timer = clearInterval(this.timer); + } } } onFpsDropLevelCapping (data) { // Don't add a restricted level more than once - if (CapLevelController.isLevelAllowed(data.droppedLevel, this.restrictedLevels)) + if (CapLevelController.isLevelAllowed(data.droppedLevel, this.restrictedLevels)) { this.restrictedLevels.push(data.droppedLevel); + } } onMediaAttaching (data) { @@ -66,8 +68,9 @@ class CapLevelController extends EventHandler { * returns level should be the one with the dimensions equal or greater than the media (player) dimensions (so the video will be downscaled) */ getMaxLevel (capLevelIndex) { - if (!this.levels) + if (!this.levels) { return -1; + } const validLevels = this.levels.filter((level, index) => CapLevelController.isLevelAllowed(index, this.restrictedLevels) && index <= capLevelIndex @@ -109,14 +112,16 @@ class CapLevelController extends EventHandler { } static getMaxLevelByMediaSize (levels, width, height) { - if (!levels || (levels && !levels.length)) + if (!levels || (levels && !levels.length)) { return -1; + } // Levels can have the same dimensions but differing bandwidths - since levels are ordered, we can look to the next // to determine whether we've chosen the greatest bandwidth for the media's dimensions const atGreatestBandiwdth = (curLevel, nextLevel) => { - if (!nextLevel) + if (!nextLevel) { return true; + } return curLevel.width !== nextLevel.width || curLevel.height !== nextLevel.height; }; diff --git a/src/controller/eme-controller.js b/src/controller/eme-controller.js index 803ef46eca3..2b2e1ff0699 100644 --- a/src/controller/eme-controller.js +++ b/src/controller/eme-controller.js @@ -162,8 +162,9 @@ class EMEController extends EventHandler { } get requestMediaKeySystemAccess () { - if (!this._requestMediaKeySystemAccess) + if (!this._requestMediaKeySystemAccess) { throw new Error('No requestMediaKeySystemAccess function configured'); + } return this._requestMediaKeySystemAccess; } @@ -337,8 +338,9 @@ class EMEController extends EventHandler { } } // if licenseXhrSetup did not yet call open, let's do it now - if (!xhr.readyState) + if (!xhr.readyState) { xhr.open('POST', url, true); + } } catch (e) { // IE11 throws an exception on xhr.open if attempting to access an HTTP resource over HTTPS logger.error('Error setting up key-system license XHR', e); @@ -455,8 +457,9 @@ class EMEController extends EventHandler { } onMediaAttached (data) { - if (!this._emeEnabled) + if (!this._emeEnabled) { return; + } const media = data.media; @@ -471,8 +474,9 @@ class EMEController extends EventHandler { } onManifestParsed (data) { - if (!this._emeEnabled) + if (!this._emeEnabled) { return; + } const audioCodecs = data.levels.map((level) => level.audioCodec); const videoCodecs = data.levels.map((level) => level.videoCodec); diff --git a/src/controller/fps-controller.js b/src/controller/fps-controller.js index 496c5ceb7fc..55ce89c4da8 100644 --- a/src/controller/fps-controller.js +++ b/src/controller/fps-controller.js @@ -12,8 +12,9 @@ class FPSController extends EventHandler { } destroy () { - if (this.timer) + if (this.timer) { clearInterval(this.timer); + } this.isVideoPlaybackQualityAvailable = false; } @@ -22,8 +23,9 @@ class FPSController extends EventHandler { const config = this.hls.config; if (config.capLevelOnFPSDrop) { const video = this.video = data.media instanceof HTMLVideoElement ? data.media : null; - if (typeof video.getVideoPlaybackQuality === 'function') + if (typeof video.getVideoPlaybackQuality === 'function') { this.isVideoPlaybackQualityAvailable = true; + } clearInterval(this.timer); this.timer = setInterval(this.checkFPSInterval.bind(this), config.fpsDroppedMonitoringPeriod); diff --git a/src/controller/id3-track-controller.js b/src/controller/id3-track-controller.js index d27dd195d1a..89115de109f 100644 --- a/src/controller/id3-track-controller.js +++ b/src/controller/id3-track-controller.js @@ -71,8 +71,9 @@ class ID3TrackController extends EventHandler { let endTime = i < samples.length - 1 ? samples[i + 1].pts : fragment.endPTS; // Give a slight bump to the endTime if it's equal to startTime to avoid a SyntaxError in IE - if (startTime === endTime) + if (startTime === endTime) { endTime += 0.0001; + } for (let j = 0; j < frames.length; j++) { const frame = frames[j]; diff --git a/src/controller/level-controller.js b/src/controller/level-controller.js index 95ea5753a76..418be8e933d 100644 --- a/src/controller/level-controller.js +++ b/src/controller/level-controller.js @@ -44,13 +44,15 @@ export default class LevelController extends EventHandler { levels.forEach(level => { level.loadError = 0; const levelDetails = level.details; - if (levelDetails && levelDetails.live) + if (levelDetails && levelDetails.live) { level.details = undefined; + } }); } // speed up live playlist refresh if timer exists - if (this.timer !== null) + if (this.timer !== null) { this.loadLevel(); + } } stopLoad () { @@ -77,8 +79,9 @@ export default class LevelController extends EventHandler { // erase audio codec info if browser does not support mp4a.40.34. // demuxer will autodetect codec and fallback to mpeg/audio - if (chromeOrFirefox === true && level.audioCodec && level.audioCodec.indexOf('mp4a.40.34') !== -1) + if (chromeOrFirefox === true && level.audioCodec && level.audioCodec.indexOf('mp4a.40.34') !== -1) { level.audioCodec = undefined; + } levelFromSet = levelSet[level.bitrate]; @@ -93,16 +96,18 @@ export default class LevelController extends EventHandler { }); // remove audio-only level if we also have levels with audio+video codecs signalled - if (videoCodecFound === true && audioCodecFound === true) + if (videoCodecFound === true && audioCodecFound === true) { levels = levels.filter(({ videoCodec }) => !!videoCodec); + } // only keep levels with supported audio/video codecs levels = levels.filter(({ audioCodec, videoCodec }) => { return (!audioCodec || isCodecSupportedInMp4(audioCodec)) && (!videoCodec || isCodecSupportedInMp4(videoCodec)); }); - if (data.audioTracks) + if (data.audioTracks) { audioTracks = data.audioTracks.filter(track => !track.audioCodec || isCodecSupportedInMp4(track.audioCodec, 'audio')); + } if (levels.length > 0) { // start bitrate is the first bitrate of the manifest @@ -152,8 +157,9 @@ export default class LevelController extends EventHandler { let levels = this._levels; if (levels) { newLevel = Math.min(newLevel, levels.length - 1); - if (this.currentLevelIndex !== newLevel || levels[newLevel].details === undefined) + if (this.currentLevelIndex !== newLevel || levels[newLevel].details === undefined) { this.setLevelInternal(newLevel); + } } } @@ -196,11 +202,13 @@ export default class LevelController extends EventHandler { set manualLevel (newLevel) { this.manualLevelIndex = newLevel; - if (this._startLevel === undefined) + if (this._startLevel === undefined) { this._startLevel = newLevel; + } - if (newLevel !== -1) + if (newLevel !== -1) { this.level = newLevel; + } } get firstLevel () { @@ -216,10 +224,11 @@ export default class LevelController extends EventHandler { // if none of these values are defined, fallback on this._firstLevel (first quality level appearing in variant manifest) if (this._startLevel === undefined) { let configStartLevel = this.hls.config.startLevel; - if (configStartLevel !== undefined) + if (configStartLevel !== undefined) { return configStartLevel; - else + } else { return this._firstLevel; + } } else { return this._startLevel; } @@ -231,8 +240,9 @@ export default class LevelController extends EventHandler { onError (data) { if (data.fatal === true) { - if (data.type === ErrorTypes.NETWORK_ERROR) + if (data.type === ErrorTypes.NETWORK_ERROR) { this.cleanTimer(); + } return; } @@ -260,8 +270,9 @@ export default class LevelController extends EventHandler { break; } - if (levelIndex !== undefined) + if (levelIndex !== undefined) { this.recoverLevel(data, levelIndex, levelError, fragmentError); + } } /** @@ -390,15 +401,17 @@ export default class LevelController extends EventHandler { } get nextLoadLevel () { - if (this.manualLevelIndex !== -1) + if (this.manualLevelIndex !== -1) { return this.manualLevelIndex; - else + } else { return this.hls.nextAutoLevel; + } } set nextLoadLevel (nextLevel) { this.level = nextLevel; - if (this.manualLevelIndex === -1) + if (this.manualLevelIndex === -1) { this.hls.nextAutoLevel = nextLevel; + } } } diff --git a/src/controller/stream-controller.js b/src/controller/stream-controller.js index 33a600966f2..733ca3f129c 100644 --- a/src/controller/stream-controller.js +++ b/src/controller/stream-controller.js @@ -103,8 +103,9 @@ class StreamController extends TaskLoop { stopLoad () { let frag = this.fragCurrent; if (frag) { - if (frag.loader) + if (frag.loader) { frag.loader.abort(); + } this.fragmentTracker.removeFragment(frag); this.fragCurrent = null; @@ -131,8 +132,9 @@ class StreamController extends TaskLoop { case State.WAITING_LEVEL: var level = this.levels[this.level]; // check if playlist is already loaded - if (level && level.details) + if (level && level.details) { this.state = State.IDLE; + } break; case State.FRAG_LOADING_WAITING_RETRY: @@ -172,31 +174,35 @@ class StreamController extends TaskLoop { // if video not attached AND start fragment already requested OR start frag prefetch disable // exit loop, as we either need more info (level not parsed) or we need media to be attached to load new fragment if (this.levelLastLoaded === undefined || ( - !media && (this.startFragRequested || !config.startFragPrefetch))) + !media && (this.startFragRequested || !config.startFragPrefetch))) { return; + } // if we have not yet loaded any fragment, start loading from start position let pos; - if (this.loadedmetadata) + if (this.loadedmetadata) { pos = media.currentTime; - else + } else { pos = this.nextLoadPosition; + } // determine next load level let level = hls.nextLoadLevel, levelInfo = this.levels[level]; - if (!levelInfo) + if (!levelInfo) { return; + } let levelBitrate = levelInfo.bitrate, maxBufLen; // compute max Buffer Length that we could get from this load level, based on level bitrate. don't buffer more than 60 MB and more than 30s - if (levelBitrate) + if (levelBitrate) { maxBufLen = Math.max(8 * config.maxBufferSize / levelBitrate, config.maxBufferLength); - else + } else { maxBufLen = config.maxBufferLength; + } maxBufLen = Math.min(maxBufLen, config.maxMaxBufferLength); @@ -206,8 +212,9 @@ class StreamController extends TaskLoop { const bufferInfo = BufferHelper.bufferInfo(this.mediaBuffer ? this.mediaBuffer : media, pos, config.maxBufferHole), bufferLen = bufferInfo.len; // Stay idle if we are still with buffer margins - if (bufferLen >= maxBufLen) + if (bufferLen >= maxBufLen) { return; + } // if buffer length is less than maxBufLen try to load a new fragment ... logger.trace(`buffer length of ${bufferLen.toFixed(3)} is below max of ${maxBufLen.toFixed(3)}. checking for more payload ...`); @@ -240,8 +247,9 @@ class StreamController extends TaskLoop { if (duration - Math.max(bufferInfo.end, fragPrevious.start) <= Math.max(0.2, fragPrevious.duration)) { // Finalize the media stream let data = {}; - if (this.altAudio) + if (this.altAudio) { data.type = 'video'; + } this.hls.trigger(Event.BUFFER_EOS, data); this.state = State.ENDED; @@ -260,8 +268,9 @@ class StreamController extends TaskLoop { fragLen = fragments.length; // empty playlist - if (fragLen === 0) + if (fragLen === 0) { return; + } // find fragment index, contiguous with end of buffer position let start = fragments[0].start, @@ -282,19 +291,23 @@ class StreamController extends TaskLoop { frag = this._ensureFragmentAtLivePoint(levelDetails, bufferEnd, start, end, fragPrevious, fragments, fragLen); // if it explicitely returns null don't load any fragment and exit function now - if (frag === null) + if (frag === null) { return; + } } else { // VoD playlist: if bufferEnd before start of playlist, load first fragment - if (bufferEnd < start) + if (bufferEnd < start) { frag = fragments[0]; + } } } - if (!frag) + if (!frag) { frag = this._findFragment(start, fragPrevious, fragLen, fragments, bufferEnd, end, levelDetails); + } - if (frag) + if (frag) { this._loadFragmentOrKey(frag, level, levelDetails, pos, bufferEnd); + } } _ensureFragmentAtLivePoint (levelDetails, bufferEnd, start, end, fragPrevious, fragments, fragLen) { @@ -310,8 +323,9 @@ class StreamController extends TaskLoop { let liveSyncPosition = this.liveSyncPosition = this.computeLivePosition(start, levelDetails); logger.log(`buffer end: ${bufferEnd.toFixed(3)} is located too far from the end of live sliding playlist, reset currentTime to : ${liveSyncPosition.toFixed(3)}`); bufferEnd = liveSyncPosition; - if (media && media.readyState && media.duration > liveSyncPosition) + if (media && media.readyState && media.duration > liveSyncPosition) { media.currentTime = liveSyncPosition; + } this.nextLoadPosition = liveSyncPosition; } @@ -326,8 +340,9 @@ class StreamController extends TaskLoop { // level 1 loaded [182580164,182580171] // // don't return null in case media not loaded yet (readystate === 0) - if (levelDetails.PTSKnown && bufferEnd > end && media && media.readyState) + if (levelDetails.PTSKnown && bufferEnd > end && media && media.readyState) { return null; + } if (this.startFragRequested && !levelDetails.PTSKnown) { /* we are switching level on live playlist, but we don't have any PTS info for that quality level ... @@ -350,8 +365,9 @@ class StreamController extends TaskLoop { frag = BinarySearch.search(fragments, function (frag) { return fragPrevious.cc - frag.cc; }); - if (frag) + if (frag) { logger.log(`live playlist, switching playlist, load frag with same CC: ${frag.sn}`); + } } } else { // Relies on PDT in order to switch bitrates (Support EXT-X-DISCONTINUITY without EXT-X-DISCONTINUITY-SEQUENCE) frag = this._findFragmentByPDT(fragments, fragPrevious.endPdt + 1); @@ -369,24 +385,28 @@ class StreamController extends TaskLoop { } _findFragmentByPDT (fragments, PDTValue) { - if (!fragments || PDTValue === undefined) + if (!fragments || PDTValue === undefined) { return null; + } // if less than start let firstSegment = fragments[0]; - if (PDTValue < firstSegment.pdt) + if (PDTValue < firstSegment.pdt) { return null; + } let lastSegment = fragments[fragments.length - 1]; - if (PDTValue >= lastSegment.endPdt) + if (PDTValue >= lastSegment.endPdt) { return null; + } for (let seg = 0; seg < fragments.length; ++seg) { let frag = fragments[seg]; - if (PDTValue < frag.endPdt) + if (PDTValue < frag.endPdt) { return frag; + } } return null; } @@ -412,24 +432,27 @@ class StreamController extends TaskLoop { // logger.log(`level/sn/start/end/bufEnd:${level}/${candidate.sn}/${candidate.start}/${(candidate.start+candidate.duration)}/${bufferEnd}`); // Set the lookup tolerance to be small enough to detect the current segment - ensures we don't skip over very small segments let candidateLookupTolerance = Math.min(maxFragLookUpTolerance, candidate.duration + (candidate.deltaPTS ? candidate.deltaPTS : 0)); - if (candidate.start + candidate.duration - candidateLookupTolerance <= bufferEnd) + if (candidate.start + candidate.duration - candidateLookupTolerance <= bufferEnd) { return 1; - // if maxFragLookUpTolerance will have negative value then don't return -1 for first element - else if (candidate.start - candidateLookupTolerance > bufferEnd && candidate.start) + } else if (candidate.start - candidateLookupTolerance > bufferEnd && candidate.start) { + // if maxFragLookUpTolerance will have negative value then don't return -1 for first element return -1; + } return 0; }; if (bufferEnd < end) { - if (bufferEnd > end - maxFragLookUpTolerance) + if (bufferEnd > end - maxFragLookUpTolerance) { maxFragLookUpTolerance = 0; + } // Prefer the next fragment if it's within tolerance - if (fragNext && !fragmentWithinToleranceTest(fragNext)) + if (fragNext && !fragmentWithinToleranceTest(fragNext)) { foundFrag = fragNext; - else + } else { foundFrag = BinarySearch.search(fragments, fragmentWithinToleranceTest); + } } return foundFrag; } @@ -513,8 +536,9 @@ class StreamController extends TaskLoop { this.fragCurrent = frag; this.startFragRequested = true; // Don't update nextLoadPosition for fragments which are not buffered - if (!isNaN(frag.sn) && !frag.bitrateTest) + if (!isNaN(frag.sn) && !frag.bitrateTest) { this.nextLoadPosition = frag.start + frag.duration; + } // Allow backtracked fragments to load if (frag.backtracked || fragState === FragmentState.NOT_LOADED) { @@ -523,14 +547,16 @@ class StreamController extends TaskLoop { this.hls.trigger(Event.FRAG_LOADING, { frag }); // lazy demuxer init, as this could take some time ... do it during frag loading - if (!this.demuxer) + if (!this.demuxer) { this.demuxer = new Demuxer(this.hls, 'main'); + } this.state = State.FRAG_LOADING; } else if (fragState === FragmentState.APPENDING) { // Lower the buffer size and try again - if (this._reduceMaxBufferLength(frag.duration)) + if (this._reduceMaxBufferLength(frag.duration)) { this.fragmentTracker.removeFragment(frag); + } } } } @@ -556,8 +582,9 @@ class StreamController extends TaskLoop { let media = this.media; if (media) { const frag = this.getBufferedFrag(media.currentTime); - if (frag) + if (frag) { return frag.level; + } } return -1; } @@ -582,10 +609,11 @@ class StreamController extends TaskLoop { get nextLevel () { const frag = this.nextBufferedFrag; - if (frag) + if (frag) { return frag.level; - else + } else { return -1; + } } _checkFragmentChanged () { @@ -598,8 +626,9 @@ class StreamController extends TaskLoop { media decode error, check this, to avoid seeking back to wrong position after a media decode error */ - if (currentTime > video.playbackRate * this.lastCurrentTime) + if (currentTime > video.playbackRate * this.lastCurrentTime) { this.lastCurrentTime = currentTime; + } if (BufferHelper.isBuffered(video, currentTime)) { fragPlayingCurrent = this.getBufferedFrag(currentTime); @@ -616,8 +645,9 @@ class StreamController extends TaskLoop { if (fragPlaying !== this.fragPlaying) { this.hls.trigger(Event.FRAG_CHANGED, { frag: fragPlaying }); const fragPlayingLevel = fragPlaying.level; - if (!this.fragPlaying || this.fragPlaying.level !== fragPlayingLevel) + if (!this.fragPlaying || this.fragPlaying.level !== fragPlayingLevel) { this.hls.trigger(Event.LEVEL_SWITCHED, { level: fragPlayingLevel }); + } this.fragPlaying = fragPlaying; } @@ -646,8 +676,9 @@ class StreamController extends TaskLoop { this.previouslyPaused = previouslyPaused; } let fragCurrent = this.fragCurrent; - if (fragCurrent && fragCurrent.loader) + if (fragCurrent && fragCurrent.loader) { fragCurrent.loader.abort(); + } this.fragCurrent = null; // flush everything @@ -667,8 +698,9 @@ class StreamController extends TaskLoop { // only nudge if currentTime is buffered media.currentTime -= 0.0001; } - if (!this.previouslyPaused) + if (!this.previouslyPaused) { media.play(); + } } } @@ -692,10 +724,11 @@ class StreamController extends TaskLoop { if (!media.paused) { // add a safety delay of 1s let nextLevelId = this.hls.nextLoadLevel, nextLevel = this.levels[nextLevelId], fragLastKbps = this.fragLastKbps; - if (fragLastKbps && this.fragCurrent) + if (fragLastKbps && this.fragCurrent) { fetchdelay = this.fragCurrent.duration * nextLevel.bitrate / (1000 * fragLastKbps) + 1; - else + } else { fetchdelay = 0; + } } else { fetchdelay = 0; } @@ -708,8 +741,9 @@ class StreamController extends TaskLoop { if (nextBufferedFrag) { // if we are here, we can also cancel any loading/demuxing in progress, as they are useless let fragCurrent = this.fragCurrent; - if (fragCurrent && fragCurrent.loader) + if (fragCurrent && fragCurrent.loader) { fragCurrent.loader.abort(); + } this.fragCurrent = null; // start flush position is the start PTS of next buffered frag. @@ -725,8 +759,9 @@ class StreamController extends TaskLoop { this.state = State.BUFFER_FLUSHING; let flushScope = { startOffset: startOffset, endOffset: endOffset }; // if alternate audio tracks are used, only flush video, otherwise flush everything - if (this.altAudio) + if (this.altAudio) { flushScope.type = 'video'; + } this.hls.trigger(Event.BUFFER_FLUSHING, flushScope); } @@ -740,8 +775,9 @@ class StreamController extends TaskLoop { media.addEventListener('seeked', this.onvseeked); media.addEventListener('ended', this.onvended); let config = this.config; - if (this.levels && config.autoStartLoad) + if (this.levels && config.autoStartLoad) { this.hls.startLoad(config.startPosition); + } } onMediaDetaching () { @@ -776,8 +812,9 @@ class StreamController extends TaskLoop { onMediaSeeking () { let media = this.media, currentTime = media ? media.currentTime : undefined, config = this.config; - if (!isNaN(currentTime)) + if (!isNaN(currentTime)) { logger.log(`media seeking to ${currentTime.toFixed(3)}`); + } let mediaBuffer = this.mediaBuffer ? this.mediaBuffer : media; let bufferInfo = BufferHelper.bufferInfo(mediaBuffer, currentTime, this.config.maxBufferHole); @@ -804,18 +841,21 @@ class StreamController extends TaskLoop { } } else if (this.state === State.ENDED) { // if seeking to unbuffered area, clean up fragPrevious - if (bufferInfo.len === 0) + if (bufferInfo.len === 0) { this.fragPrevious = 0; + } // switch to IDLE state to check for potential new fragment this.state = State.IDLE; } - if (media) + if (media) { this.lastCurrentTime = currentTime; + } // in case seeking occurs although no media buffered, adjust startPosition and nextLoadPosition to seek target - if (!this.loadedmetadata) + if (!this.loadedmetadata) { this.nextLoadPosition = this.startPosition = currentTime; + } // tick to speed up processing this.tick(); @@ -823,8 +863,9 @@ class StreamController extends TaskLoop { onMediaSeeked () { const media = this.media, currentTime = media ? media.currentTime : undefined; - if (!isNaN(currentTime)) + if (!isNaN(currentTime)) { logger.log(`media seeked to ${currentTime.toFixed(3)}`); + } // tick to speed up FRAGMENT_PLAYING triggering this.tick(); @@ -851,22 +892,26 @@ class StreamController extends TaskLoop { // detect if we have different kind of audio codecs used amongst playlists codec = level.audioCodec; if (codec) { - if (codec.indexOf('mp4a.40.2') !== -1) + if (codec.indexOf('mp4a.40.2') !== -1) { aac = true; + } - if (codec.indexOf('mp4a.40.5') !== -1) + if (codec.indexOf('mp4a.40.5') !== -1) { heaac = true; + } } }); this.audioCodecSwitch = (aac && heaac); - if (this.audioCodecSwitch) + if (this.audioCodecSwitch) { logger.log('both AAC/HE-AAC audio found in levels; declaring level codec as HE-AAC'); + } this.levels = data.levels; this.startFragRequested = false; let config = this.config; - if (config.autoStartLoad || this.forceStartLoad) + if (config.autoStartLoad || this.forceStartLoad) { this.hls.startLoad(config.startPosition); + } } onLevelLoaded (data) { @@ -931,8 +976,9 @@ class StreamController extends TaskLoop { this.nextLoadPosition = this.startPosition; } // only switch batck to IDLE state if we were waiting for level to start downloading a new fragment - if (this.state === State.WAITING_LEVEL) + if (this.state === State.WAITING_LEVEL) { this.state = State.IDLE; + } // trigger handler right now this.tick(); @@ -984,22 +1030,25 @@ class StreamController extends TaskLoop { audioCodec = this.config.defaultAudioCodec || currentLevel.audioCodec; if (this.audioCodecSwap) { logger.log('swapping playlist audio codec'); - if (audioCodec === undefined) + if (audioCodec === undefined) { audioCodec = this.lastAudioCodec; + } if (audioCodec) { - if (audioCodec.indexOf('mp4a.40.5') !== -1) + if (audioCodec.indexOf('mp4a.40.5') !== -1) { audioCodec = 'mp4a.40.2'; - else + } else { audioCodec = 'mp4a.40.5'; + } } } this.pendingBuffering = true; this.appended = false; logger.log(`Parsing ${sn} of [${details.startSN} ,${details.endSN}],level ${level}, cc ${fragCurrent.cc}`); let demuxer = this.demuxer; - if (!demuxer) + if (!demuxer) { demuxer = this.demuxer = new Demuxer(this.hls, 'main'); + } // time Offset is accurate if level PTS is known, or if playlist is not sliding (not live) and if media is not seeking (this is to overcome potential timestamp drifts between playlists and fragments) let media = this.media; @@ -1024,8 +1073,9 @@ class StreamController extends TaskLoop { let tracks = data.tracks, trackName, track; // if audio track is expected to come from audio stream controller, discard any coming from main - if (tracks.audio && this.altAudio) + if (tracks.audio && this.altAudio) { delete tracks.audio; + } // include levelCodec in audio and video tracks track = tracks.audio; @@ -1034,10 +1084,11 @@ class StreamController extends TaskLoop { ua = navigator.userAgent.toLowerCase(); if (audioCodec && this.audioCodecSwap) { logger.log('swapping playlist audio codec'); - if (audioCodec.indexOf('mp4a.40.5') !== -1) + if (audioCodec.indexOf('mp4a.40.5') !== -1) { audioCodec = 'mp4a.40.2'; - else + } else { audioCodec = 'mp4a.40.5'; + } } // in case AAC and HE-AAC audio codecs are signalled in manifest // force HE-AAC , as it seems that most browsers prefers that way, @@ -1047,8 +1098,9 @@ class StreamController extends TaskLoop { // don't force HE-AAC if mono stream if (track.metadata.channelCount !== 1 && // don't force HE-AAC if firefox - ua.indexOf('firefox') === -1) + ua.indexOf('firefox') === -1) { audioCodec = 'mp4a.40.5'; + } } // HE-AAC is broken on Android, always signal audio codec as AAC even if variant manifest states otherwise if (ua.indexOf('android') !== -1 && track.container !== 'audio/mpeg') { // Exclude mpeg audio @@ -1097,11 +1149,13 @@ class StreamController extends TaskLoop { data.endDTS = data.startDTS + fragCurrent.duration; } - if (data.hasAudio === true) + if (data.hasAudio === true) { frag.addElementaryStream(Fragment.ElementaryStreamTypes.AUDIO); + } - if (data.hasVideo === true) + if (data.hasVideo === true) { frag.addElementaryStream(Fragment.ElementaryStreamTypes.VIDEO); + } logger.log(`Parsed ${data.type},PTS:[${data.startPTS.toFixed(3)},${data.endPTS.toFixed(3)}],DTS:[${data.startDTS.toFixed(3)}/${data.endDTS.toFixed(3)}],nb:${data.nb},dropped:${data.dropped || 0}`); @@ -1226,8 +1280,9 @@ class StreamController extends TaskLoop { name = type; mediaTrack = track; // keep video source buffer reference - if (type === 'video') + if (type === 'video') { this.videoBuffer = tracks[type].buffer; + } } else { alternate = true; } @@ -1273,8 +1328,9 @@ class StreamController extends TaskLoop { onError (data) { let frag = data.frag || this.fragCurrent; // don't handle frag error not related to main fragment - if (frag && frag.type !== 'main') + if (frag && frag.type !== 'main') { return; + } // 0.5 : tolerance needed as some browsers stalls playback before reaching buffered end let mediaBuffered = !!this.media && BufferHelper.isBuffered(this.media, this.media.currentTime) && BufferHelper.isBuffered(this.media, this.media.currentTime + 0.5); @@ -1317,8 +1373,9 @@ class StreamController extends TaskLoop { logger.warn(`streamController: ${data.details},switch to ${this.state} state ...`); } else { // in case of non fatal error while loading level, if level controller is not retrying to load level , switch back to IDLE - if (!data.levelRetry && this.state === State.WAITING_LEVEL) + if (!data.levelRetry && this.state === State.WAITING_LEVEL) { this.state = State.IDLE; + } } } break; diff --git a/src/controller/subtitle-stream-controller.js b/src/controller/subtitle-stream-controller.js index b2770125e68..a2574b64d3b 100644 --- a/src/controller/subtitle-stream-controller.js +++ b/src/controller/subtitle-stream-controller.js @@ -59,8 +59,9 @@ class SubtitleStreamController extends TaskLoop { // When fragment has finished processing, add sn to list of completed if successful. onSubtitleFragProcessed (data) { - if (data.success) + if (data.success) { this.vttFragSNsProcessed[data.frag.trackId].push(data.frag.sn); + } this.currentlyProcessing = null; this.state = State.IDLE; @@ -75,8 +76,9 @@ class SubtitleStreamController extends TaskLoop { onError (data) { let frag = data.frag; // don't handle frag error not related to subtitle fragment - if (frag && frag.type !== 'subtitle') + if (frag && frag.type !== 'subtitle') { return; + } if (this.currentlyProcessing) { this.currentlyProcessing = null; @@ -99,20 +101,25 @@ class SubtitleStreamController extends TaskLoop { }; const alreadyInQueue = function (frag) { - return fragQueue.some(fragInQueue => { return fragInQueue.sn === frag.sn; }); + return fragQueue.some(fragInQueue => { + return fragInQueue.sn === frag.sn; + }); }; // exit if tracks don't exist - if (!tracks) + if (!tracks) { break; + } var trackDetails; - if (trackId < tracks.length) + if (trackId < tracks.length) { trackDetails = tracks[trackId].details; + } - if (typeof trackDetails === 'undefined') + if (typeof trackDetails === 'undefined') { break; + } // Add all fragments that haven't been, aren't currently being and aren't waiting to be processed, to queue. trackDetails.fragments.forEach(frag => { @@ -146,15 +153,17 @@ class SubtitleStreamController extends TaskLoop { onSubtitleTrackSwitch (data) { this.currentTrackId = data.id; - if (this.currentTrackId === -1) + if (this.currentTrackId === -1) { return; + } // Check if track was already loaded and if so make sure we finish // downloading its frags, if not all have been downloaded yet const currentTrack = this.tracks[this.currentTrackId]; let details = currentTrack.details; - if (details !== undefined) + if (details !== undefined) { this.tick(); + } } // Got a new set of subtitle fragments. diff --git a/src/controller/subtitle-track-controller.js b/src/controller/subtitle-track-controller.js index 7da2421410e..77c820df271 100644 --- a/src/controller/subtitle-track-controller.js +++ b/src/controller/subtitle-track-controller.js @@ -9,8 +9,9 @@ import { logger } from '../utils/logger'; function filterSubtitleTracks (textTrackList) { let tracks = []; for (let i = 0; i < textTrackList.length; i++) { - if (textTrackList[i].kind === 'subtitles') + if (textTrackList[i].kind === 'subtitles') { tracks.push(textTrackList[i]); + } } return tracks; } @@ -35,8 +36,9 @@ class SubtitleTrackController extends EventHandler { _onTextTracksChanged () { // Media is undefined when switching streams via loadSource() - if (!this.media) + if (!this.media) { return; + } let trackId = -1; let tracks = filterSubtitleTracks(this.media.textTracks); @@ -61,8 +63,9 @@ class SubtitleTrackController extends EventHandler { // Listen for subtitle track change, then extract the current track ID. onMediaAttached (data) { this.media = data.media; - if (!this.media) + if (!this.media) { return; + } if (this.queuedDefaultTrack !== undefined) { this.subtitleTrack = this.queuedDefaultTrack; @@ -82,13 +85,15 @@ class SubtitleTrackController extends EventHandler { } onMediaDetaching () { - if (!this.media) + if (!this.media) { return; + } - if (this.useTextTrackPolling) + if (this.useTextTrackPolling) { clearInterval(this.subtitlePollingInterval); - else + } else { this.media.textTracks.removeEventListener('change', this.trackChangeListener); + } this.media = undefined; } @@ -114,10 +119,11 @@ class SubtitleTrackController extends EventHandler { // if media has not been attached yet, it will fail // we keep a reference to the default track id // and we'll set subtitleTrack when onMediaAttached is triggered - if (this.media) + if (this.media) { this.subtitleTrack = track.id; - else + } else { this.queuedDefaultTrack = track.id; + } } }); } @@ -126,8 +132,9 @@ class SubtitleTrackController extends EventHandler { onTick () { const trackId = this.trackId; const subtitleTrack = this.tracks[trackId]; - if (!subtitleTrack) + if (!subtitleTrack) { return; + } const details = subtitleTrack.details; // check if we need to load playlist for this subtitle Track @@ -177,8 +184,9 @@ class SubtitleTrackController extends EventHandler { setSubtitleTrackInternal (newId) { // check if level idx is valid - if (newId < -1 || newId >= this.tracks.length) + if (newId < -1 || newId >= this.tracks.length) { return; + } // stopping live reloading timer if any if (this.timer) { @@ -189,19 +197,22 @@ class SubtitleTrackController extends EventHandler { let textTracks = filterSubtitleTracks(this.media.textTracks); // hide currently enabled subtitle track - if (this.trackId !== -1) + if (this.trackId !== -1) { textTracks[this.trackId].mode = 'disabled'; + } this.trackId = newId; logger.log(`switching to subtitle track ${newId}`); this.hls.trigger(Event.SUBTITLE_TRACK_SWITCH, { id: newId }); - if (newId === -1) + if (newId === -1) { return; + } const subtitleTrack = this.tracks[newId]; - if (newId < textTracks.length) + if (newId < textTracks.length) { textTracks[newId].mode = this.subtitleDisplay ? 'showing' : 'hidden'; + } // check if we need to load playlist for this subtitle Track let details = subtitleTrack.details; diff --git a/src/controller/timeline-controller.js b/src/controller/timeline-controller.js index ff1c8fc2606..0f7719b98b7 100644 --- a/src/controller/timeline-controller.js +++ b/src/controller/timeline-controller.js @@ -71,20 +71,23 @@ class TimelineController extends EventHandler { cueRange[0] = Math.min(cueRange[0], startTime); cueRange[1] = Math.max(cueRange[1], endTime); merged = true; - if ((overlap / (endTime - startTime)) > 0.5) + if ((overlap / (endTime - startTime)) > 0.5) { return; + } } } - if (!merged) + if (!merged) { ranges.push([startTime, endTime]); + } this.Cues.newCue(this.captionsTracks[trackName], startTime, endTime, screen); } // Triggered when an initial PTS is found; used for synchronisation of WebVTT. onInitPtsFound (data) { - if (typeof this.initPTS === 'undefined') + if (typeof this.initPTS === 'undefined') { this.initPTS = data.initPTS; + } // Due to asynchrony, initial PTS may arrive later than the first VTT fragments are loaded. // Parse any unparsed fragments upon receiving the initial PTS. @@ -101,8 +104,9 @@ class TimelineController extends EventHandler { if (media) { for (let i = 0; i < media.textTracks.length; i++) { let textTrack = media.textTracks[i]; - if (textTrack[trackName]) + if (textTrack[trackName]) { return textTrack; + } } } return null; @@ -131,8 +135,9 @@ class TimelineController extends EventHandler { createTextTrack (kind, label, lang) { const media = this.media; - if (media) + if (media) { return media.addTextTrack(kind, label, lang); + } } destroy () { @@ -165,8 +170,9 @@ class TimelineController extends EventHandler { if (media) { const textTracks = media.textTracks; if (textTracks) { - for (let i = 0; i < textTracks.length; i++) + for (let i = 0; i < textTracks.length; i++) { clearCurrentCues(textTracks[i]); + } } } } @@ -186,16 +192,19 @@ class TimelineController extends EventHandler { if (index < inUseTracks.length) { const inUseTrack = inUseTracks[index]; // Reuse tracks with the same label, but do not reuse 608/708 tracks - if (reuseVttTextTrack(inUseTrack, track)) + if (reuseVttTextTrack(inUseTrack, track)) { textTrack = inUseTrack; + } } - if (!textTrack) + if (!textTrack) { textTrack = this.createTextTrack('subtitles', track.name, track.lang); + } - if (track.default) + if (track.default) { textTrack.mode = this.hls.subtitleDisplay ? 'showing' : 'hidden'; - else + } else { textTrack.mode = 'disabled'; + } this.textTracks.push(textTrack); }); @@ -214,8 +223,9 @@ class TimelineController extends EventHandler { // if this frag isn't contiguous, clear the parser so cues with bad start/end times aren't added to the textTrack if (sn !== this.lastSn + 1) { const cea608Parser = this.cea608Parser; - if (cea608Parser) + if (cea608Parser) { cea608Parser.reset(); + } } this.lastSn = sn; } // eslint-disable-line brace-style @@ -230,8 +240,9 @@ class TimelineController extends EventHandler { let decryptData = frag.decryptdata; // If the subtitles are not encrypted, parse VTTs now. Otherwise, we need to wait. - if ((decryptData == null) || (decryptData.key == null) || (decryptData.method !== 'AES-128')) + if ((decryptData == null) || (decryptData.key == null) || (decryptData.method !== 'AES-128')) { this._parseVTTs(frag, payload); + } } else { // In case there is no payload, finish unsuccessfully. this.hls.trigger(Event.SUBTITLE_FRAG_PROCESSED, { success: false, frag: frag }); @@ -321,8 +332,9 @@ class TimelineController extends EventHandler { ccValid = (4 & tmpByte) !== 0; ccType = 3 & tmpByte; - if (ccbyte1 === 0 && ccbyte2 === 0) + if (ccbyte1 === 0 && ccbyte2 === 0) { continue; + } if (ccValid) { if (ccType === 0) { // || ccType === 1 diff --git a/src/crypt/aes-decryptor.js b/src/crypt/aes-decryptor.js index 2b3c1194b74..8755715ea0d 100644 --- a/src/crypt/aes-decryptor.js +++ b/src/crypt/aes-decryptor.js @@ -2,10 +2,11 @@ export function removePadding (buffer) { const outputBytes = buffer.byteLength; const paddingBytes = outputBytes && (new DataView(buffer)).getUint8(outputBytes - 1); - if (paddingBytes) + if (paddingBytes) { return buffer.slice(0, outputBytes - paddingBytes); - else + } else { return buffer; + } } class AESDecryptor { @@ -27,8 +28,9 @@ class AESDecryptor { uint8ArrayToUint32Array_ (arrayBuffer) { let view = new DataView(arrayBuffer); let newArray = new Uint32Array(4); - for (let i = 0; i < 4; i++) + for (let i = 0; i < 4; i++) { newArray[i] = view.getUint32(i * 4); + } return newArray; } @@ -52,10 +54,11 @@ class AESDecryptor { let xi = 0; let i = 0; for (i = 0; i < 256; i++) { - if (i < 128) + if (i < 128) { d[i] = i << 1; - else + } else { d[i] = (i << 1) ^ 0x11b; + } } for (i = 0; i < 256; i++) { @@ -104,14 +107,16 @@ class AESDecryptor { offset++; } - if (sameKey) + if (sameKey) { return; + } this.key = key; let keySize = this.keySize = key.length; - if (keySize !== 4 && keySize !== 6 && keySize !== 8) + if (keySize !== 4 && keySize !== 6 && keySize !== 8) { throw new Error('Invalid aes key size=' + keySize); + } let ksRows = this.ksRows = (keySize + 6 + 1) * 4; let ksRow; @@ -157,15 +162,17 @@ class AESDecryptor { for (invKsRow = 0; invKsRow < ksRows; invKsRow++) { ksRow = ksRows - invKsRow; - if (invKsRow & 3) + if (invKsRow & 3) { t = keySchedule[ksRow]; - else + } else { t = keySchedule[ksRow - 4]; + } - if (invKsRow < 4 || ksRow <= 4) + if (invKsRow < 4 || ksRow <= 4) { invKeySchedule[invKsRow] = t; - else + } else { invKeySchedule[invKsRow] = invSubMix0[sbox[t >>> 24]] ^ invSubMix1[sbox[(t >>> 16) & 0xff]] ^ invSubMix2[sbox[(t >>> 8) & 0xff]] ^ invSubMix3[sbox[t & 0xff]]; + } invKeySchedule[invKsRow] = invKeySchedule[invKsRow] >>> 0; } diff --git a/src/crypt/decrypter.js b/src/crypt/decrypter.js index 5282f6679d2..03396d5388c 100644 --- a/src/crypt/decrypter.js +++ b/src/crypt/decrypter.js @@ -34,8 +34,9 @@ class Decrypter { this.logEnabled = false; } let decryptor = this.decryptor; - if (!decryptor) + if (!decryptor) { this.decryptor = decryptor = new AESDecryptor(); + } decryptor.expandKey(key); callback(decryptor.decrypt(data, 0, iv, this.removePKCS7Padding)); diff --git a/src/demux/aacdemuxer.js b/src/demux/aacdemuxer.js index b24cb383083..d366f29e95e 100644 --- a/src/demux/aacdemuxer.js +++ b/src/demux/aacdemuxer.js @@ -20,8 +20,9 @@ class AACDemuxer { } static probe (data) { - if (!data) + if (!data) { return false; + } // Check for the ADTS sync word // Look for ADTS header | 1111 1111 | 1111 X00X | where X can be either 0 or 1 diff --git a/src/demux/adts.js b/src/demux/adts.js index f87faf7a19c..ec4c2b33ac7 100644 --- a/src/demux/adts.js +++ b/src/demux/adts.js @@ -146,8 +146,9 @@ export function isHeader (data, offset) { // Look for ADTS header | 1111 1111 | 1111 X00X | where X can be either 0 or 1 // Layer bits (position 14 and 15) in header should be always 0 for ADTS // More info https://wiki.multimedia.cx/index.php?title=ADTS - if (offset + 1 < data.length && isHeaderPattern(data, offset)) + if (offset + 1 < data.length && isHeaderPattern(data, offset)) { return true; + } return false; } @@ -160,12 +161,14 @@ export function probe (data, offset) { let headerLength = getHeaderLength(data, offset); // ADTS frame Length let frameLength = headerLength; - if (offset + 5 < data.length) + if (offset + 5 < data.length) { frameLength = getFullFrameLength(data, offset); + } let newOffset = offset + frameLength; - if (newOffset === data.length || (newOffset + 1 < data.length && isHeaderPattern(data, newOffset))) + if (newOffset === data.length || (newOffset + 1 < data.length && isHeaderPattern(data, newOffset))) { return true; + } } return false; } diff --git a/src/demux/demuxer-inline.js b/src/demux/demuxer-inline.js index 5a08e68eafa..d3614668f51 100644 --- a/src/demux/demuxer-inline.js +++ b/src/demux/demuxer-inline.js @@ -22,15 +22,17 @@ class DemuxerInline { destroy () { let demuxer = this.demuxer; - if (demuxer) + if (demuxer) { demuxer.destroy(); + } } push (data, decryptdata, initSegment, audioCodec, videoCodec, timeOffset, discontinuity, trackSwitch, contiguous, duration, accurateTimeOffset, defaultInitPTS) { if ((data.byteLength > 0) && (decryptdata != null) && (decryptdata.key != null) && (decryptdata.method === 'AES-128')) { let decrypter = this.decrypter; - if (decrypter == null) + if (decrypter == null) { decrypter = this.decrypter = new Decrypter(this.observer, this.config); + } let localthis = this; // performance.now() not available on WebWorker, at least on Safari Desktop @@ -100,8 +102,9 @@ class DemuxerInline { demuxer.resetTimeStamp(defaultInitPTS); remuxer.resetTimeStamp(defaultInitPTS); } - if (typeof demuxer.setDecryptData === 'function') + if (typeof demuxer.setDecryptData === 'function') { demuxer.setDecryptData(decryptdata); + } demuxer.append(data, timeOffset, contiguous, accurateTimeOffset); } diff --git a/src/demux/demuxer.js b/src/demux/demuxer.js index 506d356294b..51ae0b47d4d 100644 --- a/src/demux/demuxer.js +++ b/src/demux/demuxer.js @@ -55,7 +55,9 @@ class Demuxer { w = this.w = work(require.resolve('../demux/demuxer-worker.js')); this.onwmsg = this.onWorkerMessage.bind(this); w.addEventListener('message', this.onwmsg); - w.onerror = function (event) { hls.trigger(Event.ERROR, { type: ErrorTypes.OTHER_ERROR, details: ErrorDetails.INTERNAL_EXCEPTION, fatal: true, event: 'demuxerWorker', err: { message: event.message + ' (' + event.filename + ':' + event.lineno + ')' } }); }; + w.onerror = function (event) { + hls.trigger(Event.ERROR, { type: ErrorTypes.OTHER_ERROR, details: ErrorDetails.INTERNAL_EXCEPTION, fatal: true, event: 'demuxerWorker', err: { message: event.message + ' (' + event.filename + ':' + event.lineno + ')' } }); + }; w.postMessage({ cmd: 'init', typeSupported: typeSupported, vendor: vendor, id: id, config: JSON.stringify(config) }); } catch (err) { logger.error('error while initializing DemuxerWorker, fallback on DemuxerInline'); @@ -100,11 +102,13 @@ class Demuxer { const trackSwitch = !(lastFrag && (frag.level === lastFrag.level)); const nextSN = lastFrag && (frag.sn === (lastFrag.sn + 1)); const contiguous = !trackSwitch && nextSN; - if (discontinuity) + if (discontinuity) { logger.log(`${this.id}:discontinuity detected`); + } - if (trackSwitch) + if (trackSwitch) { logger.log(`${this.id}:switch detected`); + } this.frag = frag; if (w) { @@ -112,8 +116,9 @@ class Demuxer { w.postMessage({ cmd: 'demux', data, decryptdata, initSegment, audioCodec, videoCodec, timeOffset, discontinuity, trackSwitch, contiguous, duration, accurateTimeOffset, defaultInitPTS }, data instanceof ArrayBuffer ? [data] : []); } else { let demuxer = this.demuxer; - if (demuxer) + if (demuxer) { demuxer.push(data, decryptdata, initSegment, audioCodec, videoCodec, timeOffset, discontinuity, trackSwitch, contiguous, duration, accurateTimeOffset, defaultInitPTS); + } } } @@ -128,8 +133,9 @@ class Demuxer { // special case for FRAG_PARSING_DATA: data1 and data2 are transferable objects case Event.FRAG_PARSING_DATA: data.data.data1 = new Uint8Array(data.data1); - if (data.data2) + if (data.data2) { data.data.data2 = new Uint8Array(data.data2); + } /* falls through */ default: diff --git a/src/demux/exp-golomb.js b/src/demux/exp-golomb.js index d479e981f95..830c4b9b5c5 100644 --- a/src/demux/exp-golomb.js +++ b/src/demux/exp-golomb.js @@ -23,8 +23,9 @@ class ExpGolomb { position = data.byteLength - bytesAvailable, workingBytes = new Uint8Array(4), availableBytes = Math.min(4, bytesAvailable); - if (availableBytes === 0) + if (availableBytes === 0) { throw new Error('no bytes available'); + } workingBytes.set(data.subarray(position, position + availableBytes)); this.word = new DataView(workingBytes.buffer).getUint32(0); @@ -55,20 +56,23 @@ class ExpGolomb { let bits = Math.min(this.bitsAvailable, size), // :uint valu = this.word >>> (32 - bits); // :uint - if (size > 32) + if (size > 32) { logger.error('Cannot read more than 32 bits at a time'); + } this.bitsAvailable -= bits; - if (this.bitsAvailable > 0) + if (this.bitsAvailable > 0) { this.word <<= bits; - else if (this.bytesAvailable > 0) + } else if (this.bytesAvailable > 0) { this.loadWord(); + } bits = size - bits; - if (bits > 0 && this.bitsAvailable) + if (bits > 0 && this.bitsAvailable) { return valu << bits | this.readBits(bits); - else + } else { return valu; + } } // ():uint @@ -203,8 +207,9 @@ class ExpGolomb { profileIdc === 118 || profileIdc === 128) { let chromaFormatIdc = readUEG(); - if (chromaFormatIdc === 3) - skipBits(1); // separate_colour_plane_flag + if (chromaFormatIdc === 3) { + skipBits(1); + } // separate_colour_plane_flag skipUEG(); // bit_depth_luma_minus8 skipUEG(); // bit_depth_chroma_minus8 @@ -213,10 +218,11 @@ class ExpGolomb { scalingListCount = (chromaFormatIdc !== 3) ? 8 : 12; for (i = 0; i < scalingListCount; i++) { if (readBoolean()) { // seq_scaling_list_present_flag[ i ] - if (i < 6) + if (i < 6) { skipScalingList(16); - else + } else { skipScalingList(64); + } } } } @@ -230,16 +236,18 @@ class ExpGolomb { skipEG(); // offset_for_non_ref_pic skipEG(); // offset_for_top_to_bottom_field numRefFramesInPicOrderCntCycle = readUEG(); - for (i = 0; i < numRefFramesInPicOrderCntCycle; i++) - skipEG(); // offset_for_ref_frame[ i ] + for (i = 0; i < numRefFramesInPicOrderCntCycle; i++) { + skipEG(); + } // offset_for_ref_frame[ i ] } skipUEG(); // max_num_ref_frames skipBits(1); // gaps_in_frame_num_value_allowed_flag picWidthInMbsMinus1 = readUEG(); picHeightInMapUnitsMinus1 = readUEG(); frameMbsOnlyFlag = readBits(1); - if (frameMbsOnlyFlag === 0) - skipBits(1); // mb_adaptive_frame_field_flag + if (frameMbsOnlyFlag === 0) { + skipBits(1); + } // mb_adaptive_frame_field_flag skipBits(1); // direct_8x8_inference_flag if (readBoolean()) { // frame_cropping_flag diff --git a/src/demux/id3.js b/src/demux/id3.js index 0f6450cd16a..6ae48adb2e8 100644 --- a/src/demux/id3.js +++ b/src/demux/id3.js @@ -28,8 +28,9 @@ class ID3 { // check version is within range if (data[offset + 3] < 0xFF && data[offset + 4] < 0xFF) { // check size is within range - if (data[offset + 6] < 0x80 && data[offset + 7] < 0x80 && data[offset + 8] < 0x80 && data[offset + 9] < 0x80) + if (data[offset + 6] < 0x80 && data[offset + 7] < 0x80 && data[offset + 8] < 0x80 && data[offset + 9] < 0x80) { return true; + } } } } @@ -53,8 +54,9 @@ class ID3 { // check version is within range if (data[offset + 3] < 0xFF && data[offset + 4] < 0xFF) { // check size is within range - if (data[offset + 6] < 0x80 && data[offset + 7] < 0x80 && data[offset + 8] < 0x80 && data[offset + 9] < 0x80) + if (data[offset + 6] < 0x80 && data[offset + 7] < 0x80 && data[offset + 8] < 0x80 && data[offset + 9] < 0x80) { return true; + } } } } @@ -87,8 +89,9 @@ class ID3 { offset += length; } - if (length > 0) + if (length > 0) { return data.subarray(front, front + length); + } return undefined; } @@ -111,8 +114,9 @@ class ID3 { const frames = ID3.getID3Frames(data); for (let i = 0; i < frames.length; i++) { const frame = frames[i]; - if (ID3.isTimeStampFrame(frame)) + if (ID3.isTimeStampFrame(frame)) { return ID3._readTimeStamp(frame); + } } return undefined; @@ -159,27 +163,30 @@ class ID3 { while (offset + 8 < end) { const frameData = ID3._getFrameData(id3Data.subarray(offset)); const frame = ID3._decodeFrame(frameData); - if (frame) + if (frame) { frames.push(frame); + } // skip frame header and frame data offset += frameData.size + 10; } - if (ID3.isFooter(id3Data, offset)) + if (ID3.isFooter(id3Data, offset)) { offset += 10; + } } return frames; } static _decodeFrame (frame) { - if (frame.type === 'PRIV') + if (frame.type === 'PRIV') { return ID3._decodePrivFrame(frame); - else if (frame.type[0] === 'T') + } else if (frame.type[0] === 'T') { return ID3._decodeTextFrame(frame); - else if (frame.type[0] === 'W') + } else if (frame.type[0] === 'W') { return ID3._decodeURLFrame(frame); + } return undefined; } @@ -196,8 +203,9 @@ class ID3 { data[7]; timestamp /= 45; - if (pts33Bit) - timestamp += 47721858.84; // 2^32 / 90 + if (pts33Bit) { + timestamp += 47721858.84; + } // 2^32 / 90 return Math.round(timestamp); } @@ -209,8 +217,9 @@ class ID3 { /* Format: \0 */ - if (frame.size < 2) + if (frame.size < 2) { return undefined; + } const owner = ID3._utf8ArrayToStr(frame.data, true); const privateData = new Uint8Array(frame.data.subarray(owner.length + 1)); @@ -219,8 +228,9 @@ class ID3 { } static _decodeTextFrame (frame) { - if (frame.size < 2) + if (frame.size < 2) { return undefined; + } if (frame.type === 'TXXX') { /* @@ -253,8 +263,9 @@ class ID3 { [0] = {Text Encoding} [1-?] = {Description}\0{URL} */ - if (frame.size < 2) + if (frame.size < 2) { return undefined; + } let index = 1; const description = ID3._utf8ArrayToStr(frame.data.subarray(index)); diff --git a/src/demux/mp4demuxer.js b/src/demux/mp4demuxer.js index 092ac3797ac..7415db69fae 100644 --- a/src/demux/mp4demuxer.js +++ b/src/demux/mp4demuxer.js @@ -23,29 +23,35 @@ class MP4Demuxer { // default audio codec if nothing specified // TODO : extract that from initsegment - if (audioCodec == null) + if (audioCodec == null) { audioCodec = 'mp4a.40.5'; + } - if (videoCodec == null) + if (videoCodec == null) { videoCodec = 'avc1.42e01e'; + } const tracks = {}; if (initData.audio && initData.video) { tracks.audiovideo = { container: 'video/mp4', codec: audioCodec + ',' + videoCodec, initSegment: duration ? initSegment : null }; } else { - if (initData.audio) + if (initData.audio) { tracks.audio = { container: 'audio/mp4', codec: audioCodec, initSegment: duration ? initSegment : null }; + } - if (initData.video) + if (initData.video) { tracks.video = { container: 'video/mp4', codec: videoCodec, initSegment: duration ? initSegment : null }; + } } this.observer.trigger(Event.FRAG_PARSING_INIT_SEGMENT, { tracks }); } else { - if (audioCodec) + if (audioCodec) { this.audioCodec = audioCodec; + } - if (videoCodec) + if (videoCodec) { this.videoCodec = videoCodec; + } } } @@ -126,8 +132,9 @@ class MP4Demuxer { } else { // recursively search for the next box along the path subresults = MP4Demuxer.findBox({ data: data, start: i + 8, end: endbox }, path.slice(1)); - if (subresults.length) + if (subresults.length) { results = results.concat(subresults); + } } } i = endbox; @@ -145,8 +152,9 @@ class MP4Demuxer { let sidx = MP4Demuxer.findBox(initSegment, ['sidx']); let references; - if (!sidx || !sidx[0]) + if (!sidx || !sidx[0]) { return null; + } references = []; sidx = sidx[0]; @@ -164,10 +172,11 @@ class MP4Demuxer { let earliestPresentationTime = 0; let firstOffset = 0; - if (version === 0) + if (version === 0) { index += 8; - else + } else { index += 16; + } // skip reserved index += 2; diff --git a/src/demux/mpegaudio.js b/src/demux/mpegaudio.js index c3de38a06ec..0b95b825078 100644 --- a/src/demux/mpegaudio.js +++ b/src/demux/mpegaudio.js @@ -53,8 +53,9 @@ const MpegAudio = { appendFrame: function (track, data, offset, pts, frameIndex) { // Using http://www.datavoyage.com/mpgscript/mpeghdr.htm as a reference - if (offset + 24 > data.length) + if (offset + 24 > data.length) { return undefined; + } let header = this.parseHeader(data, offset); if (header && offset + header.frameLength <= data.length) { @@ -105,8 +106,9 @@ const MpegAudio = { // Look for MPEG header | 1111 1111 | 111X XYZX | where X can be either 0 or 1 and Y or Z should be 1 // Layer bits (position 14 and 15) in header should be always different from 0 (Layer I or Layer II or Layer III) // More info http://www.mp3-tech.org/programmer/frame_header.html - if (offset + 1 < data.length && this.isHeaderPattern(data, offset)) + if (offset + 1 < data.length && this.isHeaderPattern(data, offset)) { return true; + } return false; }, @@ -120,12 +122,14 @@ const MpegAudio = { // MPEG frame Length let header = this.parseHeader(data, offset); let frameLength = headerLength; - if (header && header.frameLength) + if (header && header.frameLength) { frameLength = header.frameLength; + } let newOffset = offset + frameLength; - if (newOffset === data.length || (newOffset + 1 < data.length && this.isHeaderPattern(data, newOffset))) + if (newOffset === data.length || (newOffset + 1 < data.length && this.isHeaderPattern(data, newOffset))) { return true; + } } return false; } diff --git a/src/demux/sample-aes.js b/src/demux/sample-aes.js index e49205f30b5..47a96544f5a 100644 --- a/src/demux/sample-aes.js +++ b/src/demux/sample-aes.js @@ -28,8 +28,9 @@ class SampleAesDecrypter { decryptedData = new Uint8Array(decryptedData); curUnit.set(decryptedData, 16); - if (!sync) + if (!sync) { localthis.decryptAacSamples(samples, sampleIndex + 1, callback); + } }); } @@ -40,15 +41,17 @@ class SampleAesDecrypter { return; } - if (samples[sampleIndex].unit.length < 32) + if (samples[sampleIndex].unit.length < 32) { continue; + } let sync = this.decrypter.isSync(); this.decryptAacSample(samples, sampleIndex, callback, sync); - if (!sync) + if (!sync) { return; + } } } @@ -57,8 +60,9 @@ class SampleAesDecrypter { let encryptedDataLen = Math.floor((decodedData.length - 48) / 160) * 16 + 16; let encryptedData = new Int8Array(encryptedDataLen); let outputPos = 0; - for (let inputPos = 32; inputPos <= decodedData.length - 16; inputPos += 160, outputPos += 16) + for (let inputPos = 32; inputPos <= decodedData.length - 16; inputPos += 160, outputPos += 16) { encryptedData.set(decodedData.subarray(inputPos, inputPos + 16), outputPos); + } return encryptedData; } @@ -66,8 +70,9 @@ class SampleAesDecrypter { getAvcDecryptedUnit (decodedData, decryptedData) { decryptedData = new Uint8Array(decryptedData); let inputPos = 0; - for (let outputPos = 32; outputPos <= decodedData.length - 16; outputPos += 160, inputPos += 16) + for (let outputPos = 32; outputPos <= decodedData.length - 16; outputPos += 160, inputPos += 16) { decodedData.set(decryptedData.subarray(inputPos, inputPos + 16), outputPos); + } return decodedData; } @@ -80,8 +85,9 @@ class SampleAesDecrypter { this.decryptBuffer(encryptedData.buffer, function (decryptedData) { curUnit.data = localthis.getAvcDecryptedUnit(decodedData, decryptedData); - if (!sync) + if (!sync) { localthis.decryptAvcSamples(samples, sampleIndex, unitIndex + 1, callback); + } }); } @@ -94,19 +100,22 @@ class SampleAesDecrypter { let curUnits = samples[sampleIndex].units; for (;; unitIndex++) { - if (unitIndex >= curUnits.length) + if (unitIndex >= curUnits.length) { break; + } let curUnit = curUnits[unitIndex]; - if (curUnit.length <= 48 || (curUnit.type !== 1 && curUnit.type !== 5)) + if (curUnit.length <= 48 || (curUnit.type !== 1 && curUnit.type !== 5)) { continue; + } let sync = this.decrypter.isSync(); this.decryptAvcSample(samples, sampleIndex, unitIndex, callback, curUnit, sync); - if (!sync) + if (!sync) { return; + } } } } diff --git a/src/demux/tsdemuxer.js b/src/demux/tsdemuxer.js index 63a7e7c5f16..93bde994702 100644 --- a/src/demux/tsdemuxer.js +++ b/src/demux/tsdemuxer.js @@ -43,10 +43,11 @@ class TSDemuxer { } setDecryptData (decryptdata) { - if ((decryptdata != null) && (decryptdata.key != null) && (decryptdata.method === 'SAMPLE-AES')) + if ((decryptdata != null) && (decryptdata.key != null) && (decryptdata.method === 'SAMPLE-AES')) { this.sampleAes = new SampleAesDecrypter(this.observer, this.config, decryptdata, this.discardEPB); - else + } else { this.sampleAes = null; + } } static probe (data) { @@ -54,8 +55,9 @@ class TSDemuxer { if (syncOffset < 0) { return false; } else { - if (syncOffset) + if (syncOffset) { logger.warn(`MPEG2-TS detected but first sync word found @ offset ${syncOffset}, junk ahead ?`); + } return true; } @@ -67,10 +69,11 @@ class TSDemuxer { let i = 0; while (i < scanwindow) { // a TS fragment should contain at least 3 TS packets, a PAT, a PMT, and one PID, each starting with 0x47 - if (data[i] === 0x47 && data[i + 188] === 0x47 && data[i + 2 * 188] === 0x47) + if (data[i] === 0x47 && data[i + 188] === 0x47 && data[i + 2 * 188] === 0x47) { return i; - else + } else { i++; + } } return -1; } @@ -172,16 +175,18 @@ class TSDemuxer { if (atf > 1) { offset = start + 5 + data[start + 4]; // continue if there is only adaptation field - if (offset === (start + 188)) + if (offset === (start + 188)) { continue; + } } else { offset = start + 4; } switch (pid) { case avcId: if (stt) { - if (avcData && (pes = parsePES(avcData)) && pes.pts !== undefined) + if (avcData && (pes = parsePES(avcData)) && pes.pts !== undefined) { parseAVCPES(pes, false); + } avcData = { data: [], size: 0 }; } @@ -193,10 +198,11 @@ class TSDemuxer { case audioId: if (stt) { if (audioData && (pes = parsePES(audioData)) && pes.pts !== undefined) { - if (audioTrack.isAAC) + if (audioTrack.isAAC) { parseAACPES(pes); - else + } else { parseMPEGPES(pes); + } } audioData = { data: [], size: 0 }; } @@ -207,8 +213,9 @@ class TSDemuxer { break; case id3Id: if (stt) { - if (id3Data && (pes = parsePES(id3Data)) && pes.pts !== undefined) + if (id3Data && (pes = parsePES(id3Data)) && pes.pts !== undefined) { parseID3PES(pes); + } id3Data = { data: [], size: 0 }; } @@ -218,14 +225,16 @@ class TSDemuxer { } break; case 0: - if (stt) + if (stt) { offset += data[offset] + 1; + } pmtId = this._pmtId = parsePAT(data, offset); break; case pmtId: - if (stt) + if (stt) { offset += data[offset] + 1; + } let parsedPIDs = parsePMT(data, offset, this.typeSupported.mpeg === true || this.typeSupported.mp3 === true, this.sampleAes != null); @@ -236,8 +245,9 @@ class TSDemuxer { // NOTE this is only the PID of the track as found in TS, // but we are not using this for MP4 track IDs. avcId = parsedPIDs.avc; - if (avcId > 0) + if (avcId > 0) { avcTrack.pid = avcId; + } audioId = parsedPIDs.audio; if (audioId > 0) { @@ -245,8 +255,9 @@ class TSDemuxer { audioTrack.isAAC = parsedPIDs.isAAC; } id3Id = parsedPIDs.id3; - if (id3Id > 0) + if (id3Id > 0) { id3Track.pid = id3Id; + } if (unknownPIDs && !pmtParsed) { logger.log('reparse from beginning'); @@ -277,15 +288,17 @@ class TSDemuxer { } if (audioData && (pes = parsePES(audioData)) && pes.pts !== undefined) { - if (audioTrack.isAAC) + if (audioTrack.isAAC) { parseAACPES(pes); - else + } else { parseMPEGPES(pes); + } audioTrack.pesData = null; } else { - if (audioData && audioData.size) + if (audioData && audioData.size) { logger.log('last AAC PES packet truncated,might overlap between fragments'); + } // either audioData null or PES truncated, keep it for next frag parsing audioTrack.pesData = audioData; @@ -299,10 +312,11 @@ class TSDemuxer { id3Track.pesData = id3Data; } - if (this.sampleAes == null) + if (this.sampleAes == null) { this.remuxer.remux(audioTrack, avcTrack, id3Track, this._txtTrack, timeOffset, contiguous, accurateTimeOffset); - else + } else { this.decryptAndRemux(audioTrack, avcTrack, id3Track, this._txtTrack, timeOffset, contiguous, accurateTimeOffset); + } } decryptAndRemux (audioTrack, videoTrack, id3Track, textTrack, timeOffset, contiguous, accurateTimeOffset) { @@ -360,16 +374,18 @@ class TSDemuxer { // ISO/IEC 13818-7 ADTS AAC (MPEG-2 lower bit-rate audio) case 0x0f: // logger.log('AAC PID:' + pid); - if (result.audio === -1) + if (result.audio === -1) { result.audio = pid; + } break; // Packetized metadata (ID3) case 0x15: // logger.log('ID3 PID:' + pid); - if (result.id3 === -1) + if (result.id3 === -1) { result.id3 = pid; + } break; @@ -383,8 +399,9 @@ class TSDemuxer { // ITU-T Rec. H.264 and ISO/IEC 14496-10 (lower bit-rate video) case 0x1b: // logger.log('AVC PID:' + pid); - if (result.avc === -1) + if (result.avc === -1) { result.avc = pid; + } break; @@ -419,8 +436,9 @@ class TSDemuxer { _parsePES (stream) { let i = 0, frag, pesFlags, pesPrefix, pesLen, pesHdrLen, pesData, pesPts, pesDts, payloadStartOffset, data = stream.data; // safety check - if (!stream || stream.size === 0) + if (!stream || stream.size === 0) { return null; + } // we might need up to 19 bytes to read PES header // if first chunk of data is less than 19 bytes, let's merge it with following ones until we get 19 bytes @@ -439,8 +457,9 @@ class TSDemuxer { pesLen = (frag[4] << 8) + frag[5]; // if PES parsed length is not zero and greater than total received length, stop parsing. PES might be truncated // minus 6 : PES header size - if (pesLen && pesLen > stream.size - 6) + if (pesLen && pesLen > stream.size - 6) { return null; + } pesFlags = frag[7]; if (pesFlags & 0xC0) { @@ -529,8 +548,9 @@ class TSDemuxer { avcTrack.dropped++; } } - if (avcSample.debug.length) + if (avcSample.debug.length) { logger.log(avcSample.pts + '/' + avcSample.dts + ':' + avcSample.debug); + } } _parseAVCPES (pes, last) { @@ -562,11 +582,13 @@ class TSDemuxer { // NDR case 1: push = true; - if (!avcSample) + if (!avcSample) { avcSample = this.avcSample = createAVCSample(true, pes.pts, pes.dts, ''); + } - if (debug) + if (debug) { avcSample.debug += 'NDR '; + } avcSample.frame = true; let data = unit.data; @@ -579,19 +601,22 @@ class TSDemuxer { // An SI slice can be coded such that its decoded samples can be constructed identically to an SP slice. // I slice: A slice that is not an SI slice that is decoded using intra prediction only. // if (sliceType === 2 || sliceType === 7) { - if (sliceType === 2 || sliceType === 4 || sliceType === 7 || sliceType === 9) + if (sliceType === 2 || sliceType === 4 || sliceType === 7 || sliceType === 9) { avcSample.key = true; + } } break; // IDR case 5: push = true; // handle PES not starting with AUD - if (!avcSample) + if (!avcSample) { avcSample = this.avcSample = createAVCSample(true, pes.pts, pes.dts, ''); + } - if (debug) + if (debug) { avcSample.debug += 'IDR '; + } avcSample.key = true; avcSample.frame = true; @@ -599,8 +624,9 @@ class TSDemuxer { // SEI case 6: push = true; - if (debug && avcSample) + if (debug && avcSample) { avcSample.debug += 'SEI '; + } expGolombDecoder = new ExpGolomb(this.discardEPB(unit.data)); @@ -663,8 +689,9 @@ class TSDemuxer { } } } else if (payloadSize < expGolombDecoder.bytesAvailable) { - for (i = 0; i < payloadSize; i++) + for (i = 0; i < payloadSize; i++) { expGolombDecoder.readUByte(); + } } } break; @@ -672,8 +699,9 @@ class TSDemuxer { case 7: push = true; spsfound = true; - if (debug && avcSample) + if (debug && avcSample) { avcSample.debug += 'SPS '; + } if (!track.sps) { expGolombDecoder = new ExpGolomb(unit.data); @@ -687,8 +715,9 @@ class TSDemuxer { let codecstring = 'avc1.'; for (i = 0; i < 3; i++) { let h = codecarray[i].toString(16); - if (h.length < 2) + if (h.length < 2) { h = '0' + h; + } codecstring += h; } @@ -698,19 +727,22 @@ class TSDemuxer { // PPS case 8: push = true; - if (debug && avcSample) + if (debug && avcSample) { avcSample.debug += 'PPS '; + } - if (!track.pps) + if (!track.pps) { track.pps = [unit.data]; + } break; // AUD case 9: push = false; track.audFound = true; - if (avcSample) + if (avcSample) { pushAccesUnit(avcSample, track); + } avcSample = this.avcSample = createAVCSample(false, pes.pts, pes.dts, debug ? 'AUD ' : ''); break; @@ -720,8 +752,9 @@ class TSDemuxer { break; default: push = false; - if (avcSample) + if (avcSample) { avcSample.debug += 'unknown NAL ' + unit.type + ' '; + } break; } @@ -887,8 +920,9 @@ class TSDemuxer { // If no Emulation Prevention Bytes were found just return the original // array - if (EPBPositions.length === 0) + if (EPBPositions.length === 0) { return data; + } // Create a new array to hold the NAL unit data newLength = length - EPBPositions.length; @@ -924,8 +958,9 @@ class TSDemuxer { } // look for ADTS header (0xFFFx) for (offset = startOffset, len = data.length; offset < len - 1; offset++) { - if (ADTS.isHeader(data, offset)) + if (ADTS.isHeader(data, offset)) { break; + } } // if ADTS header does not start straight from the beginning of the PES payload, raise an error if (offset) { @@ -939,8 +974,9 @@ class TSDemuxer { } logger.warn(`parsing error:${reason}`); this.observer.trigger(Event.ERROR, { type: ErrorTypes.MEDIA_ERROR, details: ErrorDetails.FRAG_PARSING_ERROR, fatal: fatal, reason: reason }); - if (fatal) + if (fatal) { return; + } } ADTS.initTrackConfig(track, this.observer, data, offset, this.audioCodec); @@ -976,11 +1012,12 @@ class TSDemuxer { } } - if (offset < len) + if (offset < len) { aacOverFlow = data.subarray(offset, len); - // logger.log(`AAC: overflow detected:${len-offset}`); - else + // logger.log(`AAC: overflow detected:${len-offset}`); + } else { aacOverFlow = null; + } this.aacOverFlow = aacOverFlow; this.aacLastPTS = stamp; diff --git a/src/event-handler.js b/src/event-handler.js index 7b78c4aee15..61dcaa8045e 100644 --- a/src/event-handler.js +++ b/src/event-handler.js @@ -40,8 +40,9 @@ class EventHandler { registerListeners () { if (this.isEventHandler()) { this.handledEvents.forEach(function (event) { - if (FORBIDDEN_EVENT_NAMES.has(event)) + if (FORBIDDEN_EVENT_NAMES.has(event)) { throw new Error('Forbidden event-name: ' + event); + } this.hls.on(event, this.onEvent); }, this); @@ -66,8 +67,9 @@ class EventHandler { onEventGeneric (event, data) { let eventToFunction = function (event, data) { let funcName = 'on' + event.replace('hls', ''); - if (typeof this[funcName] !== 'function') + if (typeof this[funcName] !== 'function') { throw new Error(`Event ${event} has no generic handler in this ${this.constructor.name} class (tried ${funcName})`); + } return this[funcName].bind(this, data); }; diff --git a/src/helper/aac.js b/src/helper/aac.js index f6c2841b5fa..8d88a674f4a 100644 --- a/src/helper/aac.js +++ b/src/helper/aac.js @@ -6,18 +6,19 @@ class AAC { static getSilentFrame (codec, channelCount) { switch (codec) { case 'mp4a.40.2': - if (channelCount === 1) + if (channelCount === 1) { return new Uint8Array([0x00, 0xc8, 0x00, 0x80, 0x23, 0x80]); - else if (channelCount === 2) + } else if (channelCount === 2) { return new Uint8Array([0x21, 0x00, 0x49, 0x90, 0x02, 0x19, 0x00, 0x23, 0x80]); - else if (channelCount === 3) + } else if (channelCount === 3) { return new Uint8Array([0x00, 0xc8, 0x00, 0x80, 0x20, 0x84, 0x01, 0x26, 0x40, 0x08, 0x64, 0x00, 0x8e]); - else if (channelCount === 4) + } else if (channelCount === 4) { return new Uint8Array([0x00, 0xc8, 0x00, 0x80, 0x20, 0x84, 0x01, 0x26, 0x40, 0x08, 0x64, 0x00, 0x80, 0x2c, 0x80, 0x08, 0x02, 0x38]); - else if (channelCount === 5) + } else if (channelCount === 5) { return new Uint8Array([0x00, 0xc8, 0x00, 0x80, 0x20, 0x84, 0x01, 0x26, 0x40, 0x08, 0x64, 0x00, 0x82, 0x30, 0x04, 0x99, 0x00, 0x21, 0x90, 0x02, 0x38]); - else if (channelCount === 6) + } else if (channelCount === 6) { return new Uint8Array([0x00, 0xc8, 0x00, 0x80, 0x20, 0x84, 0x01, 0x26, 0x40, 0x08, 0x64, 0x00, 0x82, 0x30, 0x04, 0x99, 0x00, 0x21, 0x90, 0x02, 0x00, 0xb2, 0x00, 0x20, 0x08, 0xe0]); + } break; // handle HE-AAC below (mp4a.40.5 / mp4a.40.29) diff --git a/src/helper/buffer-helper.js b/src/helper/buffer-helper.js index ae641119657..7a72b5e6081 100644 --- a/src/helper/buffer-helper.js +++ b/src/helper/buffer-helper.js @@ -14,8 +14,9 @@ const BufferHelper = { if (media) { let buffered = media.buffered; for (let i = 0; i < buffered.length; i++) { - if (position >= buffered.start(i) && position <= buffered.end(i)) + if (position >= buffered.start(i) && position <= buffered.end(i)) { return true; + } } } } catch (error) { @@ -30,8 +31,9 @@ const BufferHelper = { try { if (media) { let vbuffered = media.buffered, buffered = [], i; - for (i = 0; i < vbuffered.length; i++) + for (i = 0; i < vbuffered.length; i++) { buffered.push({ start: vbuffered.start(i), end: vbuffered.end(i) }); + } return this.bufferedInfo(buffered, pos, maxHoleDuration); } @@ -50,10 +52,11 @@ const BufferHelper = { // sort on buffer.start/smaller end (IE does not always return sorted buffered range) buffered.sort(function (a, b) { let diff = a.start - b.start; - if (diff) + if (diff) { return diff; - else + } else { return b.end - a.end; + } }); // there might be some small holes between buffer time range // consider that holes smaller than maxHoleDuration are irrelevant and build another @@ -68,8 +71,9 @@ const BufferHelper = { // update lastRange.end only if smaller than item.end // e.g. [ 1, 15] with [ 2,8] => [ 1,15] (no need to modify lastRange.end) // whereas [ 1, 8] with [ 2,15] => [ 1,15] ( lastRange should switch from [1,8] to [1,15]) - if (buffered[i].end > buf2end) + if (buffered[i].end > buf2end) { buffered2[buf2len - 1].end = buffered[i].end; + } } else { // big hole buffered2.push(buffered[i]); diff --git a/src/helper/fragment-tracker.js b/src/helper/fragment-tracker.js index 5e9c4e3dade..fbd49a8a9d4 100644 --- a/src/helper/fragment-tracker.js +++ b/src/helper/fragment-tracker.js @@ -43,11 +43,13 @@ export class FragmentTracker extends EventHandler { const fragments = this.fragments; const bufferedFrags = Object.keys(fragments).filter(key => { const fragmentEntity = fragments[key]; - if (fragmentEntity.body.type !== levelType) + if (fragmentEntity.body.type !== levelType) { return false; + } - if (!fragmentEntity.buffered) + if (!fragmentEntity.buffered) { return false; + } const frag = fragmentEntity.body; return frag.startPTS <= position && position <= frag.endPTS; @@ -189,12 +191,13 @@ export class FragmentTracker extends EventHandler { let state = FragmentState.NOT_LOADED; if (fragmentEntity !== undefined) { - if (!fragmentEntity.buffered) + if (!fragmentEntity.buffered) { state = FragmentState.APPENDING; - else if (this.isPartial(fragmentEntity) === true) + } else if (this.isPartial(fragmentEntity) === true) { state = FragmentState.PARTIAL; - else + } else { state = FragmentState.OK; + } } return state; @@ -211,8 +214,9 @@ export class FragmentTracker extends EventHandler { for (let i = 0; i < timeRange.length; i++) { startTime = timeRange.start(i) - this.bufferPadding; endTime = timeRange.end(i) + this.bufferPadding; - if (startPTS >= startTime && endPTS <= endTime) + if (startPTS >= startTime && endPTS <= endTime) { return true; + } if (endPTS <= startTime) { // No need to check the rest of the timeRange as it is in order diff --git a/src/helper/level-helper.js b/src/helper/level-helper.js index c5f800cb0c3..9dcde116b2d 100644 --- a/src/helper/level-helper.js +++ b/src/helper/level-helper.js @@ -12,19 +12,22 @@ export function updatePTS (fragments, fromIdx, toIdx) { // it helps to fix drifts between playlist reported duration and fragment real duration if (toIdx > fromIdx) { fragFrom.duration = fragToPTS - fragFrom.start; - if (fragFrom.duration < 0) + if (fragFrom.duration < 0) { logger.warn(`negative duration computed for frag ${fragFrom.sn},level ${fragFrom.level}, there should be some duration drift between playlist and fragment!`); + } } else { fragTo.duration = fragFrom.start - fragToPTS; - if (fragTo.duration < 0) + if (fragTo.duration < 0) { logger.warn(`negative duration computed for frag ${fragTo.sn},level ${fragTo.level}, there should be some duration drift between playlist and fragment!`); + } } } else { // we dont know startPTS[toIdx] - if (toIdx > fromIdx) + if (toIdx > fromIdx) { fragTo.start = fragFrom.start + fragFrom.duration; - else + } else { fragTo.start = Math.max(fragFrom.start - fragTo.duration, 0); + } } } @@ -34,10 +37,11 @@ export function updateFragPTSDTS (details, frag, startPTS, endPTS, startDTS, end if (!isNaN(frag.startPTS)) { // delta PTS between audio and video let deltaPTS = Math.abs(frag.startPTS - startPTS); - if (isNaN(frag.deltaPTS)) + if (isNaN(frag.deltaPTS)) { frag.deltaPTS = deltaPTS; - else + } else { frag.deltaPTS = Math.max(deltaPTS, frag.deltaPTS); + } maxStartPTS = Math.max(startPTS, frag.startPTS); startPTS = Math.min(startPTS, frag.startPTS); @@ -56,8 +60,9 @@ export function updateFragPTSDTS (details, frag, startPTS, endPTS, startDTS, end const sn = frag.sn; // exit if sn out of range - if (!details || sn < details.startSN || sn > details.endSN) + if (!details || sn < details.startSN || sn > details.endSN) { return 0; + } let fragIdx, fragments, i; fragIdx = sn - details.startSN; @@ -69,12 +74,14 @@ export function updateFragPTSDTS (details, frag, startPTS, endPTS, startDTS, end // resulting in invalid sliding computation fragments[fragIdx] = frag; // adjust fragment PTS/duration from seqnum-1 to frag 0 - for (i = fragIdx; i > 0; i--) + for (i = fragIdx; i > 0; i--) { updatePTS(fragments, i, i - 1); + } // adjust fragment PTS/duration from seqnum to last frag - for (i = fragIdx; i < fragments.length - 1; i++) + for (i = fragIdx; i < fragments.length - 1; i++) { updatePTS(fragments, i, i + 1); + } details.PTSKnown = true; // logger.log(` frag start/end:${startPTS.toFixed(3)}/${endPTS.toFixed(3)}`); @@ -92,8 +99,9 @@ export function mergeDetails (oldDetails, newDetails) { PTSFrag; // potentially retrieve cached initsegment - if (newDetails.initSegment && oldDetails.initSegment) + if (newDetails.initSegment && oldDetails.initSegment) { newDetails.initSegment = oldDetails.initSegment; + } // check if old/new playlists have fragments in common if (end < start) { @@ -119,8 +127,9 @@ export function mergeDetails (oldDetails, newDetails) { if (ccOffset) { logger.log('discontinuity sliding from playlist, take drift into account'); - for (i = 0; i < newfragments.length; i++) + for (i = 0; i < newfragments.length; i++) { newfragments[i].cc += ccOffset; + } } // if at least one fragment contains PTS info, recompute PTS information for all fragments @@ -133,8 +142,9 @@ export function mergeDetails (oldDetails, newDetails) { if (delta >= 0 && delta < oldfragments.length) { // adjust start by sliding offset let sliding = oldfragments[delta].start; - for (i = 0; i < newfragments.length; i++) + for (i = 0; i < newfragments.length; i++) { newfragments[i].start += sliding; + } } } // if we are here, it means we have fragments overlapping between diff --git a/src/helper/mediakeys-helper.js b/src/helper/mediakeys-helper.js index e7c50c29332..b7e21033077 100644 --- a/src/helper/mediakeys-helper.js +++ b/src/helper/mediakeys-helper.js @@ -1,8 +1,9 @@ const requestMediaKeySystemAccess = (function () { - if (typeof window !== 'undefined' && window.navigator && window.navigator.requestMediaKeySystemAccess) + if (typeof window !== 'undefined' && window.navigator && window.navigator.requestMediaKeySystemAccess) { return window.navigator.requestMediaKeySystemAccess.bind(window.navigator); - else + } else { return null; + } })(); export { diff --git a/src/helper/mediasource-helper.js b/src/helper/mediasource-helper.js index db87094fdee..0c65e9a60f9 100644 --- a/src/helper/mediasource-helper.js +++ b/src/helper/mediasource-helper.js @@ -3,6 +3,7 @@ */ export function getMediaSource () { - if (typeof window !== 'undefined') + if (typeof window !== 'undefined') { return window.MediaSource || window.WebKitMediaSource; + } } diff --git a/src/hls.js b/src/hls.js index 6b4d8bfa6ca..4c656620a57 100644 --- a/src/hls.js +++ b/src/hls.js @@ -69,8 +69,9 @@ export default class Hls { * @type {HlsConfig} */ static get DefaultConfig () { - if (!Hls.defaultConfig) + if (!Hls.defaultConfig) { return hlsDefaultConfig; + } return Hls.defaultConfig; } @@ -91,19 +92,22 @@ export default class Hls { constructor (config = {}) { let defaultConfig = Hls.DefaultConfig; - if ((config.liveSyncDurationCount || config.liveMaxLatencyDurationCount) && (config.liveSyncDuration || config.liveMaxLatencyDuration)) + if ((config.liveSyncDurationCount || config.liveMaxLatencyDurationCount) && (config.liveSyncDuration || config.liveMaxLatencyDuration)) { throw new Error('Illegal hls.js config: don\'t mix up liveSyncDurationCount/liveMaxLatencyDurationCount and liveSyncDuration/liveMaxLatencyDuration'); + } for (let prop in defaultConfig) { if (prop in config) continue; config[prop] = defaultConfig[prop]; } - if (config.liveMaxLatencyDurationCount !== undefined && config.liveMaxLatencyDurationCount <= config.liveSyncDurationCount) + if (config.liveMaxLatencyDurationCount !== undefined && config.liveMaxLatencyDurationCount <= config.liveSyncDurationCount) { throw new Error('Illegal hls.js config: "liveMaxLatencyDurationCount" must be gt "liveSyncDurationCount"'); + } - if (config.liveMaxLatencyDuration !== undefined && (config.liveMaxLatencyDuration <= config.liveSyncDuration || config.liveSyncDuration === undefined)) + if (config.liveMaxLatencyDuration !== undefined && (config.liveMaxLatencyDuration <= config.liveSyncDuration || config.liveSyncDuration === undefined)) { throw new Error('Illegal hls.js config: "liveMaxLatencyDuration" must be gt "liveSyncDuration"'); + } enableLogs(config.debug); this.config = config; @@ -158,8 +162,9 @@ export default class Hls { * @var {ICoreComponent | Controller} */ let Controller = config.audioStreamController; - if (Controller) + if (Controller) { networkControllers.push(new Controller(this, fragmentTracker)); + } /** * @member {INetworkController[]} networkControllers @@ -217,8 +222,9 @@ export default class Hls { // optional subtitle controller [config.subtitleStreamController, config.timelineController].forEach(Controller => { - if (Controller) + if (Controller) { coreComponents.push(new Controller(this)); + } }); /** @@ -234,7 +240,9 @@ export default class Hls { logger.log('destroy'); this.trigger(HlsEvents.DESTROYING); this.detachMedia(); - this.coreComponents.concat(this.networkControllers).forEach(component => { component.destroy(); }); + this.coreComponents.concat(this.networkControllers).forEach(component => { + component.destroy(); + }); this.url = null; this.observer.removeAllListeners(); this._autoLevelCapping = -1; @@ -280,7 +288,9 @@ export default class Hls { */ startLoad (startPosition = -1) { logger.log(`startLoad(${startPosition})`); - this.networkControllers.forEach(controller => { controller.startLoad(startPosition); }); + this.networkControllers.forEach(controller => { + controller.startLoad(startPosition); + }); } /** @@ -288,7 +298,9 @@ export default class Hls { */ stopLoad () { logger.log('stopLoad'); - this.networkControllers.forEach(controller => { controller.stopLoad(); }); + this.networkControllers.forEach(controller => { + controller.stopLoad(); + }); } /** @@ -435,8 +447,9 @@ export default class Hls { logger.log(`set startLevel:${newLevel}`); const hls = this; // if not in automatic start level detection, ensure startLevel is greater than minAutoLevel - if (newLevel !== -1) + if (newLevel !== -1) { newLevel = Math.max(newLevel, hls.minAutoLevel); + } hls.levelController.startLevel = newLevel; } @@ -482,8 +495,9 @@ export default class Hls { let hls = this, levels = hls.levels, minAutoBitrate = hls.config.minAutoBitrate, len = levels ? levels.length : 0; for (let i = 0; i < len; i++) { const levelNextBitrate = levels[i].realBitrate ? Math.max(levels[i].realBitrate, levels[i].bitrate) : levels[i].bitrate; - if (levelNextBitrate > minAutoBitrate) + if (levelNextBitrate > minAutoBitrate) { return i; + } } return 0; } @@ -497,10 +511,11 @@ export default class Hls { const levels = hls.levels; const autoLevelCapping = hls.autoLevelCapping; let maxAutoLevel; - if (autoLevelCapping === -1 && levels && levels.length) + if (autoLevelCapping === -1 && levels && levels.length) { maxAutoLevel = levels.length - 1; - else + } else { maxAutoLevel = autoLevelCapping; + } return maxAutoLevel; } @@ -551,8 +566,9 @@ export default class Hls { */ set audioTrack (audioTrackId) { const audioTrackController = this.audioTrackController; - if (audioTrackController) + if (audioTrackController) { audioTrackController.audioTrack = audioTrackId; + } } /** @@ -586,8 +602,9 @@ export default class Hls { */ set subtitleTrack (subtitleTrackId) { const subtitleTrackController = this.subtitleTrackController; - if (subtitleTrackController) + if (subtitleTrackController) { subtitleTrackController.subtitleTrack = subtitleTrackId; + } } /** @@ -604,7 +621,8 @@ export default class Hls { */ set subtitleDisplay (value) { const subtitleTrackController = this.subtitleTrackController; - if (subtitleTrackController) + if (subtitleTrackController) { subtitleTrackController.subtitleDisplay = value; + } } } diff --git a/src/loader/fragment-loader.js b/src/loader/fragment-loader.js index 50b10e43c27..4016a2c7b9d 100644 --- a/src/loader/fragment-loader.js +++ b/src/loader/fragment-loader.js @@ -17,8 +17,9 @@ class FragmentLoader extends EventHandler { let loaders = this.loaders; for (let loaderName in loaders) { let loader = loaders[loaderName]; - if (loader) + if (loader) { loader.destroy(); + } } this.loaders = {}; @@ -84,8 +85,9 @@ class FragmentLoader extends EventHandler { loaderror (response, context, networkDetails = null) { let loader = context.loader; - if (loader) + if (loader) { loader.abort(); + } this.loaders[context.type] = undefined; this.hls.trigger(Event.ERROR, { type: ErrorTypes.NETWORK_ERROR, details: ErrorDetails.FRAG_LOAD_ERROR, fatal: false, frag: context.frag, response: response, networkDetails: networkDetails }); @@ -93,8 +95,9 @@ class FragmentLoader extends EventHandler { loadtimeout (stats, context, networkDetails = null) { let loader = context.loader; - if (loader) + if (loader) { loader.abort(); + } this.loaders[context.type] = undefined; this.hls.trigger(Event.ERROR, { type: ErrorTypes.NETWORK_ERROR, details: ErrorDetails.FRAG_LOAD_TIMEOUT, fatal: false, frag: context.frag, networkDetails: networkDetails }); diff --git a/src/loader/fragment.js b/src/loader/fragment.js index aba0de784e1..fd2271f7482 100644 --- a/src/loader/fragment.js +++ b/src/loader/fragment.js @@ -30,8 +30,9 @@ export default class Fragment { } get url () { - if (!this._url && this.relurl) + if (!this._url && this.relurl) { this._url = URLToolkit.buildAbsoluteURL(this.baseurl, this.relurl, { alwaysNormalize: true }); + } return this._url; } @@ -41,18 +42,21 @@ export default class Fragment { } get programDateTime () { - if (!this._programDateTime && this.rawProgramDateTime) + if (!this._programDateTime && this.rawProgramDateTime) { this._programDateTime = new Date(Date.parse(this.rawProgramDateTime)); + } return this._programDateTime; } get byteRange () { - if (!this._byteRange && !this.rawByteRange) + if (!this._byteRange && !this.rawByteRange) { return []; + } - if (this._byteRange) + if (this._byteRange) { return this._byteRange; + } let byteRange = []; if (this.rawByteRange) { @@ -81,8 +85,9 @@ export default class Fragment { } get decryptdata () { - if (!this._decryptdata) + if (!this._decryptdata) { this._decryptdata = this.fragmentDecryptdataFromLevelkey(this.levelkey, this.sn); + } return this._decryptdata; } @@ -108,8 +113,9 @@ export default class Fragment { createInitializationVector (segmentNumber) { let uint8View = new Uint8Array(16); - for (let i = 12; i < 16; i++) + for (let i = 12; i < 16; i++) { uint8View[i] = (segmentNumber >> 8 * (15 - i)) & 0xff; + } return uint8View; } diff --git a/src/loader/key-loader.js b/src/loader/key-loader.js index 9013850f525..7f464dd82f4 100644 --- a/src/loader/key-loader.js +++ b/src/loader/key-loader.js @@ -18,8 +18,9 @@ class KeyLoader extends EventHandler { destroy () { for (let loaderName in this.loaders) { let loader = this.loaders[loaderName]; - if (loader) + if (loader) { loader.destroy(); + } } this.loaders = {}; EventHandler.prototype.destroy.call(this); @@ -67,8 +68,9 @@ class KeyLoader extends EventHandler { loaderror (response, context) { let frag = context.frag, loader = frag.loader; - if (loader) + if (loader) { loader.abort(); + } this.loaders[context.type] = undefined; this.hls.trigger(Event.ERROR, { type: ErrorTypes.NETWORK_ERROR, details: ErrorDetails.KEY_LOAD_ERROR, fatal: false, frag: frag, response: response }); @@ -77,8 +79,9 @@ class KeyLoader extends EventHandler { loadtimeout (stats, context) { let frag = context.frag, loader = frag.loader; - if (loader) + if (loader) { loader.abort(); + } this.loaders[context.type] = undefined; this.hls.trigger(Event.ERROR, { type: ErrorTypes.NETWORK_ERROR, details: ErrorDetails.KEY_LOAD_TIMEOUT, fatal: false, frag: frag }); diff --git a/src/loader/level-key.js b/src/loader/level-key.js index 76c721d7a78..34ae3f4936f 100644 --- a/src/loader/level-key.js +++ b/src/loader/level-key.js @@ -9,8 +9,9 @@ export default class LevelKey { } get uri () { - if (!this._uri && this.reluri) + if (!this._uri && this.reluri) { this._uri = URLToolkit.buildAbsoluteURL(this.baseuri, this.reluri, { alwaysNormalize: true }); + } return this._uri; } diff --git a/src/loader/m3u8-parser.js b/src/loader/m3u8-parser.js index 3b235f88fcf..b1b81fb4815 100644 --- a/src/loader/m3u8-parser.js +++ b/src/loader/m3u8-parser.js @@ -29,15 +29,17 @@ const LEVEL_PLAYLIST_REGEX_SLOW = /(?:(?:#(EXTM3U))|(?:#EXT-X-(PLAYLIST-TYPE):(. export default class M3U8Parser { static findGroup (groups, mediaGroupId) { - if (!groups) + if (!groups) { return null; + } let matchingGroup = null; for (let i = 0; i < groups.length; i++) { const group = groups[i]; - if (group.id === mediaGroupId) + if (group.id === mediaGroupId) { matchingGroup = group; + } } return matchingGroup; @@ -96,8 +98,9 @@ export default class M3U8Parser { setCodecs([].concat((attrs.CODECS || '').split(/[ ,]+/)), level); - if (level.videoCodec && level.videoCodec.indexOf('avc1') !== -1) + if (level.videoCodec && level.videoCodec.indexOf('avc1') !== -1) { level.videoCodec = M3U8Parser.convertAVC1ToAVCOTI(level.videoCodec); + } levels.push(level); } @@ -119,12 +122,14 @@ export default class M3U8Parser { media.default = (attrs.DEFAULT === 'YES'); media.autoselect = (attrs.AUTOSELECT === 'YES'); media.forced = (attrs.FORCED === 'YES'); - if (attrs.URI) + if (attrs.URI) { media.url = M3U8Parser.resolve(attrs.URI, baseurl); + } media.lang = attrs.LANGUAGE; - if (!media.name) + if (!media.name) { media.name = media.lang; + } if (audioGroups.length) { const groupCodec = M3U8Parser.findGroup(audioGroups, media.groupId); @@ -194,20 +199,23 @@ export default class M3U8Parser { frag.rawByteRange = (' ' + result[4]).slice(1); if (prevFrag) { const lastByteRangeEndOffset = prevFrag.byteRangeEndOffset; - if (lastByteRangeEndOffset) + if (lastByteRangeEndOffset) { frag.lastByteRangeEndOffset = lastByteRangeEndOffset; + } } } else if (result[5]) { // PROGRAM-DATE-TIME // avoid sliced strings https://github.com/video-dev/hls.js/issues/939 frag.rawProgramDateTime = (' ' + result[5]).slice(1); frag.tagList.push(['PROGRAM-DATE-TIME', frag.rawProgramDateTime]); - if (level.programDateTime === undefined) + if (level.programDateTime === undefined) { level.programDateTime = new Date(new Date(Date.parse(result[5])) - 1000 * totalduration); + } } else { result = result[0].match(LEVEL_PLAYLIST_REGEX_SLOW); for (i = 1; i < result.length; i++) { - if (result[i] !== undefined) + if (result[i] !== undefined) { break; + } } // avoid sliced strings https://github.com/video-dev/hls.js/issues/939 @@ -267,8 +275,9 @@ export default class M3U8Parser { let startAttrs = new AttrList(startParams); let startTimeOffset = startAttrs.decimalFloatingPoint('TIME-OFFSET'); // TIME-OFFSET can be 0 - if (!isNaN(startTimeOffset)) + if (!isNaN(startTimeOffset)) { level.startTimeOffset = startTimeOffset; + } break; case 'MAP': diff --git a/src/loader/playlist-loader.js b/src/loader/playlist-loader.js index f1228ffc302..3929851650f 100644 --- a/src/loader/playlist-loader.js +++ b/src/loader/playlist-loader.js @@ -128,8 +128,9 @@ class PlaylistLoader extends EventHandler { } resetInternalLoader (contextType) { - if (this.loaders[contextType]) + if (this.loaders[contextType]) { delete this.loaders[contextType]; + } } /** @@ -138,8 +139,9 @@ class PlaylistLoader extends EventHandler { destroyInternalLoaders () { for (let contextType in this.loaders) { let loader = this.loaders[contextType]; - if (loader) + if (loader) { loader.destroy(); + } this.resetInternalLoader(contextType); } @@ -257,10 +259,11 @@ class PlaylistLoader extends EventHandler { } // Check if chunk-list or master. handle empty chunk list case (first EXTINF not signaled, but TARGETDURATION present) - if (string.indexOf('#EXTINF:') > 0 || string.indexOf('#EXT-X-TARGETDURATION:') > 0) + if (string.indexOf('#EXTINF:') > 0 || string.indexOf('#EXT-X-TARGETDURATION:') > 0) { this._handleTrackOrLevelPlaylist(response, stats, context, networkDetails); - else + } else { this._handleMasterPlaylist(response, stats, context, networkDetails); + } } loaderror (response, context, networkDetails = null) { @@ -297,8 +300,9 @@ class PlaylistLoader extends EventHandler { // check if we have found an audio track embedded in main playlist (audio track without URI attribute) let embeddedAudioFound = false; audioTracks.forEach(audioTrack => { - if (!audioTrack.url) + if (!audioTrack.url) { embeddedAudioFound = true; + } }); // if no embedded audio track defined, but audio codec signaled in quality level, @@ -391,8 +395,9 @@ class PlaylistLoader extends EventHandler { const segRefInfo = segmentRef.info; const frag = context.levelDetails.fragments[index]; - if (frag.byteRange.length === 0) + if (frag.byteRange.length === 0) { frag.rawByteRange = String(1 + segRefInfo.end - segRefInfo.start) + '@' + String(segRefInfo.start); + } }); context.levelDetails.initSegment.rawByteRange = String(sidxInfo.moovEndOffset) + '@0'; diff --git a/src/remux/dummy-remuxer.js b/src/remux/dummy-remuxer.js index c9d512968dd..72418423052 100644 --- a/src/remux/dummy-remuxer.js +++ b/src/remux/dummy-remuxer.js @@ -29,8 +29,9 @@ class DummyRemuxer { while (track.samples.length) { avcSample = track.samples.shift(); // loop through AVC sample NALUs - while (avcSample.units.length) + while (avcSample.units.length) { unit = avcSample.units.shift(); + } } // please lint timeOffset = timeOffset; diff --git a/src/remux/mp4-generator.js b/src/remux/mp4-generator.js index b0839b4ebd0..d59d19570eb 100644 --- a/src/remux/mp4-generator.js +++ b/src/remux/mp4-generator.js @@ -150,8 +150,9 @@ class MP4 { len = i, result; // calculate the total size we need to allocate - while (i--) + while (i--) { size += payload[i].byteLength; + } result = new Uint8Array(size); result[0] = (size >> 24) & 0xff; @@ -218,10 +219,11 @@ class MP4 { } static minf (track) { - if (track.type === 'audio') + if (track.type === 'audio') { return MP4.box(MP4.types.minf, MP4.box(MP4.types.smhd, MP4.SMHD), MP4.DINF, MP4.stbl(track)); - else + } else { return MP4.box(MP4.types.minf, MP4.box(MP4.types.vmhd, MP4.VMHD), MP4.DINF, MP4.stbl(track)); + } } static moof (sn, baseMediaDecodeTime, track) { @@ -235,8 +237,9 @@ class MP4 { i = tracks.length, boxes = []; - while (i--) + while (i--) { boxes[i] = MP4.trak(tracks[i]); + } return MP4.box.apply(null, [MP4.types.moov, MP4.mvhd(tracks[0].timescale, tracks[0].duration)].concat(boxes).concat(MP4.mvex(tracks))); } @@ -246,8 +249,9 @@ class MP4 { i = tracks.length, boxes = []; - while (i--) + while (i--) { boxes[i] = MP4.trex(tracks[i]); + } return MP4.box.apply(null, [MP4.types.mvex].concat(boxes)); } @@ -460,8 +464,9 @@ class MP4 { static stsd (track) { if (track.type === 'audio') { - if (!track.isAAC && track.codec === 'mp3') + if (!track.isAAC && track.codec === 'mp3') { return MP4.box(MP4.types.stsd, MP4.STSD, MP4.mp3(track)); + } return MP4.box(MP4.types.stsd, MP4.STSD, MP4.mp4a(track)); } else { @@ -632,8 +637,9 @@ class MP4 { } static initSegment (tracks) { - if (!MP4.types) + if (!MP4.types) { MP4.init(); + } let movie = MP4.moov(tracks), result; result = new Uint8Array(MP4.FTYP.byteLength + movie.byteLength); diff --git a/src/remux/mp4-remuxer.js b/src/remux/mp4-remuxer.js index 713fa257120..8af2d8c195b 100644 --- a/src/remux/mp4-remuxer.js +++ b/src/remux/mp4-remuxer.js @@ -34,8 +34,9 @@ class MP4Remuxer { remux (audioTrack, videoTrack, id3Track, textTrack, timeOffset, contiguous, accurateTimeOffset) { // generate Init Segment if needed - if (!this.ISGenerated) + if (!this.ISGenerated) { this.generateIS(audioTrack, videoTrack, timeOffset); + } if (this.ISGenerated) { const nbAudioSamples = audioTrack.samples.length; @@ -64,8 +65,9 @@ class MP4Remuxer { // logger.log('nb AVC samples:' + videoTrack.samples.length); if (nbVideoSamples) { let audioTrackLength; - if (audioData) + if (audioData) { audioTrackLength = audioData.endPTS - audioData.startPTS; + } // if initSegment was generated without video samples, regenerate it again if (!videoTrack.timescale) { @@ -78,18 +80,21 @@ class MP4Remuxer { // logger.log('nb AVC samples:' + videoTrack.samples.length); if (nbVideoSamples) { let videoData = this.remuxVideo(videoTrack, videoTimeOffset, contiguous, 0, accurateTimeOffset); - if (videoData && audioTrack.codec) + if (videoData && audioTrack.codec) { this.remuxEmptyAudio(audioTrack, audioTimeOffset, contiguous, videoData); + } } } } // logger.log('nb ID3 samples:' + audioTrack.samples.length); - if (id3Track.samples.length) + if (id3Track.samples.length) { this.remuxID3(id3Track, timeOffset); + } // logger.log('nb ID3 samples:' + audioTrack.samples.length); - if (textTrack.samples.length) + if (textTrack.samples.length) { this.remuxText(textTrack, timeOffset); + } // notify end of parsing this.observer.trigger(Event.FRAG_PARSED); @@ -106,8 +111,9 @@ class MP4Remuxer { computePTSDTS = (this._initPTS === undefined), initPTS, initDTS; - if (computePTSDTS) + if (computePTSDTS) { initPTS = initDTS = Infinity; + } if (audioTrack.config && audioSamples.length) { // let's use audio sampling rate as MP4 time scale. @@ -203,8 +209,9 @@ class MP4Remuxer { const isSafari = this.isSafari; - if (nbSamples === 0) + if (nbSamples === 0) { return; + } // Safari does not like overlapping DTS on consecutive fragments. let's use nextAvcDts to overcome this if fragments are consecutive if (isSafari) { @@ -242,8 +249,9 @@ class MP4Remuxer { let PTSDTSshift = inputSamples.reduce((prev, curr) => Math.max(Math.min(prev, curr.pts - curr.dts), -18000), 0); if (PTSDTSshift < 0) { logger.warn(`PTS < DTS detected in video samples, shifting DTS by ${Math.round(PTSDTSshift / 90)} ms to overcome this issue`); - for (let i = 0; i < inputSamples.length; i++) + for (let i = 0; i < inputSamples.length; i++) { inputSamples[i].dts += PTSDTSshift; + } } // compute first DTS and last DTS, normalize them against reference value @@ -256,10 +264,11 @@ class MP4Remuxer { // if fragment are contiguous, detect hole/overlapping between fragments if (contiguous) { if (delta) { - if (delta > 1) + if (delta > 1) { logger.log(`AVC:${delta} ms hole between fragments detected,filling it`); - else if (delta < -1) + } else if (delta < -1) { logger.log(`AVC:${(-delta)} ms overlapping between fragments detected`); + } // remove hole/gap : set DTS to next expected DTS firstDTS = nextAvcDts; @@ -280,15 +289,17 @@ class MP4Remuxer { // on Safari let's signal the same sample duration for all samples // sample duration (as expected by trun MP4 boxes), should be the delta between sample DTS // set this constant duration as being the avg delta between consecutive DTS. - if (isSafari) + if (isSafari) { mp4SampleDuration = Math.round((lastDTS - firstDTS) / (inputSamples.length - 1)); + } let nbNalu = 0, naluLen = 0; for (let i = 0; i < nbSamples; i++) { // compute total/avc sample length and nb of NAL units let sample = inputSamples[i], units = sample.units, nbUnits = units.length, sampleLen = 0; - for (let j = 0; j < nbUnits; j++) + for (let j = 0; j < nbUnits; j++) { sampleLen += units[j].data.length; + } naluLen += sampleLen; nbNalu += nbUnits; @@ -356,8 +367,9 @@ class MP4Remuxer { // We subtract lastFrameDuration from deltaToFrameEnd to try to prevent any video // frame overlap. maxBufferHole should be >> lastFrameDuration anyway. mp4SampleDuration = deltaToFrameEnd - lastFrameDuration; - if (mp4SampleDuration < 0) + if (mp4SampleDuration < 0) { mp4SampleDuration = lastFrameDuration; + } logger.log(`It is approximately ${deltaToFrameEnd / 90} ms to the next segment; using duration ${mp4SampleDuration / 90} ms for the last video frame.`); } else { @@ -467,8 +479,9 @@ class MP4Remuxer { }); // in case all samples have negative PTS, and have been filtered out, return now - if (inputSamples.length === 0) + if (inputSamples.length === 0) { return; + } if (!contiguous) { if (!accurateTimeOffset) { @@ -561,8 +574,9 @@ class MP4Remuxer { logger.log(`${delta} ms hole between AAC samples detected,filling it`); if (numMissingFrames > 0) { fillFrame = AAC.getSilentFrame(track.manifestCodec || track.codec, track.channelCount); - if (!fillFrame) + if (!fillFrame) { fillFrame = unit.subarray(); + } track.len += numMissingFrames * fillFrame.length; } @@ -654,10 +668,11 @@ class MP4Remuxer { // logger.log('Audio/PTS/PTSend:' + audioSample.pts.toFixed(0) + '/' + this.nextAacDts.toFixed(0)); track.len = 0; track.samples = outputSamples; - if (rawMPEG) + if (rawMPEG) { moof = new Uint8Array(); - else + } else { moof = MP4.moof(track.sequenceNumber++, firstPTS / scaleFactor, track); + } track.samples = []; const start = firstPTS / inputTimeScale; @@ -767,8 +782,9 @@ class MP4Remuxer { _PTSNormalize (value, reference) { let offset; - if (reference === undefined) + if (reference === undefined) { return value; + } if (reference < value) { // - 2^33 @@ -780,8 +796,9 @@ class MP4Remuxer { /* PTS is 33bit (from 0 to 2^33 -1) if diff between value and reference is bigger than half of the amplitude (2^32) then it means that PTS looping occured. fill the gap */ - while (Math.abs(value - reference) > 4294967296) + while (Math.abs(value - reference) > 4294967296) { value += offset; + } return value; } diff --git a/src/remux/passthrough-remuxer.js b/src/remux/passthrough-remuxer.js index b7db60e8f71..9b450afada1 100644 --- a/src/remux/passthrough-remuxer.js +++ b/src/remux/passthrough-remuxer.js @@ -20,11 +20,13 @@ class PassThroughRemuxer { remux (audioTrack, videoTrack, id3Track, textTrack, timeOffset, contiguous, accurateTimeOffset, rawData) { let observer = this.observer; let streamType = ''; - if (audioTrack) + if (audioTrack) { streamType += 'audio'; + } - if (videoTrack) + if (videoTrack) { streamType += 'video'; + } observer.trigger(Event.FRAG_PARSING_DATA, { data1: rawData, diff --git a/src/task-loop.js b/src/task-loop.js index 3b8c7a9d9dc..f06e0dec113 100644 --- a/src/task-loop.js +++ b/src/task-loop.js @@ -56,8 +56,9 @@ export default class TaskLoop extends EventHandler { this._tickCallCount++; if (this._tickCallCount === 1) { this.doTick(); - if (this._tickCallCount > 1) + if (this._tickCallCount > 1) { setTimeout(this.tick.bind(this), 0); + } this._tickCallCount = 0; } diff --git a/src/utils/attr-list.js b/src/utils/attr-list.js index 45cfd93ae14..b1796d54c9d 100755 --- a/src/utils/attr-list.js +++ b/src/utils/attr-list.js @@ -4,19 +4,22 @@ const ATTR_LIST_REGEX = /\s*(.+?)\s*=((?:\".*?\")|.*?)(?:,|$)/g; // eslint-disab // adapted from https://github.com/kanongil/node-m3u8parse/blob/master/attrlist.js class AttrList { constructor (attrs) { - if (typeof attrs === 'string') + if (typeof attrs === 'string') { attrs = AttrList.parseAttrList(attrs); + } for (let attr in attrs) { - if (attrs.hasOwnProperty(attr)) + if (attrs.hasOwnProperty(attr)) { this[attr] = attrs[attr]; + } } } decimalInteger (attrName) { const intValue = parseInt(this[attrName], 10); - if (intValue > Number.MAX_SAFE_INTEGER) + if (intValue > Number.MAX_SAFE_INTEGER) { return Infinity; + } return intValue; } @@ -27,8 +30,9 @@ class AttrList { stringValue = ((stringValue.length & 1) ? '0' : '') + stringValue; const value = new Uint8Array(stringValue.length / 2); - for (let i = 0; i < stringValue.length / 2; i++) + for (let i = 0; i < stringValue.length / 2; i++) { value[i] = parseInt(stringValue.slice(i * 2, i * 2 + 2), 16); + } return value; } else { @@ -38,8 +42,9 @@ class AttrList { hexadecimalIntegerAsNumber (attrName) { const intValue = parseInt(this[attrName], 16); - if (intValue > Number.MAX_SAFE_INTEGER) + if (intValue > Number.MAX_SAFE_INTEGER) { return Infinity; + } return intValue; } @@ -54,8 +59,9 @@ class AttrList { decimalResolution (attrName) { const res = DECIMAL_RESOLUTION_REGEX.exec(this[attrName]); - if (res === null) + if (res === null) { return undefined; + } return { width: parseInt(res[1], 10), @@ -70,8 +76,9 @@ class AttrList { let value = match[2], quote = '"'; if (value.indexOf(quote) === 0 && - value.lastIndexOf(quote) === (value.length - 1)) + value.lastIndexOf(quote) === (value.length - 1)) { value = value.slice(1, -1); + } attrs[match[1]] = value; } diff --git a/src/utils/binary-search.js b/src/utils/binary-search.js index 80ca66091f9..87bd46828b4 100644 --- a/src/utils/binary-search.js +++ b/src/utils/binary-search.js @@ -25,12 +25,13 @@ let BinarySearch = { currentElement = list[currentIndex]; let comparisonResult = comparisonFunction(currentElement); - if (comparisonResult > 0) + if (comparisonResult > 0) { minIndex = currentIndex + 1; - else if (comparisonResult < 0) + } else if (comparisonResult < 0) { maxIndex = currentIndex - 1; - else + } else { return currentElement; + } } return null; diff --git a/src/utils/cea-608-parser.js b/src/utils/cea-608-parser.js index 1f69119c3e5..ba2fc65e374 100644 --- a/src/utils/cea-608-parser.js +++ b/src/utils/cea-608-parser.js @@ -144,8 +144,9 @@ let specialCea608CharsCodes = { */ let getCharForByte = function (byte) { let charCode = byte; - if (specialCea608CharsCodes.hasOwnProperty(byte)) + if (specialCea608CharsCodes.hasOwnProperty(byte)) { charCode = specialCea608CharsCodes[byte]; + } return String.fromCharCode(charCode); }; @@ -172,15 +173,17 @@ let logger = { }, log: function (severity, msg) { let minLevel = this.verboseFilter[severity]; - if (this.verboseLevel >= minLevel) + if (this.verboseLevel >= minLevel) { console.log(this.time + ' [' + severity + '] ' + msg); + } } }; let numArrayToHexArray = function (numArray) { let hexArray = []; - for (let j = 0; j < numArray.length; j++) + for (let j = 0; j < numArray.length; j++) { hexArray.push(numArray[j].toString(16)); + } return hexArray; }; @@ -206,8 +209,9 @@ class PenState { let attribs = ['foreground', 'underline', 'italics', 'background', 'flash']; for (let i = 0; i < attribs.length; i++) { let style = attribs[i]; - if (styles.hasOwnProperty(style)) + if (styles.hasOwnProperty(style)) { this[style] = styles[style]; + } } } @@ -283,8 +287,9 @@ class StyledUnicodeChar { class Row { constructor () { this.chars = []; - for (let i = 0; i < NR_COLS; i++) + for (let i = 0; i < NR_COLS; i++) { this.chars.push(new StyledUnicodeChar()); + } this.pos = 0; this.currPenState = new PenState(); @@ -302,8 +307,9 @@ class Row { } copy (other) { - for (let i = 0; i < NR_COLS; i++) + for (let i = 0; i < NR_COLS; i++) { this.chars[i].copy(other.chars[i]); + } } isEmpty () { @@ -321,8 +327,9 @@ class Row { * Set the cursor to a valid column. */ setCursor (absPos) { - if (this.pos !== absPos) + if (this.pos !== absPos) { this.pos = absPos; + } if (this.pos < 0) { logger.log('ERROR', 'Negative cursor position ' + this.pos); @@ -339,8 +346,9 @@ class Row { moveCursor (relPos) { let newPos = this.pos + relPos; if (relPos > 1) { - for (let i = this.pos + 1; i < newPos + 1; i++) + for (let i = this.pos + 1; i < newPos + 1; i++) { this.chars[i].setPenState(this.currPenState); + } } this.setCursor(newPos); } @@ -369,8 +377,9 @@ class Row { clearFromPos (startPos) { let i; - for (i = startPos; i < NR_COLS; i++) + for (i = startPos; i < NR_COLS; i++) { this.chars[i].reset(); + } } clear () { @@ -388,15 +397,17 @@ class Row { let empty = true; for (let i = 0; i < NR_COLS; i++) { let char = this.chars[i].uchar; - if (char !== ' ') + if (char !== ' ') { empty = false; + } chars.push(char); } - if (empty) + if (empty) { return ''; - else + } else { return chars.join(''); + } } setPenStyles (styles) { @@ -413,8 +424,9 @@ class Row { class CaptionScreen { constructor () { this.rows = []; - for (let i = 0; i < NR_ROWS; i++) - this.rows.push(new Row()); // Note that we use zero-based numbering (0-14) + for (let i = 0; i < NR_ROWS; i++) { + this.rows.push(new Row()); + } // Note that we use zero-based numbering (0-14) this.currRow = NR_ROWS - 1; this.nrRollUpRows = null; @@ -422,8 +434,9 @@ class CaptionScreen { } reset () { - for (let i = 0; i < NR_ROWS; i++) + for (let i = 0; i < NR_ROWS; i++) { this.rows[i].clear(); + } this.currRow = NR_ROWS - 1; } @@ -440,8 +453,9 @@ class CaptionScreen { } copy (other) { - for (let i = 0; i < NR_ROWS; i++) + for (let i = 0; i < NR_ROWS; i++) { this.rows[i].copy(other.rows[i]); + } } isEmpty () { @@ -492,14 +506,16 @@ class CaptionScreen { setPAC (pacData) { logger.log('INFO', 'pacData = ' + JSON.stringify(pacData)); let newRow = pacData.row - 1; - if (this.nrRollUpRows && newRow < this.nrRollUpRows - 1) + if (this.nrRollUpRows && newRow < this.nrRollUpRows - 1) { newRow = this.nrRollUpRows - 1; + } // Make sure this only affects Roll-up Captions by checking this.nrRollUpRows if (this.nrRollUpRows && this.currRow !== newRow) { // clear all rows first - for (let i = 0; i < NR_ROWS; i++) + for (let i = 0; i < NR_ROWS; i++) { this.rows[i].clear(); + } // Copy this.nrRollUpRows rows from lastOutputScreen and place it in the newRow location // topRowIndex - the start of rows to copy (inclusive index) @@ -510,8 +526,9 @@ class CaptionScreen { if (lastOutputScreen) { let prevLineTime = lastOutputScreen.rows[topRowIndex].cueStartTime; if (prevLineTime && prevLineTime < logger.time) { - for (let i = 0; i < this.nrRollUpRows; i++) + for (let i = 0; i < this.nrRollUpRows; i++) { this.rows[newRow - this.nrRollUpRows + i + 1].copy(lastOutputScreen.rows[topRowIndex + i]); + } } } } @@ -568,17 +585,19 @@ class CaptionScreen { let rowText = this.rows[i].getTextString(); if (rowText) { rowNr = i + 1; - if (asOneRow) + if (asOneRow) { displayText.push('Row ' + rowNr + ': \'' + rowText + '\''); - else + } else { displayText.push(rowText.trim()); + } } } if (displayText.length > 0) { - if (asOneRow) + if (asOneRow) { text = '[' + displayText.join(' | ') + ']'; - else + } else { text = displayText.join('\n'); + } } return text; } @@ -634,8 +653,9 @@ class Cea608Channel { } setMode (newMode) { - if (newMode === this.mode) + if (newMode === this.mode) { return; + } this.mode = newMode; logger.log('INFO', 'MODE=' + newMode); @@ -653,8 +673,9 @@ class Cea608Channel { } insertChars (chars) { - for (let i = 0; i < chars.length; i++) + for (let i = 0; i < chars.length; i++) { this.writeScreen.insertChar(chars[i]); + } let screen = this.writeScreen === this.displayedMemory ? 'DISP' : 'NON_DISP'; logger.log('INFO', screen + ': ' + this.writeScreen.getDisplayText(true)); @@ -671,12 +692,14 @@ class Cea608Channel { ccBS () { // BackSpace logger.log('INFO', 'BS - BackSpace'); - if (this.mode === 'MODE_TEXT') + if (this.mode === 'MODE_TEXT') { return; + } this.writeScreen.backSpace(); - if (this.writeScreen === this.displayedMemory) + if (this.writeScreen === this.displayedMemory) { this.outputDataUpdate(); + } } ccAOF () { // Reserved (formerly Alarm Off) @@ -771,8 +794,9 @@ class Cea608Channel { outputDataUpdate (dispatch = false) { let t = logger.time; - if (t === null) + if (t === null) { return; + } if (this.outputFilter) { if (this.cueStartTime === null && !this.displayedMemory.isEmpty()) { // Start of a new cue @@ -781,8 +805,9 @@ class Cea608Channel { if (!this.displayedMemory.equals(this.lastOutputScreen)) { if (this.outputFilter.newCue) { this.outputFilter.newCue(this.cueStartTime, t, this.lastOutputScreen); - if (dispatch === true && this.outputFilter.dispatchCue) + if (dispatch === true && this.outputFilter.dispatchCue) { this.outputFilter.dispatchCue(); + } } this.cueStartTime = this.displayedMemory.isEmpty() ? null : t; } @@ -794,8 +819,9 @@ class Cea608Channel { cueSplitAtTime (t) { if (this.outputFilter) { if (!this.displayedMemory.isEmpty()) { - if (this.outputFilter.newCue) + if (this.outputFilter.newCue) { this.outputFilter.newCue(this.cueStartTime, t, this.displayedMemory); + } this.cueStartTime = t; } @@ -845,14 +871,17 @@ class Cea608Parser { logger.log('DATA', '[' + numArrayToHexArray([byteList[i], byteList[i + 1]]) + '] -> (' + numArrayToHexArray([a, b]) + ')'); } cmdFound = this.parseCmd(a, b); - if (!cmdFound) + if (!cmdFound) { cmdFound = this.parseMidrow(a, b); + } - if (!cmdFound) + if (!cmdFound) { cmdFound = this.parsePAC(a, b); + } - if (!cmdFound) + if (!cmdFound) { cmdFound = this.parseBackgroundAttributes(a, b); + } if (!cmdFound) { charsFound = this.parseChars(a, b); @@ -886,8 +915,9 @@ class Cea608Parser { let cond1 = (a === 0x14 || a === 0x1C) && (b >= 0x20 && b <= 0x2F); let cond2 = (a === 0x17 || a === 0x1F) && (b >= 0x21 && b <= 0x23); - if (!(cond1 || cond2)) + if (!(cond1 || cond2)) { return false; + } if (a === this.lastCmdA && b === this.lastCmdB) { this.lastCmdA = null; @@ -896,46 +926,48 @@ class Cea608Parser { return true; } - if (a === 0x14 || a === 0x17) + if (a === 0x14 || a === 0x17) { chNr = 1; - else - chNr = 2; // (a === 0x1C || a=== 0x1f) + } else { + chNr = 2; + } // (a === 0x1C || a=== 0x1f) let channel = this.channels[chNr - 1]; if (a === 0x14 || a === 0x1C) { - if (b === 0x20) + if (b === 0x20) { channel.ccRCL(); - else if (b === 0x21) + } else if (b === 0x21) { channel.ccBS(); - else if (b === 0x22) + } else if (b === 0x22) { channel.ccAOF(); - else if (b === 0x23) + } else if (b === 0x23) { channel.ccAON(); - else if (b === 0x24) + } else if (b === 0x24) { channel.ccDER(); - else if (b === 0x25) + } else if (b === 0x25) { channel.ccRU(2); - else if (b === 0x26) + } else if (b === 0x26) { channel.ccRU(3); - else if (b === 0x27) + } else if (b === 0x27) { channel.ccRU(4); - else if (b === 0x28) + } else if (b === 0x28) { channel.ccFON(); - else if (b === 0x29) + } else if (b === 0x29) { channel.ccRDC(); - else if (b === 0x2A) + } else if (b === 0x2A) { channel.ccTR(); - else if (b === 0x2B) + } else if (b === 0x2B) { channel.ccRTD(); - else if (b === 0x2C) + } else if (b === 0x2C) { channel.ccEDM(); - else if (b === 0x2D) + } else if (b === 0x2D) { channel.ccCR(); - else if (b === 0x2E) + } else if (b === 0x2E) { channel.ccENM(); - else if (b === 0x2F) + } else if (b === 0x2F) { channel.ccEOC(); + } } else { // a == 0x17 || a == 0x1F channel.ccTO(b - 0x20); } @@ -953,10 +985,11 @@ class Cea608Parser { let chNr = null; if (((a === 0x11) || (a === 0x19)) && b >= 0x20 && b <= 0x2f) { - if (a === 0x11) + if (a === 0x11) { chNr = 1; - else + } else { chNr = 2; + } if (chNr !== this.currChNr) { logger.log('ERROR', 'Mismatch channel in midrow parsing'); @@ -979,8 +1012,9 @@ class Cea608Parser { let case1 = ((a >= 0x11 && a <= 0x17) || (a >= 0x19 && a <= 0x1F)) && (b >= 0x40 && b <= 0x7F); let case2 = (a === 0x10 || a === 0x18) && (b >= 0x40 && b <= 0x5F); - if (!(case1 || case2)) + if (!(case1 || case2)) { return false; + } if (a === this.lastCmdA && b === this.lastCmdB) { this.lastCmdA = null; @@ -1012,10 +1046,11 @@ class Cea608Parser { let pacIndex = byte; let pacData = { color: null, italics: false, indent: null, underline: false, row: row }; - if (byte > 0x5F) + if (byte > 0x5F) { pacIndex = byte - 0x60; - else + } else { pacIndex = byte - 0x40; + } pacData.underline = (pacIndex & 1) === 1; if (pacIndex <= 0xd) { @@ -1048,12 +1083,13 @@ class Cea608Parser { if (charCode1 >= 0x11 && charCode1 <= 0x13) { // Special character let oneCode = b; - if (charCode1 === 0x11) + if (charCode1 === 0x11) { oneCode = b + 0x50; - else if (charCode1 === 0x12) + } else if (charCode1 === 0x12) { oneCode = b + 0x70; - else + } else { oneCode = b + 0x90; + } logger.log('INFO', 'Special char \'' + getCharForByte(oneCode) + '\' in channel ' + channelNr); charCodes = [oneCode]; @@ -1081,21 +1117,24 @@ class Cea608Parser { let case1 = (a === 0x10 || a === 0x18) && (b >= 0x20 && b <= 0x2f); let case2 = (a === 0x17 || a === 0x1f) && (b >= 0x2d && b <= 0x2f); - if (!(case1 || case2)) + if (!(case1 || case2)) { return false; + } bkgData = {}; if (a === 0x10 || a === 0x18) { index = Math.floor((b - 0x20) / 2); bkgData.background = backgroundColors[index]; - if (b % 2 === 1) + if (b % 2 === 1) { bkgData.background = bkgData.background + '_semi'; + } } else if (b === 0x2d) { bkgData.background = 'transparent'; } else { bkgData.foreground = 'black'; - if (b === 0x2f) + if (b === 0x2f) { bkgData.underline = true; + } } chNr = (a < 0x18) ? 1 : 2; channel = this.channels[chNr - 1]; @@ -1110,8 +1149,9 @@ class Cea608Parser { */ reset () { for (let i = 0; i < this.channels.length; i++) { - if (this.channels[i]) + if (this.channels[i]) { this.channels[i].reset(); + } } this.lastCmdA = null; this.lastCmdB = null; @@ -1122,8 +1162,9 @@ class Cea608Parser { */ cueSplitAtTime (t) { for (let i = 0; i < this.channels.length; i++) { - if (this.channels[i]) + if (this.channels[i]) { this.channels[i].cueSplitAtTime(t); + } } } } diff --git a/src/utils/cues.js b/src/utils/cues.js index 5b4e7993628..3fe2e5b8931 100644 --- a/src/utils/cues.js +++ b/src/utils/cues.js @@ -27,22 +27,25 @@ export function newCue (track, startTime, endTime, captionScreen) { row.cueStartTime = startTime; // Give a slight bump to the endTime if it's equal to startTime to avoid a SyntaxError in IE - if (startTime === endTime) + if (startTime === endTime) { endTime += 0.0001; + } cue = new VTTCue(startTime, endTime, fixLineBreaks(text.trim())); - if (indent >= 16) + if (indent >= 16) { indent--; - else + } else { indent++; + } // VTTCue.line get's flakey when using controls, so let's now include line 13&14 // also, drop line 1 since it's to close to the top - if (navigator.userAgent.match(/Firefox\//)) + if (navigator.userAgent.match(/Firefox\//)) { cue.line = r + 1; - else + } else { cue.line = (r > 7 ? r - 2 : r + 1); + } cue.align = 'left'; // Clamp the position between 0 and 100 - if out of these bounds, Firefox throws an exception and captions break diff --git a/src/utils/discontinuities.js b/src/utils/discontinuities.js index 0ac57f0c240..543a32925e5 100644 --- a/src/utils/discontinuities.js +++ b/src/utils/discontinuities.js @@ -17,20 +17,22 @@ export function findFirstFragWithCC (fragments, cc) { export function findFragWithCC (fragments, CC) { return BinarySearch.search(fragments, (candidate) => { - if (candidate.cc < CC) + if (candidate.cc < CC) { return 1; - else if (candidate.cc > CC) + } else if (candidate.cc > CC) { return -1; - else + } else { return 0; + } }); } export function shouldAlignOnDiscontinuities (lastFrag, lastLevel, details) { let shouldAlign = false; if (lastLevel && lastLevel.details && details) { - if (details.endCC > details.startCC || (lastFrag && lastFrag.cc < details.startCC)) + if (details.endCC > details.startCC || (lastFrag && lastFrag.cc < details.startCC)) { shouldAlign = true; + } } return shouldAlign; } diff --git a/src/utils/fetch-loader.js b/src/utils/fetch-loader.js index 34991ec1743..34c96ca9f0c 100644 --- a/src/utils/fetch-loader.js +++ b/src/utils/fetch-loader.js @@ -31,15 +31,17 @@ class FetchLoader { const headersObj = {}; - if (context.rangeEnd) - headersObj['Range'] = 'bytes=' + context.rangeStart + '-' + String(context.rangeEnd - 1); /* jshint ignore:line */ + if (context.rangeEnd) { + headersObj['Range'] = 'bytes=' + context.rangeStart + '-' + String(context.rangeEnd - 1); + } /* jshint ignore:line */ initParams.headers = new Headers(headersObj); - if (this.fetchSetup) + if (this.fetchSetup) { request = this.fetchSetup(context, initParams); - else + } else { request = new Request(context.url, initParams); + } let fetchPromise = fetch(request, initParams); @@ -48,10 +50,11 @@ class FetchLoader { if (response.ok) { stats.tfirst = Math.max(stats.trequest, performance.now()); targetURL = response.url; - if (context.responseType === 'arraybuffer') + if (context.responseType === 'arraybuffer') { return response.arrayBuffer(); - else + } else { return response.text(); + } } else { callbacks.onError({ text: 'fetch, bad network response' }, context); } @@ -63,10 +66,11 @@ class FetchLoader { if (responseData) { stats.tload = Math.max(stats.tfirst, performance.now()); let len; - if (typeof responseData === 'string') + if (typeof responseData === 'string') { len = responseData.length; - else + } else { len = responseData.byteLength; + } stats.loaded = stats.total = len; let response = { url: targetURL, data: responseData }; diff --git a/src/utils/hex.js b/src/utils/hex.js index 4f804908e6b..6d12bf08878 100644 --- a/src/utils/hex.js +++ b/src/utils/hex.js @@ -7,8 +7,9 @@ const Hex = { let i, str = ''; for (i = 0; i < array.length; i++) { let h = array[i].toString(16); - if (h.length < 2) + if (h.length < 2) { h = '0' + h; + } str += h; } diff --git a/src/utils/logger.js b/src/utils/logger.js index 1e1d6867199..505f6e3eaae 100644 --- a/src/utils/logger.js +++ b/src/utils/logger.js @@ -31,8 +31,9 @@ function consolePrintFn (type) { const func = self.console[type]; if (func) { return function (...args) { - if (args[0]) + if (args[0]) { args[0] = formatMsg(type, args[0]); + } func.apply(self.console, args); }; diff --git a/src/utils/output-filter.js b/src/utils/output-filter.js index b7ec7757750..bbe2864485c 100644 --- a/src/utils/output-filter.js +++ b/src/utils/output-filter.js @@ -8,16 +8,18 @@ export default class OutputFilter { } dispatchCue () { - if (this.startTime === null) + if (this.startTime === null) { return; + } this.timelineController.addCues(this.trackName, this.startTime, this.endTime, this.screen); this.startTime = null; } newCue (startTime, endTime, screen) { - if (this.startTime === null || this.startTime > startTime) + if (this.startTime === null || this.startTime > startTime) { this.startTime = startTime; + } this.endTime = endTime; this.screen = screen; diff --git a/src/utils/texttrack-utils.js b/src/utils/texttrack-utils.js index 9cbdb0ce9f0..09b6f1dcabe 100644 --- a/src/utils/texttrack-utils.js +++ b/src/utils/texttrack-utils.js @@ -14,7 +14,8 @@ export function sendAddTrackEvent (track, videoEl) { export function clearCurrentCues (track) { if (track && track.cues) { - while (track.cues.length > 0) + while (track.cues.length > 0) { track.removeCue(track.cues[0]); + } } } diff --git a/src/utils/time-ranges.js b/src/utils/time-ranges.js index a79c2ce8ee0..486ea0c1c6a 100644 --- a/src/utils/time-ranges.js +++ b/src/utils/time-ranges.js @@ -5,8 +5,9 @@ const TimeRanges = { toString: function (r) { let log = '', len = r.length; - for (let i = 0; i < len; i++) + for (let i = 0; i < len; i++) { log += '[' + r.start(i).toFixed(3) + ',' + r.end(i).toFixed(3) + ']'; + } return log; } diff --git a/src/utils/vttcue.js b/src/utils/vttcue.js index 12a890bba12..30179887a73 100644 --- a/src/utils/vttcue.js +++ b/src/utils/vttcue.js @@ -15,8 +15,9 @@ */ export default (function () { - if (typeof window !== 'undefined' && window.VTTCue) + if (typeof window !== 'undefined' && window.VTTCue) { return window.VTTCue; + } let autoKeyword = 'auto'; let directionSetting = { @@ -33,16 +34,18 @@ export default (function () { }; function findDirectionSetting (value) { - if (typeof value !== 'string') + if (typeof value !== 'string') { return false; + } let dir = directionSetting[value.toLowerCase()]; return dir ? value.toLowerCase() : false; } function findAlignSetting (value) { - if (typeof value !== 'string') + if (typeof value !== 'string') { return false; + } let align = alignSetting[value.toLowerCase()]; return align ? value.toLowerCase() : false; @@ -52,8 +55,9 @@ export default (function () { let i = 1; for (; i < arguments.length; i++) { let cobj = arguments[i]; - for (let p in cobj) + for (let p in cobj) { obj[p] = cobj[p]; + } } return obj; @@ -62,17 +66,19 @@ export default (function () { function VTTCue (startTime, endTime, text) { let cue = this; let isIE8 = (function () { - if (typeof navigator === 'undefined') + if (typeof navigator === 'undefined') { return; + } return (/MSIE\s8\.0/).test(navigator.userAgent); })(); let baseObj = {}; - if (isIE8) + if (isIE8) { cue = document.createElement('custom'); - else + } else { baseObj.enumerable = true; + } /** * Shim implementation specific properties. These properties are not in @@ -127,8 +133,9 @@ export default (function () { return _startTime; }, set: function (value) { - if (typeof value !== 'number') + if (typeof value !== 'number') { throw new TypeError('Start time must be set to a number.'); + } _startTime = value; this.hasBeenReset = true; @@ -140,8 +147,9 @@ export default (function () { return _endTime; }, set: function (value) { - if (typeof value !== 'number') + if (typeof value !== 'number') { throw new TypeError('End time must be set to a number.'); + } _endTime = value; this.hasBeenReset = true; @@ -175,8 +183,9 @@ export default (function () { set: function (value) { let setting = findDirectionSetting(value); // Have to check for false because the setting an be an empty string. - if (setting === false) + if (setting === false) { throw new SyntaxError('An invalid or illegal string was specified.'); + } _vertical = setting; this.hasBeenReset = true; @@ -198,8 +207,9 @@ export default (function () { return _line; }, set: function (value) { - if (typeof value !== 'number' && value !== autoKeyword) + if (typeof value !== 'number' && value !== autoKeyword) { throw new SyntaxError('An invalid number or illegal string was specified.'); + } _line = value; this.hasBeenReset = true; @@ -212,8 +222,9 @@ export default (function () { }, set: function (value) { let setting = findAlignSetting(value); - if (!setting) + if (!setting) { throw new SyntaxError('An invalid or illegal string was specified.'); + } _lineAlign = setting; this.hasBeenReset = true; @@ -225,8 +236,9 @@ export default (function () { return _position; }, set: function (value) { - if (value < 0 || value > 100) + if (value < 0 || value > 100) { throw new Error('Position must be between 0 and 100.'); + } _position = value; this.hasBeenReset = true; @@ -239,8 +251,9 @@ export default (function () { }, set: function (value) { let setting = findAlignSetting(value); - if (!setting) + if (!setting) { throw new SyntaxError('An invalid or illegal string was specified.'); + } _positionAlign = setting; this.hasBeenReset = true; @@ -252,8 +265,9 @@ export default (function () { return _size; }, set: function (value) { - if (value < 0 || value > 100) + if (value < 0 || value > 100) { throw new Error('Size must be between 0 and 100.'); + } _size = value; this.hasBeenReset = true; @@ -266,8 +280,9 @@ export default (function () { }, set: function (value) { let setting = findAlignSetting(value); - if (!setting) + if (!setting) { throw new SyntaxError('An invalid or illegal string was specified.'); + } _align = setting; this.hasBeenReset = true; @@ -281,8 +296,9 @@ export default (function () { // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-video-element.html#text-track-cue-display-state cue.displayState = undefined; - if (isIE8) + if (isIE8) { return cue; + } } /** diff --git a/src/utils/vttparser.js b/src/utils/vttparser.js index 2743e193db0..90c3d77c1ca 100644 --- a/src/utils/vttparser.js +++ b/src/utils/vttparser.js @@ -7,11 +7,13 @@ import VTTCue from './vttcue'; const StringDecoder = function StringDecoder () { return { decode: function (data) { - if (!data) + if (!data) { return ''; + } - if (typeof data !== 'string') + if (typeof data !== 'string') { throw new Error('Error - expected string data.'); + } return decodeURIComponent(encodeURIComponent(data)); } @@ -33,8 +35,9 @@ function parseTimeStamp (input) { } let m = input.match(/^(\d+):(\d{2})(:\d{2})?\.(\d{3})/); - if (!m) + if (!m) { return null; + } if (m[3]) { // Timestamp takes the form of [hours]:[minutes]:[seconds].[milliseconds] @@ -58,8 +61,9 @@ function Settings () { Settings.prototype = { // Only accept the first assignment to any key. set: function (k, v) { - if (!this.get(k) && v !== '') + if (!this.get(k) && v !== '') { this.values[k] = v; + } }, // Return the value for a key, or a default value. // If 'defaultKey' is passed then 'dflt' is assumed to be an object with @@ -67,8 +71,9 @@ Settings.prototype = { // the key of the property that will be chosen; otherwise it's assumed to be // a single value. get: function (k, dflt, defaultKey) { - if (defaultKey) + if (defaultKey) { return this.has(k) ? this.values[k] : dflt[defaultKey]; + } return this.has(k) ? this.values[k] : dflt; }, @@ -110,12 +115,14 @@ Settings.prototype = { function parseOptions (input, callback, keyValueDelim, groupDelim) { let groups = groupDelim ? input.split(groupDelim) : [input]; for (let i in groups) { - if (typeof groups[i] !== 'string') + if (typeof groups[i] !== 'string') { continue; + } let kv = groups[i].split(keyValueDelim); - if (kv.length !== 2) + if (kv.length !== 2) { continue; + } let k = kv[0]; let v = kv[1]; @@ -134,8 +141,9 @@ function parseCue (input, cue, regionList) { // 4.1 WebVTT timestamp function consumeTimeStamp () { let ts = parseTimeStamp(input); - if (ts === null) + if (ts === null) { throw new Error('Malformed timestamp: ' + oInput); + } // Remove time stamp from input. input = input.replace(/^[^\sa-zA-Z-]+/, ''); @@ -164,19 +172,22 @@ function parseCue (input, cue, regionList) { var vals = v.split(','), vals0 = vals[0]; settings.integer(k, vals0); - if (settings.percent(k, vals0)) + if (settings.percent(k, vals0)) { settings.set('snapToLines', false); + } settings.alt(k, vals0, ['auto']); - if (vals.length === 2) + if (vals.length === 2) { settings.alt('lineAlign', vals[1], ['start', center, 'end']); + } break; case 'position': vals = v.split(','); settings.percent(k, vals[0]); - if (vals.length === 2) + if (vals.length === 2) { settings.alt('positionAlign', vals[1], ['start', center, 'end', 'line-left', 'line-right', 'auto']); + } break; case 'size': @@ -252,16 +263,19 @@ VTTParser.prototype = { buffer = fixLineBreaks(buffer); - while (pos < buffer.length && buffer[pos] !== '\r' && buffer[pos] !== '\n') + while (pos < buffer.length && buffer[pos] !== '\r' && buffer[pos] !== '\n') { ++pos; + } let line = buffer.substr(0, pos); // Advance the buffer early in case we fail below. - if (buffer[pos] === '\r') + if (buffer[pos] === '\r') { ++pos; + } - if (buffer[pos] === '\n') + if (buffer[pos] === '\n') { ++pos; + } self.buffer = buffer.substr(pos); return line; @@ -285,15 +299,17 @@ VTTParser.prototype = { let line; if (self.state === 'INITIAL') { // We can't start parsing until we have the first line. - if (!/\r\n|\n/.test(self.buffer)) + if (!/\r\n|\n/.test(self.buffer)) { return this; + } line = collectNextLine(); // strip of UTF-8 BOM if any // https://en.wikipedia.org/wiki/Byte_order_mark#UTF-8 let m = line.match(/^()?WEBVTT([ \t].*)?$/); - if (!m || !m[0]) + if (!m || !m[0]) { throw new Error('Malformed WebVTT signature.'); + } self.state = 'HEADER'; } @@ -301,13 +317,15 @@ VTTParser.prototype = { let alreadyCollectedLine = false; while (self.buffer) { // We can't parse a line until we have the full line. - if (!/\r\n|\n/.test(self.buffer)) + if (!/\r\n|\n/.test(self.buffer)) { return this; + } - if (!alreadyCollectedLine) + if (!alreadyCollectedLine) { line = collectNextLine(); - else + } else { alreadyCollectedLine = false; + } switch (self.state) { case 'HEADER': @@ -321,8 +339,9 @@ VTTParser.prototype = { continue; case 'NOTE': // Ignore NOTE blocks. - if (!line) + if (!line) { self.state = 'ID'; + } continue; case 'ID': @@ -332,8 +351,9 @@ VTTParser.prototype = { break; } // 19-29 - Allow any number of line terminators, then initialize new cue values. - if (!line) + if (!line) { continue; + } self.cue = new VTTCue(0, 0, ''); self.state = 'CUE'; @@ -364,30 +384,34 @@ VTTParser.prototype = { // one as a new cue. if (!line || hasSubstring && (alreadyCollectedLine = true)) { // We are done parsing self cue. - if (self.oncue) + if (self.oncue) { self.oncue(self.cue); + } self.cue = null; self.state = 'ID'; continue; } - if (self.cue.text) + if (self.cue.text) { self.cue.text += '\n'; + } self.cue.text += line; continue; case 'BADCUE': // BADCUE // 54-62 - Collect and discard the remaining cue. - if (!line) + if (!line) { self.state = 'ID'; + } continue; } } } catch (e) { // If we are currently parsing a cue, report what we have. - if (self.state === 'CUETEXT' && self.cue && self.oncue) + if (self.state === 'CUETEXT' && self.cue && self.oncue) { self.oncue(self.cue); + } self.cue = null; // Enter BADWEBVTT state if header was not parsed correctly otherwise @@ -409,13 +433,15 @@ VTTParser.prototype = { // If we've flushed, parsed, and we're still on the INITIAL state then // that means we don't have enough of the stream to parse the first // line. - if (self.state === 'INITIAL') + if (self.state === 'INITIAL') { throw new Error('Malformed WebVTT signature.'); + } } catch (e) { throw e; } - if (self.onflush) + if (self.onflush) { self.onflush(); + } return this; } diff --git a/src/utils/webvtt-parser.js b/src/utils/webvtt-parser.js index 9b5a893f7a7..46f1ceba2ce 100644 --- a/src/utils/webvtt-parser.js +++ b/src/utils/webvtt-parser.js @@ -12,8 +12,9 @@ const cueString2millis = function (timeString) { let mins = parseInt(timeString.substr(-9, 2)); let hours = timeString.length > 9 ? parseInt(timeString.substr(0, timeString.indexOf(':'))) : 0; - if (isNaN(ts) || isNaN(secs) || isNaN(mins) || isNaN(hours)) + if (isNaN(ts) || isNaN(secs) || isNaN(mins) || isNaN(hours)) { return -1; + } ts += 1000 * secs; ts += 60 * 1000 * mins; @@ -26,8 +27,9 @@ const cueString2millis = function (timeString) { const hash = function (text) { let hash = 5381; let i = text.length; - while (i) + while (i) { hash = (hash * 33) ^ text.charCodeAt(--i); + } return (hash >>> 0).toString(); }; @@ -104,8 +106,9 @@ const WebVTTParser = { // Fix encoding of special characters. TODO: Test with all sorts of weird characters. cue.text = decodeURIComponent(encodeURIComponent(cue.text)); - if (cue.endTime > 0) + if (cue.endTime > 0) { cues.push(cue); + } }; parser.onparsingerror = function (e) { @@ -129,10 +132,11 @@ const WebVTTParser = { inHeader = false; // Extract LOCAL and MPEGTS. line.substr(16).split(',').forEach(timestamp => { - if (startsWith(timestamp, 'LOCAL:')) + if (startsWith(timestamp, 'LOCAL:')) { cueTime = timestamp.substr(6); - else if (startsWith(timestamp, 'MPEGTS:')) + } else if (startsWith(timestamp, 'MPEGTS:')) { mpegTs = parseInt(timestamp.substr(7)); + } }); try { // Calculate subtitle offset in milliseconds. @@ -145,8 +149,9 @@ const WebVTTParser = { // Convert MPEGTS to seconds from 90kHz. presentationTime = mpegTs / 90000; - if (localTime === -1) + if (localTime === -1) { parsingError = new Error(`Malformed X-TIMESTAMP-MAP: ${line}`); + } } catch (e) { parsingError = new Error(`Malformed X-TIMESTAMP-MAP: ${line}`); } diff --git a/src/utils/xhr-loader.js b/src/utils/xhr-loader.js index ecc2cc44119..b2e08840656 100644 --- a/src/utils/xhr-loader.js +++ b/src/utils/xhr-loader.js @@ -6,8 +6,9 @@ import { logger } from '../utils/logger'; class XhrLoader { constructor (config) { - if (config && config.xhrSetup) + if (config && config.xhrSetup) { this.xhrSetup = config.xhrSetup; + } } destroy () { @@ -57,16 +58,18 @@ class XhrLoader { xhrSetup(xhr, context.url); } } - if (!xhr.readyState) + if (!xhr.readyState) { xhr.open('GET', context.url, true); + } } catch (e) { // IE11 throws an exception on xhr.open if attempting to access an HTTP resource over HTTPS this.callbacks.onError({ code: xhr.status, text: e.message }, context, xhr); return; } - if (context.rangeEnd) + if (context.rangeEnd) { xhr.setRequestHeader('Range', 'bytes=' + context.rangeStart + '-' + (context.rangeEnd - 1)); + } xhr.onreadystatechange = this.readystatechange.bind(this); xhr.onprogress = this.loadprogress.bind(this); @@ -85,15 +88,17 @@ class XhrLoader { config = this.config; // don't proceed if xhr has been aborted - if (stats.aborted) + if (stats.aborted) { return; + } // >= HEADERS_RECEIVED if (readyState >= 2) { // clear xhr timeout and rearm it if readyState less than 4 window.clearTimeout(this.requestTimeout); - if (stats.tfirst === 0) + if (stats.tfirst === 0) { stats.tfirst = Math.max(performance.now(), stats.trequest); + } if (readyState === 4) { let status = xhr.status; @@ -145,8 +150,9 @@ class XhrLoader { stats = this.stats; stats.loaded = event.loaded; - if (event.lengthComputable) + if (event.lengthComputable) { stats.total = event.total; + } let onProgress = this.callbacks.onProgress; if (onProgress) { diff --git a/tests/functional/auto/setup.js b/tests/functional/auto/setup.js index ffaace10e50..719e2eab5ef 100644 --- a/tests/functional/auto/setup.js +++ b/tests/functional/auto/setup.js @@ -14,16 +14,19 @@ let browserDescription; (function () { if (onTravis) { let UA_VERSION = process.env.UA_VERSION; - if (UA_VERSION) + if (UA_VERSION) { browserConfig.version = UA_VERSION; + } let UA = process.env.UA; - if (!UA) + if (!UA) { throw new Error('No test browser name.'); + } let OS = process.env.OS; - if (!OS) + if (!OS) { throw new Error('No test browser platform.'); + } browserConfig.name = UA; browserConfig.platform = OS; @@ -33,11 +36,13 @@ let browserDescription; browserDescription = browserConfig.name; - if (browserConfig.version) + if (browserConfig.version) { browserDescription += ' (' + browserConfig.version + ')'; + } - if (browserConfig.platform) + if (browserConfig.platform) { browserDescription += ', ' + browserConfig.platform; + } })(); // Launch static server @@ -98,8 +103,9 @@ describe('testing hls.js playback in the browser on "' + browserDescription + '" console.log('Retrieving web driver session...'); return this.browser.getSession().then(function (session) { console.log('Web driver session id: ' + session.getId()); - if (onTravis) + if (onTravis) { console.log('Job URL: https://saucelabs.com/jobs/' + session.getId()); + } return retry(function () { console.log('Loading test page...'); @@ -160,11 +166,11 @@ describe('testing hls.js playback in the browser on "' + browserDescription + '" window.switchToHighestLevel('next'); }; window.hls.on(window.Hls.Events.LEVEL_SWITCHED, function (event, data) { - var currentTime = video.currentTime; + let currentTime = video.currentTime; if (data.level === window.hls.levels.length - 1) { console.log('[log] > switched on level:' + data.level); window.setTimeout(function () { - var newCurrentTime = video.currentTime; + let newCurrentTime = video.currentTime; console.log('[log] > currentTime delta :' + (newCurrentTime - currentTime)); callback({ code: newCurrentTime > currentTime, logs: window.logString }); }, 2000); @@ -183,7 +189,9 @@ describe('testing hls.js playback in the browser on "' + browserDescription + '" window.startStream(url, config, callback); const video = window.video; video.onloadeddata = function () { - window.setTimeout(function () { video.currentTime = video.duration - 5; }, 5000); + window.setTimeout(function () { + video.currentTime = video.duration - 5; + }, 5000); }; video.onseeked = function () { callback({ code: 'seeked', logs: window.logString }); @@ -201,7 +209,9 @@ describe('testing hls.js playback in the browser on "' + browserDescription + '" window.startStream(url, config, callback); const video = window.video; video.onloadeddata = function () { - window.setTimeout(function () { video.currentTime = video.duration - 5; }, 5000); + window.setTimeout(function () { + video.currentTime = video.duration - 5; + }, 5000); }; video.onended = function () { callback({ code: 'ended', logs: window.logString }); @@ -219,7 +229,9 @@ describe('testing hls.js playback in the browser on "' + browserDescription + '" window.startStream(url, config, callback); const video = window.video; video.onloadeddata = function () { - window.setTimeout(function () { video.currentTime = video.duration; }, 5000); + window.setTimeout(function () { + video.currentTime = video.duration; + }, 5000); }; video.onended = function () { callback({ code: 'ended', logs: window.logString }); @@ -263,8 +275,9 @@ describe('testing hls.js playback in the browser on "' + browserDescription + '" let config = stream.config || {}; if (!stream.blacklist_ua || stream.blacklist_ua.indexOf(browserConfig.name) === -1) { it('should receive video loadeddata event for ' + stream.description, testLoadedData(url, config)); - if (stream.abr) + if (stream.abr) { it('should "smooth switch" to highest level and still play(readyState === 4) after 12s for ' + stream.description, testSmoothSwitch(url, config)); + } if (stream.live) { it('should seek near the end and receive video seeked event for ' + stream.description, testSeekOnLive(url, config)); diff --git a/tests/functional/auto/testbench.js b/tests/functional/auto/testbench.js index 76d2f2e22b4..e2bbc7480f1 100644 --- a/tests/functional/auto/testbench.js +++ b/tests/functional/auto/testbench.js @@ -25,8 +25,9 @@ function setupConsoleLogRedirection () { var methods = ['log', 'debug', 'info', 'warn', 'error']; methods.forEach(function (methodName) { var original = window.console[methodName]; - if (!original) + if (!original) { return; + } window.console[methodName] = function () { append(methodName, Array.prototype.slice.call(arguments).map(JSON.stringify).join(' ')); @@ -37,21 +38,24 @@ function setupConsoleLogRedirection () { // Object.assign polyfill function objectAssign (target, firstSource) { - if (target === undefined || target === null) + if (target === undefined || target === null) { throw new TypeError('Cannot convert first argument to object'); + } var to = Object(target); for (var i = 1; i < arguments.length; i++) { var nextSource = arguments[i]; - if (nextSource === undefined || nextSource === null) + if (nextSource === undefined || nextSource === null) { continue; + } var keysArray = Object.keys(Object(nextSource)); for (var nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex++) { var nextKey = keysArray[nextIndex]; var desc = Object.getOwnPropertyDescriptor(nextSource, nextKey); - if (desc !== undefined && desc.enumerable) + if (desc !== undefined && desc.enumerable) { to[nextKey] = nextSource[nextKey]; + } } } return to; @@ -59,8 +63,9 @@ function objectAssign (target, firstSource) { function startStream (streamUrl, config, callback) { var Hls = window.Hls; - if (!Hls) + if (!Hls) { throw new Error('Hls not installed'); + } if (Hls.isSupported()) { if (hls) { diff --git a/tests/test-streams.js b/tests/test-streams.js index a155074fb89..9ce47910d13 100644 --- a/tests/test-streams.js +++ b/tests/test-streams.js @@ -23,8 +23,9 @@ function createTestStream (url, description, live = false, abr = true, blacklist * @returns {{url: string, description: string, live: boolean, abr: boolean, blacklist_ua: string[]}} */ function createTestStreamWithConfig (target, config) { - if (typeof target !== 'object') + if (typeof target !== 'object') { throw new Error('target should be object'); + } const testStream = createTestStream(target.url, target.description, target.live, target.abr, target.blacklist_ua); diff --git a/tests/unit/events.js b/tests/unit/events.js index 5da36ae8687..f0df9646a04 100644 --- a/tests/unit/events.js +++ b/tests/unit/events.js @@ -7,8 +7,9 @@ function getAllCapsSnakeCaseToCamelCase (eventType) { for (let i = 0; i < eventType.length; i++) { nextChar = eventType.charAt(i); - if (i !== 0 && !previousWasUscore) + if (i !== 0 && !previousWasUscore) { nextChar = nextChar.toLowerCase(); + } previousWasUscore = false; if (nextChar === '_') { diff --git a/tests/unit/loader/playlist-loader.js b/tests/unit/loader/playlist-loader.js index 78cbbf3d14e..0d103268fcb 100644 --- a/tests/unit/loader/playlist-loader.js +++ b/tests/unit/loader/playlist-loader.js @@ -299,15 +299,17 @@ oceans_aes-audio=65000-video=236000-3.ts assert.strictEqual(result.fragments[0].decryptdata.method, 'AES-128'); let sn = 1; let uint8View = new Uint8Array(16); - for (let i = 12; i < 16; i++) + for (let i = 12; i < 16; i++) { uint8View[i] = (sn >> 8 * (15 - i)) & 0xff; + } assert(bufferIsEqual(result.fragments[0].decryptdata.iv.buffer, uint8View.buffer)); sn = 3; uint8View = new Uint8Array(16); - for (let i = 12; i < 16; i++) + for (let i = 12; i < 16; i++) { uint8View[i] = (sn >> 8 * (15 - i)) & 0xff; + } assert(bufferIsEqual(result.fragments[2].decryptdata.iv.buffer, uint8View.buffer)); }); diff --git a/tests/unit/utils/binary-search.js b/tests/unit/utils/binary-search.js index 7d38655f550..f2b7a716683 100644 --- a/tests/unit/utils/binary-search.js +++ b/tests/unit/utils/binary-search.js @@ -6,10 +6,11 @@ describe('binary search util', function () { let list = null; let buildComparisonFunction = function (itemToSearchFor) { return function (candidate) { - if (candidate < itemToSearchFor) + if (candidate < itemToSearchFor) { return 1; - else if (candidate > itemToSearchFor) + } else if (candidate > itemToSearchFor) { return -1; + } return 0; };