Skip to content

Commit

Permalink
Fail MP3 probe if AC3 or EC3 detected (#5695)
Browse files Browse the repository at this point in the history
Related to #4958
  • Loading branch information
robwalch authored Jul 26, 2023
1 parent b8c3d36 commit b724bd3
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 29 deletions.
2 changes: 1 addition & 1 deletion src/demux/audio/aacdemuxer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class AACDemuxer extends BaseAudioDemuxer {
}

// Source for probe info - https://wiki.multimedia.cx/index.php?title=ADTS
static probe(data): boolean {
static probe(data: Uint8Array | undefined): boolean {
if (!data) {
return false;
}
Expand Down
31 changes: 7 additions & 24 deletions src/demux/audio/ac3-demuxer.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import BaseAudioDemuxer from './base-audio-demuxer';
import { getID3Data, getTimeStamp } from '../id3';
import { getAudioBSID } from './dolby';
import type { HlsEventEmitter } from '../../events';
import type { AudioFrame, DemuxedAudioTrack } from '../../types/demuxer';

Expand Down Expand Up @@ -55,7 +56,7 @@ export class AC3Demuxer extends BaseAudioDemuxer {
}
}

static probe(data): boolean {
static probe(data: Uint8Array | undefined): boolean {
if (!data) {
return false;
}
Expand All @@ -66,33 +67,15 @@ export class AC3Demuxer extends BaseAudioDemuxer {
}

// look for the ac-3 sync bytes
let offset = id3Data.length;
const offset = id3Data.length;
if (
data[offset] === 0x0b &&
data[offset + 1] === 0x77 &&
getTimeStamp(id3Data) !== undefined
) {
getTimeStamp(id3Data) !== undefined &&
// check the bsid to confirm ac-3
let bsid = 0;
let numBits = 5;
offset += numBits;
const temp = new Uint32Array(1); // unsigned 32 bit for temporary storage
const mask = new Uint32Array(1); // unsigned 32 bit mask value
const byte = new Uint8Array(1); // unsigned 8 bit for temporary storage
while (numBits > 0) {
byte[0] = data[offset];
// read remaining bits, upto 8 bits at a time
const bits = Math.min(numBits, 8);
const shift = 8 - bits;
mask[0] = (0xff000000 >>> (24 + shift)) << shift;
temp[0] = (byte[0] & mask[0]) >> shift;
bsid = !bsid ? temp[0] : (bsid << bits) | temp[0];
offset += 1;
numBits -= bits;
}
if (bsid < 16) {
return true;
}
getAudioBSID(data, offset) < 16
) {
return true;
}
return false;
}
Expand Down
21 changes: 21 additions & 0 deletions src/demux/audio/dolby.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
export const getAudioBSID = (data: Uint8Array, offset: number): number => {
// check the bsid to confirm ac-3 | ec-3
let bsid = 0;
let numBits = 5;
offset += numBits;
const temp = new Uint32Array(1); // unsigned 32 bit for temporary storage
const mask = new Uint32Array(1); // unsigned 32 bit mask value
const byte = new Uint8Array(1); // unsigned 8 bit for temporary storage
while (numBits > 0) {
byte[0] = data[offset];
// read remaining bits, upto 8 bits at a time
const bits = Math.min(numBits, 8);
const shift = 8 - bits;
mask[0] = (0xff000000 >>> (24 + shift)) << shift;
temp[0] = (byte[0] & mask[0]) >> shift;
bsid = !bsid ? temp[0] : (bsid << bits) | temp[0];
offset += 1;
numBits -= bits;
}
return bsid;
};
21 changes: 17 additions & 4 deletions src/demux/audio/mp3demuxer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
* MP3 demuxer
*/
import BaseAudioDemuxer from './base-audio-demuxer';
import * as ID3 from '../id3';
import { getID3Data, getTimeStamp } from '../id3';
import { getAudioBSID } from './dolby';
import { logger } from '../../utils/logger';
import * as MpegAudio from './mpegaudio';

Expand All @@ -29,7 +30,7 @@ class MP3Demuxer extends BaseAudioDemuxer {
};
}

static probe(data): boolean {
static probe(data: Uint8Array | undefined): boolean {
if (!data) {
return false;
}
Expand All @@ -38,8 +39,20 @@ class MP3Demuxer extends BaseAudioDemuxer {
// 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
const id3Data = ID3.getID3Data(data, 0) || [];
let offset = id3Data.length;
const id3Data = getID3Data(data, 0);
let offset = id3Data?.length || 0;

// Check for ac-3|ec-3 sync bytes and return false if present
if (
id3Data &&
data[offset] === 0x0b &&
data[offset + 1] === 0x77 &&
getTimeStamp(id3Data) !== undefined &&
// check the bsid to confirm ac-3 or ec-3 (not mp3)
getAudioBSID(data, offset) <= 16
) {
return false;
}

for (let length = data.length; offset < length; offset++) {
if (MpegAudio.probe(data, offset)) {
Expand Down

0 comments on commit b724bd3

Please sign in to comment.