diff --git a/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/red5/media/CallStream.java b/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/red5/media/CallStream.java index f433014949..6287948e21 100755 --- a/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/red5/media/CallStream.java +++ b/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/red5/media/CallStream.java @@ -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); } diff --git a/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/red5/media/FlashToSipAudioStream.java b/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/red5/media/FlashToSipAudioStream.java index 385e722e34..321f1d6d97 100755 --- a/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/red5/media/FlashToSipAudioStream.java +++ b/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/red5/media/FlashToSipAudioStream.java @@ -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); } } diff --git a/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/red5/media/RtpStreamReceiver.java b/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/red5/media/RtpStreamReceiver.java index fdac0808fd..4131aa26c7 100755 --- a/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/red5/media/RtpStreamReceiver.java +++ b/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/red5/media/RtpStreamReceiver.java @@ -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. diff --git a/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/red5/media/transcoder/NellyToPcmTranscoder.java b/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/red5/media/transcoder/NellyToPcmTranscoder.java index 855a1d8c6f..5943aaf7fe 100755 --- a/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/red5/media/transcoder/NellyToPcmTranscoder.java +++ b/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/red5/media/transcoder/NellyToPcmTranscoder.java @@ -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. */ diff --git a/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/red5/media/transcoder/RtmpToRtpSpeexTranscoder.java b/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/red5/media/transcoder/RtmpToRtpSpeexTranscoder.java new file mode 100755 index 0000000000..bbd5785415 --- /dev/null +++ b/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/red5/media/transcoder/RtmpToRtpSpeexTranscoder.java @@ -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 . + * + * $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(); + } +} diff --git a/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/red5/media/transcoder/RtpToRtmpSpeexTranscoder.java b/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/red5/media/transcoder/RtpToRtmpSpeexTranscoder.java new file mode 100755 index 0000000000..0aa375f9fe --- /dev/null +++ b/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/red5/media/transcoder/RtpToRtmpSpeexTranscoder.java @@ -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 . + * + * $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(); + } +} diff --git a/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/red5/media/transcoder/SpeexToSpeexTranscoder.java b/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/red5/media/transcoder/SpeexToSpeexTranscoder.java index 16351baa7a..116e4133df 100755 --- a/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/red5/media/transcoder/SpeexToSpeexTranscoder.java +++ b/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/red5/media/transcoder/SpeexToSpeexTranscoder.java @@ -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 + + } } diff --git a/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/red5/media/transcoder/Transcoder.java b/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/red5/media/transcoder/Transcoder.java index 36d5a8657b..981a536b02 100755 --- a/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/red5/media/transcoder/Transcoder.java +++ b/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/red5/media/transcoder/Transcoder.java @@ -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(); diff --git a/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/sip/CallAgent.java b/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/sip/CallAgent.java index 917f0d02c7..c77e0947ea 100755 --- a/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/sip/CallAgent.java +++ b/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/sip/CallAgent.java @@ -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)); } } } diff --git a/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/sip/SipPeerProfile.java b/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/sip/SipPeerProfile.java index d3fcef737a..08324d156f 100755 --- a/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/sip/SipPeerProfile.java +++ b/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/sip/SipPeerProfile.java @@ -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 ************************* diff --git a/bbb-voice/src/main/java/org/red5/app/sip/codecs/CodecFactory.java b/bbb-voice/src/main/java/org/red5/app/sip/codecs/CodecFactory.java old mode 100644 new mode 100755 index 7b8510b497..55be971cd1 --- a/bbb-voice/src/main/java/org/red5/app/sip/codecs/CodecFactory.java +++ b/bbb-voice/src/main/java/org/red5/app/sip/codecs/CodecFactory.java @@ -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 = {}; diff --git a/bbb-voice/src/main/java/org/red5/app/sip/codecs/SpeexCodec.java b/bbb-voice/src/main/java/org/red5/app/sip/codecs/SpeexCodec.java old mode 100644 new mode 100755 index 1125f26a79..530fad4473 --- a/bbb-voice/src/main/java/org/red5/app/sip/codecs/SpeexCodec.java +++ b/bbb-voice/src/main/java/org/red5/app/sip/codecs/SpeexCodec.java @@ -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;