package mp4.util.atom;
/**
* The movie header atom.
*/
@SuppressWarnings("unused")
public class MvhdAtom extends LeafAtom {
private static final int V0_CREATION_TIME_OFFSET = 4;
private static final int V0_MODIFICATION_TIME_OFFSET = 8;
private static final int V0_TIMESCALE_OFFSET = 12;
private static final int V0_DURATION_OFFSET = 16;
private static final int V1_TIMESCALE_OFFSET = 20;
private static final int V1_DURATION_OFFSET = 24;
//private static final int RATE_OFFSET = 20;
//private static final int VOLUME_OFFSET = 24;
//private static final int RESERVED_OFFSET = 26;
//private static final int MATRIX_STRUCTURE_OFFSET = 36;
// quicktime has other data in the pre_defined space
//private static final int PRE_DEFINED_OFFSET = 72;
//private static final int NEXT_TRACK_ID_OFFSET = 76;
/**
* Construct an empty mvhd atom.
*/
public MvhdAtom() {
super(new byte[]{'m','v','h','d'});
}
/**
* Copy constructor. Perform a deep copy.
* @param old the old version to copy
*/
public MvhdAtom(MvhdAtom old) {
super(old);
}
// /**
// * Return the creation time of the presentation. In seconds, since
// * midnight January 1, 1904.
// * @return the creation time of the presentation.
// */
// public long getCreationTime() {
// return data.getUnsignedInt(CREATION_TIME_OFFSET);
// }
//
// /**
// * Set the creation time of the presentation. In seconds, since
// * midnight January 1, 1904.
// * @param ct the creation time
// */
// public void setCreationTime(long ct) {
// data.addUnsignedInt(CREATION_TIME_OFFSET, ct);
// }
//
// /**
// * Return the modification time of the presentation. In seconds,
// * since midnight January 1, 1904.
// * @return the modification time
// */
// public long getModificationTime() {
// return data.getUnsignedInt(MODIFICATION_TIME_OFFSET);
// }
//
// /**
// * Set the modification time of the presentation. In seconds,
// * since midnight January 1, 1904.
// * @param mt the modification time
// */
// public void setModificationTime(long mt) {
// data.addUnsignedInt(MODIFICATION_TIME_OFFSET, mt);
// }
//
/**
* Return the time-scale for the mvhd atom
* @return the time-scale
*/
public long getTimeScale() {
if (getVersion() == 0)
return data.getUnsignedInt(V0_TIMESCALE_OFFSET);
else
return data.getUnsignedInt(V1_TIMESCALE_OFFSET);
}
/**
* Set the time-scale for the mvhd atom
* @param ts the new time-scale
*/
public void setTimeScale(long ts) {
if (getVersion() == 0)
data.addUnsignedInt(V0_TIMESCALE_OFFSET, ts);
else
data.addUnsignedInt(V1_TIMESCALE_OFFSET, ts);
}
/**
* Return the duration for the mvhd atom. The duration is the maximum of the
* duration of the tracks.
* @return the duration
*/
public long getDuration() {
if (getVersion() == 0)
return data.getUnsignedInt(V0_DURATION_OFFSET);
else
return data.getLong(V1_DURATION_OFFSET);
}
/**
* Set the duration for the movie header atom. The duration is the length of the duration of its
* longest track.
* @param duration the duration for the movie header
*/
public void setDuration(long duration) {
if (getVersion() == 0)
data.addUnsignedInt(V0_DURATION_OFFSET, duration);
else
data.addLong(V1_DURATION_OFFSET, duration);
}
/**
* Return the normalized time-scale for the movie.
* @return the movie's normalized time-scale.
*/
public long getDurationNormalized() {
return getDuration() / getTimeScale();
}
/**
* Cut the movie header. The only change needed is the duration, which is easiest done
* after the entire moov atom has been updated.
* @return a copy of the movie header
*/
public MvhdAtom cut() {
MvhdAtom copy = new MvhdAtom(this);
// set to zero, and remember to update it by the caller.
copy.setDuration(0);
return copy;
}
@Override
public void accept(AtomVisitor v) throws AtomException {
v.visit(this);
}
public boolean force32BitTimes() {
if (getVersion() == 0)
return false;
data.collapse64To32(V0_CREATION_TIME_OFFSET);
data.collapse64To32(V0_MODIFICATION_TIME_OFFSET);
data.collapse64To32(V0_DURATION_OFFSET);
setVersion((byte)0);
return true;
}
}