package org.jcodec.codecs.mpeg12.bitstream;
import static org.jcodec.codecs.mpeg12.MPEGConst.EXTENSION_START_CODE;
import java.nio.ByteBuffer;
import org.jcodec.common.io.BitReader;
import org.jcodec.common.io.BitWriter;
/**
* This class is part of JCodec ( www.jcodec.org ) This software is distributed
* under FreeBSD License
*
* @author The JCodec project
*
*/
public class SequenceHeader {
public static final int Sequence_Extension = 0x1;
public static final int Sequence_Display_Extension = 0x2;
public static final int Sequence_Scalable_Extension = 0x5;
private static boolean hasExtensions;
public int horizontal_size;
public int vertical_size;
public int aspect_ratio_information;
public int frame_rate_code;
public int bit_rate;
public int marker_bit;
public int vbv_buffer_size_value;
public int constrained_parameters_flag;
public int[] intra_quantiser_matrix;
public int[] non_intra_quantiser_matrix;
public SequenceExtension sequenceExtension;
public SequenceScalableExtension sequenceScalableExtension;
public SequenceDisplayExtension sequenceDisplayExtension;
public static SequenceHeader read(ByteBuffer bb) {
BitReader in = new BitReader(bb);
SequenceHeader sh = new SequenceHeader();
sh.horizontal_size = in.readNBit(12);
sh.vertical_size = in.readNBit(12);
sh.aspect_ratio_information = in.readNBit(4);
sh.frame_rate_code = in.readNBit(4);
sh.bit_rate = in.readNBit(18);
sh.marker_bit = in.read1Bit();
sh.vbv_buffer_size_value = in.readNBit(10);
sh.constrained_parameters_flag = in.read1Bit();
if (in.read1Bit() != 0) {
sh.intra_quantiser_matrix = new int[64];
for (int i = 0; i < 64; i++) {
sh.intra_quantiser_matrix[i] = in.readNBit(8);
}
}
if (in.read1Bit() != 0) {
sh.non_intra_quantiser_matrix = new int[64];
for (int i = 0; i < 64; i++) {
sh.non_intra_quantiser_matrix[i] = in.readNBit(8);
}
}
return sh;
}
public static void readExtension(ByteBuffer bb, SequenceHeader sh) {
hasExtensions = true;
BitReader in = new BitReader(bb);
int extType = in.readNBit(4);
switch (extType) {
case Sequence_Extension:
sh.sequenceExtension = SequenceExtension.read(in);
break;
case Sequence_Scalable_Extension:
sh.sequenceScalableExtension = SequenceScalableExtension.read(in);
break;
case Sequence_Display_Extension:
sh.sequenceDisplayExtension = SequenceDisplayExtension.read(in);
break;
default:
throw new RuntimeException("Unsupported extension: " + extType);
}
}
public void write(ByteBuffer os) {
BitWriter out = new BitWriter(os);
out.writeNBit(horizontal_size, 12);
out.writeNBit(vertical_size, 12);
out.writeNBit(aspect_ratio_information, 4);
out.writeNBit(frame_rate_code, 4);
out.writeNBit(bit_rate, 18);
out.write1Bit(marker_bit);
out.writeNBit(vbv_buffer_size_value, 10);
out.write1Bit(constrained_parameters_flag);
out.write1Bit(intra_quantiser_matrix != null ? 1 : 0);
if (intra_quantiser_matrix != null) {
for (int i = 0; i < 64; i++) {
out.writeNBit(intra_quantiser_matrix[i], 8);
}
}
out.write1Bit(non_intra_quantiser_matrix != null ? 1 : 0);
if (non_intra_quantiser_matrix != null) {
for (int i = 0; i < 64; i++) {
out.writeNBit(non_intra_quantiser_matrix[i], 8);
}
}
writeExtensions(os);
}
private void writeExtensions(ByteBuffer out) {
if (sequenceExtension != null) {
out.putInt(EXTENSION_START_CODE);
BitWriter os = new BitWriter(out);
os.writeNBit(Sequence_Extension, 4);
sequenceExtension.write(os);
}
if (sequenceScalableExtension != null) {
out.putInt(EXTENSION_START_CODE);
BitWriter os = new BitWriter(out);
os.writeNBit(Sequence_Scalable_Extension, 4);
sequenceScalableExtension.write(os);
}
if (sequenceDisplayExtension != null) {
out.putInt(EXTENSION_START_CODE);
BitWriter os = new BitWriter(out);
os.writeNBit(Sequence_Display_Extension, 4);
sequenceDisplayExtension.write(os);
}
}
public boolean hasExtensions() {
return hasExtensions;
}
public void copyExtensions(SequenceHeader sh) {
sequenceExtension = sh.sequenceExtension;
sequenceScalableExtension = sh.sequenceScalableExtension;
sequenceDisplayExtension = sh.sequenceDisplayExtension;
}
}