- checkpoint: works with echo test

git-svn-id: http://bigbluebutton.googlecode.com/svn/trunk@3017 af16638f-c34d-0410-8cfa-b39d5352b314
This commit is contained in:
Richard Alam 2009-11-19 21:37:47 +00:00
parent 74a1bb5789
commit ef3385374a
13 changed files with 148 additions and 69 deletions

View File

@ -53,8 +53,20 @@ dependencies {
war.doLast {
ant.unzip(src: war.archivePath, dest: "$buildDir/sip")
ant.copy(file: "$buildDir/sip/WEB-INF/logback-sip.xml", todir: "$buildDir/sip/WEB-INF/classes")
}
task deploy() {
def red5AppsDir = '/usr/share/red5/webapps'
def sipDir = new File("${red5AppsDir}/sip")
println "Deleting $sipDir"
ant.delete(dir: sipDir)
ant.mkdir(dir: sipDir)
ant.copy(todir: sipDir) {
fileset(dir: "$buildDir/sip")
}
}
/*
task deploy(type:Copy) {
def red5AppsDir = '/usr/share/red5/webapps'
def sipDir = new File("${red5AppsDir}/sip")
@ -62,4 +74,5 @@ task deploy(type:Copy) {
ant.delete(dir: sipDir)
into(sipDir)
from "$buildDir/sip"
}
}
*/

View File

@ -30,7 +30,6 @@ import org.red5.server.api.event.IEvent;
import org.red5.server.api.stream.IBroadcastStream;
import org.red5.server.api.stream.IStreamCodecInfo;
import org.red5.server.api.stream.IStreamListener;
import org.red5.server.api.stream.IVideoStreamCodec;
import org.red5.server.api.stream.ResourceExistException;
import org.red5.server.api.stream.ResourceNotFoundException;
import org.red5.server.messaging.IMessageComponent;

View File

@ -29,7 +29,7 @@ public class CallStream {
NellyToPcmTranscoder2 pTranscoder = new NellyToPcmTranscoder2(sipCodec);
rtpSender = new RtpSender2(pTranscoder, socket, connInfo.getRemoteAddr(), connInfo.getRemotePort());
printLog( "SIPAudioLauncher", "New audio receiver on " + connInfo.getLocalPort() + "." );
rtpSender.start();
talkStream = new TalkStream(pTranscoder, rtpSender);
listenStream = new ListenStream(scopeProvider.getScope());

View File

@ -12,29 +12,16 @@ public class NellyToPcmTranscoder2 {
private static final int NELLYMOSER_DECODED_PACKET_SIZE = 256;
private static final int NELLYMOSER_ENCODED_PACKET_SIZE = 64;
/** Sip codec to be used on audio session */
private Codec sipCodec = null;
private Codec sipCodec = null; // Sip codec to be used on audio session
private Decoder decoder;
private DecoderMap decoderMap;
// Temporary buffer with received PCM audio from FlashPlayer.
float[] tempBuffer;
// Floats remaining on temporary buffer.
int tempBufferRemaining = 0;
// Encoding buffer used to encode to final codec format;
float[] encodingBuffer;
// Offset of encoding buffer.
int encodingOffset = 0;
// Indicates whether the current asao buffer was processed.
boolean asao_buffer_processed = false;
// Indicates whether the handling buffers have already
// been initialized.
boolean hasInitilializedBuffers = false;
private DecoderMap decoderMap;
float[] tempBuffer; // Temporary buffer with received PCM audio from FlashPlayer.
int tempBufferRemaining = 0; // Floats remaining on temporary buffer.
float[] encodingBuffer; // Encoding buffer used to encode to final codec format;
int encodingOffset = 0; // Offset of encoding buffer.
boolean asao_buffer_processed = false; // Indicates whether the current asao buffer was processed.
boolean hasInitilializedBuffers = false; // Indicates whether the handling buffers have already been initialized.
public NellyToPcmTranscoder2(Codec sipCodec) {
this.sipCodec = sipCodec;
@ -63,7 +50,8 @@ public class NellyToPcmTranscoder2 {
if ((tempBufferRemaining + encodingOffset) >= sipCodec.getOutgoingDecodedFrameSize()) {
copyingSize = encodingBuffer.length - encodingOffset;
System.arraycopy(tempBuffer, tempBuffer.length-tempBufferRemaining, encodingBuffer, encodingOffset, copyingSize);
System.arraycopy(tempBuffer, tempBuffer.length-tempBufferRemaining,
encodingBuffer, encodingOffset, copyingSize);
encodingOffset = sipCodec.getOutgoingDecodedFrameSize();
tempBufferRemaining -= copyingSize;
@ -71,9 +59,9 @@ public class NellyToPcmTranscoder2 {
}
else {
if (tempBufferRemaining > 0) {
BufferUtils.floatBufferIndexedCopy(encodingBuffer, encodingOffset, tempBuffer,
tempBuffer.length - tempBufferRemaining, tempBufferRemaining );
System.arraycopy(tempBuffer, tempBuffer.length - tempBufferRemaining,
encodingBuffer, encodingOffset, tempBufferRemaining);
encodingOffset += tempBufferRemaining;
finalCopySize += tempBufferRemaining;
tempBufferRemaining = 0;
@ -87,9 +75,6 @@ public class NellyToPcmTranscoder2 {
//tempBuffer = ResampleUtils.normalize(tempBuffer, 256); // normalise volume
tempBufferRemaining = tempBuffer.length;
//println( "fillRtpPacketBuffer",
// "Decoded pcm " + tempBuffer.length + " floats." );
if ( tempBuffer.length <= 0 ) {
log.error("Asao decoder Error." );
}
@ -102,8 +87,7 @@ public class NellyToPcmTranscoder2 {
copyingSize = tempBufferRemaining;
}
BufferUtils.floatBufferIndexedCopy(encodingBuffer, encodingOffset, tempBuffer,
0, copyingSize );
System.arraycopy(tempBuffer, 0, encodingBuffer, encodingOffset, copyingSize);
encodingOffset += copyingSize;
tempBufferRemaining -= copyingSize;
@ -115,7 +99,7 @@ public class NellyToPcmTranscoder2 {
int encodedBytes = sipCodec.pcmToCodec( encodingBuffer, codedBuffer );
if ( encodedBytes == sipCodec.getOutgoingEncodedFrameSize() ) {
BufferUtils.byteBufferIndexedCopy(transcodedData, dataOffset, codedBuffer, 0, codedBuffer.length );
System.arraycopy(codedBuffer, 0, transcodedData, dataOffset, codedBuffer.length);
}
else {
//println( "fillRtpPacketBuffer", "Failure encoding buffer." );
@ -149,6 +133,7 @@ public class NellyToPcmTranscoder2 {
}
if ( encodingOffset == sipCodec.getOutgoingDecodedFrameSize() ) {
System.out.println("Send this audio to asterisk.");
rtpSender.sendTranscodedData();
encodingOffset = 0;
}

View File

@ -0,0 +1,15 @@
package org.red5.app.sip;
class RtmpAudioData {
private final byte[] audioData;
RtmpAudioData(byte[] data) {
this.audioData = new byte[data.length];
System.arraycopy(data, 0, this.audioData, 0, data.length);
}
byte[] getData() {
return audioData;
}
}

View File

@ -35,7 +35,7 @@ public class RtpReceiver2 {
rtpSocket = new RtpSocket(socket);
}
initializeSocket();
// initializeSocket();
}
private void initializeSocket() {
@ -85,9 +85,10 @@ public class RtpReceiver2 {
+ ", length = " + payloadLength + "." );
System.arraycopy(packetBuffer, headerOffset, codedBuffer, 0, payloadLength);
transcoder.transcode(codedBuffer);
} catch (IOException e) {
transcoder.transcode(codedBuffer);
} catch (IOException e) {
log.error("IOException while receiving rtp packets.");
receivePackets = false;
}
}

View File

@ -154,6 +154,7 @@ public class RtpSender {
rtpPacket.setSequenceNumber( seqn++ );
rtpPacket.setTimestamp( time );
rtpPacket.setPayloadLength( transcoder.getOutgoingEncodedFrameSize() );
rtpSocketSend( rtpPacket );
}

View File

@ -3,15 +3,26 @@ package org.red5.app.sip;
import local.net.RtpPacket;
import local.net.RtpSocket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import org.slf4j.Logger;
import org.red5.logging.Red5LoggerFactory;
public class RtpSender2 {
protected static Logger log = Red5LoggerFactory.getLogger( RtpSender2.class, "sip" );
private static Logger log = Red5LoggerFactory.getLogger( RtpSender2.class, "sip" );
public static int RTP_HEADER_SIZE = 12;
private BlockingQueue<RtmpAudioData> packets = new LinkedBlockingQueue<RtmpAudioData>();
private final Executor exec = Executors.newSingleThreadExecutor();
private Runnable audioProcessor;
private volatile boolean processAudio = false;
private static final int RTP_HEADER_SIZE = 12;
private RtpSocket rtpSocket = null;
private boolean socketIsLocal = false;
@ -23,7 +34,7 @@ public class RtpSender2 {
private long timestamp = 0;
private NellyToPcmTranscoder2 transcoder;
public RtpSender2(NellyToPcmTranscoder2 transcoder, DatagramSocket srcSocket, String destAddr, int destPort) {
public RtpSender2(NellyToPcmTranscoder2 transcoder, DatagramSocket srcSocket, String destAddr, int destPort) throws UnknownHostException {
this.transcoder = transcoder;
if (srcSocket == null) {
try {
@ -34,6 +45,8 @@ public class RtpSender2 {
}
socketIsLocal = true;
}
rtpSocket = new RtpSocket(srcSocket, InetAddress.getByName(destAddr), destPort);
}
public void start() {
@ -113,13 +126,17 @@ public class RtpSender2 {
}
public void send(byte[] asaoBuffer, int offset, int num) {
System.out.println("Transcoding from Nelly to PCM");
transcoder.transcode(asaoBuffer, offset, num, packetBuffer, RTP_HEADER_SIZE, this);
}
public void sendTranscodedData() {
rtpPacket.setSequenceNumber( sequenceNum++ );
timestamp += transcoder.getOutgoingEncodedFrameSize();
rtpPacket.setTimestamp( timestamp );
rtpPacket.setPayloadLength( transcoder.getOutgoingEncodedFrameSize() );
System.out.println("Sending rtpPacket " + timestamp);
rtpSocketSend( rtpPacket );
}

View File

@ -236,7 +236,7 @@ public class SipUserAgent extends CallListenerAdapter {
callStream.stopTalkStream(broadcastStream, scope);
}
protected void closeMediaApplication() {
private void closeMediaApplication() {
log.debug("closeMediaApplication" );
if (callStream != null) {

View File

@ -22,7 +22,7 @@ public class TalkStream {
private final RtpSender2 rtpSender;
private final IStreamListener mInputListener;
private BlockingQueue<IStreamPacket> packets = new LinkedBlockingQueue<IStreamPacket>();
private BlockingQueue<RtmpAudioData> packets = new LinkedBlockingQueue<RtmpAudioData>();
private final Executor exec = Executors.newSingleThreadExecutor();
private Runnable audioProcessor;
private volatile boolean processAudio = false;
@ -42,14 +42,16 @@ public class TalkStream {
if (buf == null || buf.remaining() == 0){
log.debug("skipping empty packet with no data");
System.out.println("skipping empty packet with no data");
return;
}
if (packet instanceof AudioData) {
log.debug("adding packet type: {}; ts: {}; on stream: {}",
new Object[]{"AUDIO", packet.getTimestamp(), broadcastStream.getPublishedName()});
try {
packets.put(packet);
byte[] data = SerializeUtils.ByteBufferToByteArray(buf);
RtmpAudioData audioData = new RtmpAudioData(data);
System.out.println("Adding data " + data.length);
packets.put(audioData);
} catch (InterruptedException e) {
log.info("Interrupted exception while queieing audio packet");
}
@ -67,7 +69,7 @@ public class TalkStream {
public void run() {
while (processAudio) {
try {
IStreamPacket packet = packets.take();
RtmpAudioData packet = packets.take();
processAudioPacket(packet);
} catch (InterruptedException e) {
log.info("InterruptedExeption while taking audio packet.");
@ -78,9 +80,9 @@ public class TalkStream {
exec.execute(audioProcessor);
}
private void processAudioPacket(IStreamPacket packet) {
IoBuffer audioData = ((AudioData)packet).getData().asReadOnlyBuffer();
byte[] data = SerializeUtils.ByteBufferToByteArray(audioData);
private void processAudioPacket(RtmpAudioData packet) {
byte[] data = packet.getData();
System.out.println("Proccessing voice data");
rtpSender.send(data, 1, data.length-1);
}

View File

@ -0,0 +1,26 @@
package org.red5.app.sip;
public class TranscodedPcmAudioBuffer {
private byte[] buffer;
private int offset;
private RtpSender2 sender;
TranscodedPcmAudioBuffer(byte[] data, int offset, RtpSender2 sender) {
buffer = data;
this.offset = offset;
}
boolean copyData(byte[] data) {
if (data.length > buffer.length - offset)
return false;
System.arraycopy(data, 0, buffer, offset, data.length);
return true;
}
void sendData() {
sender.sendTranscodedData();
}
}

View File

@ -5,6 +5,7 @@ import java.util.List;
import org.slf4j.Logger;
import org.red5.app.sip.RtmpConnection;
import org.red5.app.sip.SipUserManager;
import org.red5.app.sip.User;
import org.red5.logging.Red5LoggerFactory;
import org.red5.server.adapter.MultiThreadedApplicationAdapter;
import org.red5.server.api.IClient;
@ -25,6 +26,7 @@ public class VoiceConferenceApplication extends MultiThreadedApplicationAdapter
private int startRTPPort = 3000;
private int stopRTPPort = 3029;
private int rtpPort;
private String password = "secret";
private MessageFormat callExtensionPattern = new MessageFormat("{0}");
@ -89,14 +91,18 @@ public class VoiceConferenceApplication extends MultiThreadedApplicationAdapter
log.debug( "Red5SIP Ping" );
}
public void open(String uid, String username) {
log.debug("Red5SIP open");
login(uid, username);
/******************************************************************/
public void open(String obproxy,String uid, String phone,
String username, String password, String realm, String proxy) {
System.out.println("Red5SIP open");
login(obproxy, uid, phone, username, password, realm, proxy);
register(uid);
}
public void login(String uid, String username) {
log.debug("Red5SIP login " + uid);
public void login(String obproxy, String uid, String phone,
String username, String password, String realm, String proxy) {
System.out.println("Red5SIP login " + uid);
IConnection conn = Red5.getConnectionLocal();
IServiceCapableConnection service = (IServiceCapableConnection) conn;
@ -104,15 +110,35 @@ public class VoiceConferenceApplication extends MultiThreadedApplicationAdapter
String userid = getSipUserId();
sipManager.createSipUser(userid, rtmpConnection, sipPort, rtpPort);
sipManager.login(userid, obproxy, phone, username, password, realm, proxy);
sipPort++;
if (sipPort > stopSIPPort) sipPort = startSIPPort;
rtpPort++;
if (rtpPort > stopRTPPort) rtpPort = startRTPPort;
}
/******************************************************************/
public void open(String uid, String username) {
log.debug("Red5SIP open");
login(uid, username);
register(uid);
}
public void login(String userid, String username) {
log.debug("Red5SIP login " + userid);
/*
* Let's tie this users account to the RTPPort. This allows us to dynamically
* register a user when he/she joins the conference.
*/
String password = "secret";
String realm = asteriskHost;
String realm = asteriskHost; //asteriskHost; "192.168.0.120";
String proxy = realm;
//SipUser will connect to "outbound-proxy", just pass-in the proxy for it.
sipManager.login(userid, proxy, new Integer(rtpPort).toString(),username, password, realm, proxy);
login(proxy, userid, new Integer(rtpPort).toString(), username, password, realm, proxy);
sipPort++;
if (sipPort > stopSIPPort) sipPort = startSIPPort;
@ -128,6 +154,7 @@ public class VoiceConferenceApplication extends MultiThreadedApplicationAdapter
}
public void call(String uid, String destination) {
destination = "600";
log.debug("Red5SIP Call " + destination);
String userid = getSipUserId();
String extension = callExtensionPattern.format(new String[] { destination });

View File

@ -1,13 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<contextName>sip</contextName>
<jmxConfigurator contextName="sip" />
<appender name="SIP" class="ch.qos.logback.core.FileAppender">
<File>log/sip.log</File>
<Append>true</Append>
<Append>false</Append>
<Encoding>UTF-8</Encoding>
<BufferedIO>false</BufferedIO>
<ImmediateFlush>true</ImmediateFlush>
@ -20,8 +15,6 @@
<root>
<level value="DEBUG" />
<appender-ref ref="SIP" />
</root>
<logger name="org.red5.server.webapp.sip">
<level value="DEBUG" />
</logger>
</root>
</configuration>