- can now make calls using speex. need to improve audio from fp to sip

This commit is contained in:
Richard Alam 2010-07-28 16:04:35 -04:00
parent da00988ce2
commit 0326506df6
12 changed files with 227 additions and 13 deletions

View File

@ -23,6 +23,8 @@ import java.net.DatagramSocket;
import java.net.SocketException;
import org.bigbluebutton.voiceconf.red5.media.transcoder.NellyToPcmTranscoder;
import org.bigbluebutton.voiceconf.red5.media.transcoder.PcmToNellyTranscoder;
import org.bigbluebutton.voiceconf.red5.media.transcoder.RtmpToRtpSpeexTranscoder;
import org.bigbluebutton.voiceconf.red5.media.transcoder.RtpToRtmpSpeexTranscoder;
import org.bigbluebutton.voiceconf.red5.media.transcoder.SpeexToSpeexTranscoder;
import org.bigbluebutton.voiceconf.red5.media.transcoder.Transcoder;
import org.bigbluebutton.voiceconf.sip.SipConnectInfo;
@ -50,17 +52,19 @@ public class CallStream implements StreamObserver {
public void start() {
Transcoder rtmpToRtpTranscoder, rtpToRtmpTranscoder;
System.out.println("Using codec " + sipCodec.getCodecId() + " " + sipCodec.getCodecName());
if (sipCodec.getCodecId() == SpeexCodec.codecId) {
rtmpToRtpTranscoder = new SpeexToSpeexTranscoder(sipCodec);
rtpToRtmpTranscoder = new SpeexToSpeexTranscoder(sipCodec, userListenStream);
System.out.println("Using SPEEX codec " + sipCodec.getCodecId() + " " + sipCodec.getCodecName());
rtmpToRtpTranscoder = new RtmpToRtpSpeexTranscoder(sipCodec);
rtpToRtmpTranscoder = new RtpToRtmpSpeexTranscoder(sipCodec);
} else {
rtmpToRtpTranscoder = new NellyToPcmTranscoder(sipCodec);
rtpToRtmpTranscoder = new PcmToNellyTranscoder(sipCodec);
userListenStream = new SipToFlashAudioStream(scope, rtpToRtmpTranscoder, connInfo.getSocket());
userListenStream.addListenStreamObserver(this);
((PcmToNellyTranscoder)rtpToRtmpTranscoder).addTranscodedAudioDataListener(userListenStream);
}
userListenStream = new SipToFlashAudioStream(scope, rtpToRtmpTranscoder, connInfo.getSocket());
userListenStream.addListenStreamObserver(this);
rtpToRtmpTranscoder.addTranscodedAudioDataListener(userListenStream);
userTalkStream = new FlashToSipAudioStream(rtmpToRtpTranscoder, connInfo.getSocket(), connInfo);
}

View File

@ -68,6 +68,7 @@ public class FlashToSipAudioStream {
if (packet instanceof AudioData) {
byte[] data = SerializeUtils.ByteBufferToByteArray(buf);
System.out.println("Speex header " + data[0] + " packet length " + (data.length -1));
rtpSender.send(data, 1, data.length-1);
}
}

View File

@ -84,9 +84,11 @@ public class RtpStreamReceiver {
while (receivePackets) {
try {
byte[] internalBuffer = new byte[internalBufferLength];
RtpPacket rtpPacket = new RtpPacket(internalBuffer, 0);
RtpPacket rtpPacket = new RtpPacket(internalBuffer, 0);
System.out.println("Waiting for RTP packet [" + rtpPacket.getLength() + "," + rtpPacket.getPayloadLength() + "," + internalBufferLength + "]");
rtpSocket.receive(rtpPacket);
packetReceivedCounter++;
System.out.println("Received RTP packet [" + rtpPacket.getLength() + "," + rtpPacket.getPayloadLength() + "]");
transcoder.transcode(rtpPacket.getPayload());
} catch (IOException e) {
// We get this when the socket closes when the call hangs up.

View File

@ -179,6 +179,13 @@ public class NellyToPcmTranscoder implements Transcoder {
}
}
/**
* Not implemented. Implemented by transcoders for voice conf server to Flash.
*/
public void addTranscodedAudioDataListener(TranscodedAudioDataListener listener) {
log.error("Not implemented.");
}
/**
* Not implemented. Implemented by transcoders for voice conf server to Flash.
*/

View File

@ -0,0 +1,82 @@
/*
* BigBlueButton - http://www.bigbluebutton.org
*
* Copyright (c) 2008-2009 by respective authors (see below). All rights reserved.
*
* BigBlueButton is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation; either version 3 of the License, or (at your option) any later
* version.
*
* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along
* with BigBlueButton; if not, If not, see <http://www.gnu.org/licenses/>.
*
* $Id: $
*/
package org.bigbluebutton.voiceconf.red5.media.transcoder;
import org.bigbluebutton.voiceconf.red5.media.RtpStreamSender;
import org.bigbluebutton.voiceconf.red5.media.StreamException;
import org.red5.app.sip.codecs.Codec;
import org.red5.logging.Red5LoggerFactory;
import org.slf4j.Logger;
public class RtmpToRtpSpeexTranscoder implements Transcoder {
protected static Logger log = Red5LoggerFactory.getLogger(RtmpToRtpSpeexTranscoder.class, "sip");
private Codec audioCodec;
public RtmpToRtpSpeexTranscoder(Codec audioCodec) {
this.audioCodec = audioCodec;
}
public void transcode(byte[] asaoBuffer, int offset, int num,
byte[] transcodedData, int dataOffset, RtpStreamSender rtpSender) {
System.arraycopy(asaoBuffer, offset, transcodedData, dataOffset, num);
try {
rtpSender.sendTranscodedData();
} catch (StreamException e) {
// Swallow this error for now. We don't really want to end the call if sending hiccups.
// Just log it for now. (ralam june 18, 2010)
log.warn("Error while sending transcoded audio packet.");
}
}
/**
* Not implemented. Implemented by transcoders for voice conf server to Flash.
*/
public void addTranscodedAudioDataListener(TranscodedAudioDataListener listener) {
log.error("Not implemented.");
}
/**
* Not implemented. Implemented by transcoders for voice conf server to Flash.
*/
public void transcode(byte[] codedBuffer) {
log.error("Not implemented.");
}
/**
* Not implemented. Implemented by transcoders for voice conf server to Flash.
*/
public int getIncomingEncodedFrameSize() {
log.error("Not implemented.");
return 0;
}
public int getCodecId() {
return audioCodec.getCodecId();
}
public int getOutgoingEncodedFrameSize() {
return audioCodec.getOutgoingEncodedFrameSize();
}
public int getOutgoingPacketization() {
return audioCodec.getOutgoingPacketization();
}
}

View File

@ -0,0 +1,106 @@
/*
* BigBlueButton - http://www.bigbluebutton.org
*
* Copyright (c) 2008-2009 by respective authors (see below). All rights reserved.
*
* BigBlueButton is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation; either version 3 of the License, or (at your option) any later
* version.
*
* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along
* with BigBlueButton; if not, If not, see <http://www.gnu.org/licenses/>.
*
* $Id: $
*/
package org.bigbluebutton.voiceconf.red5.media.transcoder;
import org.apache.mina.core.buffer.IoBuffer;
import org.bigbluebutton.voiceconf.red5.media.RtpStreamSender;
import org.bigbluebutton.voiceconf.red5.media.StreamException;
import org.red5.app.sip.codecs.Codec;
import org.red5.logging.Red5LoggerFactory;
import org.red5.server.net.rtmp.event.AudioData;
import org.slf4j.Logger;
public class RtpToRtmpSpeexTranscoder implements Transcoder {
protected static Logger log = Red5LoggerFactory.getLogger(RtpToRtmpSpeexTranscoder.class, "sip");
private Codec audioCodec;
private TranscodedAudioDataListener listener;
private int timestamp = 0;
private static final int SPEEX_CODEC = 178; /* 1011 1111 (see flv spec) */
private long start = 0;
public RtpToRtmpSpeexTranscoder(Codec audioCodec, TranscodedAudioDataListener listener) {
this.audioCodec = audioCodec;
this.listener = listener;
start = System.currentTimeMillis();
}
public RtpToRtmpSpeexTranscoder(Codec audioCodec) {
this.audioCodec = audioCodec;
}
public void addTranscodedAudioDataListener(TranscodedAudioDataListener listener) {
this.listener = listener;
}
public void transcode(byte[] asaoBuffer, int offset, int num,
byte[] transcodedData, int dataOffset, RtpStreamSender rtpSender) {
System.arraycopy(asaoBuffer, offset, transcodedData, dataOffset, num);
try {
rtpSender.sendTranscodedData();
} catch (StreamException e) {
// Swallow this error for now. We don't really want to end the call if sending hiccups.
// Just log it for now. (ralam june 18, 2010)
log.warn("Error while sending transcoded audio packet.");
}
}
public void transcode(byte[] codedBuffer) {
pushAudio(codedBuffer);
}
private void pushAudio(byte[] audio) {
timestamp = timestamp + audio.length;
IoBuffer buffer = IoBuffer.allocate(1024);
buffer.setAutoExpand(true);
buffer.clear();
buffer.put((byte) SPEEX_CODEC);
byte[] copy = new byte[audio.length];
System.arraycopy(audio, 0, copy, 0, audio.length );
buffer.put(copy);
buffer.flip();
AudioData audioData = new AudioData( buffer );
audioData.setTimestamp((int)(System.currentTimeMillis() - start) );
listener.handleTranscodedAudioData(audioData);
}
public int getCodecId() {
return audioCodec.getCodecId();
}
public int getOutgoingEncodedFrameSize() {
return audioCodec.getOutgoingEncodedFrameSize();
}
public int getOutgoingPacketization() {
return audioCodec.getOutgoingPacketization();
}
public int getIncomingEncodedFrameSize() {
return audioCodec.getIncomingEncodedFrameSize();
}
}

View File

@ -35,10 +35,12 @@ public class SpeexToSpeexTranscoder implements Transcoder {
private int timestamp = 0;
private static final int SPEEX_CODEC = 178; /* 1011 1111 (see flv spec) */
private long start = 0;
public SpeexToSpeexTranscoder(Codec audioCodec, TranscodedAudioDataListener listener) {
this.audioCodec = audioCodec;
this.listener = listener;
start = System.currentTimeMillis();
}
public SpeexToSpeexTranscoder(Codec audioCodec) {
@ -77,7 +79,7 @@ public class SpeexToSpeexTranscoder implements Transcoder {
buffer.flip();
AudioData audioData = new AudioData( buffer );
audioData.setTimestamp((int)timestamp );
audioData.setTimestamp((int)(System.currentTimeMillis() - start) );
listener.handleTranscodedAudioData(audioData);
}
@ -97,4 +99,11 @@ public class SpeexToSpeexTranscoder implements Transcoder {
public int getIncomingEncodedFrameSize() {
return audioCodec.getIncomingEncodedFrameSize();
}
@Override
public void addTranscodedAudioDataListener(
TranscodedAudioDataListener listener) {
// TODO Auto-generated method stub
}
}

View File

@ -24,7 +24,7 @@ import org.bigbluebutton.voiceconf.red5.media.RtpStreamSender;
public interface Transcoder {
void transcode(byte[] asaoBuffer, int offset, int num, byte[] transcodedData, int dataOffset, RtpStreamSender rtpSender);
void transcode(byte[] codedBuffer);
void addTranscodedAudioDataListener(TranscodedAudioDataListener listener);
int getOutgoingEncodedFrameSize();
int getCodecId();

View File

@ -28,6 +28,7 @@ import org.bigbluebutton.voiceconf.red5.CallStreamFactory;
import org.bigbluebutton.voiceconf.red5.ClientConnectionManager;
import org.bigbluebutton.voiceconf.red5.media.CallStream;
import org.bigbluebutton.voiceconf.red5.media.StreamException;
import org.bigbluebutton.voiceconf.util.StackTraceUtil;
import org.red5.app.sip.codecs.Codec;
import org.red5.app.sip.codecs.CodecUtils;
import org.slf4j.Logger;
@ -181,6 +182,7 @@ public class CallAgent extends CallListenerAdapter {
notifyListenersOnCallConnected(callStream.getTalkStreamName(), callStream.getListenStreamName());
} catch (Exception e) {
log.error("Failed to create Call Stream.");
System.out.println(StackTraceUtil.getStackTrace(e));
}
}
}

View File

@ -174,8 +174,8 @@ public class SipPeerProfile {
/** VIC command-line executable */
public String binVIC = "vic";
public String audioCodecsPrecedence = "8;18;0;110;111";
//public String audioCodecsPrecedence = "";
public String audioCodecsPrecedence = "110;8;18;0;111";
//public String audioCodecsPrecedence = "110";
// ************************** Costructors *************************

View File

@ -14,6 +14,7 @@ public class CodecFactory {
private static final int audioCodeciLBC = 111;
private int[] availableAudioCodecsId = {audioCodecPCMU, audioCodecPCMA, audioCodecG729, audioCodecSpeex, audioCodeciLBC};
// private int[] availableAudioCodecsId = {audioCodecSpeex};
private int[] availableVideoCodecsId = {};

View File

@ -11,8 +11,8 @@ import local.media.G711;
public class SpeexCodec implements Codec {
private static final String codecName = "Speex";
private static int defaultEncodedFrameSize = 160;
private static int defaultDecodedFrameSize = 160;
private static int defaultEncodedFrameSize = 320;
private static int defaultDecodedFrameSize = 320;
private static int defaultSampleRate = 16000;
private int outgoingPacketization = 0;
private int incomingPacketization = 0;