diff --git a/src/net/java/sip/communicator/impl/neomedia/MediaStreamImpl.java b/src/net/java/sip/communicator/impl/neomedia/MediaStreamImpl.java index 16f97feb6..2d02d5bed 100644 --- a/src/net/java/sip/communicator/impl/neomedia/MediaStreamImpl.java +++ b/src/net/java/sip/communicator/impl/neomedia/MediaStreamImpl.java @@ -17,6 +17,8 @@ import javax.media.rtp.*; import javax.media.rtp.event.*; +import com.sun.media.rtp.*; + import net.java.sip.communicator.impl.neomedia.device.*; import net.java.sip.communicator.impl.neomedia.format.*; import net.java.sip.communicator.impl.neomedia.transform.*; @@ -129,12 +131,18 @@ public class MediaStreamImpl /** * The SSRC identifier of the party that we are exchanging media with. */ - private String remoteSourceID = null; + private long remoteSourceID = -1; /** * Our own SSRC identifier. */ - private String localSourceID = null; + private long localSourceID = -1; + + /** + * The list of CSRC IDs that the remote party reported as contributing to + * the media they are sending toward us. + */ + private long[] remoteContributingSourceIDList = new long[0]; /** * The indicator which determines whether this MediaStream is set @@ -164,6 +172,8 @@ public MediaStreamImpl(StreamConnector connector, MediaDevice device) setDevice(device); this.rtpConnector = new RTPTransformConnector(connector); + + } /** @@ -419,8 +429,7 @@ public MediaDirection getDirection() MediaDeviceSession deviceSession = getDeviceSession(); - return - (deviceSession == null) + return (deviceSession == null) ? MediaDirection.INACTIVE : deviceSession.getDevice().getDirection(); } @@ -445,8 +454,7 @@ public Map getDynamicRTPPayloadTypes() { synchronized (dynamicRTPPayloadTypes) { - return - new HashMap(dynamicRTPPayloadTypes); + return new HashMap(dynamicRTPPayloadTypes); } } @@ -465,16 +473,15 @@ public MediaFormat getFormat() /** * Gets the synchronization source (SSRC) identifier of the local peer or - * null if it is not yet known. + * -1 if it is not yet known. * * @return the synchronization source (SSRC) identifier of the local peer - * or null if it is not yet known + * or -1 if it is not yet known * @see MediaStream#getLocalSourceID() */ - public String getLocalSourceID() + public long getLocalSourceID() { - // TODO Auto-generated method stub - return null; + return this.localSourceID; } /** @@ -486,8 +493,7 @@ public String getLocalSourceID() */ public InetSocketAddress getRemoteControlAddress() { - return - (InetSocketAddress) + return (InetSocketAddress) rtpConnector.getControlSocket().getRemoteSocketAddress(); } @@ -500,20 +506,19 @@ public InetSocketAddress getRemoteControlAddress() */ public InetSocketAddress getRemoteDataAddress() { - return - (InetSocketAddress) + return (InetSocketAddress) rtpConnector.getDataSocket().getRemoteSocketAddress(); } /** * Get the synchronization source (SSRC) identifier of the remote peer or - * null if it is not yet known. + * -1 if it is not yet known. * * @return the synchronization source (SSRC) identifier of the remote - * peer or null if it is not yet known + * peer or -1 if it is not yet known * @see MediaStream#getRemoteSourceID() */ - public String getRemoteSourceID() + public long getRemoteSourceID() { return remoteSourceID; } @@ -579,9 +584,7 @@ private RTPManager getRTPManager() //JMF inits the local SSRC upon initialize(RTPConnector) so now's //the time to ask: - setLocalSourceID(Long.toHexString( - (((com.sun.media.rtp.RTPSessionMgr) - rtpManager).getLocalSSRC()))); + setLocalSourceID(((RTPSessionMgr)rtpManager).getLocalSSRC()); createSendStreams(); } @@ -1256,7 +1259,7 @@ public void update(ReceiveStreamEvent event) logger.trace("Received new ReceiveStream with ssrc " + receiveStream.getSSRC()); - setRemoteSourceID( Long.toHexString( receiveStream.getSSRC() )); + setRemoteSourceID( receiveStream.getSSRC() ); synchronized (receiveStreams) { @@ -1326,9 +1329,9 @@ public void update(SessionEvent event) * @param ssrc the SSRC identifier that this stream will be using in * outgoing RTP packets from now on. */ - private void setLocalSourceID(String ssrc) + private void setLocalSourceID(long ssrc) { - String oldValue = this.localSourceID; + Long oldValue = this.localSourceID; this.localSourceID = ssrc; firePropertyChange(PNAME_LOCAL_SSRC, oldValue, ssrc); @@ -1341,11 +1344,64 @@ private void setLocalSourceID(String ssrc) * @param ssrc the SSRC identifier that this stream will be using in * outgoing RTP packets from now on. */ - private void setRemoteSourceID(String ssrc) + private void setRemoteSourceID(long ssrc) { - String oldValue = this.remoteSourceID; + Long oldValue = this.remoteSourceID; this.remoteSourceID = ssrc; firePropertyChange(PNAME_REMOTE_SSRC, oldValue, ssrc); } + + /** + * Returns the list of CSRC identifiers for all parties currently known + * to contribute to the media that this stream is sending toward its remote + * counter part. In other words, the method returns the list of CSRC IDs + * that this stream will include in outgoing RTP packets. This method will + * return an empty List in case this stream is not part of a mixed + * conference call. + * + * @return a List of CSRC IDs for parties that are currently known + * to contribute to the media that this stream is currently streaming or + * an empty List in case this MediaStream is not part of + * a conference call. + */ + public List getLocalContributingSourceIDs() + { + List csrcList = new ArrayList(); + + MediaDeviceSession deviceSession = getDeviceSession(); + if( this.deviceSession != null) + csrcList.addAll( deviceSession.getRemoteSSRCList() ); + + Iterator csrcIter = csrcList.iterator(); + + //in case of a conf call the mixer would return all SSRC IDs that are + //currently contributing including this stream's counterpart. This + //method is about + while(csrcIter.hasNext()) + { + String csrc = csrcIter.next(); + + if (csrc.equals(getRemoteSourceID())) + csrcIter.remove(); + } + + return csrcList; + } + + /** + * Returns the List of CSRC identifiers representing the parties + * contributing to the stream that we are receiving from this + * MediaStream's remote party. + * + * @return a List of CSRC identifiers representing the parties + * contributing to the stream that we are receiving from this + * MediaStream's remote party. + */ + public List getRemoteContributingSourceIDs() + { + List csrcList = new ArrayList(); + + return csrcList; + } } diff --git a/src/net/java/sip/communicator/impl/neomedia/RawPacket.java b/src/net/java/sip/communicator/impl/neomedia/RawPacket.java index d46d5d2d8..d374bd5c6 100755 --- a/src/net/java/sip/communicator/impl/neomedia/RawPacket.java +++ b/src/net/java/sip/communicator/impl/neomedia/RawPacket.java @@ -6,6 +6,9 @@ */ package net.java.sip.communicator.impl.neomedia; +import java.math.*; +import java.util.*; + /** * When using TransformConnector, a RTP/RTCP packet is represented using * RawPacket. RawPacket stores the buffer holding the RTP/RTCP packet, as well @@ -19,6 +22,7 @@ * * @author Werner Dittmann (Werner.Dittmann@t-online.de) * @author Bing SU (nova.su@gmail.com) + * @author Emil Ivov */ public class RawPacket { @@ -39,6 +43,11 @@ public class RawPacket */ protected int length; + /** + * The size of the fixed part of the RTP header as defined by RFC 3550. + */ + public static final int FIXED_HEADER_SIZE = 12; + /** * Construct a RawPacket using specified value. * @@ -237,4 +246,100 @@ public void shrink(int len) this.length = 0; } } + + /** + * Returns the number of CSRC identifiers currently included in this packet. + * + * @return the CSRC count for this RawPacket. + */ + public int getCsrcCount() + { + return (buffer[offset] & 0x0fb); + } + + /** + * Replaces the existing CSRC list (even if empty) with newCsrcList + * and updates the CC (CSRC count) field of this RawPacket + * accordingly. + * + * @param newCsrcList the list of CSRC identifiers that we'd like to set for + * this RawPacket. + */ + public void setCsrcList(long[] newCsrcList) + { + int newCsrcCount = newCsrcList.length; + byte[] csrcBuff = new byte[newCsrcCount * 4]; + int csrcOffset = 0; + + for(long csrc : newCsrcList) + { + csrcBuff[csrcOffset] = (byte)(csrc >> 24); + csrcBuff[csrcOffset+1] = (byte)(csrc >> 16); + csrcBuff[csrcOffset+2] = (byte)(csrc >> 8); + csrcBuff[csrcOffset+3] = (byte)csrc; + + csrcOffset += 4; + } + + int oldCsrcCount = getCsrcCount(); + + byte[] oldBuffer = this.getBuffer(); + + //the new buffer needs to be bigger than the new one in order to + //accommodate the list of CSRC IDs (unless there were more of them + //previously than after setting the new list). + byte[] newBuffer + = new byte[oldBuffer.length + csrcBuff.length - oldCsrcCount*4]; + + //copy the part up to the CSRC list + System.arraycopy( + oldBuffer, 0, newBuffer, 0, offset + FIXED_HEADER_SIZE); + + //copy the new CSRC list + System.arraycopy( csrcBuff, 0, newBuffer, + offset + FIXED_HEADER_SIZE, csrcBuff.length); + + //now copy the payload from the old buff and make sure we don't copy + //the CSRC list if there was one in the old packet + int payloadOffsetForOldBuff + = offset + FIXED_HEADER_SIZE + oldCsrcCount*4; + + int payloadOffsetForNewBuff + = offset + FIXED_HEADER_SIZE + newCsrcCount*4; + + System.arraycopy( oldBuffer, payloadOffsetForOldBuff, + newBuffer, payloadOffsetForNewBuff, + csrcBuff.length - payloadOffsetForOldBuff); + + //set the new CSRC count + newBuffer[offset] = (byte)((newBuffer[offset] & 0xF0b) + & newCsrcCount); + } + + /** + * Returns the list of CSRC IDs, currently encapsulated in this packet. + * + * @return an array containing the list of CSRC IDs, currently encapsulated + * in this packet. + */ + public long[] extractCsrcList() + { + int csrcCount = getCsrcCount(); + byte[] buffer = getBuffer(); + + long[] csrcList = new long[csrcCount]; + + int csrcStartIndex = offset + FIXED_HEADER_SIZE; + for (int i = 0; i < csrcCount; i++) + { + csrcList[i] = buffer[csrcStartIndex] << 24 + & buffer[csrcStartIndex + 1] << 16 + & buffer[csrcStartIndex + 2] << 8 + & buffer[csrcStartIndex + 3]; + + csrcStartIndex += 4; + } + + return csrcList; + } } diff --git a/src/net/java/sip/communicator/impl/neomedia/transform/TransformEngineChain.java b/src/net/java/sip/communicator/impl/neomedia/transform/TransformEngineChain.java index 2c545c32c..f77470783 100644 --- a/src/net/java/sip/communicator/impl/neomedia/transform/TransformEngineChain.java +++ b/src/net/java/sip/communicator/impl/neomedia/transform/TransformEngineChain.java @@ -116,7 +116,10 @@ public RawPacket transform(RawPacket pkt) ? engine.getRTPTransformer() : engine.getRTCPTransformer(); - pkt = pTransformer.transform(pkt); + //the packet transformer may be null if for example the engine + //only does RTP transformations and this is an RTCP transformer. + if( pTransformer != null) + pkt = pTransformer.transform(pkt); } return pkt; @@ -144,7 +147,10 @@ public RawPacket reverseTransform(RawPacket pkt) ? engine.getRTPTransformer() : engine.getRTCPTransformer(); - pkt = pTransformer.reverseTransform(pkt); + //the packet transformer may be null if for example the engine + //only does RTP transformations and this is an RTCP transformer. + if( pTransformer != null) + pkt = pTransformer.reverseTransform(pkt); } return pkt; diff --git a/src/net/java/sip/communicator/impl/protocol/sip/OperationSetTelephonyConferencingSipImpl.java b/src/net/java/sip/communicator/impl/protocol/sip/OperationSetTelephonyConferencingSipImpl.java index 83346ada1..c4b202ea9 100644 --- a/src/net/java/sip/communicator/impl/protocol/sip/OperationSetTelephonyConferencingSipImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/sip/OperationSetTelephonyConferencingSipImpl.java @@ -626,7 +626,7 @@ private void getMediaXML(CallPeerSipImpl callPeer, StringBuffer xml) // append(xml, ""); - String srcId = stream.getRemoteSourceID(); + String srcId = Long.toString(stream.getRemoteSourceID()); if (srcId != null) { diff --git a/src/net/java/sip/communicator/service/neomedia/MediaStream.java b/src/net/java/sip/communicator/service/neomedia/MediaStream.java index c5fa7fde2..1b93e04a7 100644 --- a/src/net/java/sip/communicator/service/neomedia/MediaStream.java +++ b/src/net/java/sip/communicator/service/neomedia/MediaStream.java @@ -97,25 +97,25 @@ public interface MediaStream /** * Returns the synchronization source (SSRC) identifier of the remote - * participant or null if that identifier is not yet known at this + * participant or -1 if that identifier is not yet known at this * point. * * @return the synchronization source (SSRC) identifier of the remote - * participant or null if that identifier is not yet known at this + * participant or -1 if that identifier is not yet known at this * point. */ - public String getRemoteSourceID(); + public long getRemoteSourceID(); /** * Returns the synchronization source (SSRC) identifier of the local - * participant or null if that identifier is not yet known at this + * participant or -1 if that identifier is not yet known at this * point. * * @return the synchronization source (SSRC) identifier of the local - * participant or null if that identifier is not yet known at this + * participant or -1 if that identifier is not yet known at this * point. */ - public String getLocalSourceID(); + public long getLocalSourceID(); /** * Returns the address that this stream is sending RTCP traffic to.