/*
* @(#)JavaEncoder.java 1.13 02/08/21
*
* Copyright (c) 1996-2002 Sun Microsystems, Inc. All rights reserved.
*/
package com.ibm.media.codec.audio.gsm;
import javax.media.*;
import javax.media.format.*;
import javax.media.format.*;
import com.sun.media.*;
/**
* RTP GSM encoder plugin wrapper, which uses Java methods to do the encoding.
* @author Shay Ben-David bendavid@haifa.vnet.ibm.com
*/
public class JavaEncoder extends com.ibm.media.codec.audio.BufferedEncoder {
////////////////////////////////////////////////////////////////////////////
// Variables
/** <FONT COLOR="#FF0000">
* Licensed Materials - Property of IBM <br><br>
* "Restricted Materials of IBM" <br><br>
* 5648-B81 <br><br>
* (c) Copyright IBM Corporation 1997,1999 All Rights Reserved <br><br>
* US Government Users Restricted Rights - Use, duplication or
* disclosure restricted by GSA ADP Schedule Contract with
* IBM Corporation.</FONT>
*
**/
public static final String a_copyright_notice="(c) Copyright IBM Corporation 1997,1999.";
protected GsmEncoder encoder;
// the default RTP packet size for the outputformat in units of samples.
// for gsm, 160 audio samples are compressed to 33 bytes. We want the
//default millisec perpacket to be 20ms --> 160 audio samples --> 33 octets.
private int sample_count = 160;
private long currentSeq = (long) (System.currentTimeMillis() * Math.random
());
// current timestamp on RTP format packets.
//private long timestamp = (long) (System.currentTimeMillis() * Math.random());
private long timestamp = 0L;
// the buffer used by the RTP packetization method
byte[] pendingBuffer = null;
////////////////////////////////////////////////////////////////////////////
// Methods
public JavaEncoder() {
supportedInputFormats = new AudioFormat[] {
new AudioFormat(AudioFormat.LINEAR,
Format.NOT_SPECIFIED,
16,
1,
AudioFormat.LITTLE_ENDIAN,
AudioFormat.SIGNED,
Format.NOT_SPECIFIED,
Format.NOT_SPECIFIED,
Format.byteArray) };
defaultOutputFormats = new AudioFormat[] {
new AudioFormat(AudioFormat.GSM) /*,
new AudioFormat(AudioFormat.GSM_RTP)*/};
PLUGIN_NAME="GSM Encoder";
historySize = 320;
pendingFrames = 0;
// for RTP, set default packetsize to 160 audiosamples for a
// default ms/packet of 20ms. This works out to 33 octets.
//note if this value changes in setPacketSize(), sample count
// needs to be updated as well.
packetSize = 33;
}
protected Format[] getMatchingOutputFormats(Format in) {
AudioFormat af =(AudioFormat) in;
supportedOutputFormats = new AudioFormat[] {
new AudioFormat(
AudioFormat.GSM,
af.getSampleRate(),
16,
af.getChannels(),
Format.NOT_SPECIFIED,
Format.NOT_SPECIFIED,
264,
Format.NOT_SPECIFIED,
Format.byteArray
)/*,
new AudioFormat(
AudioFormat.GSM_RTP,
af.getSampleRate(),
Format.NOT_SPECIFIED,
af.getChannels(),
Format.NOT_SPECIFIED,
Format.NOT_SPECIFIED,
264,
Format.NOT_SPECIFIED,
Format.byteArray
) */
};
return supportedOutputFormats;
}
public void open() throws ResourceUnavailableException{
encoder=new GsmVadEncoder();
encoder.gsm_encoder_reset();
}
public void codecReset() {
encoder.gsm_encoder_reset();
}
public void close() {
encoder=null;
}
public int process(Buffer inputBuffer, Buffer outputBuffer){
// let the buffered encoder process the input buffer. this will
// encode the data for us.Only RTP packetization will be desired
// at this time.
int retVal = super.process(inputBuffer, outputBuffer);
// if the output format is not RTP, just return the from here.
if (!outputFormat.getEncoding().equals(AudioFormat.GSM_RTP))
return retVal;
// if it is RTP, packetize the data.
if (outputFormat.getEncoding().equals(AudioFormat.GSM_RTP)){
// before we proceed for packetization, check for failure in
// encoding and EOM
if (retVal == BUFFER_PROCESSED_FAILED)
return retVal;
if (isEOM(inputBuffer) ) {
propagateEOM(outputBuffer);
return BUFFER_PROCESSED_OK;
}
// Now, if there are no pending frames, we are beginning
// packetization of a new buffer.get a handle over the buffer to
// be packetized
if (pendingFrames == 0)
pendingBuffer = (byte[])outputBuffer.getData();
// start packetizing one frame at a time (160 samples)
// the size of outputdata depends on the packet size set.
byte[] outData = new byte[packetSize];
outputBuffer.setData(outData);
updateOutput(outputBuffer, outputFormat,packetSize, 0);
outputBuffer.setSequenceNumber(currentSeq++);
outputBuffer.setTimeStamp(timestamp);
timestamp+=sample_count;
System.arraycopy(pendingBuffer,
regions[pendingFrames],
outData,
0,
packetSize);
if (pendingFrames + 1== frameNumber[0]){
pendingFrames = 0;
pendingBuffer = null;
return BUFFER_PROCESSED_OK;
}else
pendingFrames++;
return INPUT_BUFFER_NOT_CONSUMED;
}//end of GSM_RTP
return retVal;
}
protected int calculateOutputSize(int inputSize) {
return calculateFramesNumber(inputSize) * 33 ;
}
protected int calculateFramesNumber(int inputSize) {
return inputSize / 320;
}
protected boolean codecProcess(byte[] inpData,int readPtr,
byte[] outData,int writePtr,
int inpLength,
int[] readBytes,int[] writeBytes,
int[] frameNumber,
int[] regions,int[] regionsTypes) {
int inCount = 0;
int outCount = 0;
int channels=inputFormat.getChannels();
boolean isStereo = ( channels == 2);
int frames = inpLength/(320);
regions[0]=writePtr;
for (int frameCounter = 0; frameCounter<frames ; frameCounter++) {
encoder.gsm_encode_frame(inpData, readPtr , outData,writePtr);
readPtr += 320;
inCount += 320;
outCount += 33;
writePtr += 33;
//regions [frameCounter+1]= outCount + writePtr;
regions [frameCounter +1] = writePtr;
regionsTypes[frameCounter ]= 0;
//System.out.println(inCount+" "+outCount+" "+inpLength);
}
readBytes [0]=inCount;
writeBytes[0]=outCount;
frameNumber[0]=frames;
return true;
}
}
|