package org.jcodec.codecs.prores;
import static org.jcodec.common.model.ColorSpace.YUV422_10;
import java.nio.ByteBuffer;
import org.jcodec.common.model.Picture;
public class DCT2Prores extends ProresEncoder {
public DCT2Prores(Profile profile) {
super(profile);
}
@Override
protected int encodeSlice(ByteBuffer out, int[][] scaledLuma, int[][] scaledChroma, int[] scan, int sliceMbCount,
int mbX, int mbY, Picture source, int prevQp, int mbWidth, int mbHeight, boolean unsafe) {
Picture striped = sliceData(source, mbX, mbY, mbWidth, sliceMbCount);
int est = (sliceMbCount >> 2) * profile.bitrate;
int low = est - (est >> 3); // 12% bitrate fluctuation
int high = est + (est >> 3);
int qp = prevQp;
out.put((byte) (6 << 3)); // hdr size
out.put((byte) qp); // qscale
ByteBuffer fork = out.duplicate();
out.putInt(0);
int rem = out.position();
int[] sizes = new int[3];
encodeSliceData(out, scaledLuma[qp - 1], scaledChroma[qp - 1], scan, sliceMbCount, striped, qp, sizes);
if (bits(sizes) > high && qp < profile.lastQp) {
do {
++qp;
out.position(rem);
encodeSliceData(out, scaledLuma[qp - 1], scaledChroma[qp - 1], scan, sliceMbCount, striped, qp, sizes);
} while (bits(sizes) > high && qp < profile.lastQp);
} else if (bits(sizes) < low && qp > profile.firstQp) {
do {
--qp;
out.position(rem);
encodeSliceData(out, scaledLuma[qp - 1], scaledChroma[qp - 1], scan, sliceMbCount, striped, qp, sizes);
} while (bits(sizes) < low && qp > profile.firstQp);
}
fork.putShort((short) sizes[0]);
fork.putShort((short) sizes[1]);
return qp;
}
private Picture sliceData(Picture source, int mbX, int mbY, int mbWidth, int sliceMbCount) {
Picture pic = Picture.create(sliceMbCount << 4, 16, YUV422_10);
int[][] out = pic.getData();
int[][] in = source.getData();
System.arraycopy(in[0], (mbY * mbWidth + mbX) << 8, out[0], 0, out[0].length);
System.arraycopy(in[1], (mbY * mbWidth + mbX) << 7, out[1], 0, out[1].length);
System.arraycopy(in[2], (mbY * mbWidth + mbX) << 7, out[2], 0, out[2].length);
return pic;
}
}