Revision: 71
Author: timur.tleuke...@gmail.com
Date: Wed Feb 6 09:31:44 2013
Log: red5sip:
1) Switch red5sip to RTPStreamMultiplexingSender.
2) Added per-stream jitter buffers.
http://code.google.com/p/red5phone/source/detail?r=71
Added:
/branches/red5sip/src/java/org/red5/sip/app/IMediaStream.java
/branches/red5sip/src/java/org/red5/sip/app/RTPStream.java
/branches/red5sip/src/java/org/red5/sip/app/RTPStreamForMultiplex.java
Modified:
/branches/red5sip/lib/red5sip.jar
/branches/red5sip/red5sip.iml
/branches/red5sip/src/java/org/red5/sip/app/IMediaSender.java
/branches/red5sip/src/java/org/red5/sip/app/PlayNetStream.java
/branches/red5sip/src/java/org/red5/sip/app/RTMPRoomClient.java
/branches/red5sip/src/java/org/red5/sip/app/RTPStreamMultiplexingSender.java
/branches/red5sip/src/java/org/red5/sip/app/RTPStreamSender.java
/branches/red5sip/src/java/org/red5/sip/app/SIPAudioLauncher.java
=======================================
--- /dev/null
+++ /branches/red5sip/src/java/org/red5/sip/app/IMediaStream.java Wed Feb
6 09:31:44 2013
@@ -0,0 +1,7 @@
+package org.red5.sip.app;
+
+public interface IMediaStream {
+
+ void send(long timestamp, byte[] asaoBuffer, int offset, int num);
+
+}
=======================================
--- /dev/null
+++ /branches/red5sip/src/java/org/red5/sip/app/RTPStream.java Wed Feb 6
09:31:44 2013
@@ -0,0 +1,171 @@
+package org.red5.sip.app;
+
+import local.net.RtpPacket;
+import org.red5.codecs.asao.ByteStream;
+import org.red5.logging.Red5LoggerFactory;
+import org.slf4j.Logger;
+
+public class RTPStream implements IMediaStream {
+
+ protected static Logger log =
Red5LoggerFactory.getLogger(RTPStream.class, "sip");
+
+ private int streamId;
+ private RTPStreamSender sender;
+ private long syncSource;
+ private long timestamp;
+
+ /** Sip codec to be used on audio session */
+ private byte[] packetBuffer;
+ private RtpPacket rtpPacket;
+
+ // 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;
+
+ public RTPStream(int streamId, long syncSource, RTPStreamSender
sender) {
+ this.streamId = streamId;
+ this.syncSource = syncSource;
+ this.sender = sender;
+ this.packetBuffer = new byte[
sender.sipCodec.getOutgoingEncodedFrameSize() +
RTPStreamSender.RTP_HEADER_SIZE ];
+ this.rtpPacket = new RtpPacket( this.packetBuffer, 0 );
+ this.rtpPacket.setPayloadType( sender.sipCodec.getCodecId() );
+ this.tempBuffer = new float[
RTPStreamSender.NELLYMOSER_DECODED_PACKET_SIZE ];
+ this.encodingBuffer = new float[
sender.sipCodec.getOutgoingDecodedFrameSize() ];
+ }
+
+ public void send(long timestamp, byte[] asaoBuffer, int offset, int
num) {
+ if(RTPStreamSender.useASAO) {
+ sendASAO(asaoBuffer, offset, num);
+ } else {
+ sendRaw(asaoBuffer, offset, num);
+ }
+ }
+
+ public void sendRaw(byte[] asaoInput, int offset, int num ) {
+ System.arraycopy(asaoInput, offset, packetBuffer,
RTPStreamSender.RTP_HEADER_SIZE, num);
+ rtpPacket.setSscr(syncSource);
+ rtpPacket.setTimestamp( timestamp );
+ rtpPacket.setPayloadLength(
sender.sipCodec.getOutgoingEncodedFrameSize() );
+ sender.send(rtpPacket);
+ }
+
+ public void sendASAO(byte[] asaoBuffer, int offset, int num) {
+ asao_buffer_processed = false;
+
+ if ( num > 0 ) {
+ do {
+ int encodedBytes = fillRtpPacketBuffer( asaoBuffer );
+ if ( encodedBytes == 0 ) {
+ break;
+ }
+ if ( encodingOffset ==
sender.sipCodec.getOutgoingDecodedFrameSize() ) {
+ try {
+ rtpPacket.setSscr(syncSource);
+ rtpPacket.setTimestamp(timestamp);
+
rtpPacket.setPayloadLength(sender.sipCodec.getOutgoingEncodedFrameSize());
+ sender.send(rtpPacket);
+ timestamp +=
sender.sipCodec.getOutgoingPacketization();
+ }
+ catch ( Exception e ) {
+ log.error( "sendASAO: " +
sender.sipCodec.getCodecName() + " encoder error.", e );
+ }
+ encodingOffset = 0;
+ }
+ }
+ while ( !asao_buffer_processed );
+ }
+ }
+
+ /** Fill the buffer of RtpPacket with necessary data. */
+ private int fillRtpPacketBuffer(byte[] asaoBuffer) {
+
+ boolean isBufferFilled = false;
+ int copyingSize = 0;
+ int finalCopySize = 0;
+ byte[] codedBuffer = new byte[
sender.sipCodec.getOutgoingEncodedFrameSize() ];
+
+ try {
+ if ( ( tempBufferRemaining + encodingOffset ) >=
sender.sipCodec.getOutgoingDecodedFrameSize() ) {
+
+ copyingSize = encodingBuffer.length - encodingOffset;
+
+ BufferUtils.floatBufferIndexedCopy(
+ encodingBuffer,
+ encodingOffset,
+ tempBuffer,
+ tempBuffer.length - tempBufferRemaining,
+ copyingSize );
+
+ encodingOffset =
sender.sipCodec.getOutgoingDecodedFrameSize();
+ tempBufferRemaining -= copyingSize;
+ finalCopySize =
sender.sipCodec.getOutgoingDecodedFrameSize();
+
+ //println( "fillRtpPacketBuffer", "Simple copy of " +
copyingSize + " bytes." );
+ }
+ else {
+ if ( tempBufferRemaining > 0 ) {
+ BufferUtils.floatBufferIndexedCopy(
+ encodingBuffer,
+ encodingOffset,
+ tempBuffer,
+ tempBuffer.length - tempBufferRemaining,
+ tempBufferRemaining );
+
+ encodingOffset += tempBufferRemaining;
+ finalCopySize += tempBufferRemaining;
+ tempBufferRemaining = 0;
+ }
+
+ // Decode new asao packet.
+
+ asao_buffer_processed = true;
+
+ ByteStream audioStream = new ByteStream( asaoBuffer, 1,
RTPStreamSender.NELLYMOSER_ENCODED_PACKET_SIZE );
+
+ sender.decoderMap = sender.decoder.decode(
sender.decoderMap, audioStream.bytes, 1, tempBuffer, 0 );
+
+ tempBufferRemaining = tempBuffer.length;
+
+ if ( ( encodingOffset + tempBufferRemaining ) >
sender.sipCodec.getOutgoingDecodedFrameSize() ) {
+ copyingSize = encodingBuffer.length - encodingOffset;
+ }
+ else {
+ copyingSize = tempBufferRemaining;
+ }
+
+ BufferUtils.floatBufferIndexedCopy(
+ encodingBuffer,
+ encodingOffset,
+ tempBuffer,
+ 0,
+ copyingSize );
+
+ encodingOffset += copyingSize;
+ tempBufferRemaining -= copyingSize;
+ finalCopySize += copyingSize;
+ }
+
+ if (encodingOffset == encodingBuffer.length)
+ {
+ isBufferFilled = true;
+ int encodedBytes = sender.sipCodec.pcmToCodec(
encodingBuffer, codedBuffer );
+ if ( encodedBytes ==
sender.sipCodec.getOutgoingEncodedFrameSize() ) {
+ BufferUtils.byteBufferIndexedCopy( packetBuffer,
+ RTPStreamSender.RTP_HEADER_SIZE, codedBuffer,
0, codedBuffer.length );
+ }
+ }
+ }
+ catch ( Exception e ) {
+ e.printStackTrace();
+ }
+
+ return finalCopySize;
+ }
+}
=======================================
--- /dev/null
+++ /branches/red5sip/src/java/org/red5/sip/app/RTPStreamForMultiplex.java
Wed Feb 6 09:31:44 2013
@@ -0,0 +1,73 @@
+package org.red5.sip.app;
+
+import org.red5.logging.Red5LoggerFactory;
+import org.slf4j.Logger;
+
+public class RTPStreamForMultiplex implements IMediaStream {
+ protected static Logger log =
Red5LoggerFactory.getLogger(RTPStreamForMultiplex.class, "sip");
+
+ private int streamId;
+ private RTPStreamMultiplexingSender sender;
+ private long syncSource;
+ private static int BUFFERS_COUNT = 1024;
+ private byte[][] buffer = new byte[BUFFERS_COUNT][65];
+ private int[] bufLen = new int[BUFFERS_COUNT];
+ private int start, end;
+ private boolean ready = false;
+
+ protected RTPStreamForMultiplex(int streamId, long syncSource,
RTPStreamMultiplexingSender sender) {
+ this.streamId = streamId;
+ this.sender = sender;
+ this.syncSource = syncSource;
+ end = 0;
+ start = -1;
+ }
+
+ public int getStreamId() {
+ return streamId;
+ }
+
+ public synchronized void send(long timestamp, byte[] asaoBuffer, int
offset, int num) {
+ if(end == start) {
+ log.error("Stream buffer overflow: streamId: " + streamId + ",
start: " + start + ", end: " + end);
+ return;
+ }
+ System.arraycopy(asaoBuffer, 0, buffer[end], 0, asaoBuffer.length);
+ bufLen[end++] = num;
+ if(end == BUFFERS_COUNT) {
+ end = 0;
+ }
+ if(start == -1) {
+ start = 0;
+ }
+
+ if(!ready && available() > 10) {
+ ready = true;
+ }
+ }
+
+ protected synchronized int available() {
+ return (end > start) ? (end - start) : (BUFFERS_COUNT - start +
end);
+ }
+
+ protected synchronized boolean ready() {
+ return ready;
+ }
+
+ protected synchronized int read(byte[] dst, int offset) {
+ int res = -1;
+ if(start >= 0) {
+ System.arraycopy(buffer[start], 0, dst, offset, dst.length);
+ res = start++;
+ if(start == BUFFERS_COUNT) {
+ start = 0;
+ }
+ if(start == end) {
+ start = -1;
+ end = 0;
+ ready = false;
+ }
+ }
+ return res;
+ }
+}
=======================================
--- /branches/red5sip/lib/red5sip.jar Tue Jan 29 03:52:07 2013
+++ /branches/red5sip/lib/red5sip.jar Wed Feb 6 09:31:44 2013
Binary file, no diff available.
=======================================
--- /branches/red5sip/red5sip.iml Mon Feb 4 23:34:05 2013
+++ /branches/red5sip/red5sip.iml Wed Feb 6 09:31:44 2013
@@ -512,6 +512,7 @@
</library>
</orderEntry>
<orderEntry type="library" name="lib" level="project" />
+ <orderEntry type="library" name="Unnamed" level="project" />
</component>
</module>
=======================================
--- /branches/red5sip/src/java/org/red5/sip/app/IMediaSender.java Fri Feb
10 07:37:46 2012
+++ /branches/red5sip/src/java/org/red5/sip/app/IMediaSender.java Wed Feb
6 09:31:44 2013
@@ -2,7 +2,9 @@
public interface IMediaSender {
- void send(int streamId, byte[] asaoBuffer, int offset, int num);
+ IMediaStream createStream(int streamId);
+
+ void deleteStream(int streamId);
void start();
=======================================
--- /branches/red5sip/src/java/org/red5/sip/app/PlayNetStream.java Fri Feb
10 07:37:46 2012
+++ /branches/red5sip/src/java/org/red5/sip/app/PlayNetStream.java Wed Feb
6 09:31:44 2013
@@ -11,6 +11,9 @@
import org.red5.server.stream.AbstractClientStream;
import org.red5.server.stream.IStreamData;
import org.slf4j.Logger;
+import org.zoolu.tools.Random;
+
+import java.util.concurrent.atomic.AtomicLong;
public class PlayNetStream extends AbstractClientStream implements
IEventDispatcher {
@@ -18,32 +21,30 @@
private int audioTs = 0;
- private int kt = 0;
+ private IMediaSender mediaSender;
- private int kt2 = 0;
-
- private IMediaSender mediaSender;
+ private IMediaStream mediaStream;
public PlayNetStream(IMediaSender mediaSender) {
this.mediaSender = mediaSender;
- if(mediaSender instanceof RTPStreamMultiplexingSender) {
- ((RTPStreamMultiplexingSender) mediaSender).streamAdded();
- }
}
-
-
public void close() {
-
+ if(mediaSender != null) {
+ mediaSender.deleteStream(getStreamId());
+ }
}
-
public void start() {
-
+ if(mediaSender != null) {
+ mediaStream = mediaSender.createStream(getStreamId());
+ }
}
public void stop() {
-
+ if(mediaSender != null) {
+ mediaSender.deleteStream(getStreamId());
+ }
}
public void dispatchEvent(IEvent event) {
@@ -55,11 +56,6 @@
IRTMPEvent rtmpEvent = (IRTMPEvent) event;
- if (logger.isDebugEnabled()) {
- // logger.debug("rtmp event: " + rtmpEvent.getHeader() + ", " +
- // rtmpEvent.getClass().getSimpleName());
- }
-
if (!(rtmpEvent instanceof IStreamData)) {
logger.debug("skipping non stream data");
return;
@@ -75,28 +71,18 @@
// tag.setTimestamp(videoTs);
} else if (rtmpEvent instanceof AudioData) {
- audioTs += rtmpEvent.getTimestamp();
+ audioTs = rtmpEvent.getTimestamp();
IoBuffer audioData = ((IStreamData)
rtmpEvent).getData().asReadOnlyBuffer();
byte[] data = SerializeUtils.ByteBufferToByteArray(audioData);
-
- //System.out.println( "RTMPUser.dispatchEvent() - AudioData ->
length = " + data.length + ".");
-
- kt2++;
-
- if (kt2 < 10) {
- logger.debug("*** " + data.length);
- System.out.println("*** " + data.length);
- }
try {
- if (mediaSender != null) {
- mediaSender.send(getStreamId(), data, 1, data.length -
1);
+ if(mediaStream != null) {
+ mediaStream.send(audioTs, data, 1, data.length - 1);
}
} catch (Exception e) {
System.out.println("PlayNetStream dispatchEvent
exception " + e);
}
-
}
}
}
=======================================
--- /branches/red5sip/src/java/org/red5/sip/app/RTMPRoomClient.java Tue Jan
29 03:52:07 2013
+++ /branches/red5sip/src/java/org/red5/sip/app/RTMPRoomClient.java Wed
Feb 6 09:31:44 2013
@@ -2,7 +2,7 @@
import org.apache.mina.core.RuntimeIoException;
import org.apache.mina.core.buffer.IoBuffer;
-import org.apache.openmeetings.persistence.beans.rooms.Client;
+import org.apache.openmeetings.persistence.beans.room.Client;
import org.red5.io.utils.ObjectMap;
import org.red5.server.api.IScope;
import org.red5.server.api.event.IEvent;
@@ -31,7 +31,7 @@
private static final int MAX_RETRY_NUMBER = 100;
private static final int UPDATE_MS = 10000;
- private List<Integer> broadcastIds = new ArrayList<Integer>();
+ private Set<Integer> broadcastIds = new HashSet<Integer>();
private Map<Long,Integer> clientStreamMap = new HashMap<Long,
Integer>();
private String publicSID = null;
private long broadCastId = -1;
@@ -170,6 +170,7 @@
stream.setStreamId(streamIdInt.intValue());
conn.addClientStream(stream);
play(streamIdInt, "" + broadCastId, -2000, -1000);
+ stream.start();
}
}
@@ -193,7 +194,6 @@
protected void startStreaming() {
//red5 -> SIP
- //createPlayStream(56);
for(long broadCastId: broadcastIds) {
if(broadCastId != this.broadCastId) {
createPlayStream(broadCastId);
@@ -306,14 +306,6 @@
this.micMuted = !client.getPublicSID().equals(this.publicSID);
log.info("Mic switched: " + this.micMuted);
}
-
- public void receiveMicMuteSwitched(Client client) {
- log.debug("receiveMicMuteSwitched:" + client.getPublicSID());
- if(client.getPublicSID().equals(this.publicSID)) {
- log.info("Mic switched: " + client.getMicMuted());
- this.micMuted = client.getMicMuted();
- }
- }
public void sendVarsToMessageWithClient(Object message) {
if(message instanceof Map) {
@@ -337,11 +329,10 @@
log.debug("closeStream:" + client.getBroadCastID());
Integer streamId = clientStreamMap.get(client.getBroadCastID());
if(streamId != null) {
- if(sender instanceof RTPStreamMultiplexingSender) {
- ((RTPStreamMultiplexingSender) sender).streamRemoved();
- }
clientStreamMap.remove(client.getBroadCastID());
+ conn.getStreamById(streamId).stop();
conn.removeClientStream(streamId);
+ conn.deleteStreamById(streamId);
}
}
=======================================
---
/branches/red5sip/src/java/org/red5/sip/app/RTPStreamMultiplexingSender.java
Tue Jan 29 03:52:07 2013
+++
/branches/red5sip/src/java/org/red5/sip/app/RTPStreamMultiplexingSender.java
Wed Feb 6 09:31:44 2013
@@ -2,6 +2,7 @@
import local.net.RtpPacket;
import local.net.RtpSocket;
+import org.apache.mina.util.ConcurrentHashSet;
import org.red5.codecs.SIPCodec;
import org.red5.codecs.asao.ByteStream;
import org.red5.codecs.asao.Decoder;
@@ -9,8 +10,10 @@
import org.red5.logging.Red5LoggerFactory;
import org.slf4j.Logger;
+import java.lang.ref.WeakReference;
import java.net.DatagramSocket;
import java.net.InetAddress;
+import java.util.*;
public class RTPStreamMultiplexingSender implements IMediaSender, Runnable
{
protected static Logger log =
Red5LoggerFactory.getLogger(RTPStreamMultiplexingSender.class, "sip");
@@ -23,7 +26,9 @@
RtpSocket rtpSocket = null;
- /** Sip codec to be used on audio session */
+ /**
+ * Sip codec to be used on audio session
+ */
protected SIPCodec sipCodec = null;
boolean socketIsLocal = false;
@@ -41,20 +46,25 @@
private int seqn = 0;
private long time = 0;
+ private long syncSource = 0;
// Temporary buffer with received PCM audio from FlashPlayer.
float[] tempBuffer;
- int[] multiplexedStreams;
float[] decodedBuffer1;
float[] decodedBuffer2;
- long sendInterval = 0;
volatile int multiplexingCount = 0;
- int streamsCount = 0;
+ private Thread sendThread = new Thread(this);
- private Thread sendThread;
+ ConcurrentHashSet<WeakReference<RTPStreamForMultiplex>> streamSet =
new ConcurrentHashSet<WeakReference<RTPStreamForMultiplex>>();
+ //Set<RTPStreamForMultiplex> streamSet =
Collections.synchronizedSet(new WeakHashSet<RTPStreamForMultiplex>());
+
+ private static int SEND_BUFFER_MAX = 100;
+ private byte[][] sendBuffer = new byte[SEND_BUFFER_MAX][];
+ private int[] sendBufferLength = new int[SEND_BUFFER_MAX];
+ private int sendBufferPos = 0;
// Floats remaining on temporary buffer.
int tempBufferRemaining = 0;
@@ -72,32 +82,26 @@
// been initialized.
boolean hasInitilializedBuffers = false;
-
/**
* Constructs a RtpStreamSender.
*
- * @param mediaReceiver
- * the RTMP stream source
- * @param do_sync
- * whether time synchronization must be performed by the
- * RtpStreamSender, or it is performed by the InputStream
(e.g.
- * the system audio input)
- * @param sipCodec
- * codec to be used on audio session
- * @param dest_addr
- * the destination address
- * @param dest_port
- * the destination port
+ * @param mediaReceiver the RTMP stream source
+ * @param do_sync whether time synchronization must be performed
by the
+ * RtpStreamSender, or it is performed by the
InputStream (e.g.
+ * the system audio input)
+ * @param sipCodec codec to be used on audio session
+ * @param dest_addr the destination address
+ * @param dest_port the destination port
*/
public RTPStreamMultiplexingSender(
- IMediaReceiver mediaReceiver,
- boolean do_sync,
- SIPCodec sipCodec,
- String dest_addr,
- int dest_port ) {
+ IMediaReceiver mediaReceiver,
+ boolean do_sync,
+ SIPCodec sipCodec,
+ String dest_addr,
+ int dest_port) {
- init( mediaReceiver, do_sync, sipCodec, null, dest_addr, dest_port
);
+ init(mediaReceiver, do_sync, sipCodec, null, dest_addr, dest_port);
}
@@ -125,136 +129,188 @@
// {
// init( mediaReceiver, do_sync, payloadType, frame_rate, frame_size,
null, src_port, dest_addr, dest_port);
// }
+
/**
* Constructs a RtpStreamSender.
*
- * @param mediaReceiver
- * the RTMP stream source
- * @param do_sync
- * whether time synchronization must be performed by the
- * RtpStreamSender, or it is performed by the InputStream
(e.g.
- * the system audio input)
- * @param sipCodec
- * codec to be used on audio session
- * @param src_socket
- * the socket used to send the RTP packet
- * @param dest_addr
- * the destination address
- * @param dest_port
- * the thestination port
+ * @param mediaReceiver the RTMP stream source
+ * @param do_sync whether time synchronization must be performed
by the
+ * RtpStreamSender, or it is performed by the
InputStream (e.g.
+ * the system audio input)
+ * @param sipCodec codec to be used on audio session
+ * @param src_socket the socket used to send the RTP packet
+ * @param dest_addr the destination address
+ * @param dest_port the thestination port
*/
public RTPStreamMultiplexingSender(
- IMediaReceiver mediaReceiver,
- boolean do_sync,
- SIPCodec sipCodec,
- DatagramSocket src_socket,
- String dest_addr,
- int dest_port ) {
+ IMediaReceiver mediaReceiver,
+ boolean do_sync,
+ SIPCodec sipCodec,
+ DatagramSocket src_socket,
+ String dest_addr,
+ int dest_port) {
- init( mediaReceiver, do_sync, sipCodec, src_socket, dest_addr,
dest_port );
+ init(mediaReceiver, do_sync, sipCodec, src_socket, dest_addr,
dest_port);
}
- /** Inits the RtpStreamSender */
+ /**
+ * Inits the RtpStreamSender
+ */
private void init(
- IMediaReceiver mediaReceiver,
- boolean do_sync,
- SIPCodec sipCodec,
- DatagramSocket src_socket,
- String dest_addr,
- int dest_port ) {
+ IMediaReceiver mediaReceiver,
+ boolean do_sync,
+ SIPCodec sipCodec,
+ DatagramSocket src_socket,
+ String dest_addr,
+ int dest_port) {
mediaReceiver.setSender(this);
this.sipCodec = sipCodec;
this.doSync = do_sync;
+ this.sendBufferPos = 0;
+
+ for(int i=0; i<SEND_BUFFER_MAX; i++) {
+ sendBuffer[i] = new
byte[sipCodec.getOutgoingEncodedFrameSize() + RTP_HEADER_SIZE];
+ }
try {
- if ( src_socket == null ) {
+ if (src_socket == null) {
src_socket = new DatagramSocket();
socketIsLocal = true;
}
- rtpSocket = new RtpSocket( src_socket,
InetAddress.getByName(dest_addr), dest_port );
- }
- catch ( Exception e ) {
+ rtpSocket = new RtpSocket(src_socket,
InetAddress.getByName(dest_addr), dest_port);
+ } catch (Exception e) {
e.printStackTrace();
}
}
-
- public void streamAdded() {
- this.streamsCount++;
- }
-
- public void streamRemoved() {
- this.streamsCount--;
- }
public void start() {
-
- packetBuffer = new byte[ sipCodec.getOutgoingEncodedFrameSize() +
RTP_HEADER_SIZE ];
- rtpPacket = new RtpPacket( packetBuffer, 0 );
- rtpPacket.setPayloadType( sipCodec.getCodecId() );
+ packetBuffer = new byte[sipCodec.getOutgoingEncodedFrameSize() +
RTP_HEADER_SIZE];
+ rtpPacket = new RtpPacket(packetBuffer, 0);
+ rtpPacket.setPayloadType(sipCodec.getCodecId());
seqn = 0;
time = 0;
+ syncSource = 0;
- println( "start()", "using blocks of " + ( packetBuffer.length -
RTP_HEADER_SIZE ) + " bytes." );
+ println("start()", "using blocks of " + (packetBuffer.length -
RTP_HEADER_SIZE) + " bytes.");
decoder = new Decoder();
decoderMap = null;
- sendThread = new Thread(this);
- sendInterval = System.currentTimeMillis();
sendThread.start();
}
private void fillDecodedBuffer(byte[] asaoBuffer, float[] tempBuffer) {
- ByteStream audioStream = new ByteStream( asaoBuffer, 1,
NELLYMOSER_ENCODED_PACKET_SIZE );
- decoderMap = decoder.decode( decoderMap, audioStream.bytes, 1,
tempBuffer, 0 );
+ ByteStream audioStream = new ByteStream(asaoBuffer, 1,
NELLYMOSER_ENCODED_PACKET_SIZE);
+ decoderMap = decoder.decode(decoderMap, audioStream.bytes, 1,
tempBuffer, 0);
+ //ResampleUtils.normalize(tempBuffer, tempBuffer.length);
}
- public void send(int streamId, byte[] asaoBuffer, int offset, int num)
{
- boolean bufferAvailable = false;
- do {
- synchronized (this) {
- bufferAvailable = multiplexingCount < streamsCount;
- for(int i=0; i<multiplexingCount; i++) {
- bufferAvailable = bufferAvailable && streamId !=
multiplexedStreams[i];
- }
+ public synchronized IMediaStream createStream(int streamId) {
+ RTPStreamForMultiplex stream = new RTPStreamForMultiplex(streamId,
syncSource, this);
+ streamSet.add(new WeakReference<RTPStreamForMultiplex>(stream));
+ return stream;
+ }
+
+ public void deleteStream(int streamId) {
+ for (Iterator<WeakReference<RTPStreamForMultiplex>> iterator =
streamSet.iterator(); iterator.hasNext(); ) {
+ WeakReference<RTPStreamForMultiplex> ref = iterator.next();
+ if (ref.get() != null && ref.get().getStreamId() == streamId )
{
+ iterator.remove();
}
- try {
- if(bufferAvailable) {
- fillDecodedBuffer(asaoBuffer, decodedBuffer1);
- synchronized (this) {
- if(multiplexingCount != 0) {
- ResampleUtils.multiplex(decodedBuffer2,
decodedBuffer1);
+ }
+ }
+
+ private void doRtpDelay() {
+ try {
+ Thread.sleep( sipCodec.getOutgoingPacketization() - 2);
+ }
+ catch ( Exception e ) {
+ }
+ }
+
+ public void run() {
+ if (!hasInitilializedBuffers) {
+ tempBuffer = new float[NELLYMOSER_DECODED_PACKET_SIZE];
+ decodedBuffer1 = new float[NELLYMOSER_DECODED_PACKET_SIZE];
+ decodedBuffer2 = new float[NELLYMOSER_DECODED_PACKET_SIZE];
+ encodingBuffer = new
float[sipCodec.getOutgoingDecodedFrameSize()];
+ multiplexingCount = 0;
+ hasInitilializedBuffers = true;
+ }
+ byte[] asaoBuffer = new byte[65];
+ while(rtpSocket != null) {
+ multiplexingCount = 0;
+ for(Iterator<WeakReference<RTPStreamForMultiplex>> i =
streamSet.iterator(); i.hasNext();) {
+ int len = -1;
+ WeakReference<RTPStreamForMultiplex> ref = i.next();
+ RTPStreamForMultiplex stream = ref.get();
+ if(stream != null) {
+ synchronized (stream) {
+ System.out.println(String.format("Stream id %d,
avail %d", stream.getStreamId(), stream.available()));
+ if(stream != null && stream.ready()) {
+ len = stream.read(asaoBuffer, 0);
} else {
-
BufferUtils.floatBufferIndexedCopy(decodedBuffer2, 0, decodedBuffer1, 0,
decodedBuffer1.length);
+ break;
}
- multiplexedStreams[multiplexingCount++] = streamId;
}
- //System.out.println("Multiplex: " + multiplexingCount
+ "("+streamId+")");
} else {
- Thread.yield();
+ i.remove();
+ break;
+ }
+ if(len != -1) {
+ fillDecodedBuffer(asaoBuffer, decodedBuffer1);
+ if (multiplexingCount > 0) {
+ ResampleUtils.multiplex(decodedBuffer2,
decodedBuffer1);
+ } else {
+ BufferUtils.floatBufferIndexedCopy(decodedBuffer2,
0, decodedBuffer1, 0, decodedBuffer1.length);
+ }
+ multiplexingCount++;
+ //System.out.println("Multiplex stream: " + streamId);
+ }
+ Thread.yield();
+ }
+ if(multiplexingCount > 0) {
+ //System.out.println("Send: multiplexed: " +
multiplexingCount + ", total streams: " + streamSet.size());
+ ResampleUtils.normalize(decodedBuffer2,
decodedBuffer2.length);
+ try {
+ asao_buffer_processed = false;
+ do {
+ int encodedBytes = fillRtpPacketBuffer();
+ if (encodedBytes == 0) {
+ break;
+ }
+ if (encodingOffset ==
sipCodec.getOutgoingDecodedFrameSize()) {
+ rtpSocketSend(rtpPacket);
+ doRtpDelay();
+ encodingOffset = 0;
+ }
+ }
+ while (!asao_buffer_processed);
+ } catch (Exception e) {
+ log.error("Error preparing RTP packet", e);
}
- } catch (Exception e) {
- log.debug("Send error : ", e);
}
- } while (!bufferAvailable);
+ }
}
- /** Fill the buffer of RtpPacket with necessary data. */
+ /**
+ * Fill the buffer of RtpPacket with necessary data.
+ */
private int fillRtpPacketBuffer() {
int copyingSize = 0;
int finalCopySize = 0;
- byte[] codedBuffer = new byte[
sipCodec.getOutgoingEncodedFrameSize() ];
+ byte[] codedBuffer = new
byte[sipCodec.getOutgoingEncodedFrameSize()];
try {
- if ( ( tempBufferRemaining + encodingOffset ) >=
sipCodec.getOutgoingDecodedFrameSize() ) {
+ if ((tempBufferRemaining + encodingOffset) >=
sipCodec.getOutgoingDecodedFrameSize()) {
copyingSize = encodingBuffer.length - encodingOffset;
@@ -263,22 +319,19 @@
encodingOffset,
tempBuffer,
tempBuffer.length - tempBufferRemaining,
- copyingSize );
+ copyingSize);
encodingOffset = sipCodec.getOutgoingDecodedFrameSize();
tempBufferRemaining -= copyingSize;
finalCopySize = sipCodec.getOutgoingDecodedFrameSize();
-
- //println( "fillRtpPacketBuffer", "Simple copy of " +
copyingSize + " bytes." );
- }
- else {
- if ( tempBufferRemaining > 0 ) {
+ } else {
+ if (tempBufferRemaining > 0) {
BufferUtils.floatBufferIndexedCopy(
encodingBuffer,
encodingOffset,
tempBuffer,
tempBuffer.length - tempBufferRemaining,
- tempBufferRemaining );
+ tempBufferRemaining);
encodingOffset += tempBufferRemaining;
finalCopySize += tempBufferRemaining;
@@ -289,46 +342,21 @@
// Decode new asao packet.
asao_buffer_processed = true;
-
- boolean bufferAvailable = false;
- int waitCount = 0;
- do {
- if(multiplexingCount != 0) {
- synchronized (this) {
- bufferAvailable = multiplexingCount ==
streamsCount || waitCount++ > streamsCount;
- if(bufferAvailable) {
-// System.out.println("waitCount:" +
waitCount);
- multiplexingCount = 0;
- waitCount = 0;
-
BufferUtils.floatBufferIndexedCopy(tempBuffer, 0, decodedBuffer2, 0,
decodedBuffer2.length);
- }
- }
- }
- if(!bufferAvailable) {
- Thread.sleep(5);
- }
- } while (!bufferAvailable);
- long tmp = System.currentTimeMillis() - sendInterval;
- if(tmp > 50) {
- System.out.println("Send: " + tmp);
- }
- sendInterval = System.currentTimeMillis();
-
+ BufferUtils.floatBufferIndexedCopy(tempBuffer, 0,
decodedBuffer2, 0, decodedBuffer2.length);
// tempBuffer = ResampleUtils.normalize(tempBuffer, 256);
// normalise volume
tempBufferRemaining = tempBuffer.length;
- if ( tempBuffer.length <= 0 ) {
+ if (tempBuffer.length <= 0) {
- println( "fillRtpPacketBuffer", "Asao decoder Error."
);
+ println("fillRtpPacketBuffer", "Asao decoder Error.");
}
// Try to complete the encodingBuffer with necessary data.
- if ( ( encodingOffset + tempBufferRemaining ) >
sipCodec.getOutgoingDecodedFrameSize() ) {
+ if ((encodingOffset + tempBufferRemaining) >
sipCodec.getOutgoingDecodedFrameSize()) {
copyingSize = encodingBuffer.length - encodingOffset;
- }
- else {
+ } else {
copyingSize = tempBufferRemaining;
}
@@ -337,93 +365,29 @@
encodingOffset,
tempBuffer,
0,
- copyingSize );
+ copyingSize);
encodingOffset += copyingSize;
tempBufferRemaining -= copyingSize;
finalCopySize += copyingSize;
}
- if (encodingOffset == encodingBuffer.length)
- {
- int encodedBytes = sipCodec.pcmToCodec( encodingBuffer,
codedBuffer );
+ if (encodingOffset == encodingBuffer.length) {
+ int encodedBytes = sipCodec.pcmToCodec(encodingBuffer,
codedBuffer);
- if ( encodedBytes ==
sipCodec.getOutgoingEncodedFrameSize() ) {
+ if (encodedBytes ==
sipCodec.getOutgoingEncodedFrameSize()) {
- BufferUtils.byteBufferIndexedCopy( packetBuffer,
- RTP_HEADER_SIZE, codedBuffer, 0,
codedBuffer.length );
+ BufferUtils.byteBufferIndexedCopy(packetBuffer,
+ RTP_HEADER_SIZE, codedBuffer, 0,
codedBuffer.length);
}
}
- }
- catch ( Exception e ) {
+ } catch (Exception e) {
e.printStackTrace();
}
return finalCopySize;
}
-
-
- public void run() {
-
- if ( rtpSocket == null ) {
- return;
- }
-
- asao_buffer_processed = false;
-
- if ( !hasInitilializedBuffers ) {
-
- tempBuffer = new float[ NELLYMOSER_DECODED_PACKET_SIZE ];
- multiplexedStreams = new int[100];
- decodedBuffer1 = new float[ NELLYMOSER_DECODED_PACKET_SIZE ];
- decodedBuffer2 = new float[ NELLYMOSER_DECODED_PACKET_SIZE ];
- encodingBuffer = new float[
sipCodec.getOutgoingDecodedFrameSize() ];
-
- hasInitilializedBuffers = true;
- }
-
- //println( "send",
- // "asaoBuffer.length = [" + asaoBuffer.length + "], offset
= ["
- // + offset + "], num = [" + num + "]." );
- do {
-
- do {
-
- int encodedBytes = fillRtpPacketBuffer();
-
- //println( "send", sipCodec.getCodecName() + " encoded " +
encodedBytes + " bytes." );
-
- if ( encodedBytes == 0 ) {
-
- break;
- }
-
- if ( encodingOffset ==
sipCodec.getOutgoingDecodedFrameSize() ) {
-
- //println( "send", "Seding packet with " +
encodedBytes + " bytes." );
-
- try {
-
- rtpPacket.setSequenceNumber(seqn++);
- rtpPacket.setTimestamp(time);
-
rtpPacket.setPayloadLength(sipCodec.getOutgoingEncodedFrameSize());
- rtpSocketSend( rtpPacket );
- }
- catch ( Exception e ) {
- println( "send", sipCodec.getCodecName() + "
encoder error." );
- }
-
- encodingOffset = 0;
- }
-
- //println( "send", "asao_buffer_processed = ["
- // + asao_buffer_processed + "] ." );
- }
- while ( !asao_buffer_processed );
-
- } while (rtpSocket != null);
- }
public void halt() {
@@ -431,29 +395,34 @@
rtpSocket.close();
- if ( socketIsLocal && socket != null ) {
+ if (socketIsLocal && socket != null) {
socket.close();
}
rtpSocket = null;
sendThread = null;
- println( "halt", "Terminated" );
+ println("halt", "Terminated");
}
- private synchronized void rtpSocketSend(RtpPacket rtpPacket) {
+ private long lastMS = System.currentTimeMillis();
+ private void rtpSocketSend(RtpPacket rtpPacket) {
try {
- rtpSocket.send( rtpPacket );
- time += sipCodec.getOutgoingDecodedFrameSize();
- }
- catch ( Exception e ) {
+ rtpPacket.setTimestamp(time);
+ rtpPacket.setSequenceNumber(seqn++);
+
rtpPacket.setPayloadLength(sipCodec.getOutgoingEncodedFrameSize());
+ rtpPacket.setPayloadType(sipCodec.getCodecId());
+ rtpSocket.send(rtpPacket);
+ time += sipCodec.getOutgoingPacketization();
+ //System.out.println(String.format("Send RTP: interval %d,
ts %d", System.currentTimeMillis() - lastMS, time));
+ } catch (Exception e) {
+ log.error("Error sending RTP packet", e);
}
}
- private static void println( String method, String message ) {
-
- log.debug( "RTPStreamSender - " + method + " -> " + message );
- System.out.println( "RTPStreamSender - " + method + " -> " +
message );
+ private static void println(String method, String message) {
+ log.debug("RTPStreamSender - " + method + " -> " + message);
+ System.out.println("RTPStreamSender - " + method + " -> " +
message);
}
}
=======================================
--- /branches/red5sip/src/java/org/red5/sip/app/RTPStreamSender.java Tue
Jan 29 03:52:07 2013
+++ /branches/red5sip/src/java/org/red5/sip/app/RTPStreamSender.java Wed
Feb 6 09:31:44 2013
@@ -12,6 +12,8 @@
import java.net.DatagramSocket;
import java.net.InetAddress;
+import java.util.HashMap;
+import java.util.concurrent.atomic.AtomicLong;
public class RTPStreamSender implements IMediaSender {
@@ -35,37 +37,13 @@
boolean doSync = true;
- private Decoder decoder;
+ protected Decoder decoder;
- private DecoderMap decoderMap;
-
- private byte[] packetBuffer;
-
- private RtpPacket rtpPacket;
+ protected DecoderMap decoderMap;
private int seqn = 0;
- private long time = 0;
-
- // 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 AtomicLong syncSourceBase = new AtomicLong(Random.nextLong());
/**
* Constructs a RtpStreamSender.
@@ -176,248 +154,26 @@
}
}
- public void start() {
+ public IMediaStream createStream(int streamId) {
+ return new RTPStream(streamId, syncSourceBase.getAndIncrement(),
this);
+ }
- packetBuffer = new byte[ sipCodec.getOutgoingEncodedFrameSize() +
RTP_HEADER_SIZE ];
- rtpPacket = new RtpPacket( packetBuffer, 0 );
- rtpPacket.setPayloadType( sipCodec.getCodecId() );
+ public void deleteStream(int streamId) {
+ //nothing to do
+ }
+ public void start() {
seqn = 0;
- time = 0;
-
- println( "start()", "using blocks of " + ( packetBuffer.length -
RTP_HEADER_SIZE ) + " bytes." );
-
decoder = new Decoder();
decoderMap = null;
}
- /** Fill the buffer of RtpPacket with necessary data. */
- private int fillRtpPacketBuffer(byte[] asaoBuffer) {
-
- boolean isBufferFilled = false;
- int copyingSize = 0;
- int finalCopySize = 0;
- byte[] codedBuffer = new byte[
sipCodec.getOutgoingEncodedFrameSize() ];
-
- try {
- //println( "fillRtpPacketBuffer",
- // "packetBuffer.length = " + packetBuffer.length
- // + ", asaoBuffer.length = " + asaoBuffer.length
- // + ", tempBuffer.length = " + tempBuffer.length
- // + ", encodingOffset = " + encodingOffset
- // + ", tempBufferRemaining = " + tempBufferRemaining
+ "." );
-
- if ( ( tempBufferRemaining + encodingOffset ) >=
sipCodec.getOutgoingDecodedFrameSize() ) {
-
- copyingSize = encodingBuffer.length - encodingOffset;
-
- BufferUtils.floatBufferIndexedCopy(
- encodingBuffer,
- encodingOffset,
- tempBuffer,
- tempBuffer.length - tempBufferRemaining,
- copyingSize );
-
- encodingOffset = sipCodec.getOutgoingDecodedFrameSize();
- tempBufferRemaining -= copyingSize;
- finalCopySize = sipCodec.getOutgoingDecodedFrameSize();
-
- //println( "fillRtpPacketBuffer", "Simple copy of " +
copyingSize + " bytes." );
- }
- else {
- if ( tempBufferRemaining > 0 ) {
- BufferUtils.floatBufferIndexedCopy(
- encodingBuffer,
- encodingOffset,
- tempBuffer,
- tempBuffer.length - tempBufferRemaining,
- tempBufferRemaining );
-
- encodingOffset += tempBufferRemaining;
- finalCopySize += tempBufferRemaining;
- tempBufferRemaining = 0;
-
- //println( "fillRtpPacketBuffer",
- // "tempBufferRemaining copied -> "
- // + "encodingOffset = " + encodingOffset
- // + ", tempBufferRemaining = " +
tempBufferRemaining + "." );
- }
-
- // Decode new asao packet.
-
- asao_buffer_processed = true;
-
- ByteStream audioStream = new ByteStream( asaoBuffer, 1,
NELLYMOSER_ENCODED_PACKET_SIZE );
-
- decoderMap = decoder.decode( decoderMap,
audioStream.bytes, 1, tempBuffer, 0 );
-
-// tempBuffer = ResampleUtils.normalize(tempBuffer, 256);
// normalise volume
-
- tempBufferRemaining = tempBuffer.length;
-
- //println( "fillRtpPacketBuffer",
- // "Decoded pcm " + tempBuffer.length + " floats."
);
-
- if ( tempBuffer.length <= 0 ) {
-
- println( "fillRtpPacketBuffer", "Asao decoder Error."
);
- }
-
- // Try to complete the encodingBuffer with necessary data.
-
- //println( "fillRtpPacketBuffer",
- // "New buffer processed -> "
- // + "finalCopySize = " + finalCopySize
- // + ", encodingOffset = " + encodingOffset
- // + ", tempBufferRemaining = " +
tempBufferRemaining + "." );
-
- if ( ( encodingOffset + tempBufferRemaining ) >
sipCodec.getOutgoingDecodedFrameSize() ) {
- copyingSize = encodingBuffer.length - encodingOffset;
- }
- else {
- copyingSize = tempBufferRemaining;
- }
-
- //println( "fillRtpPacketBuffer", "CopyingSize = " +
copyingSize + "." );
-
- BufferUtils.floatBufferIndexedCopy(
- encodingBuffer,
- encodingOffset,
- tempBuffer,
- 0,
- copyingSize );
-
- encodingOffset += copyingSize;
- tempBufferRemaining -= copyingSize;
- finalCopySize += copyingSize;
- }
-
- if (encodingOffset == encodingBuffer.length)
- {
- isBufferFilled = true;
-
- int encodedBytes = sipCodec.pcmToCodec( encodingBuffer,
codedBuffer );
-
- //println( "fillRtpPacketBuffer",
- // "encodedBytes = " + encodedBytes +
- // ", outgoingEncodedFrameSize = " +
sipCodec.getOutgoingEncodedFrameSize() + "." );
-
- if ( encodedBytes ==
sipCodec.getOutgoingEncodedFrameSize() ) {
-
- BufferUtils.byteBufferIndexedCopy( packetBuffer,
- RTP_HEADER_SIZE, codedBuffer, 0,
codedBuffer.length );
- }
- else {
- //println( "fillRtpPacketBuffer", "Failure encoding
buffer." );
- }
- }
-
- //println( "fillRtpPacketBuffer",
- // "finalCopySize = " + finalCopySize
- // + ", isBufferFilled = " + isBufferFilled
- // + ", encodingOffset = " + encodingOffset
- // + ", tempBufferRemaining = " + tempBufferRemaining
+ "." );
- }
- catch ( Exception e ) {
- e.printStackTrace();
- }
-
- return finalCopySize;
- }
-
- public void send( int streamId, byte[] asaoInput, int offset, int num
) {
- if(this.useASAO) {
- sendASAO(streamId, asaoInput, offset, num);
- } else {
- sendRaw(streamId, asaoInput, offset, num);
- }
- }
-
- public void sendRaw( int streamId, byte[] asaoInput, int offset, int
num ) {
-
- if ( rtpSocket == null ) {
- return;
- }
-
- if ( num > 0 ) {
-
- byte [] asaoBuffer = new byte[num];
- System.arraycopy(asaoInput, offset, packetBuffer,
RTP_HEADER_SIZE, num);
-
- Random.setSeed(streamId);
- rtpPacket.setSscr(Random.nextLong());
- rtpPacket.setSequenceNumber( seqn++);
- rtpPacket.setTimestamp( time );
- rtpPacket.setPayloadLength(
sipCodec.getOutgoingEncodedFrameSize() );
- rtpSocketSend( rtpPacket );
-
- } else if ( num < 0 ) {
-
- println( "send", "Closing" );
- }
- }
-
-
- public void sendASAO(int streamId, byte[] asaoBuffer, int offset, int
num) {
-
+ protected void send(RtpPacket rtpPacket) {
if ( rtpSocket == null ) {
return;
}
-
- asao_buffer_processed = false;
-
- if ( !hasInitilializedBuffers ) {
-
- tempBuffer = new float[ NELLYMOSER_DECODED_PACKET_SIZE ];
- encodingBuffer = new float[
sipCodec.getOutgoingDecodedFrameSize() ];
-
- hasInitilializedBuffers = true;
- }
-
- //println( "send",
- // "asaoBuffer.length = [" + asaoBuffer.length + "], offset
= ["
- // + offset + "], num = [" + num + "]." );
-
- if ( num > 0 ) {
-
- do {
-
- int encodedBytes = fillRtpPacketBuffer( asaoBuffer );
-
- //println( "send", sipCodec.getCodecName() + " encoded " +
encodedBytes + " bytes." );
-
- if ( encodedBytes == 0 ) {
-
- break;
- }
-
- if ( encodingOffset ==
sipCodec.getOutgoingDecodedFrameSize() ) {
-
- //println( "send", "Seding packet with " +
encodedBytes + " bytes." );
-
- try {
- Random.setSeed(streamId);
- rtpPacket.setSscr(Random.nextLong());
- rtpPacket.setSequenceNumber(seqn++);
- rtpPacket.setTimestamp(time);
-
rtpPacket.setPayloadLength(sipCodec.getOutgoingEncodedFrameSize());
- rtpSocketSend( rtpPacket );
- }
- catch ( Exception e ) {
- println( "send", sipCodec.getCodecName() + "
encoder error." );
- }
-
- encodingOffset = 0;
- }
-
- //println( "send", "asao_buffer_processed = ["
- // + asao_buffer_processed + "] ." );
- }
- while ( !asao_buffer_processed );
- }
- else if ( num < 0 ) {
- println( "send", "Closing" );
- }
+ rtpPacket.setSequenceNumber(seqn++);
+ rtpSocketSend( rtpPacket );
}
@@ -438,7 +194,6 @@
private void doRtpDelay() {
-
try {
Thread.sleep( sipCodec.getOutgoingPacketization() - 2 );
}
@@ -448,17 +203,15 @@
private synchronized void rtpSocketSend(RtpPacket rtpPacket) {
-
try {
rtpSocket.send( rtpPacket );
- time += sipCodec.getOutgoingDecodedFrameSize();
+ System.out.println(rtpPacket.getSscr() + " : " +
rtpPacket.getTimestamp());
}
catch ( Exception e ) {
}
}
private static void println( String method, String message ) {
-
log.debug( "RTPStreamSender - " + method + " -> " + message );
System.out.println( "RTPStreamSender - " + method + " -> " +
message );
}
=======================================
--- /branches/red5sip/src/java/org/red5/sip/app/SIPAudioLauncher.java Tue
Jan 29 03:52:07 2013
+++ /branches/red5sip/src/java/org/red5/sip/app/SIPAudioLauncher.java Wed
Feb 6 09:31:44 2013
@@ -36,10 +36,10 @@
"sender configs: payloadType = [" +
sipCodec.getCodecId() +
"], payloadName = [" + sipCodec.getCodecName() + "].");
- sender = new RTPStreamSender( mediaReceiver, false,
- sipCodec, socket, remoteAddr, remotePort );
-// sender = new RTPStreamMultiplexingSender( mediaReceiver,
false,
+// sender = new RTPStreamSender( mediaReceiver, false,
// sipCodec, socket, remoteAddr, remotePort );
+ sender = new RTPStreamMultiplexingSender( mediaReceiver, false,
+ sipCodec, socket, remoteAddr, remotePort );
printLog( "SIPAudioLauncher", "New audio receiver on " +
localPort + "." );