1dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu/* 2dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * Copyright 2008 CoreMedia AG, Hamburg 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; 18dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 19dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 20dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport com.coremedia.iso.IsoTypeReader; 21dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport com.coremedia.iso.IsoTypeWriter; 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.Collections; 27dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport java.util.List; 28dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 29dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport static com.googlecode.mp4parser.util.CastUtils.l2i; 30dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 31dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu/** 32dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * This box contains a compact version of a table that allows indexing from decoding time to sample number. 33dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * Other tables give sample sizes and pointers, from the sample number. Each entry in the table gives the 34dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * number of consecutive samples with the same time delta, and the delta of those samples. By adding the 35dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * deltas a complete time-to-sample map may be built.<br> 36dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * The Decoding Time to Sample Box contains decode time delta's: <code>DT(n+1) = DT(n) + STTS(n)</code> where STTS(n) 37dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * is the (uncompressed) table entry for sample n.<br> 38dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * The sample entries are ordered by decoding time stamps; therefore the deltas are all non-negative. <br> 39dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * 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 40dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * deltas gives the length of the media in the track (not mapped to the overall timescale, and not considering 41dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * any edit list). <br> 42dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * The Edit List Box provides the initial CT value if it is non-empty (non-zero). 43dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu */ 44dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhupublic class TimeToSampleBox extends AbstractFullBox { 45dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public static final String TYPE = "stts"; 46dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 47dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu List<Entry> entries = Collections.emptyList(); 48dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 49dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 50dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public TimeToSampleBox() { 51dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu super(TYPE); 52dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 53dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 54dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu protected long getContentSize() { 55dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu return 8 + entries.size() * 8; 56dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 57dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 58dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu @Override 59dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public void _parseDetails(ByteBuffer content) { 60dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu parseVersionAndFlags(content); 61dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu int entryCount = l2i(IsoTypeReader.readUInt32(content)); 62dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu entries = new ArrayList<Entry>(entryCount); 63dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 64dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu for (int i = 0; i < entryCount; i++) { 65dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu entries.add(new Entry(IsoTypeReader.readUInt32(content), IsoTypeReader.readUInt32(content))); 66dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 67dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 68dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 69dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 70dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu @Override 71dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu protected void getContent(ByteBuffer byteBuffer) { 72dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu writeVersionAndFlags(byteBuffer); 73dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu IsoTypeWriter.writeUInt32(byteBuffer, entries.size()); 74dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu for (Entry entry : entries) { 75dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu IsoTypeWriter.writeUInt32(byteBuffer, entry.getCount()); 76dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu IsoTypeWriter.writeUInt32(byteBuffer, entry.getDelta()); 77dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 78dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 79dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 80dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public List<Entry> getEntries() { 81dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu return entries; 82dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 83dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 84dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public void setEntries(List<Entry> entries) { 85dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu this.entries = entries; 86dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 87dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 88dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public String toString() { 89dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu return "TimeToSampleBox[entryCount=" + entries.size() + "]"; 90dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 91dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 92dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public static class Entry { 93dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu long count; 94dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu long delta; 95dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 96dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public Entry(long count, long delta) { 97dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu this.count = count; 98dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu this.delta = delta; 99dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 100dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 101dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public long getCount() { 102dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu return count; 103dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 104dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 105dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public long getDelta() { 106dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu return delta; 107dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 108dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 109dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public void setCount(long count) { 110dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu this.count = count; 111dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 112dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 113dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public void setDelta(long delta) { 114dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu this.delta = delta; 115dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 116dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 117dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu @Override 118dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public String toString() { 119dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu return "Entry{" + 120dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu "count=" + count + 121dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu ", delta=" + delta + 122dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu '}'; 123dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 124dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 125dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 126dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu /** 127dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * Decompresses the list of entries and returns the list of decoding times. 128dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * 129dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * @return decoding time per sample 130dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu */ 131dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public static long[] blowupTimeToSamples(List<TimeToSampleBox.Entry> entries) { 132dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu long numOfSamples = 0; 133dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu for (TimeToSampleBox.Entry entry : entries) { 134dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu numOfSamples += entry.getCount(); 135dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 136dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu assert numOfSamples <= Integer.MAX_VALUE; 137dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu long[] decodingTime = new long[(int) numOfSamples]; 138dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 139dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu int current = 0; 140dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 141dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 142dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu for (TimeToSampleBox.Entry entry : entries) { 143dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu for (int i = 0; i < entry.getCount(); i++) { 144dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu decodingTime[current++] = entry.getDelta(); 145dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 146dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 147dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 148dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu return decodingTime; 149dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 150dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 151dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 152dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu} 153