package org.jcodec.containers.flv;
import org.jcodec.common.io.NIOUtils;
import org.jcodec.common.io.SeekableByteChannel;
import org.jcodec.containers.flv.FLVTag.Type;
import java.io.IOException;
import java.nio.ByteBuffer;
/**
* This class is part of JCodec ( www.jcodec.org ) This software is distributed
* under FreeBSD License
*
* FLV ( Flash Media Video ) muxer
*
* @author Stan Vitvitskyy
*
*/
public class FLVWriter {
// Write buffer, 1M
private static final int WRITE_BUFFER_SIZE = 0x100000;
private int startOfLastPacket = 9;
private SeekableByteChannel out;
private ByteBuffer writeBuf;
public FLVWriter(SeekableByteChannel out) {
this.out = out;
writeBuf = ByteBuffer.allocate(WRITE_BUFFER_SIZE);
writeHeader(writeBuf);
}
/**
* Add a packet to the underlying file
*
* @param pkt
* @throws IOException
*/
public void addPacket(FLVTag pkt) throws IOException {
if (!writePacket(writeBuf, pkt)) {
writeBuf.flip();
startOfLastPacket -= out.write(writeBuf);
writeBuf.clear();
if (!writePacket(writeBuf, pkt))
throw new RuntimeException("Unexpected");
}
}
/**
* Finish muxing and write the remaining data
*
* @throws IOException
*/
public void finish() throws IOException {
writeBuf.flip();
out.write(writeBuf);
}
private boolean writePacket(ByteBuffer writeBuf, FLVTag pkt) {
int pktType = pkt.getType() == Type.VIDEO ? 0x9 : (pkt.getType() == Type.SCRIPT ? 0x12 : 0x8);
int dataLen = pkt.getData().remaining();
if (writeBuf.remaining() < 15 + dataLen)
return false;
writeBuf.putInt(writeBuf.position() - startOfLastPacket);
startOfLastPacket = writeBuf.position();
writeBuf.put((byte) pktType);
writeBuf.putShort((short) (dataLen >> 8));
writeBuf.put((byte) (dataLen & 0xff));
writeBuf.putShort((short) ((pkt.getPts() >> 8) & 0xffff));
writeBuf.put((byte) (pkt.getPts() & 0xff));
writeBuf.put((byte) ((pkt.getPts() >> 24) & 0xff));
writeBuf.putShort((short) 0);
writeBuf.put((byte) 0);
NIOUtils.write(writeBuf, pkt.getData().duplicate());
return true;
}
private static void writeHeader(ByteBuffer writeBuf) {
writeBuf.put((byte) 'F');
writeBuf.put((byte) 'L');
writeBuf.put((byte) 'V');
writeBuf.put((byte) 1);
writeBuf.put((byte) 5);
writeBuf.putInt(9);
}
}