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 Zhuimport com.coremedia.iso.IsoTypeReader; 20dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport com.coremedia.iso.IsoTypeWriter; 21dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport com.googlecode.mp4parser.AbstractFullBox; 22dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 23dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport java.nio.ByteBuffer; 24dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport java.util.ArrayList; 25dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport java.util.Collections; 26dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport java.util.Iterator; 27dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport java.util.LinkedList; 28dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport java.util.List; 29dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 30dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport static com.googlecode.mp4parser.util.CastUtils.l2i; 31dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 32dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu/** 33dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * Samples within the media data are grouped into chunks. Chunks can be of different sizes, and the 34dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * samples within a chunk can have different sizes. This table can be used to find the chunk that 35dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * contains a sample, its position, and the associated sample description. Defined in ISO/IEC 14496-12. 36dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu */ 37dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhupublic class SampleToChunkBox extends AbstractFullBox { 38dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu List<Entry> entries = Collections.emptyList(); 39dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 40dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public static final String TYPE = "stsc"; 41dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 42dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public SampleToChunkBox() { 43dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu super(TYPE); 44dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 45dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 46dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public List<Entry> getEntries() { 47dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu return entries; 48dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 49dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 50dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public void setEntries(List<Entry> entries) { 51dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu this.entries = entries; 52dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 53dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 54dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu protected long getContentSize() { 55dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu return entries.size() * 12 + 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 62dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu int entryCount = l2i(IsoTypeReader.readUInt32(content)); 63dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu entries = new ArrayList<Entry>(entryCount); 64dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu for (int i = 0; i < entryCount; i++) { 65dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu entries.add(new Entry( 66dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu IsoTypeReader.readUInt32(content), 67dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu IsoTypeReader.readUInt32(content), 68dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu IsoTypeReader.readUInt32(content))); 69dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 70dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 71dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 72dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu @Override 73dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu protected void getContent(ByteBuffer byteBuffer) { 74dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu writeVersionAndFlags(byteBuffer); 75dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu IsoTypeWriter.writeUInt32(byteBuffer, entries.size()); 76dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu for (Entry entry : entries) { 77dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu IsoTypeWriter.writeUInt32(byteBuffer, entry.getFirstChunk()); 78dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu IsoTypeWriter.writeUInt32(byteBuffer, entry.getSamplesPerChunk()); 79dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu IsoTypeWriter.writeUInt32(byteBuffer, entry.getSampleDescriptionIndex()); 80dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 81dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 82dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 83dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public String toString() { 84dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu return "SampleToChunkBox[entryCount=" + entries.size() + "]"; 85dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 86dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 87dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu /** 88dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * Decompresses the list of entries and returns the number of samples per chunk for 89dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * every single chunk. 90dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * 91dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * @param chunkCount overall number of chunks 92dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * @return number of samples per chunk 93dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu */ 94dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public long[] blowup(int chunkCount) { 95dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu long[] numberOfSamples = new long[chunkCount]; 96dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu int j = 0; 97dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu List<SampleToChunkBox.Entry> sampleToChunkEntries = new LinkedList<Entry>(entries); 98dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu Collections.reverse(sampleToChunkEntries); 99dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu Iterator<Entry> iterator = sampleToChunkEntries.iterator(); 100dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu SampleToChunkBox.Entry currentEntry = iterator.next(); 101dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 102dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu for (int i = numberOfSamples.length; i > 1; i--) { 103dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu numberOfSamples[i - 1] = currentEntry.getSamplesPerChunk(); 104dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu if (i == currentEntry.getFirstChunk()) { 105dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu currentEntry = iterator.next(); 106dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 107dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 108dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu numberOfSamples[0] = currentEntry.getSamplesPerChunk(); 109dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu return numberOfSamples; 110dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 111dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 112dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public static class Entry { 113dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu long firstChunk; 114dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu long samplesPerChunk; 115dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu long sampleDescriptionIndex; 116dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 117dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public Entry(long firstChunk, long samplesPerChunk, long sampleDescriptionIndex) { 118dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu this.firstChunk = firstChunk; 119dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu this.samplesPerChunk = samplesPerChunk; 120dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu this.sampleDescriptionIndex = sampleDescriptionIndex; 121dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 122dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 123dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public long getFirstChunk() { 124dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu return firstChunk; 125dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 126dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 127dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public void setFirstChunk(long firstChunk) { 128dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu this.firstChunk = firstChunk; 129dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 130dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 131dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public long getSamplesPerChunk() { 132dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu return samplesPerChunk; 133dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 134dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 135dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public void setSamplesPerChunk(long samplesPerChunk) { 136dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu this.samplesPerChunk = samplesPerChunk; 137dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 138dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 139dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public long getSampleDescriptionIndex() { 140dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu return sampleDescriptionIndex; 141dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 142dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 143dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public void setSampleDescriptionIndex(long sampleDescriptionIndex) { 144dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu this.sampleDescriptionIndex = sampleDescriptionIndex; 145dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 146dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 147dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu @Override 148dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public String toString() { 149dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu return "Entry{" + 150dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu "firstChunk=" + firstChunk + 151dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu ", samplesPerChunk=" + samplesPerChunk + 152dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu ", sampleDescriptionIndex=" + sampleDescriptionIndex + 153dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu '}'; 154dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 155dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 156dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu} 157