FileDocCategorySizeDatePackage
Packetizer.javaAPI DocJMF 2.1.1e9864Mon May 12 12:20:46 BST 2003com.sun.media.codec.video.jpeg

Packetizer

public class Packetizer extends BasicCodec

Fields Summary
static final JPEGFormat
fJPEG
private VideoFormat
inputFormat
private VideoFormat
outputFormat
private int
PACKET_SIZE
private int
currentSeq
private int
copyLength
private boolean
newFrame
private boolean
dropFrame
private boolean
minimal
private int
offset
private int
frameLength
private static final int
J_SOF
private static final int
J_SOF1
private int
decimation
private static final int
DEFAULT_FRAMERATE
private float
frame_duration
Constructors Summary
public Packetizer()
Codec Methods

           
  
    // Initialize default formats.
      
	inputFormats = new VideoFormat[] {new VideoFormat(VideoFormat.JPEG)};
	outputFormats = new VideoFormat[] {new VideoFormat(VideoFormat.JPEG_RTP)};

	FrameProcessingControl fpc = new FrameProcessingControl() {
	    public boolean setMinimalProcessing(boolean newMinimal) {
		minimal = newMinimal;
		return minimal;
	    }

	    public void setFramesBehind(float frames) {
		if (frames >= 1)
		    dropFrame = true;
		else
		    dropFrame = false;
	    }

	    public Component getControlComponent() {
		return null;
	    }

            public int getFramesDropped() {
                return 0;       ///XXX not implemented
            }

	};

	controls = new Control[1];
	controls[0] = fpc;
    
Methods Summary
public voidfinalize()

	close();
    
intgetDecimationFromSOF(byte[] data, int i, int length)

	int sectionLen;
	int dummy;
	int ncomp;
	int deccode;
	int hsf, vsf;
	int id;
	
	sectionLen = (data[i++] & 0xFF) << 8;
	sectionLen |= (data[i++] & 0xFF);

	i += 5; // skip precision, 2height, 2width
	ncomp = (data[i++] & 0xFF);

	if (sectionLen != ncomp * 3 + 8)
	    System.err.println("Bogus SOF length");

	id = data[i++] & 0xFF;
	deccode = data[i++] & 0xFF;
	hsf = (deccode >> 4) & 15;
	vsf = (deccode     ) & 15;
	if (vsf == 2 && hsf == 2)
	    return JPEGFormat.DEC_420;
	else if (vsf == 1 && hsf == 1)
	    return JPEGFormat.DEC_444;
	else
	    return JPEGFormat.DEC_422;
    
protected javax.media.FormatgetInputFormat()

	return inputFormat;
    
public java.lang.StringgetName()

	return "JPEG Packetizer";
    
protected javax.media.FormatgetOutputFormat()

	return outputFormat;
    
public javax.media.Format[]getSupportedOutputFormats(javax.media.Format in)

	if (in == null)
	    return outputFormats;
    
	// Make sure the input is JPEG video format
	if (!verifyInputFormat(in))
	    return new Format[0];
    
	Format out [] = new Format[1];
	// check the frame Rate and if it is dont care, its needs
	// to be set to the default frame rate.
    
	if ( ((VideoFormat)in).getFrameRate() == VideoFormat.NOT_SPECIFIED)
	    out[0] = new VideoFormat(VideoFormat.JPEG_RTP,
				     ((VideoFormat)in).getSize(),
				     ((VideoFormat)in).getMaxDataLength(),
				     Format.byteArray,
				     DEFAULT_FRAMERATE);
	else
	    out[0] = new VideoFormat(VideoFormat.JPEG_RTP,
				     ((VideoFormat)in).getSize(),
				     ((VideoFormat)in).getMaxDataLength(),
				     Format.byteArray,
				     ((VideoFormat)in).getFrameRate());
    
	return out;
    
public voidopen()

	if (inputFormat == null || outputFormat == null)
	    throw new ResourceUnavailableException("Incorrect formats set on JPEG Packetizer");

	// Validate the sizes.
	Dimension size = inputFormat.getSize();
	if (size != null){
	    // the JPEG packetizer cannot handle non standard format sizes,
	    // so it checks the size here and will return null if the size
	    // is not a multiple of 8 pixels  
	    if ((size.width % 8 != 0) || (size.height % 8 != 0)){
		Log.error("Class: " + this);
		Log.error("  can only packetize in sizes of multiple of 8 pixels.");
		throw new ResourceUnavailableException("Incorrect formats set on JPEG Packetizer");
	    }
	}
	super.open();
    
intpeekJPEGDecimation(byte[] data, int dataLen)

	int i = 0;
	int code;
	if ((data[0] & 0xFF) != 0xFF || data[1] == 0)
	    return -1;
	while (i < dataLen - 2) {
	    if ((data[i] & 0xFF) == 0xFF) {
		i++;
		code = data[i] & 0xFF;
		i++;
		switch (code) {
		case J_SOF:
		case J_SOF1:
		    return getDecimationFromSOF(data, i, dataLen);
		}
	    } else
		i++;
	}
	return -1;
    
public synchronized intprocess(javax.media.Buffer inBuffer, javax.media.Buffer outBuffer)


	if (isEOM(inBuffer)) {
	    propagateEOM(outBuffer);
	    return BUFFER_PROCESSED_OK;
	}

	if (inBuffer.isDiscard()) {
	    updateOutput(outBuffer, outputFormat, 0, 0);
	    outBuffer.setDiscard(true);
	    return OUTPUT_BUFFER_NOT_FILLED;
	}

	if (inBuffer.getLength() <= 0) {
	    outBuffer.setDiscard(true);
	    return OUTPUT_BUFFER_NOT_FILLED;
	}

	byte [] inData = (byte[]) inBuffer.getData();
    
	outBuffer.setFormat(outputFormat);
      
	Dimension size = inputFormat.getSize();
	int keyFrame = 0;

	if (newFrame) {
	    if (dropFrame || minimal) {
		outBuffer.setDiscard(true);
		return BUFFER_PROCESSED_OK;
	    }
	    int tempdec = peekJPEGDecimation(inData, inBuffer.getLength());
	    if (tempdec >= 0)
		decimation = tempdec;
	    if (inputFormat instanceof JPEGFormat)
	      stripTables(inBuffer);
	    
	    frameLength = inBuffer.getLength();
	    offset = 0;
	    newFrame = false;
	    keyFrame = Buffer.FLAG_KEY_FRAME;
	}

	//copy correct part of the encoded buffer into outputbuffer
	if (frameLength - offset < PACKET_SIZE)
	    copyLength = frameLength - offset;
	else
	    copyLength = PACKET_SIZE;
      
	byte[] outData = (byte[])outBuffer.getData();
	if ((outData == null) || outData.length < copyLength + 8){
	    outData = new byte[copyLength + 8];
	    outBuffer.setData(outData);
	}

	System.arraycopy(inData, offset + inBuffer.getOffset(), 
			outData, 8, copyLength);

	int qfactor = (inputFormat instanceof JPEGFormat ? 
			   ((JPEGFormat)inputFormat).getQFactor() : 80);
	decimation =  (inputFormat instanceof JPEGFormat ?
		       ((JPEGFormat)inputFormat).getDecimation() : decimation);
	if (decimation == -1)
	    decimation = 1;

	outBuffer.setLength(copyLength + 8);
	outBuffer.setOffset(0);
	//outBuffer.setTimeStamp(timestamp);
	outBuffer.setSequenceNumber(currentSeq++);
	outBuffer.setFormat(outputFormat);
	outData[0] = 0;
	outData[1] = (byte) (offset >> 16);
	outData[2] = (byte) (offset >> 8);
	outData[3] = (byte) (offset);
	outData[4] = (byte)decimation;
	outData[5] = (byte)qfactor;
	outData[6] = (byte)(size.width/8);
	outData[7] = (byte)(size.height/8);

	offset += copyLength;

	outBuffer.setFlags(outBuffer.getFlags() | keyFrame);

	if (offset == frameLength) {
	    outBuffer.setFlags(outBuffer.getFlags() | Buffer.FLAG_RTP_MARKER);
	    newFrame = true;
	    return BUFFER_PROCESSED_OK;
	}

	return INPUT_BUFFER_NOT_CONSUMED;

    
public voidreset()

	// Anything to do?
    
public javax.media.FormatsetInputFormat(javax.media.Format input)

	if (!verifyInputFormat(input))
	    return null;
	inputFormat = (VideoFormat)input;
	float rate = inputFormat.getFrameRate();
	if (rate != Format.NOT_SPECIFIED)
	    // frame duration in msec
	    frame_duration = 1000/rate;
	if (opened) {
	    outputFormat = (VideoFormat) getSupportedOutputFormats(input)[0];
	}
	return input;
    
public javax.media.FormatsetOutputFormat(javax.media.Format output)

	if (matches(output, outputFormats) == null)
	    return null;
	outputFormat = (VideoFormat) output;
	return output;
    
private voidstripTables(javax.media.Buffer inb)

	byte [] data = (byte[]) inb.getData();
	int offset = inb.getOffset();
	int length = inb.getLength();
	int i = offset;
	while (i < length + offset - 8) {
	    if (data[i] == (byte)0xFF) {
		if (data[i+1] == (byte)0xDA) {
		    // Found SOS Start of Scan marker
		    // Skip over this block
		    int blockSize = ((data[i+2] & 0xFF) << 8) |
			            (data[i+3] & 0xFF);
		    i += 2 + blockSize;
		    System.arraycopy(data, i,
				     data, 0,
				     length + offset - i);
		    inb.setOffset(0);
		    inb.setLength(length + offset - i);
		    break;
		}
	    }
	    i++;
	}
    
private booleanverifyInputFormat(javax.media.Format input)

	// -- by hsy to improve robustness & performance
	//if ((input instanceof VideoFormat) && 
	//    (input.getEncoding().equals(VideoFormat.JPEG)))
	//    return true;
	//return false;

	return fJPEG.matches(input);