Fix speex sending packets and ticking rtp time, reported by Marian Kechlibar.

cusax-fix
Damian Minkov 16 years ago
parent 2111ac215f
commit 238fb19f7e

@ -161,12 +161,9 @@ public void initializeFormatPreferences()
setEncodingPreference("PCMA", 8000, 600);
setEncodingPreference("iLBC", 8000, 500);
setEncodingPreference("GSM", 8000, 450);
// not selected for use till confirmed its working
// cause uses some old speex impl which seems
// incompatable with some clients
setEncodingPreference("speex", 8000, 0);
setEncodingPreference("speex", 16000, 0);
setEncodingPreference("speex", 32000, 0);
setEncodingPreference("speex", 8000, 352);
setEncodingPreference("speex", 16000, 351);
setEncodingPreference("speex", 32000, 350);
setEncodingPreference("DVI4", 8000, 300);
setEncodingPreference("DVI4", 16000, 250);
setEncodingPreference("G723", 8000, 150);

@ -11,6 +11,7 @@
import org.xiph.speex.*;
import net.java.sip.communicator.impl.neomedia.codec.*;
import net.sf.fmj.media.*;
/**
* The Speex Encoder
@ -18,16 +19,48 @@
* @author Damian Minkov
*/
public class JavaEncoder
extends com.ibm.media.codec.audio.AudioCodec
extends AbstractCodec
{
/**
* Default output formats.
*/
protected Format[] DEFAULT_OUTPUT_FORMATS = new Format[] {
new AudioFormat(Constants.SPEEX_RTP)};
/**
* The last input format used by this instance of the encoder.
* If null we must create the encoder with the current input format.
*/
private Format lastFormat = null;
/**
* Our custom output format which computes the rtp data duration correctly.
*/
private AudioFormat outFormat = null;
/**
* The frame size used for current encoder configuration.
*/
private int FRAME_SIZE = -1;
/**
* The speex encoder instance.
*/
private SpeexEncoder encoder = null;
/**
* Narrow band used for 8 kHz.
*/
final static int NARROW_BAND= 0;
/**
* Wide band used for 16 kHz.
*/
final static int WIDE_BAND= 1;
/**
* Utra wide band used for 32 kHz.
*/
final static int ULTRA_WIDE_BAND= 2;
/**
@ -35,7 +68,7 @@ public class JavaEncoder
*/
public JavaEncoder()
{
supportedInputFormats = new AudioFormat[]
this.inputFormats = new AudioFormat[]
{
new AudioFormat(
AudioFormat.LINEAR,
@ -62,11 +95,35 @@ public JavaEncoder()
AudioFormat.SIGNED //isSigned());
)
};
}
/**
* Returns the name of this plugin/codec.
* @return the name.
*/
public String getName()
{
return "pcm to speex converter";
}
/**
* Return the list of formats supported at the output.
*
* @param in the input format.
* @return array of formats supported at output
*/
public Format[] getSupportedOutputFormats(Format in)
{
// null input format
if (in == null)
return DEFAULT_OUTPUT_FORMATS;
defaultOutputFormats = new AudioFormat[]
{new AudioFormat(Constants.SPEEX_RTP)};
// mismatch input format
if (!(in instanceof AudioFormat)
|| (null == AbstractCodecExt.matches(in, inputFormats)))
return new Format[0];
PLUGIN_NAME = "pcm to speex converter";
return getMatchingOutputFormats(in);
}
/**
@ -74,11 +131,11 @@ public JavaEncoder()
* @param in input format
* @return array of formats that match input ones
*/
protected Format[] getMatchingOutputFormats(Format in)
private Format[] getMatchingOutputFormats(Format in)
{
AudioFormat af = (AudioFormat) in;
supportedOutputFormats = new AudioFormat[]
return new AudioFormat[]
{new AudioFormat(
Constants.SPEEX_RTP,
af.getSampleRate(),
@ -87,8 +144,6 @@ protected Format[] getMatchingOutputFormats(Format in)
af.getEndian(),
af.getSigned()
)};
return supportedOutputFormats;
}
/**
@ -107,30 +162,54 @@ public void close()
}
/**
* Initialize the encoder with the supplied input format.
* @param inFormat the input format.
*/
private void initConverter(AudioFormat inFormat)
{
lastFormat = inFormat;
AudioFormat oFormat = (AudioFormat)outputFormat;
outFormat = new AudioFormat(
oFormat.getEncoding(),
oFormat.getSampleRate(),
oFormat.getSampleSizeInBits(),
oFormat.getChannels(),
oFormat.getEndian(),
oFormat.getSigned(),
oFormat.getFrameSizeInBits(),
oFormat.getFrameRate(),
oFormat.getDataType())
{
/**
* The length in nanoseconds.
*/
public long computeDuration(long l)
{
// 20ms in nano
return 20 * 1000000;
}
};
encoder = new SpeexEncoder();
int sampleRate =
(int)inFormat.getSampleRate();
int band = NARROW_BAND;
FRAME_SIZE = 320;
if(sampleRate == 16000)
{
band = WIDE_BAND;
FRAME_SIZE = 640;
}
else if(sampleRate == 32000)
{
band = ULTRA_WIDE_BAND;
FRAME_SIZE = 1280;
band = ULTRA_WIDE_BAND;
}
encoder.init(band, 4, sampleRate, 1);
FRAME_SIZE = 2 * encoder.getFrameSize();
}
/**
@ -175,12 +254,31 @@ public int process(Buffer inputBuffer, Buffer outputBuffer)
byte[] buff = new byte[encoder.getProcessedDataByteSize()];
encoder.getProcessedData(buff, 0);
byte[] outData = validateByteArraySize(outputBuffer, buff.length);
/*
* Do not always allocate a new data array for outBuffer, try to reuse
* the existing one if it is suitable.
*/
Object outData = outputBuffer.getData();
byte[] out;
if (outData instanceof byte[])
{
out = (byte[]) outData;
if (out.length < buff.length)
out = null;
}
else
out = null;
if (out == null)
out = new byte[buff.length];
System.arraycopy(buff, 0, outData, outputBuffer.getOffset(),
System.arraycopy(buff, 0, out, outputBuffer.getOffset(),
buff.length);
updateOutput(outputBuffer, outputFormat, outData.length, 0);
outputBuffer.setData(out);
outputBuffer.setLength(out.length);
outputBuffer.setOffset(0);
outputBuffer.setFormat(outFormat);
if ( (inpLength - inOffset) > FRAME_SIZE)
{

Loading…
Cancel
Save