mirror of
https://github.com/arcodange-org/mediabunny.git
synced 2026-10-01 21:03:46 +02:00
Add codec-specific encoder configs
This commit is contained in:
+39
-3
@@ -181,6 +181,42 @@ export const buildAudioCodecString = (codec: AudioCodec, numberOfChannels: numbe
|
||||
throw new TypeError(`Unhandled codec '${codec}'.`);
|
||||
};
|
||||
|
||||
export const getVideoEncoderConfigExtension = (codec: VideoCodec) => {
|
||||
if (codec === 'avc') {
|
||||
return {
|
||||
avc: {
|
||||
format: 'avc' as const // Ensure the format is not Annex B
|
||||
}
|
||||
};
|
||||
} else if (codec === 'hevc') {
|
||||
return {
|
||||
hevc: {
|
||||
format: 'hevc' as const // Ensure the format is not Annex B
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return {};
|
||||
};
|
||||
|
||||
export const getAudioEncoderConfigExtension = (codec: AudioCodec) => {
|
||||
if (codec === 'aac') {
|
||||
return {
|
||||
aac: {
|
||||
format: 'aac' as const // Ensure the format is not ADTS
|
||||
}
|
||||
};
|
||||
} else if (codec === 'opus') {
|
||||
return {
|
||||
opus: {
|
||||
format: 'opus' as const
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return {};
|
||||
};
|
||||
|
||||
export const validateVideoChunkMetadata = (metadata: EncodedVideoChunkMetadata | undefined) => {
|
||||
if (!metadata) {
|
||||
throw new TypeError("Video chunk metadata must be provided.");
|
||||
@@ -236,12 +272,9 @@ export const validateVideoChunkMetadata = (metadata: EncodedVideoChunkMetadata |
|
||||
}
|
||||
|
||||
if ((metadata.decoderConfig.codec.startsWith('avc1') || metadata.decoderConfig.codec.startsWith('avc3')) && !metadata.decoderConfig.description) {
|
||||
// TODO Technically not correct, they can also lack a description in which case the chunks are annexb. Generally,
|
||||
// go through all the codec registrations and catch these edge cases.
|
||||
throw new TypeError("Video chunk metadata decoder configuration for AVC must include a description, which is expected to be an AVCDecoderConfigurationRecord as specified in ISO 14496-15.");
|
||||
}
|
||||
if ((metadata.decoderConfig.codec.startsWith('hev1') || metadata.decoderConfig.codec.startsWith('hvc1')) && !metadata.decoderConfig.description) {
|
||||
// TODO Same as above
|
||||
throw new TypeError("Video chunk metadata decoder configuration for HEVC must include a description, which is expected to be an HEVCDecoderConfigurationRecord as specified in ISO 14496-15.");
|
||||
}
|
||||
if ((metadata.decoderConfig.codec === 'vp8' || metadata.decoderConfig.codec.startsWith('vp09')) && metadata.decoderConfig.colorSpace === undefined) {
|
||||
@@ -278,6 +311,9 @@ export const validateAudioChunkMetadata = (metadata: EncodedAudioChunkMetadata |
|
||||
}
|
||||
}
|
||||
|
||||
if (metadata.decoderConfig.codec.startsWith('mp4a') && !metadata.decoderConfig.description) {
|
||||
throw new TypeError("Audio chunk metadata decoder configuration for AAC must include a description, which is expected to be an AudioSpecificConfig as specified in ISO 14496-3.");
|
||||
}
|
||||
if (metadata.decoderConfig.codec === 'opus' && metadata.decoderConfig.description && metadata.decoderConfig.description.byteLength < 18) {
|
||||
throw new TypeError('Invalid decoder description provided for Opus; must be at least 18 bytes long.');
|
||||
}
|
||||
|
||||
@@ -696,7 +696,7 @@ export const dOps = (trackData: IsobmffAudioTrackData) => {
|
||||
// https://www.rfc-editor.org/rfc/rfc7845#section-5
|
||||
const description = trackData.info.decoderConfig?.description;
|
||||
if (description) {
|
||||
assert(description.byteLength < 18); // Is validated in an earlier step
|
||||
assert(description.byteLength >= 18); // Is validated in an earlier step
|
||||
|
||||
const view = ArrayBuffer.isView(description)
|
||||
? new DataView(description.buffer, description.byteOffset, description.byteLength)
|
||||
|
||||
+3
-1
@@ -1,4 +1,4 @@
|
||||
import { buildAudioCodecString, buildVideoCodecString } from "./codec";
|
||||
import { buildAudioCodecString, buildVideoCodecString, getAudioEncoderConfigExtension, getVideoEncoderConfigExtension } from "./codec";
|
||||
import { assert } from "./misc";
|
||||
import { Muxer } from "./muxer";
|
||||
import { OutputAudioTrack, OutputSubtitleTrack, OutputTrack, OutputVideoTrack } from "./output";
|
||||
@@ -194,6 +194,7 @@ class VideoEncoderWrapper {
|
||||
bitrate: this.codecConfig.bitrate,
|
||||
framerate: this.source._connectedTrack?.metadata.frameRate,
|
||||
latencyMode: this.codecConfig.latencyMode,
|
||||
...getVideoEncoderConfigExtension(this.codecConfig.codec)
|
||||
});
|
||||
|
||||
assert(this.source._connectedTrack);
|
||||
@@ -438,6 +439,7 @@ class AudioEncoderWrapper {
|
||||
numberOfChannels: audioData.numberOfChannels,
|
||||
sampleRate: audioData.sampleRate,
|
||||
bitrate: this.codecConfig.bitrate,
|
||||
...getAudioEncoderConfigExtension(this.codecConfig.codec)
|
||||
});
|
||||
|
||||
assert(this.source._connectedTrack);
|
||||
|
||||
Reference in New Issue
Block a user