• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2008 CoreMedia AG, Hamburg
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.coremedia.iso.boxes;
18 
19 
20 import com.coremedia.iso.IsoTypeReader;
21 import com.coremedia.iso.IsoTypeWriter;
22 import com.googlecode.mp4parser.AbstractFullBox;
23 
24 import java.nio.ByteBuffer;
25 import java.util.ArrayList;
26 import java.util.Collections;
27 import java.util.List;
28 
29 import static com.googlecode.mp4parser.util.CastUtils.l2i;
30 
31 /**
32  * This box contains a compact version of a table that allows indexing from decoding time to sample number.
33  * Other tables give sample sizes and pointers, from the sample number. Each entry in the table gives the
34  * number of consecutive samples with the same time delta, and the delta of those samples. By adding the
35  * deltas a complete time-to-sample map may be built.<br>
36  * The Decoding Time to Sample Box contains decode time delta's: <code>DT(n+1) = DT(n) + STTS(n)</code> where STTS(n)
37  * is the (uncompressed) table entry for sample n.<br>
38  * The sample entries are ordered by decoding time stamps; therefore the deltas are all non-negative. <br>
39  * The DT axis has a zero origin; <code>DT(i) = SUM(for j=0 to i-1 of delta(j))</code>, and the sum of all
40  * deltas gives the length of the media in the track (not mapped to the overall timescale, and not considering
41  * any edit list).    <br>
42  * The Edit List Box provides the initial CT value if it is non-empty (non-zero).
43  */
44 public class TimeToSampleBox extends AbstractFullBox {
45     public static final String TYPE = "stts";
46 
47     List<Entry> entries = Collections.emptyList();
48 
49 
TimeToSampleBox()50     public TimeToSampleBox() {
51         super(TYPE);
52     }
53 
getContentSize()54     protected long getContentSize() {
55         return 8 + entries.size() * 8;
56     }
57 
58     @Override
_parseDetails(ByteBuffer content)59     public void _parseDetails(ByteBuffer content) {
60         parseVersionAndFlags(content);
61         int entryCount = l2i(IsoTypeReader.readUInt32(content));
62         entries = new ArrayList<Entry>(entryCount);
63 
64         for (int i = 0; i < entryCount; i++) {
65             entries.add(new Entry(IsoTypeReader.readUInt32(content), IsoTypeReader.readUInt32(content)));
66         }
67 
68     }
69 
70     @Override
getContent(ByteBuffer byteBuffer)71     protected void getContent(ByteBuffer byteBuffer) {
72         writeVersionAndFlags(byteBuffer);
73         IsoTypeWriter.writeUInt32(byteBuffer, entries.size());
74         for (Entry entry : entries) {
75             IsoTypeWriter.writeUInt32(byteBuffer, entry.getCount());
76             IsoTypeWriter.writeUInt32(byteBuffer, entry.getDelta());
77         }
78     }
79 
getEntries()80     public List<Entry> getEntries() {
81         return entries;
82     }
83 
setEntries(List<Entry> entries)84     public void setEntries(List<Entry> entries) {
85         this.entries = entries;
86     }
87 
toString()88     public String toString() {
89         return "TimeToSampleBox[entryCount=" + entries.size() + "]";
90     }
91 
92     public static class Entry {
93         long count;
94         long delta;
95 
Entry(long count, long delta)96         public Entry(long count, long delta) {
97             this.count = count;
98             this.delta = delta;
99         }
100 
getCount()101         public long getCount() {
102             return count;
103         }
104 
getDelta()105         public long getDelta() {
106             return delta;
107         }
108 
setCount(long count)109         public void setCount(long count) {
110             this.count = count;
111         }
112 
setDelta(long delta)113         public void setDelta(long delta) {
114             this.delta = delta;
115         }
116 
117         @Override
toString()118         public String toString() {
119             return "Entry{" +
120                     "count=" + count +
121                     ", delta=" + delta +
122                     '}';
123         }
124     }
125 
126     /**
127      * Decompresses the list of entries and returns the list of decoding times.
128      *
129      * @return decoding time per sample
130      */
blowupTimeToSamples(List<TimeToSampleBox.Entry> entries)131     public static long[] blowupTimeToSamples(List<TimeToSampleBox.Entry> entries) {
132         long numOfSamples = 0;
133         for (TimeToSampleBox.Entry entry : entries) {
134             numOfSamples += entry.getCount();
135         }
136         assert numOfSamples <= Integer.MAX_VALUE;
137         long[] decodingTime = new long[(int) numOfSamples];
138 
139         int current = 0;
140 
141 
142         for (TimeToSampleBox.Entry entry : entries) {
143             for (int i = 0; i < entry.getCount(); i++) {
144                 decodingTime[current++] = entry.getDelta();
145             }
146         }
147 
148         return decodingTime;
149     }
150 
151 
152 }
153