summaryrefslogtreecommitdiff
path: root/isoparser/src/main/java/com/coremedia/iso/boxes/CompositionTimeToSample.java
diff options
context:
space:
mode:
Diffstat (limited to 'isoparser/src/main/java/com/coremedia/iso/boxes/CompositionTimeToSample.java')
-rw-r--r--isoparser/src/main/java/com/coremedia/iso/boxes/CompositionTimeToSample.java150
1 files changed, 150 insertions, 0 deletions
diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/CompositionTimeToSample.java b/isoparser/src/main/java/com/coremedia/iso/boxes/CompositionTimeToSample.java
new file mode 100644
index 0000000..411bfe9
--- /dev/null
+++ b/isoparser/src/main/java/com/coremedia/iso/boxes/CompositionTimeToSample.java
@@ -0,0 +1,150 @@
+package com.coremedia.iso.boxes;
+
+import com.coremedia.iso.IsoTypeReader;
+import com.coremedia.iso.IsoTypeWriter;
+import com.googlecode.mp4parser.AbstractFullBox;
+
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import static com.googlecode.mp4parser.util.CastUtils.l2i;
+
+/**
+ * <pre>
+ * aligned(8) class CompositionOffsetBox
+ * extends FullBox(‘ctts’, version = 0, 0) {
+ * unsigned int(32) entry_count;
+ * int i;
+ * if (version==0) {
+ * for (i=0; i < entry_count; i++) {
+ * unsigned int(32) sample_count;
+ * unsigned int(32) sample_offset;
+ * }
+ * }
+ * else if (version == 1) {
+ * for (i=0; i < entry_count; i++) {
+ * unsigned int(32) sample_count;
+ * signed int(32) sample_offset;
+ * }
+ * }
+ * }
+ * </pre>
+ * <p/>
+ * This box provides the offset between decoding time and composition time.
+ * In version 0 of this box the decoding time must be less than the composition time, and
+ * the offsets are expressed as unsigned numbers such that
+ * CT(n) = DT(n) + CTTS(n) where CTTS(n) is the (uncompressed) table entry for sample n.
+ * <p/>
+ * In version 1 of this box, the composition timeline and the decoding timeline are
+ * still derived from each other, but the offsets are signed.
+ * It is recommended that for the computed composition timestamps, there is
+ * exactly one with the value 0 (zero).
+ */
+public class CompositionTimeToSample extends AbstractFullBox {
+ public static final String TYPE = "ctts";
+
+ List<Entry> entries = Collections.emptyList();
+
+ public CompositionTimeToSample() {
+ super(TYPE);
+ }
+
+ protected long getContentSize() {
+ return 8 + 8 * entries.size();
+ }
+
+ public List<Entry> getEntries() {
+ return entries;
+ }
+
+ public void setEntries(List<Entry> entries) {
+ this.entries = entries;
+ }
+
+ @Override
+ public void _parseDetails(ByteBuffer content) {
+ parseVersionAndFlags(content);
+ int numberOfEntries = l2i(IsoTypeReader.readUInt32(content));
+ entries = new ArrayList<Entry>(numberOfEntries);
+ for (int i = 0; i < numberOfEntries; i++) {
+ Entry e = new Entry(l2i(IsoTypeReader.readUInt32(content)), content.getInt());
+ entries.add(e);
+ }
+ }
+
+ @Override
+ protected void getContent(ByteBuffer byteBuffer) {
+ writeVersionAndFlags(byteBuffer);
+ IsoTypeWriter.writeUInt32(byteBuffer, entries.size());
+
+ for (Entry entry : entries) {
+ IsoTypeWriter.writeUInt32(byteBuffer, entry.getCount());
+ byteBuffer.putInt(entry.getOffset());
+ }
+
+ }
+
+
+ public static class Entry {
+ int count;
+ int offset;
+
+ public Entry(int count, int offset) {
+ this.count = count;
+ this.offset = offset;
+ }
+
+ public int getCount() {
+ return count;
+ }
+
+ public int getOffset() {
+ return offset;
+ }
+
+ public void setCount(int count) {
+ this.count = count;
+ }
+
+ public void setOffset(int offset) {
+ this.offset = offset;
+ }
+
+ @Override
+ public String toString() {
+ return "Entry{" +
+ "count=" + count +
+ ", offset=" + offset +
+ '}';
+ }
+ }
+
+
+ /**
+ * Decompresses the list of entries and returns the list of composition times.
+ *
+ * @return decoding time per sample
+ */
+ public static int[] blowupCompositionTimes(List<CompositionTimeToSample.Entry> entries) {
+ long numOfSamples = 0;
+ for (CompositionTimeToSample.Entry entry : entries) {
+ numOfSamples += entry.getCount();
+ }
+ assert numOfSamples <= Integer.MAX_VALUE;
+ int[] decodingTime = new int[(int) numOfSamples];
+
+ int current = 0;
+
+
+ for (CompositionTimeToSample.Entry entry : entries) {
+ for (int i = 0; i < entry.getCount(); i++) {
+ decodingTime[current++] = entry.getOffset();
+ }
+ }
+
+ return decodingTime;
+ }
+
+}