mirror of
https://github.com/arcodange-org/mediabunny.git
synced 2026-09-27 10:53:50 +02:00
Fix invalid encoder AAC description on WebKit (fixes #206)
This commit is contained in:
@@ -621,6 +621,54 @@ export const parseAacAudioSpecificConfig = (bytes: Uint8Array | null): AacAudioS
|
||||
};
|
||||
};
|
||||
|
||||
export const buildAacAudioSpecificConfig = (config: {
|
||||
objectType: number;
|
||||
sampleRate: number;
|
||||
numberOfChannels: number;
|
||||
}) => {
|
||||
let frequencyIndex = aacFrequencyTable.indexOf(config.sampleRate);
|
||||
let customSampleRate: number | null = null;
|
||||
|
||||
if (frequencyIndex === -1) {
|
||||
frequencyIndex = 15;
|
||||
customSampleRate = config.sampleRate;
|
||||
}
|
||||
|
||||
const channelConfiguration = aacChannelMap.indexOf(config.numberOfChannels);
|
||||
if (channelConfiguration === -1) {
|
||||
throw new TypeError(`Unsupported number of channels: ${config.numberOfChannels}`);
|
||||
}
|
||||
|
||||
let bitCount = 5 + 4 + 4;
|
||||
if (config.objectType >= 32) {
|
||||
bitCount += 6;
|
||||
}
|
||||
if (frequencyIndex === 15) {
|
||||
bitCount += 24;
|
||||
}
|
||||
|
||||
const byteCount = Math.ceil(bitCount / 8);
|
||||
const bytes = new Uint8Array(byteCount);
|
||||
const bitstream = new Bitstream(bytes);
|
||||
|
||||
if (config.objectType < 32) {
|
||||
bitstream.writeBits(5, config.objectType);
|
||||
} else {
|
||||
bitstream.writeBits(5, 31);
|
||||
bitstream.writeBits(6, config.objectType - 32);
|
||||
}
|
||||
|
||||
bitstream.writeBits(4, frequencyIndex);
|
||||
|
||||
if (frequencyIndex === 15) {
|
||||
bitstream.writeBits(24, customSampleRate!);
|
||||
}
|
||||
|
||||
bitstream.writeBits(4, channelConfiguration);
|
||||
|
||||
return bytes;
|
||||
};
|
||||
|
||||
export const OPUS_SAMPLE_RATE = 48_000;
|
||||
|
||||
const PCM_CODEC_REGEX = /^pcm-([usf])(\d+)+(be)?$/;
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
import {
|
||||
AUDIO_CODECS,
|
||||
AudioCodec,
|
||||
buildAacAudioSpecificConfig,
|
||||
parseAacAudioSpecificConfig,
|
||||
parsePcmCodec,
|
||||
PCM_AUDIO_CODECS,
|
||||
PcmAudioCodec,
|
||||
@@ -24,9 +26,11 @@ import {
|
||||
CallSerializer,
|
||||
clamp,
|
||||
isFirefox,
|
||||
last,
|
||||
promiseWithResolvers,
|
||||
setInt24,
|
||||
setUint24,
|
||||
toUint8Array,
|
||||
} from './misc';
|
||||
import { Muxer } from './muxer';
|
||||
import { SubtitleParser } from './subtitles';
|
||||
@@ -1515,6 +1519,32 @@ class AudioEncoderWrapper {
|
||||
|
||||
this.encoder = new AudioEncoder({
|
||||
output: (chunk, meta) => {
|
||||
// WebKit emits an invalid description for AAC (https://bugs.webkit.org/show_bug.cgi?id=302253),
|
||||
// which we try to detect here. If detected, we'll provide our own description instead, derived
|
||||
// from the codec string and audio parameters.
|
||||
if (this.encodingConfig.codec === 'aac' && meta?.decoderConfig) {
|
||||
let needsDescriptionOverwrite = false;
|
||||
if (!meta.decoderConfig.description || meta.decoderConfig.description.byteLength < 2) {
|
||||
needsDescriptionOverwrite = true;
|
||||
} else {
|
||||
const audioSpecificConfig = parseAacAudioSpecificConfig(
|
||||
toUint8Array(meta.decoderConfig.description),
|
||||
);
|
||||
|
||||
needsDescriptionOverwrite = audioSpecificConfig.objectType === 0;
|
||||
}
|
||||
|
||||
if (needsDescriptionOverwrite) {
|
||||
const objectType = Number(last(encoderConfig.codec.split('.')));
|
||||
|
||||
meta.decoderConfig.description = buildAacAudioSpecificConfig({
|
||||
objectType,
|
||||
numberOfChannels: meta.decoderConfig.numberOfChannels,
|
||||
sampleRate: meta.decoderConfig.sampleRate,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const packet = EncodedPacket.fromEncodedChunk(chunk);
|
||||
|
||||
this.encodingConfig.onEncodedPacket?.(packet, meta);
|
||||
|
||||
Reference in New Issue
Block a user