mirror of
https://github.com/arcodange-org/mediabunny.git
synced 2026-10-02 05:13:50 +02:00
Add MP3 support to ISOBMFF demuxer
This commit is contained in:
+5
-1
@@ -13,7 +13,7 @@ import { SubtitleMetadata } from './subtitles';
|
||||
/** @public */
|
||||
export const VIDEO_CODECS = ['avc', 'hevc', 'vp8', 'vp9', 'av1'] as const;
|
||||
/** @public */
|
||||
export const AUDIO_CODECS = ['aac', 'opus'] as const; // TODO add the rest
|
||||
export const AUDIO_CODECS = ['aac', 'mp3', 'opus'] as const; // TODO add the rest
|
||||
/** @public */
|
||||
export const SUBTITLE_CODECS = ['webvtt'] as const; // TODO add the rest
|
||||
|
||||
@@ -353,6 +353,8 @@ export const buildAudioCodecString = (codec: AudioCodec, numberOfChannels: numbe
|
||||
|
||||
// Default to standard AAC-LC for higher sample rates
|
||||
return 'mp4a.40.2'; // AAC-LC
|
||||
} else if (codec === 'mp3') {
|
||||
return 'mp3'; // Easy, this one
|
||||
} else if (codec === 'opus') {
|
||||
return 'opus'; // Easy, this one
|
||||
} else if (codec === 'vorbis') {
|
||||
@@ -367,6 +369,8 @@ export const extractAudioCodecString = (codec: AudioCodec, description: Uint8Arr
|
||||
if (codec === 'aac') {
|
||||
const audioSpecificConfig = parseAacAudioSpecificConfig(description);
|
||||
return `mp4a.40.${audioSpecificConfig.objectType}`;
|
||||
} else if (codec === 'mp3') {
|
||||
return 'mp3';
|
||||
} else if (codec === 'opus') {
|
||||
return 'opus';
|
||||
} else if (codec === 'vorbis') {
|
||||
|
||||
@@ -613,7 +613,7 @@ export class IsobmffDemuxer extends Demuxer {
|
||||
this.readContiguousBoxes(startPos + sampleBoxInfo.totalSize - this.isobmffReader.pos);
|
||||
} else {
|
||||
if (sampleBoxInfo.name === 'mp4a') {
|
||||
track.info.codec = 'aac';
|
||||
// We don't know the codec yet, need to read the esds box
|
||||
} else if (sampleBoxInfo.name.toLowerCase() === 'opus') {
|
||||
track.info.codec = 'opus';
|
||||
} else {
|
||||
@@ -811,12 +811,12 @@ export class IsobmffDemuxer extends Demuxer {
|
||||
|
||||
case 'esds': {
|
||||
const track = this.currentTrack;
|
||||
assert(track && track.info);
|
||||
assert(track && track.info?.type === 'audio');
|
||||
|
||||
this.isobmffReader.pos += 4; // Version + flags
|
||||
|
||||
const tag = this.isobmffReader.readU8();
|
||||
assert(tag === 0x03);
|
||||
assert(tag === 0x03); // ES Descriptor
|
||||
|
||||
this.isobmffReader.readIsomVariableInteger(); // Length
|
||||
|
||||
@@ -839,24 +839,38 @@ export class IsobmffDemuxer extends Demuxer {
|
||||
}
|
||||
|
||||
const decoderConfigTag = this.isobmffReader.readU8();
|
||||
assert(decoderConfigTag === 0x04);
|
||||
assert(decoderConfigTag === 0x04); // DecoderConfigDescriptor
|
||||
|
||||
this.isobmffReader.readIsomVariableInteger(); // Length
|
||||
const decoderConfigDescriptorLength = this.isobmffReader.readIsomVariableInteger(); // Length
|
||||
|
||||
const payloadStart = this.isobmffReader.pos;
|
||||
|
||||
const objectTypeIndication = this.isobmffReader.readU8();
|
||||
assert(objectTypeIndication === 0x40); // Assert it's MPEG-4 audio
|
||||
if (objectTypeIndication === 0x40) {
|
||||
track.info.codec = 'aac';
|
||||
} else if (objectTypeIndication === 0x69 || objectTypeIndication === 0x6b) {
|
||||
track.info.codec = 'mp3';
|
||||
} else {
|
||||
console.warn(
|
||||
`Unsupported audio codec (objectTypeIndication ${objectTypeIndication}) - discarding track.`,
|
||||
);
|
||||
}
|
||||
|
||||
this.isobmffReader.pos += 1 + 3 + 4 + 4;
|
||||
|
||||
const decoderSpecificInfoTag = this.isobmffReader.readU8();
|
||||
assert(decoderSpecificInfoTag === 0x05);
|
||||
if (decoderConfigDescriptorLength > this.isobmffReader.pos - payloadStart) {
|
||||
// There's a DecoderSpecificInfo at the end, let's read it
|
||||
|
||||
const decoderSpecificInfoLength = this.isobmffReader.readIsomVariableInteger();
|
||||
const decoderSpecificInfoTag = this.isobmffReader.readU8();
|
||||
assert(decoderSpecificInfoTag === 0x05); // DecoderSpecificInfo
|
||||
|
||||
track.info.codecDescription = this.isobmffReader.readRange(
|
||||
this.isobmffReader.pos,
|
||||
this.isobmffReader.pos + decoderSpecificInfoLength,
|
||||
);
|
||||
const decoderSpecificInfoLength = this.isobmffReader.readIsomVariableInteger();
|
||||
|
||||
track.info.codecDescription = this.isobmffReader.readRange(
|
||||
this.isobmffReader.pos,
|
||||
this.isobmffReader.pos + decoderSpecificInfoLength,
|
||||
);
|
||||
}
|
||||
}; break;
|
||||
|
||||
case 'stts': {
|
||||
@@ -2003,17 +2017,16 @@ const getSampleInfo = (sampleTable: SampleTable, sampleIndex: number): SampleInf
|
||||
+ Math.floor((sampleIndex - chunkEntry.startSampleIndex) / chunkEntry.samplesPerChunk);
|
||||
const chunkOffset = sampleTable.chunkOffsets[chunkIndex]!;
|
||||
|
||||
const startSampleIndexOfChunk = chunkEntry.startSampleIndex
|
||||
+ (chunkIndex - chunkEntry.startChunkIndex) * chunkEntry.samplesPerChunk;
|
||||
let chunkSize = 0;
|
||||
|
||||
let sampleOffset = chunkOffset;
|
||||
|
||||
if (sampleTable.sampleSizes.length === 1) {
|
||||
sampleOffset += sampleSize * (sampleIndex - chunkEntry.startSampleIndex);
|
||||
sampleOffset += sampleSize * (sampleIndex - startSampleIndexOfChunk);
|
||||
chunkSize += sampleSize * chunkEntry.samplesPerChunk;
|
||||
} else {
|
||||
const startSampleIndex = chunkEntry.startSampleIndex
|
||||
+ (chunkIndex - chunkEntry.startChunkIndex) * chunkEntry.samplesPerChunk;
|
||||
|
||||
for (let i = startSampleIndex; i < startSampleIndex + chunkEntry.samplesPerChunk; i++) {
|
||||
for (let i = startSampleIndexOfChunk; i < startSampleIndexOfChunk + chunkEntry.samplesPerChunk; i++) {
|
||||
const sampleSize = sampleTable.sampleSizes[i]!;
|
||||
|
||||
if (i < sampleIndex) {
|
||||
|
||||
Reference in New Issue
Block a user