diff options
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.java | 355 |
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; + } +} |