package org.jcodec.codecs.y4m;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.WritableByteChannel;
import org.jcodec.common.model.Picture8Bit;
/**
* Stores frames into Y4M file.
*
* @author Stanislav Vitvitskiy
*
*/
public class Y4MEncoder {
private WritableByteChannel ch;
private boolean headerWritten;
private int width;
private int height;
private byte[] scratchBuffer;
public static final byte[] frameTag = "FRAME\n".getBytes();
public Y4MEncoder(WritableByteChannel ch) {
this.ch = ch;
}
public void encodeFrame(Picture8Bit picture) throws IOException {
if (!headerWritten) {
writeHeader(picture);
headerWritten = true;
}
if (picture.getWidth() != width || picture.getHeight() != height) {
throw new RuntimeException("Changing picture dimentsions is not allowed in Y4M.");
}
ch.write(ByteBuffer.wrap(frameTag));
ch.write(shiftPlane(picture.getPlaneData(0)));
ch.write(shiftPlane(picture.getPlaneData(1)));
ch.write(shiftPlane(picture.getPlaneData(2)));
}
protected void writeHeader(Picture8Bit picture) throws IOException {
byte[] bytes = String.format("YUV4MPEG2 W%d H%d F25:1 Ip A0:0 C420jpeg XYSCSS=420JPEG\n", picture.getWidth(),
picture.getHeight()).getBytes();
ch.write(ByteBuffer.wrap(bytes));
this.width = picture.getWidth();
this.height = picture.getHeight();
this.scratchBuffer = new byte[width * height];
}
protected ByteBuffer shiftPlane(byte[] data) {
for (int i = 0; i < data.length; i++) {
scratchBuffer[i] = (byte) (data[i] + 128);
}
return ByteBuffer.wrap(scratchBuffer, 0, data.length);
}
}