package org.jcodec.containers.mp4;
import java.io.IOException;
import org.jcodec.common.NIOUtils;
import org.jcodec.common.SeekableByteChannel;
import org.jcodec.containers.mp4.boxes.AliasBox;
import org.jcodec.containers.mp4.boxes.ChunkOffsets64Box;
import org.jcodec.containers.mp4.boxes.ChunkOffsetsBox;
import org.jcodec.containers.mp4.boxes.DataInfoBox;
import org.jcodec.containers.mp4.boxes.DataRefBox;
import org.jcodec.containers.mp4.boxes.MediaInfoBox;
import org.jcodec.containers.mp4.boxes.NodeBox;
import org.jcodec.containers.mp4.boxes.SampleEntry;
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 ChunkWriter {
private long[] offsets;
private SampleEntry[] entries;
private SeekableByteChannel[] inputs;
private int curChunk;
private SeekableByteChannel out;
byte[] buf = new byte[8092];
private TrakBox trak;
public ChunkWriter(TrakBox trak, SeekableByteChannel[] inputs, SeekableByteChannel out) {
entries = NodeBox.findAll(trak, SampleEntry.class, "mdia", "minf", "stbl", "stsd", null);
ChunkOffsetsBox stco = NodeBox.findFirst(trak, ChunkOffsetsBox.class, "mdia", "minf", "stbl", "stco");
ChunkOffsets64Box co64 = NodeBox.findFirst(trak, ChunkOffsets64Box.class, "mdia", "minf", "stbl", "co64");
int size;
if (stco != null)
size = stco.getChunkOffsets().length;
else
size = co64.getChunkOffsets().length;
this.inputs = inputs;
offsets = new long[size];
this.out = out;
this.trak = trak;
}
public void apply() {
NodeBox stbl = NodeBox.findFirst(trak, NodeBox.class, "mdia", "minf", "stbl");
stbl.removeChildren("stco", "co64");
stbl.add(new ChunkOffsets64Box(offsets));
cleanDrefs(trak);
}
private void cleanDrefs(TrakBox trak) {
MediaInfoBox minf = trak.getMdia().getMinf();
DataInfoBox dinf = trak.getMdia().getMinf().getDinf();
if (dinf == null) {
dinf = new DataInfoBox();
minf.add(dinf);
}
DataRefBox dref = dinf.getDref();
if (dref == null) {
dref = new DataRefBox();
dinf.add(dref);
}
dref.getBoxes().clear();
dref.add(AliasBox.createSelfRef());
for (SampleEntry entry : NodeBox.findAll(trak, SampleEntry.class, "mdia", "minf", "stbl", "stsd", null)) {
entry.setDrefInd((short) 1);
}
}
private SeekableByteChannel getInput(Chunk chunk) {
SampleEntry se = entries[chunk.getEntry() - 1];
return inputs[se.getDrefInd() - 1];
}
public void write(Chunk chunk) throws IOException {
SeekableByteChannel input = getInput(chunk);
input.position(chunk.getOffset());
long pos = out.position();
out.write(NIOUtils.fetchFrom(input, (int) chunk.getSize()));
offsets[curChunk++] = pos;
}
}