summaryrefslogtreecommitdiff
path: root/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/TrackRunBox.java
diff options
context:
space:
mode:
Diffstat (limited to 'isoparser/src/main/java/com/coremedia/iso/boxes/fragment/TrackRunBox.java')
-rw-r--r--isoparser/src/main/java/com/coremedia/iso/boxes/fragment/TrackRunBox.java355
1 files changed, 355 insertions, 0 deletions
diff --git a/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/TrackRunBox.java b/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/TrackRunBox.java
new file mode 100644
index 0000000..fc4faac
--- /dev/null
+++ b/isoparser/src/main/java/com/coremedia/iso/boxes/fragment/TrackRunBox.java
@@ -0,0 +1,355 @@
+/*
+ * Copyright 2009 castLabs GmbH, Berlin
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.coremedia.iso.boxes.fragment;
+
+import com.coremedia.iso.IsoTypeReader;
+import com.coremedia.iso.IsoTypeWriter;
+import com.coremedia.iso.boxes.MovieBox;
+import com.googlecode.mp4parser.AbstractFullBox;
+
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+
+import static com.googlecode.mp4parser.util.CastUtils.l2i;
+
+/**
+ * aligned(8) class TrackRunBox
+ * extends FullBox('trun', 0, tr_flags) {
+ * unsigned int(32) sample_count;
+ * // the following are optional fields
+ * signed int(32) data_offset;
+ * unsigned int(32) first_sample_flags;
+ * // all fields in the following array are optional
+ * {
+ * unsigned int(32) sample_duration;
+ * unsigned int(32) sample_size;
+ * unsigned int(32) sample_flags
+ * unsigned int(32) sample_composition_time_offset;
+ * }[ sample_count ]
+ * }
+ */
+
+public class TrackRunBox extends AbstractFullBox {
+ public static final String TYPE = "trun";
+ private int dataOffset;
+ private SampleFlags firstSampleFlags;
+ private List<Entry> entries = new ArrayList<Entry>();
+
+
+ public List<Entry> getEntries() {
+ return entries;
+ }
+
+ public static class Entry {
+ private long sampleDuration;
+ private long sampleSize;
+ private SampleFlags sampleFlags;
+ private int sampleCompositionTimeOffset;
+
+ public Entry() {
+ }
+
+ public Entry(long sampleDuration, long sampleSize, SampleFlags sampleFlags, int sampleCompositionTimeOffset) {
+ this.sampleDuration = sampleDuration;
+ this.sampleSize = sampleSize;
+ this.sampleFlags = sampleFlags;
+ this.sampleCompositionTimeOffset = sampleCompositionTimeOffset;
+ }
+
+ public long getSampleDuration() {
+ return sampleDuration;
+ }
+
+ public long getSampleSize() {
+ return sampleSize;
+ }
+
+ public SampleFlags getSampleFlags() {
+ return sampleFlags;
+ }
+
+ public int getSampleCompositionTimeOffset() {
+ return sampleCompositionTimeOffset;
+ }
+
+ public void setSampleDuration(long sampleDuration) {
+ this.sampleDuration = sampleDuration;
+ }
+
+ public void setSampleSize(long sampleSize) {
+ this.sampleSize = sampleSize;
+ }
+
+ public void setSampleFlags(SampleFlags sampleFlags) {
+ this.sampleFlags = sampleFlags;
+ }
+
+ public void setSampleCompositionTimeOffset(int sampleCompositionTimeOffset) {
+ this.sampleCompositionTimeOffset = sampleCompositionTimeOffset;
+ }
+
+ @Override
+ public String toString() {
+ return "Entry{" +
+ "sampleDuration=" + sampleDuration +
+ ", sampleSize=" + sampleSize +
+ ", sampleFlags=" + sampleFlags +
+ ", sampleCompositionTimeOffset=" + sampleCompositionTimeOffset +
+ '}';
+ }
+ }
+
+ public void setDataOffset(int dataOffset) {
+ if (dataOffset == -1) {
+ setFlags(getFlags() & (0xFFFFFF ^ 1));
+ } else {
+ setFlags(getFlags() | 0x1); // turn on dataoffset
+ }
+ this.dataOffset = dataOffset;
+ }
+
+ public long[] getSampleCompositionTimeOffsets() {
+ if (isSampleCompositionTimeOffsetPresent()) {
+ long[] result = new long[entries.size()];
+
+ for (int i = 0; i < result.length; i++) {
+ result[i] = entries.get(i).getSampleCompositionTimeOffset();
+ }
+ return result;
+ }
+ return null;
+ }
+
+ public TrackExtendsBox getTrackExtendsBox() {
+ final TrackFragmentHeaderBox tfhd = ((TrackFragmentBox) getParent()).getTrackFragmentHeaderBox();
+ final List<MovieBox> movieBoxes = tfhd.getIsoFile().getBoxes(MovieBox.class);
+ if (movieBoxes.size() == 0) {
+ return null;
+ }
+
+ final List<TrackExtendsBox> trexBoxes = movieBoxes.get(0).getBoxes(TrackExtendsBox.class, true);
+ TrackExtendsBox trex = null;
+ for (TrackExtendsBox aTrex : trexBoxes) {
+ if (aTrex.getTrackId() == tfhd.getTrackId()) {
+ trex = aTrex;
+ }
+ }
+ return trex;
+ }
+
+ public TrackRunBox() {
+ super(TYPE);
+ }
+
+ protected long getContentSize() {
+ long size = 8;
+ int flags = getFlags();
+
+ if ((flags & 0x1) == 0x1) { //dataOffsetPresent
+ size += 4;
+ }
+ if ((flags & 0x4) == 0x4) { //firstSampleFlagsPresent
+ size += 4;
+ }
+
+ long entrySize = 0;
+ if ((flags & 0x100) == 0x100) { //sampleDurationPresent
+ entrySize += 4;
+ }
+ if ((flags & 0x200) == 0x200) { //sampleSizePresent
+ entrySize += 4;
+ }
+ if ((flags & 0x400) == 0x400) { //sampleFlagsPresent
+ entrySize += 4;
+ }
+ if ((flags & 0x800) == 0x800) { //sampleCompositionTimeOffsetPresent
+ entrySize += 4;
+ }
+ size += entrySize * entries.size();
+ return size;
+ }
+
+ protected void getContent(ByteBuffer byteBuffer) {
+ writeVersionAndFlags(byteBuffer);
+ IsoTypeWriter.writeUInt32(byteBuffer, entries.size());
+ int flags = getFlags();
+
+ if ((flags & 0x1) == 1) { //dataOffsetPresent
+ IsoTypeWriter.writeUInt32(byteBuffer, dataOffset);
+ }
+ if ((flags & 0x4) == 0x4) { //firstSampleFlagsPresent
+ firstSampleFlags.getContent(byteBuffer);
+ }
+
+ for (Entry entry : entries) {
+ if ((flags & 0x100) == 0x100) { //sampleDurationPresent
+ IsoTypeWriter.writeUInt32(byteBuffer, entry.sampleDuration);
+ }
+ if ((flags & 0x200) == 0x200) { //sampleSizePresent
+ IsoTypeWriter.writeUInt32(byteBuffer, entry.sampleSize);
+ }
+ if ((flags & 0x400) == 0x400) { //sampleFlagsPresent
+ entry.sampleFlags.getContent(byteBuffer);
+ }
+ if ((flags & 0x800) == 0x800) { //sampleCompositionTimeOffsetPresent
+ byteBuffer.putInt(entry.sampleCompositionTimeOffset);
+ }
+ }
+ }
+
+ @Override
+ public void _parseDetails(ByteBuffer content) {
+ parseVersionAndFlags(content);
+ long sampleCount = IsoTypeReader.readUInt32(content);
+
+ if ((getFlags() & 0x1) == 1) { //dataOffsetPresent
+ dataOffset = l2i(IsoTypeReader.readUInt32(content));
+ } else {
+ dataOffset = -1;
+ }
+ if ((getFlags() & 0x4) == 0x4) { //firstSampleFlagsPresent
+ firstSampleFlags = new SampleFlags(content);
+ }
+
+ for (int i = 0; i < sampleCount; i++) {
+ Entry entry = new Entry();
+ if ((getFlags() & 0x100) == 0x100) { //sampleDurationPresent
+ entry.sampleDuration = IsoTypeReader.readUInt32(content);
+ }
+ if ((getFlags() & 0x200) == 0x200) { //sampleSizePresent
+ entry.sampleSize = IsoTypeReader.readUInt32(content);
+ }
+ if ((getFlags() & 0x400) == 0x400) { //sampleFlagsPresent
+ entry.sampleFlags = new SampleFlags(content);
+ }
+ if ((getFlags() & 0x800) == 0x800) { //sampleCompositionTimeOffsetPresent
+ entry.sampleCompositionTimeOffset = content.getInt();
+ }
+ entries.add(entry);
+ }
+
+ }
+
+ public long getSampleCount() {
+ return entries.size();
+ }
+
+ public boolean isDataOffsetPresent() {
+ return (getFlags() & 0x1) == 1;
+ }
+
+ public boolean isFirstSampleFlagsPresent() {
+ return (getFlags() & 0x4) == 0x4;
+ }
+
+
+ public boolean isSampleSizePresent() {
+ return (getFlags() & 0x200) == 0x200;
+ }
+
+ public boolean isSampleDurationPresent() {
+ return (getFlags() & 0x100) == 0x100;
+ }
+
+ public boolean isSampleFlagsPresent() {
+ return (getFlags() & 0x400) == 0x400;
+ }
+
+ public boolean isSampleCompositionTimeOffsetPresent() {
+ return (getFlags() & 0x800) == 0x800;
+ }
+
+ public void setDataOffsetPresent(boolean v) {
+ if (v) {
+ setFlags(getFlags() | 0x01);
+ } else {
+ setFlags(getFlags() & (0xFFFFFF ^ 0x1));
+ }
+ }
+
+ public void setSampleSizePresent(boolean v) {
+ if (v) {
+ setFlags(getFlags() | 0x200);
+ } else {
+ setFlags(getFlags() & (0xFFFFFF ^ 0x200));
+ }
+ }
+
+ public void setSampleDurationPresent(boolean v) {
+
+ if (v) {
+ setFlags(getFlags() | 0x100);
+ } else {
+ setFlags(getFlags() & (0xFFFFFF ^ 0x100));
+ }
+ }
+
+ public void setSampleFlagsPresent(boolean v) {
+ if (v) {
+ setFlags(getFlags() | 0x400);
+ } else {
+ setFlags(getFlags() & (0xFFFFFF ^ 0x400));
+ }
+ }
+
+ public void setSampleCompositionTimeOffsetPresent(boolean v) {
+ if (v) {
+ setFlags(getFlags() | 0x800);
+ } else {
+ setFlags(getFlags() & (0xFFFFFF ^ 0x800));
+ }
+
+ }
+
+ public int getDataOffset() {
+ return dataOffset;
+ }
+
+ public SampleFlags getFirstSampleFlags() {
+ return firstSampleFlags;
+ }
+
+ public void setFirstSampleFlags(SampleFlags firstSampleFlags) {
+ if (firstSampleFlags == null) {
+ setFlags(getFlags() & (0xFFFFFF ^ 0x4));
+ } else {
+ setFlags(getFlags() | 0x4);
+ }
+ this.firstSampleFlags = firstSampleFlags;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("TrackRunBox");
+ sb.append("{sampleCount=").append(entries.size());
+ sb.append(", dataOffset=").append(dataOffset);
+ sb.append(", dataOffsetPresent=").append(isDataOffsetPresent());
+ sb.append(", sampleSizePresent=").append(isSampleSizePresent());
+ sb.append(", sampleDurationPresent=").append(isSampleDurationPresent());
+ sb.append(", sampleFlagsPresentPresent=").append(isSampleFlagsPresent());
+ sb.append(", sampleCompositionTimeOffsetPresent=").append(isSampleCompositionTimeOffsetPresent());
+ sb.append(", firstSampleFlags=").append(firstSampleFlags);
+ sb.append('}');
+ return sb.toString();
+ }
+
+ public void setEntries(List<Entry> entries) {
+ this.entries = entries;
+ }
+}