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