diff --git a/src/demux/adts.ts b/src/demux/adts.ts index cdd1f00ffe7..0df74a56e00 100644 --- a/src/demux/adts.ts +++ b/src/demux/adts.ts @@ -29,7 +29,7 @@ export function getAudioConfig( audioCodec: string ): AudioConfig | void { let adtsObjectType: number; - let adtsExtensionSampleingIndex: number; + let adtsExtensionSamplingIndex: number; let adtsChanelConfig: number; let config: number[]; const userAgent = navigator.userAgent.toLowerCase(); @@ -51,13 +51,13 @@ export function getAudioConfig( ]; // byte 2 adtsObjectType = ((data[offset + 2] & 0xc0) >>> 6) + 1; - const adtsSampleingIndex = (data[offset + 2] & 0x3c) >>> 2; - if (adtsSampleingIndex > adtsSampleingRates.length - 1) { + const adtsSamplingIndex = (data[offset + 2] & 0x3c) >>> 2; + if (adtsSamplingIndex > adtsSampleingRates.length - 1) { observer.trigger(Events.ERROR, { type: ErrorTypes.MEDIA_ERROR, details: ErrorDetails.FRAG_PARSING_ERROR, fatal: true, - reason: `invalid ADTS sampling index:${adtsSampleingIndex}`, + reason: `invalid ADTS sampling index:${adtsSamplingIndex}`, }); return; } @@ -65,27 +65,27 @@ export function getAudioConfig( // byte 3 adtsChanelConfig |= (data[offset + 3] & 0xc0) >>> 6; logger.log( - `manifest codec:${audioCodec},ADTS data:type:${adtsObjectType},sampleingIndex:${adtsSampleingIndex}[${adtsSampleingRates[adtsSampleingIndex]}Hz],channelConfig:${adtsChanelConfig}` + `manifest codec:${audioCodec}, ADTS type:${adtsObjectType}, samplingIndex:${adtsSamplingIndex}` ); // firefox: freq less than 24kHz = AAC SBR (HE-AAC) if (/firefox/i.test(userAgent)) { - if (adtsSampleingIndex >= 6) { + if (adtsSamplingIndex >= 6) { adtsObjectType = 5; config = new Array(4); // HE-AAC uses SBR (Spectral Band Replication) , high frequencies are constructed from low frequencies // there is a factor 2 between frame sample rate and output sample rate // multiply frequency by 2 (see table below, equivalent to substract 3) - adtsExtensionSampleingIndex = adtsSampleingIndex - 3; + adtsExtensionSamplingIndex = adtsSamplingIndex - 3; } else { adtsObjectType = 2; config = new Array(2); - adtsExtensionSampleingIndex = adtsSampleingIndex; + adtsExtensionSamplingIndex = adtsSamplingIndex; } // Android : always use AAC } else if (userAgent.indexOf('android') !== -1) { adtsObjectType = 2; config = new Array(2); - adtsExtensionSampleingIndex = adtsSampleingIndex; + adtsExtensionSamplingIndex = adtsSamplingIndex; } else { /* for other browsers (Chrome/Vivaldi/Opera ...) always force audio type to be HE-AAC SBR, as some browsers do not support audio codec switch properly (like Chrome ...) @@ -97,26 +97,26 @@ export function getAudioConfig( (audioCodec && (audioCodec.indexOf('mp4a.40.29') !== -1 || audioCodec.indexOf('mp4a.40.5') !== -1)) || - (!audioCodec && adtsSampleingIndex >= 6) + (!audioCodec && adtsSamplingIndex >= 6) ) { // HE-AAC uses SBR (Spectral Band Replication) , high frequencies are constructed from low frequencies // there is a factor 2 between frame sample rate and output sample rate // multiply frequency by 2 (see table below, equivalent to substract 3) - adtsExtensionSampleingIndex = adtsSampleingIndex - 3; + adtsExtensionSamplingIndex = adtsSamplingIndex - 3; } else { // if (manifest codec is AAC) AND (frequency less than 24kHz AND nb channel is 1) OR (manifest codec not specified and mono audio) // Chrome fails to play back with low frequency AAC LC mono when initialized with HE-AAC. This is not a problem with stereo. if ( (audioCodec && audioCodec.indexOf('mp4a.40.2') !== -1 && - ((adtsSampleingIndex >= 6 && adtsChanelConfig === 1) || + ((adtsSamplingIndex >= 6 && adtsChanelConfig === 1) || /vivaldi/i.test(userAgent))) || (!audioCodec && adtsChanelConfig === 1) ) { adtsObjectType = 2; config = new Array(2); } - adtsExtensionSampleingIndex = adtsSampleingIndex; + adtsExtensionSamplingIndex = adtsSamplingIndex; } } /* refer to http://wiki.multimedia.cx/index.php?title=MPEG-4_Audio#Audio_Specific_Config @@ -155,14 +155,14 @@ export function getAudioConfig( // audioObjectType = profile => profile, the MPEG-4 Audio Object Type minus 1 config[0] = adtsObjectType << 3; // samplingFrequencyIndex - config[0] |= (adtsSampleingIndex & 0x0e) >> 1; - config[1] |= (adtsSampleingIndex & 0x01) << 7; + config[0] |= (adtsSamplingIndex & 0x0e) >> 1; + config[1] |= (adtsSamplingIndex & 0x01) << 7; // channelConfiguration config[1] |= adtsChanelConfig << 3; if (adtsObjectType === 5) { // adtsExtensionSampleingIndex - config[1] |= (adtsExtensionSampleingIndex & 0x0e) >> 1; - config[2] = (adtsExtensionSampleingIndex & 0x01) << 7; + config[1] |= (adtsExtensionSamplingIndex & 0x0e) >> 1; + config[2] = (adtsExtensionSamplingIndex & 0x01) << 7; // adtsObjectType (force to 2, chrome is checking that object type is less than 5 ??? // https://chromium.googlesource.com/chromium/src.git/+/master/media/formats/mp4/aac.cc config[2] |= 2 << 2; @@ -170,7 +170,7 @@ export function getAudioConfig( } return { config, - samplerate: adtsSampleingRates[adtsSampleingIndex], + samplerate: adtsSampleingRates[adtsSamplingIndex], channelCount: adtsChanelConfig, codec: 'mp4a.40.' + adtsObjectType, manifestCodec, @@ -208,7 +208,7 @@ export function canParse(data: Uint8Array, offset: number): boolean { return ( canGetFrameLength(data, offset) && isHeaderPattern(data, offset) && - getFullFrameLength(data, offset) < data.length - offset + getFullFrameLength(data, offset) <= data.length - offset ); } @@ -251,7 +251,7 @@ export function initTrackConfig( track.codec = config.codec; track.manifestCodec = config.manifestCodec; logger.log( - `parsed codec:${track.codec},rate:${config.samplerate},nb channel:${config.channelCount}` + `parsed codec:${track.codec}, rate:${config.samplerate}, channels:${config.channelCount}` ); } } diff --git a/src/demux/base-audio-demuxer.ts b/src/demux/base-audio-demuxer.ts index 9dec7c2f732..3e4013a2708 100644 --- a/src/demux/base-audio-demuxer.ts +++ b/src/demux/base-audio-demuxer.ts @@ -127,12 +127,13 @@ class BaseAudioDemuxer implements Demuxer { flush(timeOffset: number): DemuxerResult { // Parse cache in case of remaining frames. - if (this.cachedData) { - this.demux(this.cachedData, 0); + const cachedData = this.cachedData; + if (cachedData) { + this.cachedData = null; + this.demux(cachedData, 0); } this.frameIndex = 0; - this.cachedData = null; return { audioTrack: this._audioTrack, diff --git a/src/demux/mpegaudio.ts b/src/demux/mpegaudio.ts index 4b37952f42f..f75b3d66c0c 100644 --- a/src/demux/mpegaudio.ts +++ b/src/demux/mpegaudio.ts @@ -227,7 +227,7 @@ export function isHeader(data: Uint8Array, offset: number): boolean { export function canParse(data: Uint8Array, offset: number): boolean { const headerSize = 4; - return isHeaderPattern(data, offset) && data.length - offset >= headerSize; + return isHeaderPattern(data, offset) && headerSize <= data.length - offset; } export function probe(data: Uint8Array, offset: number): boolean { diff --git a/src/remux/mp4-remuxer.ts b/src/remux/mp4-remuxer.ts index e556195d039..10acbd150bf 100644 --- a/src/remux/mp4-remuxer.ts +++ b/src/remux/mp4-remuxer.ts @@ -281,9 +281,6 @@ export default class MP4Remuxer implements Remuxer { // using audio sampling rate here helps having an integer MP4 frame duration // this avoids potential rounding issue and AV sync issue audioTrack.timescale = audioTrack.samplerate; - logger.log( - `[mp4-remuxer]: audio sampling rate : ${audioTrack.samplerate}` - ); if (!audioTrack.isAAC) { if (typeSupported.mpeg) { // Chrome and Safari