/**
*
*/
package mp4.util.atom;
/**
* Sync sample atoms identify key frames in the media.
*/
public class StssAtom extends LeafAtom {
private static final int ENTRIES_OFFSET = 4;
private static final int TABLE_OFFSET = 8;
private static final int ENTRY_SIZE = 4;
private static final int KEY_FRAME = 0;
/**
* Construct an empty stts atom
*/
public StssAtom() {
super(new byte[]{'s','t','s','s'});
}
/**
* Copy constructor. Performs a deep copy.
* @param old the version to copy
*/
public StssAtom(StssAtom old) {
super(old);
}
/**
* Allocate space for the atom's data
*/
@Override
public void allocateData(long numEntries) {
long size = TABLE_OFFSET + (numEntries * ENTRY_SIZE);
super.allocateData(size);
}
/**
* Return the number of entries in the sync sample table
* @return the number of entries in the able
*/
public long getNumEntries() {
return data.getUnsignedInt(ENTRIES_OFFSET);
}
/**
* Set the number of entries in the sync sample table.
* @param numEntries the number of entries
*/
public void setNumEntries(long numEntries) {
data.addUnsignedInt(ENTRIES_OFFSET, numEntries);
}
/**
* Return the ith entry in the table
* @param i the entry number
* @return the ith entry in the table
*/
public long getSampleEntry(long i) {
return data.getUnsignedInt(TABLE_OFFSET + ((int)i * ENTRY_SIZE) + KEY_FRAME);
}
/**
* Set the ith entry in the table.
* @param index the table index number
* @param keyFrame the value inserted in to the table
*/
public void setSampleEntry(int index, long keyFrame) {
data.addUnsignedInt(TABLE_OFFSET + (index * ENTRY_SIZE) + KEY_FRAME, keyFrame);
}
/**
* Return the key frame for the specified index.
* @param sampleNum the sample number
* @return the key frame
*/
public long getKeyFrame(long sampleNum) {
if (sampleNum > Integer.MAX_VALUE) {
return 0;
}
long numEntries = getNumEntries();
long lastKeyFrame = 0;
for (long i = 0; i < numEntries; i++) {
long keyFrame = getSampleEntry(i);
if (sampleNum < keyFrame) {
return lastKeyFrame;
}
lastKeyFrame = keyFrame;
}
return sampleNum;
}
/**
* Cut the stss table at the specified sample point and create
* a new atom with the subsequent entries
* @param bs the byte stream with the new data
* @param sampleNum the sample number
* @return the new stss atom
*/
public StssAtom cut(long sampleNum) {
// find the first entry
long numEntries = getNumEntries();
long i;
for (i = 0; i < numEntries; i++) {
if (sampleNum == getSampleEntry(i)) {
break;
}
}
assert sampleNum == getSampleEntry(i);
StssAtom cutStss = new StssAtom();
// create the new table
cutStss.allocateData(numEntries - i);
cutStss.setNumEntries(numEntries - i);
for (int entryNumber = 0; i < numEntries; i++, entryNumber++) {
cutStss.setSampleEntry(entryNumber, getSampleEntry(i) - sampleNum + 1);
}
return cutStss;
}
@Override
public void accept(AtomVisitor v) throws AtomException {
v.visit(this);
}
}