FileDocCategorySizeDatePackage
Mp4EsdsBox.javaAPI DocJaudiotagger 2.0.410838Wed Mar 30 16:11:44 BST 2011org.jaudiotagger.audio.mp4.atom

Mp4EsdsBox

public class Mp4EsdsBox extends AbstractMp4Box
EsdsBox ( stream specific description box), usually holds the Bitrate/No of Channels

It contains a number of (possibly optional?) sections (section 3 - 6) (containing optional filler) with differeent info in each section.

-> 4 bytes version/flags = 8-bit hex version + 24-bit hex flags (current = 0)

Section 3 -> 1 byte ES descriptor type tag = 8-bit hex value 0x03 -> 3 bytes optional extended descriptor type tag string = 3 * 8-bit hex value - types are 0x80,0x81,0xFE -> 1 byte descriptor type length = 8-bit unsigned length -> 2 bytes ES ID = 16-bit unsigned value -> 1 byte stream priority = 8-bit unsigned value - Defaults to 16 and ranges from 0 through to 31

Section 4 -> 1 byte decoder config descriptor type tag = 8-bit hex value 0x04 -> 3 bytes optional extended descriptor type tag string = 3 * 8-bit hex value - types are 0x80,0x81,0xFE -> 1 byte descriptor type length = 8-bit unsigned length * -> 1 byte object type ID = 8-bit unsigned value -> 6 bits stream type = 3/4 byte hex value - type IDs are object descript. = 1 ; clock ref. = 2 - type IDs are scene descript. = 4 ; visual = 4 - type IDs are audio = 5 ; MPEG-7 = 6 ; IPMP = 7 - type IDs are OCI = 8 ; MPEG Java = 9 - type IDs are user private = 32 -> 1 bit upstream flag = 1/8 byte hex value -> 1 bit reserved flag = 1/8 byte hex value set to 1 -> 3 bytes buffer size = 24-bit unsigned value -> 4 bytes maximum bit rate = 32-bit unsigned value -> 4 bytes average bit rate = 32-bit unsigned value

Section 5 -> 1 byte decoder specific descriptor type tag 8-bit hex value 0x05 -> 3 bytes optional extended descriptor type tag string = 3 * 8-bit hex value - types are 0x80,0x81,0xFE -> 1 byte descriptor type length = 8-bit unsigned length -> 1 byte Audio profile Id - 5 bits Profile Id - 3 bits Unknown -> 8 bits other flags - 3 bits unknown - 2 bits is No of Channels - 3 bits unknown

Section 6

-> 1 byte SL config descriptor type tag = 8-bit hex value 0x06 -> 3 bytes optional extended descriptor type tag string = 3 * 8-bit hex value - types are 0x80,0x81,0xFE -> 1 byte descriptor type length = 8-bit unsigned length -> 1 byte SL value = 8-bit hex value set to 0x02

Fields Summary
public static final int
VERSION_FLAG_LENGTH
public static final int
OTHER_FLAG_LENGTH
public static final int
DESCRIPTOR_TYPE_LENGTH
public static final int
ES_ID_LENGTH
public static final int
STREAM_PRIORITY_LENGTH
public static final int
CONFIG_TYPE_LENGTH
public static final int
OBJECT_TYPE_LENGTH
public static final int
STREAM_TYPE_LENGTH
public static final int
BUFFER_SIZE_LENGTH
public static final int
MAX_BITRATE_LENGTH
public static final int
AVERAGE_BITRATE_LENGTH
public static final int
DESCRIPTOR_OBJECT_TYPE_LENGTH
public static final int
CHANNEL_FLAGS_LENGTH
private Kind
kind
private AudioProfile
audioProfile
private int
numberOfChannels
private int
maxBitrate
private int
avgBitrate
private static final int
SECTION_THREE
private static final int
SECTION_FOUR
private static final int
SECTION_FIVE
private static final int
SECTION_SIX
private static final int
FILLER_START
private static final int
FILLER_OTHER
private static final int
FILLER_END
private static Map
kindMap
private static Map
audioProfileMap
Constructors Summary
public Mp4EsdsBox(Mp4BoxHeader header, ByteBuffer dataBuffer)
DataBuffer must start from from the start of the body

param
header header info
param
dataBuffer data of box (doesnt include header data)



    
    
        //Create maps to speed up lookup from raw value to enum
        kindMap = new HashMap<Integer, Kind>();
        for (Kind next : Kind.values())
        {
            kindMap.put(next.getId(), next);
        }

        audioProfileMap = new HashMap<Integer, AudioProfile>();
        for (AudioProfile next : AudioProfile.values())
        {
            audioProfileMap.put(next.getId(), next);
        }
    
        this.header = header;

        //Not currently used, as lengths can extend over more than one section i think
        int sectionThreeLength;
        int sectionFourLength;
        int sectionFiveLength;
        int sectionSixLength;

        //As explained earlier the length of this atom is not fixed so processing is a bit more difficult
        //Process Flags
        dataBuffer.position(dataBuffer.position() + VERSION_FLAG_LENGTH + OTHER_FLAG_LENGTH);

        //Process Section 3 if exists
        if (dataBuffer.get() == SECTION_THREE)
        {
            sectionThreeLength = processSectionHeader(dataBuffer);
            //Skip Other Section 3 data
            dataBuffer.position(dataBuffer.position() + ES_ID_LENGTH + STREAM_PRIORITY_LENGTH);
        }

        //Process Section 4 (to getFields type and bitrate)
        if (dataBuffer.get() == SECTION_FOUR)
        {
            sectionFourLength = processSectionHeader(dataBuffer);

            //kind (in iTunes)
            kind = kindMap.get((int) dataBuffer.get());

            //Skip Other Section 4 data
            dataBuffer.position(dataBuffer.position() + STREAM_TYPE_LENGTH + BUFFER_SIZE_LENGTH);

            //Bit rates
            this.maxBitrate = Utils.getIntBE(dataBuffer, dataBuffer.position(), (dataBuffer.position() + MAX_BITRATE_LENGTH - 1));
            dataBuffer.position(dataBuffer.position() + MAX_BITRATE_LENGTH);

            this.avgBitrate = Utils.getIntBE(dataBuffer, dataBuffer.position(), (dataBuffer.position() + AVERAGE_BITRATE_LENGTH - 1));
            dataBuffer.position(dataBuffer.position() + AVERAGE_BITRATE_LENGTH);


        }
        //Process Section 5,(to getFields no of channels and audioprofile(profile in itunes))
        if (dataBuffer.get() == SECTION_FIVE)
        {
            sectionFiveLength = processSectionHeader(dataBuffer);

            //Audio Profile
            audioProfile = audioProfileMap.get((dataBuffer.get() >> 3));

            //Channels
            byte channelByte = dataBuffer.get();
            numberOfChannels = (channelByte << 1) >> 4;
        }

        //Process Section 6, not needed ...


    
Methods Summary
public org.jaudiotagger.audio.mp4.atom.Mp4EsdsBox$AudioProfilegetAudioProfile()
Get audio profile, usually AAC Low Complexity

return
the audio profile

        return audioProfile;
    
public intgetAvgBitrate()

return
average bit rate (bps)

        return avgBitrate;
    
public org.jaudiotagger.audio.mp4.atom.Mp4EsdsBox$KindgetKind()
Only expext MPG_Audio, TODO shouldnt matter if another type of audio, but something gone wrong if type of video

return
the file type for the track

        return kind;
    
public intgetMaxBitrate()

return
maximum bit rate (bps)

        return maxBitrate;
    
public intgetNumberOfChannels()

        return numberOfChannels;
    
public intprocessSectionHeader(java.nio.ByteBuffer dataBuffer)
Process header, skipping filler bytes and calculating size

param
dataBuffer
return
section header

        int datalength;
        byte nextByte = dataBuffer.get();
        if (((nextByte & 0xFF) == FILLER_START) || ((nextByte & 0xFF) == FILLER_OTHER) || ((nextByte & 0xFF) == FILLER_END))
        {
            dataBuffer.get();
            dataBuffer.get();
            datalength = dataBuffer.get();
        }
        else
        {
            datalength = nextByte;
        }
        return datalength;