Mp4AudioHeader info = new Mp4AudioHeader();
//File Identification
Mp4BoxHeader ftypHeader = Mp4BoxHeader.seekWithinLevel(raf, Mp4NotMetaFieldKey.FTYP.getFieldName());
if (ftypHeader == null) {
throw new CannotReadException(ErrorMessage.MP4_FILE_NOT_CONTAINER.getMsg());
}
ByteBuffer ftypBuffer = ByteBuffer.allocate(ftypHeader.getLength() - Mp4BoxHeader.HEADER_LENGTH);
raf.getChannel().read(ftypBuffer);
ftypBuffer.rewind();
Mp4FtypBox ftyp = new Mp4FtypBox(ftypHeader, ftypBuffer);
ftyp.processData();
info.setBrand(ftyp.getMajorBrand());
//Get to the facts everything we are interested in is within the moov box, so just load data from file
//once so no more file I/O needed
Mp4BoxHeader moovHeader = Mp4BoxHeader.seekWithinLevel(raf, Mp4NotMetaFieldKey.MOOV.getFieldName());
if (moovHeader == null) {
throw new CannotReadException(ErrorMessage.MP4_FILE_NOT_AUDIO.getMsg());
}
ByteBuffer moovBuffer = ByteBuffer.allocate(moovHeader.getLength() - Mp4BoxHeader.HEADER_LENGTH);
raf.getChannel().read(moovBuffer);
moovBuffer.rewind();
//Level 2-Searching for "mvhd" somewhere within "moov", we make a slice after finding header
//so all get() methods will be relative to mvdh positions
Mp4BoxHeader boxHeader = Mp4BoxHeader.seekWithinLevel(moovBuffer, Mp4NotMetaFieldKey.MVHD.getFieldName());
if (boxHeader == null) {
throw new CannotReadException(ErrorMessage.MP4_FILE_NOT_AUDIO.getMsg());
}
ByteBuffer mvhdBuffer = moovBuffer.slice();
Mp4MvhdBox mvhd = new Mp4MvhdBox(boxHeader, mvhdBuffer);
info.setPreciseLength(mvhd.getLength());
//Advance position, TODO should we put this in box code ?
mvhdBuffer.position(mvhdBuffer.position() + boxHeader.getDataLength());
//Level 2-Searching for "trak" within "moov"
boxHeader = Mp4BoxHeader.seekWithinLevel(mvhdBuffer, Mp4NotMetaFieldKey.TRAK.getFieldName());
int endOfFirstTrackInBuffer = mvhdBuffer.position() + boxHeader.getDataLength();
if (boxHeader == null) {
throw new CannotReadException(ErrorMessage.MP4_FILE_NOT_AUDIO.getMsg());
}
//Level 3-Searching for "mdia" within "trak"
boxHeader = Mp4BoxHeader.seekWithinLevel(mvhdBuffer, Mp4NotMetaFieldKey.MDIA.getFieldName());
if (boxHeader == null) {
throw new CannotReadException(ErrorMessage.MP4_FILE_NOT_AUDIO.getMsg());
}
//Level 4-Searching for "mdhd" within "mdia"
boxHeader = Mp4BoxHeader.seekWithinLevel(mvhdBuffer, Mp4NotMetaFieldKey.MDHD.getFieldName());
if (boxHeader == null) {
throw new CannotReadException(ErrorMessage.MP4_FILE_NOT_AUDIO.getMsg());
}
Mp4MdhdBox mdhd = new Mp4MdhdBox(boxHeader, mvhdBuffer.slice());
info.setSamplingRate(mdhd.getSampleRate());
//Level 4-Searching for "hdlr" within "mdia"
/*We dont currently need to process this because contains nothing we want
mvhdBuffer.position(mvhdBuffer.position() + boxHeader.getDataLength());
boxHeader = Mp4BoxHeader.seekWithinLevel(mvhdBuffer, Mp4NotMetaFieldKey.HDLR.getFieldName());
if (boxHeader == null)
{
throw new CannotReadException(ErrorMessage.MP4_FILE_NOT_AUDIO.getMsg());
}
Mp4HdlrBox hdlr = new Mp4HdlrBox(boxHeader, mvhdBuffer.slice());
hdlr.processData();
*/
//Level 4-Searching for "minf" within "mdia"
mvhdBuffer.position(mvhdBuffer.position() + boxHeader.getDataLength());
boxHeader = Mp4BoxHeader.seekWithinLevel(mvhdBuffer, Mp4NotMetaFieldKey.MINF.getFieldName());
if (boxHeader == null) {
throw new CannotReadException(ErrorMessage.MP4_FILE_NOT_AUDIO.getMsg());
}
//Level 5-Searching for "smhd" within "minf"
//Only an audio track would have a smhd frame
boxHeader = Mp4BoxHeader.seekWithinLevel(mvhdBuffer, Mp4NotMetaFieldKey.SMHD.getFieldName());
if (boxHeader == null) {
throw new CannotReadException(ErrorMessage.MP4_FILE_NOT_AUDIO.getMsg());
}
mvhdBuffer.position(mvhdBuffer.position() + boxHeader.getDataLength());
//Level 5-Searching for "stbl within "minf"
boxHeader = Mp4BoxHeader.seekWithinLevel(mvhdBuffer, Mp4NotMetaFieldKey.STBL.getFieldName());
if (boxHeader == null) {
throw new CannotReadException(ErrorMessage.MP4_FILE_NOT_AUDIO.getMsg());
}
//Level 6-Searching for "stsd within "stbl" and process it direct data, dont think these are mandatory so dont throw
//exception if unable to find
boxHeader = Mp4BoxHeader.seekWithinLevel(mvhdBuffer, Mp4NotMetaFieldKey.STSD.getFieldName());