package org.jcodec.codecs.aac; import static org.jcodec.codecs.aac.ObjectType.AOT_ESCAPE; import java.nio.ByteBuffer; import org.jcodec.codecs.mpeg4.mp4.EsdsBox; import org.jcodec.common.AudioFormat; import org.jcodec.common.io.BitReader; import org.jcodec.common.model.ChannelLabel; import org.jcodec.containers.mp4.boxes.Box; import org.jcodec.containers.mp4.boxes.LeafBox; import org.jcodec.containers.mp4.boxes.SampleEntry; /** * This class is part of JCodec ( www.jcodec.org ) This software is distributed * under FreeBSD License * * @author The JCodec project * */ public class AACUtils { public static class AudioInfo { private AudioFormat format; private ChannelLabel[] labels; public AudioInfo(AudioFormat format, ChannelLabel[] labels) { this.format = format; this.labels = labels; } public AudioFormat getFormat() { return format; } public ChannelLabel[] getLabels() { return labels; } } private static int getObjectType(BitReader reader) { int objectType = reader.readNBit(5); if (objectType == AOT_ESCAPE.ordinal()) objectType = 32 + reader.readNBit(6); return objectType; } private static ChannelLabel[][] AAC_DEFAULT_CONFIGS = { null, // { ChannelLabel.MONO }, // { ChannelLabel.STEREO_LEFT, ChannelLabel.STEREO_RIGHT }, // { ChannelLabel.CENTER, ChannelLabel.FRONT_LEFT, ChannelLabel.FRONT_RIGHT }, // { ChannelLabel.CENTER, ChannelLabel.FRONT_LEFT, ChannelLabel.FRONT_RIGHT, ChannelLabel.REAR_CENTER }, // { ChannelLabel.CENTER, ChannelLabel.FRONT_LEFT, ChannelLabel.FRONT_RIGHT, ChannelLabel.REAR_LEFT, ChannelLabel.REAR_RIGHT }, // { ChannelLabel.CENTER, ChannelLabel.FRONT_LEFT, ChannelLabel.FRONT_RIGHT, ChannelLabel.REAR_LEFT, ChannelLabel.REAR_RIGHT, ChannelLabel.LFE }, // { ChannelLabel.CENTER, ChannelLabel.FRONT_LEFT, ChannelLabel.FRONT_RIGHT, ChannelLabel.SIDE_LEFT, ChannelLabel.SIDE_RIGHT, ChannelLabel.REAR_LEFT, ChannelLabel.REAR_RIGHT, ChannelLabel.LFE } // }; public static AudioInfo parseAudioInfo(ByteBuffer privData) { BitReader reader = new BitReader(privData); int objectType = getObjectType(reader); int index = reader.readNBit(4); int sampleRate = index == 0x0f ? reader.readNBit(24) : AACConts.AAC_SAMPLE_RATES[index]; int channelConfig = reader.readNBit(4); if (channelConfig == 0 || channelConfig >= AAC_DEFAULT_CONFIGS.length) return null; ChannelLabel[] channels = AAC_DEFAULT_CONFIGS[channelConfig]; return new AudioInfo(new AudioFormat(sampleRate, 16, channels.length, true, false), channels); } public static AudioInfo getChannels(SampleEntry mp4a) { if (!"mp4a".equals(mp4a.getFourcc())) throw new IllegalArgumentException("Not mp4a sample entry"); LeafBox b = Box.findFirst(mp4a, LeafBox.class, "esds"); if (b == null) b = Box.findFirst(mp4a, LeafBox.class, null, "esds"); if (b == null) return null; EsdsBox esds = new EsdsBox(); esds.parse(b.getData()); return parseAudioInfo(esds.getStreamInfo()); } }