Mp4EsdsBoxpublic 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
//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$AudioProfile | getAudioProfile()Get audio profile, usually AAC Low Complexity
return audioProfile;
| public int | getAvgBitrate()
return avgBitrate;
| public org.jaudiotagger.audio.mp4.atom.Mp4EsdsBox$Kind | getKind()Only expext MPG_Audio,
TODO shouldnt matter if another type of audio, but something gone wrong if type of video
return kind;
| public int | getMaxBitrate()
return maxBitrate;
| public int | getNumberOfChannels()
return numberOfChannels;
| public int | processSectionHeader(java.nio.ByteBuffer dataBuffer)Process header, skipping filler bytes and calculating size
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;
|
|