mirror of https://github.com/sipwise/jitsi.git
parent
89021696cb
commit
913f7bee58
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,16 @@
|
||||
/*
|
||||
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*/
|
||||
package net.java.sip.communicator.impl.media.codec;
|
||||
|
||||
/**
|
||||
* Constants needed in codecs impl.
|
||||
* @author Damian Minkov
|
||||
*/
|
||||
public class Constants
|
||||
{
|
||||
public static final String ALAW_RTP = "ALAW/rtp";
|
||||
}
|
||||
@ -0,0 +1,113 @@
|
||||
/*
|
||||
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*/
|
||||
package net.java.sip.communicator.impl.media.codec.audio.alaw;
|
||||
|
||||
import javax.media.*;
|
||||
import javax.media.format.*;
|
||||
|
||||
import com.sun.media.codec.audio.*;
|
||||
import net.java.sip.communicator.impl.media.codec.*;
|
||||
|
||||
/**
|
||||
* DePacketizer for ALAW codec
|
||||
* @author Damian Minkov
|
||||
*/
|
||||
public class DePacketizer
|
||||
extends AudioCodec
|
||||
{
|
||||
/**
|
||||
* Creates DePacketizer
|
||||
*/
|
||||
public DePacketizer()
|
||||
{
|
||||
inputFormats = new Format[]{new AudioFormat(Constants.ALAW_RTP)};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the DePacketizer
|
||||
* @return String
|
||||
*/
|
||||
public String getName()
|
||||
{
|
||||
return "ALAW DePacketizer";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the supported output formats
|
||||
* @param in Format
|
||||
* @return Format[]
|
||||
*/
|
||||
public Format[] getSupportedOutputFormats(Format in)
|
||||
{
|
||||
|
||||
if (in == null)
|
||||
{
|
||||
return new Format[]{new AudioFormat(AudioFormat.ALAW)};
|
||||
}
|
||||
|
||||
if (matches(in, inputFormats) == null)
|
||||
{
|
||||
return new Format[1];
|
||||
}
|
||||
|
||||
if (! (in instanceof AudioFormat))
|
||||
{
|
||||
return new Format[]{new AudioFormat(AudioFormat.ALAW)};
|
||||
}
|
||||
|
||||
AudioFormat af = (AudioFormat) in;
|
||||
return new Format[]
|
||||
{
|
||||
new AudioFormat(
|
||||
AudioFormat.ALAW,
|
||||
af.getSampleRate(),
|
||||
af.getSampleSizeInBits(),
|
||||
af.getChannels())
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the codec.
|
||||
*/
|
||||
public void open()
|
||||
{}
|
||||
|
||||
/**
|
||||
* Clean up
|
||||
*/
|
||||
public void close()
|
||||
{}
|
||||
|
||||
/**
|
||||
* decode the buffer
|
||||
* @param inputBuffer Buffer
|
||||
* @param outputBuffer Buffer
|
||||
* @return int
|
||||
*/
|
||||
public int process(Buffer inputBuffer, Buffer outputBuffer)
|
||||
{
|
||||
|
||||
if (!checkInputBuffer(inputBuffer))
|
||||
{
|
||||
return BUFFER_PROCESSED_FAILED;
|
||||
}
|
||||
|
||||
if (isEOM(inputBuffer))
|
||||
{
|
||||
propagateEOM(outputBuffer);
|
||||
return BUFFER_PROCESSED_OK;
|
||||
}
|
||||
|
||||
Object outData = outputBuffer.getData();
|
||||
outputBuffer.setData(inputBuffer.getData());
|
||||
inputBuffer.setData(outData);
|
||||
outputBuffer.setLength(inputBuffer.getLength());
|
||||
outputBuffer.setFormat(outputFormat);
|
||||
outputBuffer.setOffset(inputBuffer.getOffset());
|
||||
return BUFFER_PROCESSED_OK;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,342 @@
|
||||
/*
|
||||
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*/
|
||||
package net.java.sip.communicator.impl.media.codec.audio.alaw;
|
||||
|
||||
import javax.media.*;
|
||||
import javax.media.format.*;
|
||||
|
||||
/**
|
||||
* The ALAW Encoder
|
||||
*
|
||||
* @author Damian Minkov
|
||||
*/
|
||||
public class JavaEncoder
|
||||
extends com.ibm.media.codec.audio.AudioCodec
|
||||
{
|
||||
private Format lastFormat = null;
|
||||
private int numberOfInputChannels;
|
||||
private int numberOfOutputChannels = 1;
|
||||
private boolean downmix = false;
|
||||
private int inputSampleSize;
|
||||
private boolean bigEndian = false;
|
||||
|
||||
public JavaEncoder()
|
||||
{
|
||||
supportedInputFormats = new AudioFormat[]
|
||||
{
|
||||
new AudioFormat(
|
||||
AudioFormat.LINEAR,
|
||||
Format.NOT_SPECIFIED,
|
||||
16,
|
||||
1,
|
||||
Format.NOT_SPECIFIED,
|
||||
Format.NOT_SPECIFIED
|
||||
),
|
||||
new AudioFormat(
|
||||
AudioFormat.LINEAR,
|
||||
Format.NOT_SPECIFIED,
|
||||
16,
|
||||
2,
|
||||
Format.NOT_SPECIFIED,
|
||||
Format.NOT_SPECIFIED
|
||||
),
|
||||
new AudioFormat(
|
||||
AudioFormat.LINEAR,
|
||||
Format.NOT_SPECIFIED,
|
||||
8,
|
||||
1,
|
||||
Format.NOT_SPECIFIED,
|
||||
Format.NOT_SPECIFIED
|
||||
),
|
||||
new AudioFormat(
|
||||
AudioFormat.LINEAR,
|
||||
Format.NOT_SPECIFIED,
|
||||
8,
|
||||
2,
|
||||
Format.NOT_SPECIFIED,
|
||||
Format.NOT_SPECIFIED
|
||||
)}; // support 1/2 channels and 8/16 bit samples
|
||||
|
||||
defaultOutputFormats = new AudioFormat[]
|
||||
{
|
||||
new AudioFormat(
|
||||
AudioFormat.ALAW,
|
||||
8000,
|
||||
8,
|
||||
1,
|
||||
Format.NOT_SPECIFIED,
|
||||
Format.NOT_SPECIFIED
|
||||
)};
|
||||
PLUGIN_NAME = "pcm to alaw converter";
|
||||
}
|
||||
|
||||
protected Format[] getMatchingOutputFormats(Format in)
|
||||
{
|
||||
|
||||
AudioFormat inFormat = (AudioFormat) in;
|
||||
int channels = inFormat.getChannels();
|
||||
int sampleRate = (int) (inFormat.getSampleRate());
|
||||
|
||||
if (channels == 2)
|
||||
{
|
||||
supportedOutputFormats = new AudioFormat[]
|
||||
{
|
||||
new AudioFormat(
|
||||
AudioFormat.ALAW,
|
||||
sampleRate,
|
||||
8,
|
||||
2,
|
||||
Format.NOT_SPECIFIED,
|
||||
Format.NOT_SPECIFIED
|
||||
),
|
||||
new AudioFormat(
|
||||
AudioFormat.ALAW,
|
||||
sampleRate,
|
||||
8,
|
||||
1,
|
||||
Format.NOT_SPECIFIED,
|
||||
Format.NOT_SPECIFIED
|
||||
)};
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
supportedOutputFormats = new AudioFormat[]
|
||||
{
|
||||
new AudioFormat(
|
||||
AudioFormat.ALAW,
|
||||
sampleRate,
|
||||
8,
|
||||
1,
|
||||
Format.NOT_SPECIFIED,
|
||||
Format.NOT_SPECIFIED
|
||||
)};
|
||||
|
||||
}
|
||||
|
||||
return supportedOutputFormats;
|
||||
}
|
||||
|
||||
public void open() throws ResourceUnavailableException
|
||||
{}
|
||||
|
||||
public void close()
|
||||
{}
|
||||
|
||||
private int calculateOutputSize(int inputLength)
|
||||
{
|
||||
if (inputSampleSize == 16)
|
||||
{
|
||||
inputLength /= 2;
|
||||
}
|
||||
|
||||
if (downmix)
|
||||
{
|
||||
inputLength /= 2;
|
||||
}
|
||||
|
||||
return inputLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Init the converter to the new format
|
||||
* @param inFormat AudioFormat
|
||||
*/
|
||||
private void initConverter(AudioFormat inFormat)
|
||||
{
|
||||
|
||||
lastFormat = inFormat;
|
||||
numberOfInputChannels = inFormat.getChannels();
|
||||
if (outputFormat != null)
|
||||
{
|
||||
numberOfOutputChannels = outputFormat.getChannels();
|
||||
}
|
||||
inputSampleSize = inFormat.getSampleSizeInBits();
|
||||
|
||||
bigEndian = inFormat.getEndian()==AudioFormat.BIG_ENDIAN;
|
||||
|
||||
if ( (numberOfInputChannels == 2) && (numberOfOutputChannels == 1))
|
||||
{
|
||||
downmix = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
downmix = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes the input buffer passing it to the output one
|
||||
* @param inputBuffer Buffer
|
||||
* @param outputBuffer Buffer
|
||||
* @return int
|
||||
*/
|
||||
public int process(Buffer inputBuffer, Buffer outputBuffer)
|
||||
{
|
||||
if (!checkInputBuffer(inputBuffer))
|
||||
{
|
||||
return BUFFER_PROCESSED_FAILED;
|
||||
}
|
||||
|
||||
if (isEOM(inputBuffer))
|
||||
{
|
||||
propagateEOM(outputBuffer);
|
||||
return BUFFER_PROCESSED_OK;
|
||||
}
|
||||
|
||||
Format newFormat = inputBuffer.getFormat();
|
||||
|
||||
if (lastFormat != newFormat)
|
||||
{
|
||||
initConverter( (AudioFormat) newFormat);
|
||||
}
|
||||
|
||||
int inpLength = inputBuffer.getLength();
|
||||
int outLength = calculateOutputSize(inputBuffer.getLength());
|
||||
|
||||
byte[] inpData = (byte[]) inputBuffer.getData();
|
||||
byte[] outData = validateByteArraySize(outputBuffer, outLength);
|
||||
|
||||
pcm162alaw(
|
||||
inpData, inputBuffer.getOffset(), outData, 0, outData.length, bigEndian);
|
||||
|
||||
updateOutput(outputBuffer, outputFormat, outLength, 0);
|
||||
return BUFFER_PROCESSED_OK;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* This source code is a product of Sun Microsystems, Inc. and is provided
|
||||
* for unrestricted use. Users may copy or modify this source code without
|
||||
* charge.
|
||||
*
|
||||
* linear2alaw() - Convert a 16-bit linear PCM value to 8-bit A-law
|
||||
*
|
||||
* linear2alaw() accepts an 16-bit integer and encodes it as A-law data.
|
||||
*
|
||||
* Linear Input Code Compressed Code
|
||||
* ------------------------ ---------------
|
||||
* 0000000wxyza 000wxyz
|
||||
* 0000001wxyza 001wxyz
|
||||
* 000001wxyzab 010wxyz
|
||||
* 00001wxyzabc 011wxyz
|
||||
* 0001wxyzabcd 100wxyz
|
||||
* 001wxyzabcde 101wxyz
|
||||
* 01wxyzabcdef 110wxyz
|
||||
* 1wxyzabcdefg 111wxyz
|
||||
*
|
||||
* For further information see John C. Bellamy's Digital Telephony, 1982,
|
||||
* John Wiley & Sons, pps 98-111 and 472-476.
|
||||
*/
|
||||
private static final byte QUANT_MASK = 0xf; /* Quantization field mask. */
|
||||
private static final byte SEG_SHIFT = 4;
|
||||
/* Left shift for segment number. */
|
||||
private static final short[] seg_end =
|
||||
{
|
||||
0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF
|
||||
};
|
||||
|
||||
private static byte linear2alaw(short pcm_val)
|
||||
/* 2's complement (16-bit range) */
|
||||
{
|
||||
byte mask;
|
||||
byte seg = 8;
|
||||
byte aval;
|
||||
|
||||
if (pcm_val >= 0)
|
||||
{
|
||||
mask = (byte) 0xD5; /* sign (7th) bit = 1 */
|
||||
}
|
||||
else
|
||||
{
|
||||
mask = 0x55; /* sign bit = 0 */
|
||||
pcm_val = (short) ( -pcm_val - 8);
|
||||
}
|
||||
|
||||
/* Convert the scaled magnitude to segment number. */
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
if (pcm_val <= seg_end[i])
|
||||
{
|
||||
seg = (byte) i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Combine the sign, segment, and quantization bits. */
|
||||
if (seg >= 8) /* out of range, return maximum value. */
|
||||
{
|
||||
return (byte) ( (0x7F ^ mask) & 0xFF);
|
||||
}
|
||||
else
|
||||
{
|
||||
aval = (byte) (seg << SEG_SHIFT);
|
||||
if (seg < 2)
|
||||
{
|
||||
aval |= (pcm_val >> 4) & QUANT_MASK;
|
||||
}
|
||||
else
|
||||
{
|
||||
aval |= (pcm_val >> (seg + 3)) & QUANT_MASK;
|
||||
}
|
||||
return (byte) ( (aval ^ mask) & 0xFF);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the input buffer to the otput one using the alaw codec
|
||||
* @param inBuffer byte[]
|
||||
* @param inByteOffset int
|
||||
* @param outBuffer byte[]
|
||||
* @param outByteOffset int
|
||||
* @param sampleCount int
|
||||
* @param bigEndian boolean
|
||||
*/
|
||||
private static void pcm162alaw(byte[] inBuffer, int inByteOffset,
|
||||
byte[] outBuffer, int outByteOffset,
|
||||
int sampleCount, boolean bigEndian)
|
||||
{
|
||||
int shortIndex = inByteOffset;
|
||||
int alawIndex = outByteOffset;
|
||||
if (bigEndian)
|
||||
{
|
||||
while (sampleCount > 0)
|
||||
{
|
||||
outBuffer[alawIndex++] = linear2alaw
|
||||
(bytesToShort16(inBuffer[shortIndex],
|
||||
inBuffer[shortIndex + 1]));
|
||||
shortIndex++;
|
||||
shortIndex++;
|
||||
sampleCount--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (sampleCount > 0)
|
||||
{
|
||||
outBuffer[alawIndex++] = linear2alaw
|
||||
(bytesToShort16(inBuffer[shortIndex + 1],
|
||||
inBuffer[shortIndex]));
|
||||
shortIndex++;
|
||||
shortIndex++;
|
||||
sampleCount--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the 2 bytes to the corresponding short value
|
||||
* @param highByte byte
|
||||
* @param lowByte byte
|
||||
* @return short
|
||||
*/
|
||||
private static short bytesToShort16(byte highByte, byte lowByte)
|
||||
{
|
||||
return (short) ( (highByte << 8) | (lowByte & 0xFF));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,147 @@
|
||||
/*
|
||||
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*/
|
||||
package net.java.sip.communicator.impl.media.codec.audio.alaw;
|
||||
|
||||
import javax.media.*;
|
||||
import javax.media.format.*;
|
||||
|
||||
import com.ibm.media.codec.audio.*;
|
||||
import net.java.sip.communicator.impl.media.codec.*;
|
||||
|
||||
/**
|
||||
* Packetizer for ALAW codec
|
||||
* @author Damian Minkov
|
||||
*/
|
||||
public class Packetizer
|
||||
extends AudioPacketizer
|
||||
{
|
||||
public Packetizer()
|
||||
{
|
||||
packetSize = 480;
|
||||
supportedInputFormats = new AudioFormat[]
|
||||
{
|
||||
new AudioFormat(
|
||||
AudioFormat.ALAW,
|
||||
Format.NOT_SPECIFIED,
|
||||
8,
|
||||
1,
|
||||
Format.NOT_SPECIFIED,
|
||||
Format.NOT_SPECIFIED,
|
||||
8,
|
||||
Format.NOT_SPECIFIED,
|
||||
Format.byteArray
|
||||
)
|
||||
};
|
||||
defaultOutputFormats = new AudioFormat[]
|
||||
{
|
||||
new AudioFormat(
|
||||
AudioFormat.ALAW,
|
||||
Format.NOT_SPECIFIED,
|
||||
8,
|
||||
1,
|
||||
Format.NOT_SPECIFIED,
|
||||
Format.NOT_SPECIFIED,
|
||||
8,
|
||||
Format.NOT_SPECIFIED,
|
||||
Format.byteArray
|
||||
)
|
||||
};
|
||||
|
||||
PLUGIN_NAME = "Mu-Law Packetizer";
|
||||
|
||||
}
|
||||
|
||||
protected Format[] getMatchingOutputFormats(Format in)
|
||||
{
|
||||
|
||||
AudioFormat af = (AudioFormat) in;
|
||||
|
||||
supportedOutputFormats = new AudioFormat[]
|
||||
{
|
||||
new AudioFormat(
|
||||
Constants.ALAW_RTP,
|
||||
af.getSampleRate(),
|
||||
8,
|
||||
1,
|
||||
Format.NOT_SPECIFIED,
|
||||
Format.NOT_SPECIFIED,
|
||||
8,
|
||||
Format.NOT_SPECIFIED,
|
||||
Format.byteArray
|
||||
)
|
||||
};
|
||||
return supportedOutputFormats;
|
||||
}
|
||||
|
||||
public void open() throws ResourceUnavailableException
|
||||
{
|
||||
setPacketSize(packetSize);
|
||||
reset();
|
||||
}
|
||||
|
||||
public java.lang.Object[] getControls()
|
||||
{
|
||||
if (controls == null)
|
||||
{
|
||||
controls = new Control[1];
|
||||
controls[0] = new PacketSizeAdapter(this, packetSize, true);
|
||||
}
|
||||
return (Object[]) controls;
|
||||
}
|
||||
|
||||
public synchronized void setPacketSize(int newPacketSize)
|
||||
{
|
||||
packetSize = newPacketSize;
|
||||
|
||||
sample_count = packetSize;
|
||||
|
||||
if (history == null)
|
||||
{
|
||||
history = new byte[packetSize];
|
||||
return;
|
||||
}
|
||||
|
||||
if (packetSize > history.length)
|
||||
{
|
||||
byte[] newHistory = new byte[packetSize];
|
||||
System.arraycopy(history, 0, newHistory, 0, historyLength);
|
||||
history = newHistory;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class PacketSizeAdapter
|
||||
extends com.sun.media.controls.PacketSizeAdapter
|
||||
{
|
||||
public PacketSizeAdapter(Codec newOwner, int newPacketSize,
|
||||
boolean newIsSetable)
|
||||
{
|
||||
super(newOwner, newPacketSize, newIsSetable);
|
||||
}
|
||||
|
||||
public int setPacketSize(int numBytes)
|
||||
{
|
||||
|
||||
int numOfPackets = numBytes;
|
||||
|
||||
if (numOfPackets < 10)
|
||||
{
|
||||
numOfPackets = 10;
|
||||
}
|
||||
|
||||
if (numOfPackets > 8000)
|
||||
{
|
||||
numOfPackets = 8000;
|
||||
}
|
||||
packetSize = numOfPackets;
|
||||
|
||||
( (Packetizer) owner).setPacketSize(packetSize);
|
||||
|
||||
return packetSize;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in new issue