FileDocCategorySizeDatePackage
Mp4StcoBox.javaAPI DocJaudiotagger 2.0.49209Thu Sep 22 11:19:18 BST 2011org.jaudiotagger.audio.mp4.atom

Mp4StcoBox

public class Mp4StcoBox extends AbstractMp4Box
StcoBox ( media (stream) header), holds offsets into the Audio data

Fields Summary
public static final int
VERSION_FLAG_POS
public static final int
OTHER_FLAG_POS
public static final int
NO_OF_OFFSETS_POS
public static final int
VERSION_FLAG_LENGTH
public static final int
OTHER_FLAG_LENGTH
public static final int
NO_OF_OFFSETS_LENGTH
public static final int
OFFSET_LENGTH
private int
noOfOffSets
private int
firstOffSet
Constructors Summary
public Mp4StcoBox(Mp4BoxHeader header, ByteBuffer buffer)
Construct box from data and show contents

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


                             
        
    
        this.header = header;

        //Make a slice of databuffer then we can work with relative or absolute methods safetly
        dataBuffer = buffer.slice();

        //Skip the flags
        dataBuffer.position(dataBuffer.position() + VERSION_FLAG_LENGTH + OTHER_FLAG_LENGTH);

        //No of offsets
        this.noOfOffSets = Utils.getIntBE(dataBuffer, dataBuffer.position(), (dataBuffer.position() + NO_OF_OFFSETS_LENGTH - 1));
        dataBuffer.position(dataBuffer.position() + NO_OF_OFFSETS_LENGTH);

        //First Offset, useful for sanity checks
        firstOffSet = Utils.getIntBE(dataBuffer, dataBuffer.position(), (dataBuffer.position() + OFFSET_LENGTH - 1));
    
public Mp4StcoBox(Mp4BoxHeader header, ByteBuffer originalDataBuffer, int adjustment)
Construct box from data and adjust offets accordingly

param
header header info
param
originalDataBuffer data of box (doesnt include header data)
param
adjustment

        this.header = header;

        //Make a slice of databuffer then we can work with relative or absolute methods safetly
        this.dataBuffer = originalDataBuffer.slice();

        //Skip the flags
        dataBuffer.position(dataBuffer.position() + VERSION_FLAG_LENGTH + OTHER_FLAG_LENGTH);

        //No of offsets
        this.noOfOffSets = Utils.getIntBE(dataBuffer, dataBuffer.position(), (dataBuffer.position() + NO_OF_OFFSETS_LENGTH - 1));
        dataBuffer.position(dataBuffer.position() + NO_OF_OFFSETS_LENGTH);

        for (int i = 0; i < noOfOffSets; i++)
        {
            int offset = Utils.getIntBE(dataBuffer, dataBuffer.position(), (dataBuffer.position() + NO_OF_OFFSETS_LENGTH - 1));

            //Calculate new offset and update buffer
            offset = offset + adjustment;
            dataBuffer.put(Utils.getSizeBEInt32(offset));
        }
    
Methods Summary
public voidadjustOffsets(int adjustment)

        //Skip the flags
        dataBuffer.rewind();
        dataBuffer.position(dataBuffer.position() + VERSION_FLAG_LENGTH + OTHER_FLAG_LENGTH + NO_OF_OFFSETS_LENGTH);
        for (int i = 0; i < noOfOffSets; i++)
        {
            int offset = Utils.getIntBE(dataBuffer, dataBuffer.position(), (dataBuffer.position() + NO_OF_OFFSETS_LENGTH - 1));

            //Calculate new offset and update buffer
            offset = offset + adjustment;
            dataBuffer.put(Utils.getSizeBEInt32(offset));
        }
    
public static voiddebugShowStcoInfo(java.io.RandomAccessFile raf)

        Mp4BoxHeader moovHeader = Mp4BoxHeader.seekWithinLevel(raf, Mp4AtomIdentifier.MOOV.getFieldName());
        if (moovHeader == null)
        {
            throw new CannotReadException("This file does not appear to be an audio file");
        }
        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 getFields() methods will be relative to mvdh positions
        Mp4BoxHeader boxHeader = Mp4BoxHeader.seekWithinLevel(moovBuffer, Mp4AtomIdentifier.MVHD.getFieldName());
        if (boxHeader == null)
        {
            throw new CannotReadException("This file does not appear to be an audio file");
        }
        ByteBuffer mvhdBuffer = moovBuffer.slice();
        Mp4MvhdBox mvhd = new Mp4MvhdBox(boxHeader, mvhdBuffer);
        mvhdBuffer.position(mvhdBuffer.position() + boxHeader.getDataLength());

        //Level 2-Searching for "trak" within "moov"
        boxHeader = Mp4BoxHeader.seekWithinLevel(mvhdBuffer, Mp4AtomIdentifier.TRAK.getFieldName());
        int endOfFirstTrackInBuffer = mvhdBuffer.position() + boxHeader.getDataLength();

        if (boxHeader == null)
        {
            throw new CannotReadException("This file does not appear to be an audio file");
        }
        //Level 3-Searching for "mdia" within "trak"
        boxHeader = Mp4BoxHeader.seekWithinLevel(mvhdBuffer, Mp4AtomIdentifier.MDIA.getFieldName());
        if (boxHeader == null)
        {
            throw new CannotReadException("This file does not appear to be an audio file");
        }

        //Level 4-Searching for "mdhd" within "mdia"
        boxHeader = Mp4BoxHeader.seekWithinLevel(mvhdBuffer, Mp4AtomIdentifier.MDHD.getFieldName());
        if (boxHeader == null)
        {
            throw new CannotReadException("This file does not appear to be an audio file");
        }

        //Level 4-Searching for "minf" within "mdia"
        mvhdBuffer.position(mvhdBuffer.position() + boxHeader.getDataLength());
        boxHeader = Mp4BoxHeader.seekWithinLevel(mvhdBuffer, Mp4AtomIdentifier.MINF.getFieldName());
        if (boxHeader == null)
        {
            throw new CannotReadException("This file does not appear to be an audio file");
        }

        //Level 5-Searching for "smhd" within "minf"
        //Only an audio track would have a smhd frame
        boxHeader = Mp4BoxHeader.seekWithinLevel(mvhdBuffer, Mp4AtomIdentifier.SMHD.getFieldName());
        if (boxHeader == null)
        {
            throw new CannotReadException("This file does not appear to be an audio file");
        }
        mvhdBuffer.position(mvhdBuffer.position() + boxHeader.getDataLength());

        //Level 5-Searching for "stbl within "minf"
        boxHeader = Mp4BoxHeader.seekWithinLevel(mvhdBuffer, Mp4AtomIdentifier.STBL.getFieldName());
        if (boxHeader == null)
        {
            throw new CannotReadException("This file does not appear to be an audio file");
        }

        //Level 6-Searching for "stco within "stbl"
        boxHeader = Mp4BoxHeader.seekWithinLevel(mvhdBuffer, Mp4AtomIdentifier.STCO.getFieldName());
        if (boxHeader == null)
        {
            throw new CannotReadException("This file does not appear to be an audio file");
        }
        Mp4StcoBox stco = new Mp4StcoBox(boxHeader, mvhdBuffer);
        stco.printAlloffsets();
    
public intgetFirstOffSet()
The value of the first offset

return

        return firstOffSet;
    
public intgetNoOfOffSets()
The number of offsets

return

        return noOfOffSets;
    
public voidprintAlloffsets()
Show All offsets, useful for debugging

        System.out.println("Print Offsets:start");
        dataBuffer.rewind();
        dataBuffer.position(VERSION_FLAG_LENGTH + OTHER_FLAG_LENGTH + NO_OF_OFFSETS_LENGTH);
        for (int i = 0; i < noOfOffSets - 1; i++)
        {
            int offset = Utils.getIntBE(dataBuffer, dataBuffer.position(), (dataBuffer.position() + OFFSET_LENGTH - 1));
            System.out.println("offset into audio data is:" + offset);

            dataBuffer.position(dataBuffer.position() + OFFSET_LENGTH);
        }
        int offset = Utils.getIntBE(dataBuffer, dataBuffer.position(), (dataBuffer.position() + OFFSET_LENGTH - 1));
        System.out.println("offset into audio data is:" + offset);
        System.out.println("Print Offsets:end");

    
public voidprintTotalOffset()

        int offset = 0;
        dataBuffer.rewind();
        dataBuffer.position(VERSION_FLAG_LENGTH + OTHER_FLAG_LENGTH + NO_OF_OFFSETS_LENGTH);
        for (int i = 0; i < noOfOffSets - 1; i++)
        {
            offset += Utils.getIntBE(dataBuffer, dataBuffer.position(), (dataBuffer.position() + OFFSET_LENGTH - 1));
            dataBuffer.position(dataBuffer.position() + OFFSET_LENGTH);
        }
        offset += Utils.getIntBE(dataBuffer, dataBuffer.position(), (dataBuffer.position() + OFFSET_LENGTH - 1));
        System.out.println("Print Offset Total:" + offset);