1dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu/*
2dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * Copyright 2009 castLabs GmbH, Berlin
3dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu *
4dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * Licensed under the Apache License, Version 2.0 (the License);
5dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * you may not use this file except in compliance with the License.
6dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * You may obtain a copy of the License at
7dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu *
8dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu *     http://www.apache.org/licenses/LICENSE-2.0
9dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu *
10dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * Unless required by applicable law or agreed to in writing, software
11dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * distributed under the License is distributed on an AS IS BASIS,
12dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * See the License for the specific language governing permissions and
14dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * limitations under the License.
15dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu */
16dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
17dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhupackage com.coremedia.iso.boxes.fragment;
18dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
19dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport com.coremedia.iso.IsoTypeReader;
20dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport com.coremedia.iso.IsoTypeWriter;
21dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport com.coremedia.iso.boxes.MovieBox;
22dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport com.googlecode.mp4parser.AbstractFullBox;
23dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
24dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport java.nio.ByteBuffer;
25dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport java.util.ArrayList;
26dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport java.util.List;
27dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
28dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport static com.googlecode.mp4parser.util.CastUtils.l2i;
29dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
30dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu/**
31dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * aligned(8) class TrackRunBox
32dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * extends FullBox('trun', 0, tr_flags) {
33dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * unsigned int(32) sample_count;
34dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * // the following are optional fields
35dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * signed int(32) data_offset;
36dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * unsigned int(32) first_sample_flags;
37dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * // all fields in the following array are optional
38dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * {
39dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * unsigned int(32) sample_duration;
40dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * unsigned int(32) sample_size;
41dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * unsigned int(32) sample_flags
42dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * unsigned int(32) sample_composition_time_offset;
43dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * }[ sample_count ]
44dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * }
45dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu */
46dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
47dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhupublic class TrackRunBox extends AbstractFullBox {
48dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    public static final String TYPE = "trun";
49dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    private int dataOffset;
50dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    private SampleFlags firstSampleFlags;
51dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    private List<Entry> entries = new ArrayList<Entry>();
52dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
53dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
54dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    public List<Entry> getEntries() {
55dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        return entries;
56dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    }
57dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
58dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    public static class Entry {
59dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        private long sampleDuration;
60dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        private long sampleSize;
61dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        private SampleFlags sampleFlags;
62dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        private int sampleCompositionTimeOffset;
63dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
64dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        public Entry() {
65dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        }
66dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
67dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        public Entry(long sampleDuration, long sampleSize, SampleFlags sampleFlags, int sampleCompositionTimeOffset) {
68dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            this.sampleDuration = sampleDuration;
69dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            this.sampleSize = sampleSize;
70dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            this.sampleFlags = sampleFlags;
71dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            this.sampleCompositionTimeOffset = sampleCompositionTimeOffset;
72dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        }
73dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
74dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        public long getSampleDuration() {
75dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            return sampleDuration;
76dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        }
77dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
78dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        public long getSampleSize() {
79dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            return sampleSize;
80dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        }
81dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
82dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        public SampleFlags getSampleFlags() {
83dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            return sampleFlags;
84dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        }
85dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
86dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        public int getSampleCompositionTimeOffset() {
87dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            return sampleCompositionTimeOffset;
88dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        }
89dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
90dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        public void setSampleDuration(long sampleDuration) {
91dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            this.sampleDuration = sampleDuration;
92dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        }
93dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
94dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        public void setSampleSize(long sampleSize) {
95dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            this.sampleSize = sampleSize;
96dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        }
97dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
98dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        public void setSampleFlags(SampleFlags sampleFlags) {
99dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            this.sampleFlags = sampleFlags;
100dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        }
101dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
102dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        public void setSampleCompositionTimeOffset(int sampleCompositionTimeOffset) {
103dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            this.sampleCompositionTimeOffset = sampleCompositionTimeOffset;
104dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        }
105dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
106dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        @Override
107dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        public String toString() {
108dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            return "Entry{" +
109dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                    "sampleDuration=" + sampleDuration +
110dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                    ", sampleSize=" + sampleSize +
111dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                    ", sampleFlags=" + sampleFlags +
112dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                    ", sampleCompositionTimeOffset=" + sampleCompositionTimeOffset +
113dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                    '}';
114dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        }
115dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    }
116dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
117dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    public void setDataOffset(int dataOffset) {
118dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        if (dataOffset == -1) {
119dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            setFlags(getFlags() & (0xFFFFFF ^ 1));
120dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        } else {
121dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            setFlags(getFlags() | 0x1); // turn on dataoffset
122dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        }
123dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        this.dataOffset = dataOffset;
124dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    }
125dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
126dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    public long[] getSampleCompositionTimeOffsets() {
127dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        if (isSampleCompositionTimeOffsetPresent()) {
128dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            long[] result = new long[entries.size()];
129dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
130dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            for (int i = 0; i < result.length; i++) {
131dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                result[i] = entries.get(i).getSampleCompositionTimeOffset();
132dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            }
133dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            return result;
134dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        }
135dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        return null;
136dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    }
137dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
138dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    public TrackExtendsBox getTrackExtendsBox() {
139dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        final TrackFragmentHeaderBox tfhd = ((TrackFragmentBox) getParent()).getTrackFragmentHeaderBox();
140dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        final List<MovieBox> movieBoxes = tfhd.getIsoFile().getBoxes(MovieBox.class);
141dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        if (movieBoxes.size() == 0) {
142dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            return null;
143dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        }
144dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
145dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        final List<TrackExtendsBox> trexBoxes = movieBoxes.get(0).getBoxes(TrackExtendsBox.class, true);
146dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        TrackExtendsBox trex = null;
147dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        for (TrackExtendsBox aTrex : trexBoxes) {
148dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            if (aTrex.getTrackId() == tfhd.getTrackId()) {
149dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                trex = aTrex;
150dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            }
151dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        }
152dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        return trex;
153dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    }
154dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
155dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    public TrackRunBox() {
156dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        super(TYPE);
157dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    }
158dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
159dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    protected long getContentSize() {
160dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        long size = 8;
161dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        int flags = getFlags();
162dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
163dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        if ((flags & 0x1) == 0x1) { //dataOffsetPresent
164dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            size += 4;
165dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        }
166dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        if ((flags & 0x4) == 0x4) { //firstSampleFlagsPresent
167dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            size += 4;
168dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        }
169dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
170dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        long entrySize = 0;
171dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        if ((flags & 0x100) == 0x100) { //sampleDurationPresent
172dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            entrySize += 4;
173dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        }
174dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        if ((flags & 0x200) == 0x200) { //sampleSizePresent
175dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            entrySize += 4;
176dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        }
177dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        if ((flags & 0x400) == 0x400) { //sampleFlagsPresent
178dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            entrySize += 4;
179dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        }
180dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        if ((flags & 0x800) == 0x800) { //sampleCompositionTimeOffsetPresent
181dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            entrySize += 4;
182dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        }
183dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        size += entrySize * entries.size();
184dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        return size;
185dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    }
186dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
187dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    protected void getContent(ByteBuffer byteBuffer) {
188dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        writeVersionAndFlags(byteBuffer);
189dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        IsoTypeWriter.writeUInt32(byteBuffer, entries.size());
190dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        int flags = getFlags();
191dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
192dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        if ((flags & 0x1) == 1) { //dataOffsetPresent
193dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            IsoTypeWriter.writeUInt32(byteBuffer, dataOffset);
194dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        }
195dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        if ((flags & 0x4) == 0x4) { //firstSampleFlagsPresent
196dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            firstSampleFlags.getContent(byteBuffer);
197dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        }
198dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
199dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        for (Entry entry : entries) {
200dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            if ((flags & 0x100) == 0x100) { //sampleDurationPresent
201dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                IsoTypeWriter.writeUInt32(byteBuffer, entry.sampleDuration);
202dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            }
203dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            if ((flags & 0x200) == 0x200) { //sampleSizePresent
204dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                IsoTypeWriter.writeUInt32(byteBuffer, entry.sampleSize);
205dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            }
206dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            if ((flags & 0x400) == 0x400) { //sampleFlagsPresent
207dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                entry.sampleFlags.getContent(byteBuffer);
208dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            }
209dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            if ((flags & 0x800) == 0x800) { //sampleCompositionTimeOffsetPresent
210dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                byteBuffer.putInt(entry.sampleCompositionTimeOffset);
211dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            }
212dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        }
213dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    }
214dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
215dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    @Override
216dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    public void _parseDetails(ByteBuffer content) {
217dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        parseVersionAndFlags(content);
218dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        long sampleCount = IsoTypeReader.readUInt32(content);
219dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
220dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        if ((getFlags() & 0x1) == 1) { //dataOffsetPresent
221dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            dataOffset = l2i(IsoTypeReader.readUInt32(content));
222dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        } else {
223dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            dataOffset = -1;
224dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        }
225dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        if ((getFlags() & 0x4) == 0x4) { //firstSampleFlagsPresent
226dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            firstSampleFlags = new SampleFlags(content);
227dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        }
228dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
229dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        for (int i = 0; i < sampleCount; i++) {
230dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            Entry entry = new Entry();
231dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            if ((getFlags() & 0x100) == 0x100) { //sampleDurationPresent
232dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                entry.sampleDuration = IsoTypeReader.readUInt32(content);
233dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            }
234dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            if ((getFlags() & 0x200) == 0x200) { //sampleSizePresent
235dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                entry.sampleSize = IsoTypeReader.readUInt32(content);
236dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            }
237dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            if ((getFlags() & 0x400) == 0x400) { //sampleFlagsPresent
238dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                entry.sampleFlags = new SampleFlags(content);
239dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            }
240dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            if ((getFlags() & 0x800) == 0x800) { //sampleCompositionTimeOffsetPresent
241dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                entry.sampleCompositionTimeOffset = content.getInt();
242dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            }
243dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            entries.add(entry);
244dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        }
245dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
246dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    }
247dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
248dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    public long getSampleCount() {
249dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        return entries.size();
250dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    }
251dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
252dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    public boolean isDataOffsetPresent() {
253dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        return (getFlags() & 0x1) == 1;
254dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    }
255dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
256dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    public boolean isFirstSampleFlagsPresent() {
257dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        return (getFlags() & 0x4) == 0x4;
258dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    }
259dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
260dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
261dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    public boolean isSampleSizePresent() {
262dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        return (getFlags() & 0x200) == 0x200;
263dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    }
264dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
265dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    public boolean isSampleDurationPresent() {
266dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        return (getFlags() & 0x100) == 0x100;
267dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    }
268dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
269dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    public boolean isSampleFlagsPresent() {
270dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        return (getFlags() & 0x400) == 0x400;
271dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    }
272dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
273dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    public boolean isSampleCompositionTimeOffsetPresent() {
274dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        return (getFlags() & 0x800) == 0x800;
275dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    }
276dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
277dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    public void setDataOffsetPresent(boolean v) {
278dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        if (v) {
279dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            setFlags(getFlags() | 0x01);
280dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        } else {
281dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            setFlags(getFlags() & (0xFFFFFF ^ 0x1));
282dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        }
283dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    }
284dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
285dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    public void setSampleSizePresent(boolean v) {
286dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        if (v) {
287dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            setFlags(getFlags() | 0x200);
288dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        } else {
289dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            setFlags(getFlags() & (0xFFFFFF ^ 0x200));
290dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        }
291dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    }
292dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
293dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    public void setSampleDurationPresent(boolean v) {
294dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
295dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        if (v) {
296dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            setFlags(getFlags() | 0x100);
297dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        } else {
298dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            setFlags(getFlags() & (0xFFFFFF ^ 0x100));
299dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        }
300dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    }
301dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
302dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    public void setSampleFlagsPresent(boolean v) {
303dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        if (v) {
304dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            setFlags(getFlags() | 0x400);
305dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        } else {
306dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            setFlags(getFlags() & (0xFFFFFF ^ 0x400));
307dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        }
308dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    }
309dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
310dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    public void setSampleCompositionTimeOffsetPresent(boolean v) {
311dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        if (v) {
312dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            setFlags(getFlags() | 0x800);
313dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        } else {
314dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            setFlags(getFlags() & (0xFFFFFF ^ 0x800));
315dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        }
316dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
317dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    }
318dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
319dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    public int getDataOffset() {
320dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        return dataOffset;
321dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    }
322dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
323dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    public SampleFlags getFirstSampleFlags() {
324dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        return firstSampleFlags;
325dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    }
326dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
327dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    public void setFirstSampleFlags(SampleFlags firstSampleFlags) {
328dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        if (firstSampleFlags == null) {
329dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            setFlags(getFlags() & (0xFFFFFF ^ 0x4));
330dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        } else {
331dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            setFlags(getFlags() | 0x4);
332dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        }
333dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        this.firstSampleFlags = firstSampleFlags;
334dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    }
335dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
336dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    @Override
337dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    public String toString() {
338dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        final StringBuilder sb = new StringBuilder();
339dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        sb.append("TrackRunBox");
340dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        sb.append("{sampleCount=").append(entries.size());
341dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        sb.append(", dataOffset=").append(dataOffset);
342dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        sb.append(", dataOffsetPresent=").append(isDataOffsetPresent());
343dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        sb.append(", sampleSizePresent=").append(isSampleSizePresent());
344dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        sb.append(", sampleDurationPresent=").append(isSampleDurationPresent());
345dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        sb.append(", sampleFlagsPresentPresent=").append(isSampleFlagsPresent());
346dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        sb.append(", sampleCompositionTimeOffsetPresent=").append(isSampleCompositionTimeOffsetPresent());
347dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        sb.append(", firstSampleFlags=").append(firstSampleFlags);
348dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        sb.append('}');
349dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        return sb.toString();
350dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    }
351dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
352dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    public void setEntries(List<Entry> entries) {
353dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        this.entries = entries;
354dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    }
355dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu}
356