
org.jcodec.containers.mp4.ChunkReader Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jcodec Show documentation
Show all versions of jcodec Show documentation
Pure Java implementation of video/audio codecs and formats
package org.jcodec.containers.mp4;
import static java.util.Arrays.copyOfRange;
import org.jcodec.containers.mp4.boxes.AudioSampleEntry;
import org.jcodec.containers.mp4.boxes.Box;
import org.jcodec.containers.mp4.boxes.ChunkOffsets64Box;
import org.jcodec.containers.mp4.boxes.ChunkOffsetsBox;
import org.jcodec.containers.mp4.boxes.NodeBox;
import org.jcodec.containers.mp4.boxes.SampleDescriptionBox;
import org.jcodec.containers.mp4.boxes.SampleSizesBox;
import org.jcodec.containers.mp4.boxes.SampleToChunkBox;
import org.jcodec.containers.mp4.boxes.SampleToChunkBox.SampleToChunkEntry;
import org.jcodec.containers.mp4.boxes.TimeToSampleBox;
import org.jcodec.containers.mp4.boxes.TimeToSampleBox.TimeToSampleEntry;
import org.jcodec.containers.mp4.boxes.TrakBox;
/**
* This class is part of JCodec ( www.jcodec.org ) This software is distributed
* under FreeBSD License
*
* @author The JCodec project
*
*/
public class ChunkReader {
private int curChunk;
private int sampleNo;
private int s2cIndex;
private int ttsInd = 0;
private int ttsSubInd = 0;
private long chunkTv = 0;
private long[] chunkOffsets;
private SampleToChunkEntry[] sampleToChunk;
private SampleSizesBox stsz;
private TimeToSampleEntry[] tts;
private SampleDescriptionBox stsd;
public ChunkReader(TrakBox trakBox) {
TimeToSampleBox stts = NodeBox.findFirst(trakBox, TimeToSampleBox.class, "mdia", "minf", "stbl", "stts");
tts = stts.getEntries();
ChunkOffsetsBox stco = NodeBox.findFirst(trakBox, ChunkOffsetsBox.class, "mdia", "minf", "stbl", "stco");
ChunkOffsets64Box co64 = NodeBox.findFirst(trakBox, ChunkOffsets64Box.class, "mdia", "minf", "stbl", "co64");
stsz = NodeBox.findFirst(trakBox, SampleSizesBox.class, "mdia", "minf", "stbl", "stsz");
SampleToChunkBox stsc = NodeBox.findFirst(trakBox, SampleToChunkBox.class, "mdia", "minf", "stbl", "stsc");
if (stco != null)
chunkOffsets = stco.getChunkOffsets();
else
chunkOffsets = co64.getChunkOffsets();
sampleToChunk = stsc.getSampleToChunk();
stsd = NodeBox.findFirst(trakBox, SampleDescriptionBox.class, "mdia", "minf", "stbl", "stsd");
}
public boolean hasNext() {
return curChunk < chunkOffsets.length;
}
public Chunk next() {
if (curChunk >= chunkOffsets.length)
return null;
if (s2cIndex + 1 < sampleToChunk.length && curChunk + 1 == sampleToChunk[s2cIndex + 1].getFirst())
s2cIndex++;
int sampleCount = sampleToChunk[s2cIndex].getCount();
int[] samplesDur = null;
int sampleDur = 0;
if (ttsSubInd + sampleCount <= tts[ttsInd].getSampleCount()) {
sampleDur = tts[ttsInd].getSampleDuration();
ttsSubInd += sampleCount;
} else {
samplesDur = new int[sampleCount];
for (int i = 0; i < sampleCount; i++) {
if (ttsSubInd >= tts[ttsInd].getSampleCount() && ttsInd < tts.length - 1) {
ttsSubInd = 0;
++ttsInd;
}
samplesDur[i] = tts[ttsInd].getSampleDuration();
++ttsSubInd;
}
}
int size = 0;
int[] sizes = null;
if (stsz.getDefaultSize() > 0) {
size = getFrameSize();
} else {
sizes = copyOfRange(stsz.getSizes(), sampleNo, sampleNo + sampleCount);
}
int dref = sampleToChunk[s2cIndex].getEntry();
Chunk chunk = new Chunk(chunkOffsets[curChunk], chunkTv, sampleCount, size, sizes, sampleDur, samplesDur, dref);
chunkTv += chunk.getDuration();
sampleNo += sampleCount;
++curChunk;
return chunk;
}
private int getFrameSize() {
int size = stsz.getDefaultSize();
Box box = stsd.getBoxes().get(sampleToChunk[s2cIndex].getEntry() - 1);
if (box instanceof AudioSampleEntry) {
return ((AudioSampleEntry) box).calcFrameSize();
}
return size;
}
public int size() {
return chunkOffsets.length;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy