Support to fix speex wideband

This commit is contained in:
yuan 2011-02-28 14:46:26 +00:00
parent 4a92404295
commit a86c7e6186
9 changed files with 263 additions and 113 deletions

View File

@ -19,12 +19,7 @@
**/
package org.bigbluebutton.voiceconf.red5.media;
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.net.DatagramSocket;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import org.apache.mina.core.buffer.IoBuffer;
import org.bigbluebutton.voiceconf.red5.media.transcoder.FlashToSipTranscoder;
import org.bigbluebutton.voiceconf.red5.media.transcoder.TranscodedAudioDataListener;
@ -41,12 +36,7 @@ import org.slf4j.Logger;
public class FlashToSipAudioStream {
private final static Logger log = Red5LoggerFactory.getLogger(FlashToSipAudioStream.class, "sip");
private final PipedOutputStream streamFromFlash;
private PipedInputStream streamToSip;
private final Executor exec = Executors.newSingleThreadExecutor();
private Runnable audioDataProcessor;
private volatile boolean processAudioData = false;
private final FlashToSipTranscoder transcoder;
private IStreamListener mInputListener;
@ -54,24 +44,23 @@ public class FlashToSipAudioStream {
private final SipConnectInfo connInfo;
private String talkStreamName;
private RtpStreamSender rtpSender;
private TranscodedAudioListener transcodedAudioListener;
private volatile boolean processAudioData = false;
public FlashToSipAudioStream(final FlashToSipTranscoder transcoder, DatagramSocket srcSocket, SipConnectInfo connInfo) {
this.transcoder = transcoder;
this.srcSocket = srcSocket;
this.connInfo = connInfo;
talkStreamName = "microphone_" + System.currentTimeMillis();
streamFromFlash = new PipedOutputStream();
try {
streamToSip = new PipedInputStream(streamFromFlash);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
transcodedAudioListener = new TranscodedAudioListener();
transcoder.setTranscodedAudioListener(transcodedAudioListener);
transcoder.setProcessAudioData(processAudioData);
}
public void start(IBroadcastStream broadcastStream, IScope scope) throws StreamException {
log.debug("startTranscodingStream({},{})", broadcastStream.getPublishedName(), scope.getName());
processAudioData = true;
transcoder.setProcessAudioData(processAudioData);
mInputListener = new IStreamListener() {
public void packetReceived(IBroadcastStream broadcastStream, IStreamPacket packet) {
IoBuffer buf = packet.getData();
@ -85,12 +74,8 @@ public class FlashToSipAudioStream {
if (packet instanceof AudioData) {
byte[] data = SerializeUtils.ByteBufferToByteArray(buf);
try {
streamFromFlash.write(data, 1, data.length-1);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (data.length > 20) //==Don't send silence data whose data length is 11
transcoder.handlePacket(data, 1, data.length-1);
}
}
};
@ -99,39 +84,9 @@ public class FlashToSipAudioStream {
rtpSender = new RtpStreamSender(srcSocket, connInfo);
rtpSender.connect();
processAudioData = true;
audioDataProcessor = new Runnable() {
public void run() {
processAudioData();
}
};
exec.execute(audioDataProcessor);
}
private void processAudioData() {
int len = 64;
byte[] nellyAudio = new byte[len];
int remaining = len;
int offset = 0;
TranscodedAudioListener transcodedAudioListener = new TranscodedAudioListener();
while (processAudioData) {
try {
int bytesRead = streamToSip.read(nellyAudio, offset, remaining);
remaining -= bytesRead;
if (remaining == 0) {
remaining = len;
offset = 0;
transcoder.transcode(nellyAudio, 0, nellyAudio.length, transcodedAudioListener);
} else {
offset += bytesRead;
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void stop(IBroadcastStream broadcastStream, IScope scope) {
broadcastStream.removeStreamListener(mInputListener);
if (broadcastStream != null) {
@ -139,6 +94,7 @@ public class FlashToSipAudioStream {
broadcastStream.close();
}
processAudioData = false;
transcoder.setProcessAudioData(processAudioData);
srcSocket.close();
}
@ -146,7 +102,7 @@ public class FlashToSipAudioStream {
return talkStreamName;
}
private class TranscodedAudioListener implements TranscodedAudioDataListener {
public class TranscodedAudioListener implements TranscodedAudioDataListener {
@Override
public void handleTranscodedAudioData(byte[] audioData, long timestamp) {
if (audioData != null && processAudioData) {

View File

@ -60,12 +60,7 @@ public class RtpStreamReceiver {
}
private void initializeSocket() {
/* try {
rtpSocket.getDatagramSocket().setSoTimeout(SO_TIMEOUT);
} catch (SocketException e1) {
log.warn("SocketException while setting socket block time.");
}
*/ }
}
public void start() {
receivePackets = true;
@ -91,9 +86,6 @@ public class RtpStreamReceiver {
try {
rtpSocket.receive(rtpPacket);
packetReceivedCounter++;
// log.debug("Received packet [" + rtpPacket.getRtcpPayloadType() + "," + rtpPacket.getPayloadType() + ", length=" + rtpPacket.getPayloadLength() + "] seqNum[rtpSeqNum=" + rtpPacket.getSeqNum() + ",lastSeqNum=" + lastSequenceNumber
// + "][rtpTS=" + rtpPacket.getTimestamp() + ",lastTS=" + lastPacketTimestamp + "][port=" + rtpSocket.getDatagramSocket().getLocalPort() + "]");
if (shouldDropDelayedPacket(rtpPacket)) {
continue;
}
@ -107,11 +99,9 @@ public class RtpStreamReceiver {
+ "][rtpTS=" + rtpPacket.getTimestamp() + ",lastTS=" + lastPacketTimestamp + "][port=" + rtpSocket.getDatagramSocket().getLocalPort() + "]");
} else {
if (shouldHandlePacket(rtpPacket)) {
// log.debug("Handling packet [" + rtpPacket.getRtcpPayloadType() + "," + rtpPacket.getPayloadType() + ", length=" + rtpPacket.getPayloadLength() + "] seqNum[rtpSeqNum=" + rtpPacket.getSeqNum() + ",lastSeqNum=" + lastSequenceNumber
// + "][rtpTS=" + rtpPacket.getTimestamp() + ",lastTS=" + lastPacketTimestamp + "][port=" + rtpSocket.getDatagramSocket().getLocalPort() + "]");
lastSequenceNumber = rtpPacket.getSeqNum();
lastPacketTimestamp = rtpPacket.getTimestamp();
processRtpPacket(internalBuffer, RTP_HEADER_SIZE, payloadLength);
processRtpPacket(internalBuffer, RTP_HEADER_SIZE, rtpPacket.getPayloadLength());
} else {
if (log.isDebugEnabled())
log.debug("Corrupt packet [" + rtpPacket.getRtcpPayloadType() + "," + rtpPacket.getPayloadType() + ", length=" + rtpPacket.getPayloadLength() + "] seqNum[rtpSeqNum=" + rtpPacket.getSeqNum() + ",lastSeqNum=" + lastSequenceNumber

View File

@ -19,12 +19,7 @@
**/
package org.bigbluebutton.voiceconf.red5.media;
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.net.DatagramSocket;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import org.apache.mina.core.buffer.IoBuffer;
import org.bigbluebutton.voiceconf.red5.media.transcoder.SipToFlashTranscoder;
import org.bigbluebutton.voiceconf.red5.media.transcoder.TranscodedAudioDataListener;
@ -38,15 +33,11 @@ import org.red5.server.stream.BroadcastScope;
import org.red5.server.stream.IBroadcastScope;
import org.red5.server.stream.IProviderService;
import org.slf4j.Logger;
public class SipToFlashAudioStream implements TranscodedAudioDataListener, RtpStreamReceiverListener {
final private Logger log = Red5LoggerFactory.getLogger(SipToFlashAudioStream.class, "sip");
private final PipedOutputStream streamFromSip;
private PipedInputStream streamToFlash;
private final Executor exec = Executors.newSingleThreadExecutor();
private Runnable audioDataProcessor;
// private Runnable audioDataProcessor;
private volatile boolean processAudioData = false;
private AudioBroadcastStream audioBroadcastStream;
@ -72,23 +63,26 @@ public class SipToFlashAudioStream implements TranscodedAudioDataListener, RtpSt
};
public SipToFlashAudioStream(IScope scope, SipToFlashTranscoder transcoder, DatagramSocket socket) {
processAudioData = true;
transcoder.setProcessAudioData(processAudioData);
this.scope = scope;
this.transcoder = transcoder;
rtpStreamReceiver = new RtpStreamReceiver(socket, transcoder.getIncomingEncodedFrameSize());
rtpStreamReceiver.setRtpStreamReceiverListener(this);
listenStreamName = "speaker_" + System.currentTimeMillis();
scope.setName(listenStreamName);
streamFromSip = new PipedOutputStream();
try {
streamToFlash = new PipedInputStream(streamFromSip);
// streamFromSip = new PipedOutputStream();
// try {
// streamToFlash = new PipedInputStream(streamFromSip);
startNow();
mBuffer = IoBuffer.allocate(1024);
mBuffer = mBuffer.setAutoExpand(true);
audioData = new AudioData();
} catch (IOException e) {
// } catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// e.printStackTrace();
// }
transcoder.setTranscodedAudioListener(this); //
}
public String getStreamName() {
@ -102,6 +96,7 @@ public class SipToFlashAudioStream implements TranscodedAudioDataListener, RtpSt
public void stop() {
log.debug("Stopping stream for {}", listenStreamName);
processAudioData = false;
transcoder.setProcessAudioData(processAudioData);
rtpStreamReceiver.stop();
log.debug("Stopped RTP Stream Receiver for {}", listenStreamName);
if (audioBroadcastStream != null) {
@ -137,18 +132,19 @@ public class SipToFlashAudioStream implements TranscodedAudioDataListener, RtpSt
audioBroadcastStream.start();
processAudioData = true;
transcoder.setProcessAudioData(processAudioData);
audioDataProcessor = new Runnable() {
/* audioDataProcessor = new Runnable() {
public void run() {
processAudioData();
}
};
exec.execute(audioDataProcessor);
*/
rtpStreamReceiver.start();
}
private void processAudioData() {
/* private void processAudioData() {
int len = 160;
byte[] pcmAudio = new byte[len];
int remaining = len;
@ -171,7 +167,7 @@ public class SipToFlashAudioStream implements TranscodedAudioDataListener, RtpSt
}
}
}
*/
@Override
public void onStoppedReceiving() {
if (observer != null) observer.onStreamStopped();
@ -179,12 +175,7 @@ public class SipToFlashAudioStream implements TranscodedAudioDataListener, RtpSt
@Override
public void onAudioDataReceived(byte[] audioData, int offset, int len) {
try {
streamFromSip.write(audioData, offset, len);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
transcoder.handleData(audioData, offset, len);
}
@Override

View File

@ -19,9 +19,13 @@
**/
package org.bigbluebutton.voiceconf.red5.media.transcoder;
public interface FlashToSipTranscoder {
void transcode(byte[] audioData, int startOffset, int length, TranscodedAudioDataListener listener);
import org.bigbluebutton.voiceconf.red5.media.FlashToSipAudioStream.TranscodedAudioListener;
public interface FlashToSipTranscoder {
void transcode(byte[] audioData, int startOffset, int length);
void handlePacket(byte[] data, int begin, int end);
int getOutgoingEncodedFrameSize();
int getCodecId();
void setTranscodedAudioListener(TranscodedAudioListener transcodedAudioListener);
void setProcessAudioData(boolean isProcessing);
}

View File

@ -19,10 +19,16 @@
**/
package org.bigbluebutton.voiceconf.red5.media.transcoder;
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.nio.FloatBuffer;
import java.util.Random;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import org.slf4j.Logger;
import org.bigbluebutton.voiceconf.red5.media.FlashToSipAudioStream.TranscodedAudioListener;
import org.red5.logging.Red5LoggerFactory;
import org.red5.app.sip.codecs.Codec;
import org.red5.app.sip.codecs.asao.Decoder;
@ -65,6 +71,14 @@ public class NellyFlashToSipTranscoderImp implements FlashToSipTranscoder {
private long timestamp = 0;
private final static int TS_INCREMENT = 180; // Determined from PCAP traces.
private final PipedOutputStream streamFromFlash;
private PipedInputStream streamToSip;
private final Executor exec = Executors.newSingleThreadExecutor();
private Runnable audioDataProcessor;
private boolean processAudioData = false;
private TranscodedAudioListener transcodedAudioListener;
/**
* The transcode process works by taking a 64-byte-array Nelly audio and converting it into a 256-float-array L16 audio. From the
* 256-float-array L16 audio, we take 160-float-array and convert it to a 160-byte-array Ulaw audio. The remaining 96-float-array
@ -79,6 +93,22 @@ public class NellyFlashToSipTranscoderImp implements FlashToSipTranscoder {
Random rgen = new Random();
timestamp = rgen.nextInt(1000);
viewBuffer = l16Audio.asReadOnlyBuffer();
streamFromFlash = new PipedOutputStream();
try {
streamToSip = new PipedInputStream(streamFromFlash);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
processAudioData = true;
audioDataProcessor = new Runnable() {
public void run() {
processAudioData();
}
};
exec.execute(audioDataProcessor);
}
@Override
@ -91,8 +121,42 @@ public class NellyFlashToSipTranscoderImp implements FlashToSipTranscoder {
return sipCodec.getCodecId();
}
@Override
public void handlePacket(byte[] data, int begin, int end) {
try {
streamFromFlash.write(data, begin, end);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void processAudioData() {
int len = 64;
byte[] nellyAudio = new byte[len];
int remaining = len;
int offset = 0;
while (processAudioData) {
try {
int bytesRead = streamToSip.read(nellyAudio, offset, remaining);
remaining -= bytesRead;
if (remaining == 0) {
remaining = len;
offset = 0;
transcode(nellyAudio, 0, nellyAudio.length);
} else {
offset += bytesRead;
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
@Override
public void transcode(byte[] audioData, int startOffset, int length, TranscodedAudioDataListener listener) {
public void transcode(byte[] audioData, int startOffset, int length) {
if (audioData.length != NELLY_AUDIO_LENGTH) {
log.warn("Receiving bad nelly audio. Expecting {}, got {}.", NELLY_AUDIO_LENGTH, audioData.length);
return;
@ -111,7 +175,7 @@ public class NellyFlashToSipTranscoderImp implements FlashToSipTranscoder {
int encodedBytes = sipCodec.pcmToCodec(tempUlawBuffer, ulawEncodedBuffer);
// Send it to the server
listener.handleTranscodedAudioData(ulawEncodedBuffer, timestamp += TS_INCREMENT);
transcodedAudioListener.handleTranscodedAudioData(ulawEncodedBuffer, timestamp += TS_INCREMENT);
if (l16Audio.position() == l16Audio.capacity()) {
/**
@ -125,7 +189,7 @@ public class NellyFlashToSipTranscoderImp implements FlashToSipTranscoder {
viewBuffer.get(tempUlawBuffer);
encodedBytes = sipCodec.pcmToCodec(tempUlawBuffer, ulawEncodedBuffer);
if (encodedBytes == sipCodec.getOutgoingEncodedFrameSize()) {
listener.handleTranscodedAudioData(ulawEncodedBuffer, timestamp += TS_INCREMENT);
transcodedAudioListener.handleTranscodedAudioData(ulawEncodedBuffer, timestamp += TS_INCREMENT);
} else {
log.error("Failure encoding buffer." );
}
@ -134,7 +198,7 @@ public class NellyFlashToSipTranscoderImp implements FlashToSipTranscoder {
viewBuffer.get(tempUlawBuffer);
encodedBytes = sipCodec.pcmToCodec(tempUlawBuffer, ulawEncodedBuffer);
if (encodedBytes == sipCodec.getOutgoingEncodedFrameSize()) {
listener.handleTranscodedAudioData(ulawEncodedBuffer, timestamp += TS_INCREMENT);
transcodedAudioListener.handleTranscodedAudioData(ulawEncodedBuffer, timestamp += TS_INCREMENT);
} else {
log.error("Failure encoding buffer." );
}
@ -143,7 +207,7 @@ public class NellyFlashToSipTranscoderImp implements FlashToSipTranscoder {
viewBuffer.get(tempUlawBuffer);
encodedBytes = sipCodec.pcmToCodec(tempUlawBuffer, ulawEncodedBuffer);
if (encodedBytes == sipCodec.getOutgoingEncodedFrameSize()) {
listener.handleTranscodedAudioData(ulawEncodedBuffer, timestamp += TS_INCREMENT);
transcodedAudioListener.handleTranscodedAudioData(ulawEncodedBuffer, timestamp += TS_INCREMENT);
} else {
log.error("Failure encoding buffer." );
}
@ -153,4 +217,13 @@ public class NellyFlashToSipTranscoderImp implements FlashToSipTranscoder {
viewBuffer.clear();
}
}
public void setTranscodedAudioListener(TranscodedAudioListener transcodedAudioListener) {
this.transcodedAudioListener = transcodedAudioListener;
}
@Override
public void setProcessAudioData(boolean isProcessing){
processAudioData = isProcessing;
}
}

View File

@ -19,9 +19,16 @@
**/
package org.bigbluebutton.voiceconf.red5.media.transcoder;
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.nio.FloatBuffer;
import java.util.Random;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import org.slf4j.Logger;
import org.bigbluebutton.voiceconf.red5.media.SipToFlashAudioStream;
import org.red5.logging.Red5LoggerFactory;
import org.red5.server.api.IConnection;
import org.red5.server.api.Red5;
@ -70,6 +77,16 @@ public class NellySipToFlashTranscoderImp implements SipToFlashTranscoder {
private long timestamp = 0;
private final static int TS_INCREMENT = 32; // Determined from PCAP traces.
private final PipedOutputStream streamFromSip;
private PipedInputStream streamToFlash;
// private NellySipToFlashTranscoderImp transcoder;
private TranscodedAudioDataListener transcodedAudioListener;
private boolean processAudioData;
private final Executor exec = Executors.newSingleThreadExecutor();
private Runnable audioDataProcessor;
/**
* The transcode takes a 160-byte Ulaw audio and converts it to a 160-float L16 audio. Whenever there is an
* available 256-float L16 audio, that gets converted into a 64-byte Nelly audio. Therefore, 8 Ulaw packets
@ -82,17 +99,24 @@ public class NellySipToFlashTranscoderImp implements SipToFlashTranscoder {
Random rgen = new Random();
timestamp = rgen.nextInt(1000);
viewBuffer = l16Audio.asReadOnlyBuffer();
streamFromSip = new PipedOutputStream();
try {
streamToFlash = new PipedInputStream(streamFromSip);
} catch (IOException e) {
e.printStackTrace();
}
startNow();
}
@Override
public void transcode(byte[] audioData, TranscodedAudioDataListener listener) {
public void transcode(byte[] audioData) {
if (audioData.length != ULAW_AUDIO_LENGTH) {
log.warn("Received corrupt audio. Got {}, expected {}.", audioData.length, ULAW_AUDIO_LENGTH);
return;
}
// Convert Ulaw to L16
int decodedBytes = audioCodec.codecToPcm(audioData, tempL16Buffer);
audioCodec.codecToPcm(audioData, tempL16Buffer);
// Store into the buffer
l16Audio.put(tempL16Buffer);
@ -118,7 +142,7 @@ public class NellySipToFlashTranscoderImp implements SipToFlashTranscoder {
}
}
if (sendPacket) listener.handleTranscodedAudioData(nellyBytes, timestamp += TS_INCREMENT);
if (sendPacket) transcodedAudioListener.handleTranscodedAudioData(nellyBytes, timestamp += TS_INCREMENT);
}
if (l16Audio.position() == l16Audio.capacity()) {
@ -137,5 +161,64 @@ public class NellySipToFlashTranscoderImp implements SipToFlashTranscoder {
public int getCodecId() {
return NELLYMOSER_CODEC_ID;
}
@Override
public void handleData(byte[] audioData, int offset, int len) {
try {
streamFromSip.write(audioData, offset, len);
} catch (IOException e) {
e.printStackTrace();
}
}
private void startNow() {
audioDataProcessor = new Runnable() {
public void run() {
processAudioData();
}
};
exec.execute(audioDataProcessor);
}
private void processAudioData() {
int len = 160;
byte[] pcmAudio = new byte[len];
int remaining = len;
int offset = 0;
while (processAudioData) {
try {
int bytesRead = streamToFlash.read(pcmAudio, offset, remaining);
remaining -= bytesRead;
if (remaining == 0) {
remaining = len;
offset = 0;
transcode(pcmAudio);
} else {
offset += bytesRead;
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Override
public void setProcessAudioData(boolean isProcessing){
processAudioData = isProcessing;
}
@Override
public void setTranscodedAudioListener(
SipToFlashAudioStream sipToFlashAudioStream) {
this.transcodedAudioListener = sipToFlashAudioStream;
}
}

View File

@ -19,8 +19,14 @@
**/
package org.bigbluebutton.voiceconf.red5.media.transcoder;
import org.bigbluebutton.voiceconf.red5.media.SipToFlashAudioStream;
public interface SipToFlashTranscoder {
void transcode(byte[] audioData, TranscodedAudioDataListener listener);
void transcode(byte[] audioData);
int getCodecId();
int getIncomingEncodedFrameSize();
void handleData(byte[] audioData, int offset, int len);
void setTranscodedAudioListener(SipToFlashAudioStream sipToFlashAudioStream);
void setProcessAudioData(boolean isProcessing);
}

View File

@ -20,6 +20,8 @@
package org.bigbluebutton.voiceconf.red5.media.transcoder;
import java.util.Random;
import org.bigbluebutton.voiceconf.red5.media.FlashToSipAudioStream.TranscodedAudioListener;
import org.red5.app.sip.codecs.Codec;
import org.red5.logging.Red5LoggerFactory;
import org.slf4j.Logger;
@ -30,17 +32,19 @@ public class SpeexFlashToSipTranscoderImp implements FlashToSipTranscoder {
private Codec audioCodec;
private long timestamp = 0;
private final static int TS_INCREMENT = 320; // Determined from PCAP traces.
private TranscodedAudioListener transcodedAudioListener;
public SpeexFlashToSipTranscoderImp(Codec audioCodec) {
this.audioCodec = audioCodec;
Random rgen = new Random();
timestamp = rgen.nextInt(1000);
System.out.println("Speex start!");
}
public void transcode(byte[] audioData, int startOffset, int length, TranscodedAudioDataListener listener) {
public void transcode(byte[] audioData, int startOffset, int length) {
byte[] transcodedAudio = new byte[length];
System.arraycopy(audioData, startOffset, transcodedAudio, 0, length);
listener.handleTranscodedAudioData(transcodedAudio, timestamp += TS_INCREMENT);
transcodedAudioListener.handleTranscodedAudioData(transcodedAudio, timestamp += TS_INCREMENT);
}
public int getCodecId() {
@ -54,4 +58,23 @@ public class SpeexFlashToSipTranscoderImp implements FlashToSipTranscoder {
public int getOutgoingPacketization() {
return audioCodec.getOutgoingPacketization();
}
@Override
public void handlePacket(byte[] data, int begin, int end) {
transcode(data, begin, end);
}
@Override
public void setTranscodedAudioListener(
TranscodedAudioListener transcodedAudioListener) {
this.transcodedAudioListener = transcodedAudioListener;
}
@Override
public void setProcessAudioData(boolean isProcessing) {
// TODO do nothing here;
}
}

View File

@ -20,6 +20,8 @@
package org.bigbluebutton.voiceconf.red5.media.transcoder;
import java.util.Random;
import org.bigbluebutton.voiceconf.red5.media.SipToFlashAudioStream;
import org.red5.app.sip.codecs.Codec;
import org.red5.logging.Red5LoggerFactory;
import org.slf4j.Logger;
@ -31,7 +33,8 @@ public class SpeexSipToFlashTranscoderImp implements SipToFlashTranscoder {
private Codec audioCodec = null;
private long timestamp = 0;
private static final int TS_INCREMENT = 20; // Determined from PCAP traces.
private TranscodedAudioDataListener transcodedAudioListener;
public SpeexSipToFlashTranscoderImp(Codec codec) {
this.audioCodec = codec;
Random rgen = new Random();
@ -39,9 +42,10 @@ public class SpeexSipToFlashTranscoderImp implements SipToFlashTranscoder {
}
@Override
public void transcode(byte[] audioData, TranscodedAudioDataListener listener) {
public void transcode(byte[] audioData ) {
byte[] codedBuffer = audioData;
listener.handleTranscodedAudioData(codedBuffer, timestamp += TS_INCREMENT);
// System.out.println("Speex transcode:"+audioData.length);
transcodedAudioListener.handleTranscodedAudioData(codedBuffer, timestamp += TS_INCREMENT);
}
@Override
@ -54,5 +58,25 @@ public class SpeexSipToFlashTranscoderImp implements SipToFlashTranscoder {
return audioCodec.getIncomingEncodedFrameSize();
}
@Override
public void handleData(byte[] audioData, int offset, int len) {
byte[] data = new byte[len];
System.arraycopy(audioData, offset, data, 0, len);
transcode(data);
}
@Override
public void setTranscodedAudioListener(
SipToFlashAudioStream sipToFlashAudioStream) {
this.transcodedAudioListener = sipToFlashAudioStream;
}
@Override
public void setProcessAudioData(boolean isProcessing) {
}
}