/* * @(#)DePacketizer.java 1.6 01/02/13 * * Copyright 1998 by Sun Microsystems, Inc., * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A. * All rights reserved. * * This software is the confidential and proprietary information * of Sun Microsystems, Inc. ("Confidential Information"). You * shall not disclose such Confidential Information and shall use * it only in accordance with the terms of the license agreement * you entered into with Sun. */ package com.sun.media.codec.video.jpeg; import javax.media.*; import javax.media.Format; import javax.media.format.VideoFormat; import javax.media.format.JPEGFormat; import javax.media.control.*; import java.awt.Component; import java.awt.Dimension; import com.sun.media.*; import com.sun.media.util.*; public class DePacketizer extends BasicCodec { private VideoFormat inputFormat = null; private JPEGFormat outputFormat = null; // Decimation values. Initial value is unknown (-1) private int decimation = -1; private int quality = JPEGFormat.NOT_SPECIFIED; // RTP depacketizer if inputFormat is JPEG_RTP private RTPDePacketizer rtpdp = null; int DEFAULT_WIDTH = 320; int DEFAULT_HEIGHT = 240; // Initialize default formats. public DePacketizer() { inputFormats = new Format[] { new VideoFormat(VideoFormat.JPEG_RTP) }; outputFormats = new Format[] { new VideoFormat(VideoFormat.JPEG) }; } protected Format getInputFormat() { return inputFormat; } protected Format getOutputFormat() { return outputFormat; } // Return supported output formats public Format [] getSupportedOutputFormats(Format in) { if (in == null) return outputFormats; // Make sure the input is JPEG video format if (matches(in, inputFormats) == null) return new Format[0]; Format out [] = new Format[1]; out[0] = makeJPEGFormat(in); return out; } public Format setInputFormat(Format input) { inputFormat = (VideoFormat) input; if (opened) { outputFormat = makeJPEGFormat(inputFormat); } return input; } public Format setOutputFormat(Format output) { if (!(output instanceof VideoFormat)) return null; outputFormat = makeJPEGFormat(output); return outputFormat; } private final JPEGFormat makeJPEGFormat(Format in) { VideoFormat vf = (VideoFormat)in; return new JPEGFormat((vf.getSize() != null ? vf.getSize() : new Dimension(DEFAULT_WIDTH, DEFAULT_HEIGHT)), VideoFormat.NOT_SPECIFIED, Format.byteArray, vf.getFrameRate(), quality, decimation); } public void open() throws ResourceUnavailableException { if (inputFormat == null || outputFormat == null) throw new ResourceUnavailableException("Incorrect formats set on JPEG converter"); rtpdp = new RTPDePacketizer(); super.open(); } public synchronized void close() { rtpdp = null; super.close(); } public void reset() { // Anything to do? } public synchronized int process(Buffer inBuffer, 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 the encoding is JPEG_RTP, send this packet over to the // depacketizer, which will do all the work for you. If the // depacketizer has not finished constructing a frame, dont // send it for decoding and just return. If the depacketizer // has finished constructing an entire frame, send it to the // decoder after getting a handle over the decimation and // quality from the depacketizer. int retVal = rtpdp.process(inBuffer, outBuffer); // return any value from the depacketizer except, // BUFFER_PROCESSED_OK, which indicates a complete frame // is ready for decoding if (retVal != BUFFER_PROCESSED_OK) { return retVal; } // at this time, the inBuffer contains a complete JPEG // frame of format JPEG int type = rtpdp.getType(); int q = rtpdp.getQuality(); // compute thje outputFormat only if the type has changed // or this is the first time. if (type != decimation || q != quality) { decimation = type; quality = q; outputFormat = makeJPEGFormat(inBuffer.getFormat()); } outBuffer.setFormat(outputFormat); // the following code fragment has been removed since the RTPDePacketizer // now uses the outBuffer for frame assembly. /* byte [] inData = (byte[]) inBuffer.getData(); byte [] outData = (byte[]) outBuffer.getData(); if (outData == null || outData.length < inData.length) { outData = new byte[inData.length]; outBuffer.setData(outData); } */ // Neither copying or setting the data is optimal. // We'll need to rewrite RTPDePacketizer to reuse the array. // -ivg //System.arraycopy((byte[])inData, 0, (byte[])outData, 0, inBuffer.getLength()); /* outBuffer.setData(inData); outBuffer.setLength(inBuffer.getLength()); */ outBuffer.setOffset(0); outBuffer.setTimeStamp(inBuffer.getTimeStamp()); inBuffer.setLength(0); outBuffer.setFlags(outBuffer.getFlags() | Buffer.FLAG_KEY_FRAME); return BUFFER_PROCESSED_OK; } public void finalize() { close(); } public String getName() { return "JPEG DePacketizer"; } }