You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@openmeetings.apache.org by co...@google.com on 2013/02/21 18:13:20 UTC

[red5phone] r97 committed - Unstable video support is removed

Revision: 97
Author:   solomax666@gmail.com
Date:     Thu Feb 21 09:13:01 2013
Log:      Unstable video support is removed
http://code.google.com/p/red5phone/source/detail?r=97

Deleted:
  /branches/red5sip/src/java/org/red5/codecs/SIPCodecH264.java
  /branches/red5sip/src/java/org/red5/sip/app/RTPStreamVideoReceiver.java
  /branches/red5sip/src/java/org/red5/sip/app/SIPVideoLauncher.java
Modified:
  /branches/red5sip/src/java/org/red5/codecs/SIPCodec.java
  /branches/red5sip/src/java/org/red5/codecs/SIPCodecFactory.java
  /branches/red5sip/src/java/org/red5/sip/app/Application.java
  /branches/red5sip/src/java/org/red5/sip/app/IMediaReceiver.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/SIPTransport.java
  /branches/red5sip/src/java/org/red5/sip/app/SIPUserAgent.java
  /branches/red5sip/src/java/org/red5/sip/app/SIPUserAgentProfile.java
  /branches/red5sip/src/java/org/red5/sip/app/SdpUtils.java
  /branches/red5sip/src/java/org/zoolu/sdp/SessionDescriptor.java

=======================================
--- /branches/red5sip/src/java/org/red5/codecs/SIPCodecH264.java	Tue Feb 19  
11:33:08 2013
+++ /dev/null
@@ -1,114 +0,0 @@
-package org.red5.codecs;
-
-public class SIPCodecH264 implements SIPCodec {
-
-	private static final String codecName = "H264";
-	private static final int codecId = 35;
-	private static int defaultEncodedFrameSize = 160;
-    private static int defaultDecodedFrameSize = 160;
-	private int outgoingPacketization = 90000;
-    private int incomingPacketization = 90000;
-
-	@Override
-	public void encodeInit(int defaultEncodePacketization) {
-		if (this.outgoingPacketization == 0) {
-            this.outgoingPacketization = defaultEncodePacketization;
-        }
-	}
-
-	@Override
-	public void decodeInit(int defaultDecodePacketization) {
-		if (this.incomingPacketization == 0) {
-            this.incomingPacketization = defaultDecodePacketization;
-        }
-	}
-
-	@Override
-	public String codecNegotiateAttribute(String attributeName,
-			String localAttributeValue, String remoteAttributeValue) {
-		// TODO Auto-generated method stub
-		return null;
-	}
-
-	@Override
-	public int getCodecBlankPacket(byte[] buffer, int offset) {
-		// TODO Auto-generated method stub
-		return 0;
-	}
-
-	@Override
-	public int pcmToCodec(float[] bufferIn, byte[] bufferOut) {
-		// TODO Auto-generated method stub
-		return 0;
-	}
-
-	@Override
-	public int codecToPcm(byte[] bufferIn, float[] bufferOut) {
-		// TODO Auto-generated method stub
-		return 0;
-	}
-
-	@Override
-	public int getIncomingEncodedFrameSize() {
-		return (defaultEncodedFrameSize / SIPCodec.DEFAULT_PACKETIZATION) *  
incomingPacketization;
-	}
-
-	@Override
-	public int getIncomingDecodedFrameSize() {
-		return (defaultDecodedFrameSize / SIPCodec.DEFAULT_PACKETIZATION) *  
incomingPacketization;
-	}
-
-	@Override
-	public int getOutgoingEncodedFrameSize() {
-		return (defaultEncodedFrameSize / SIPCodec.DEFAULT_PACKETIZATION) *  
outgoingPacketization;
-	}
-
-	@Override
-	public int getOutgoingDecodedFrameSize() {
-		return (defaultDecodedFrameSize / SIPCodec.DEFAULT_PACKETIZATION) *  
outgoingPacketization;
-	}
-
-	@Override
-	public int getSampleRate() {
-		return 90000;
-	}
-
-	@Override
-	public String getCodecName() {
-		return codecName;
-	}
-
-	@Override
-	public int getCodecId() {
-		return codecId;
-	}
-
-	@Override
-	public int getIncomingPacketization() {
-		return (defaultEncodedFrameSize / SIPCodec.DEFAULT_PACKETIZATION) *  
incomingPacketization;
-	}
-
-	@Override
-	public int getOutgoingPacketization() {
-		return 2048;//( defaultDecodedFrameSize / SIPCodec.DEFAULT_PACKETIZATION  
) * outgoingPacketization;
-	}
-
-	@Override
-	public void setLocalPtime(int localPtime) {
-		// TODO Auto-generated method stub
-
-	}
-
-	@Override
-	public void setRemotePtime(int remotePtime) {
-		// TODO Auto-generated method stub
-
-	}
-
-	@Override
-	public String[] getCodecMediaAttributes() {
-		// TODO Auto-generated method stub
-		return null;
-	}
-
-}
=======================================
--- /branches/red5sip/src/java/org/red5/sip/app/RTPStreamVideoReceiver.java	 
Tue Feb 19 11:33:08 2013
+++ /dev/null
@@ -1,50 +0,0 @@
-package org.red5.sip.app;
-
-import java.net.DatagramSocket;
-import org.red5.codecs.SIPCodec;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import local.net.RtpPacket;
-import local.net.RtpSocket;
-
-public class RTPStreamVideoReceiver extends Thread {
-
-	protected static Logger log =  
LoggerFactory.getLogger(RTPStreamVideoReceiver.class);
-	public static int RTP_HEADER_SIZE = 12;
-	protected RtpSocket rtpSocket;
-	protected IMediaReceiver mediaReceiver;
-	protected SIPCodec codec;
-	private boolean running;
-
-	public RTPStreamVideoReceiver(IMediaReceiver mediaReceiver,  
DatagramSocket socket, SIPCodec codec) {
-		this.mediaReceiver = mediaReceiver;
-		rtpSocket = new RtpSocket(socket);
-		this.codec = codec;
-	}
-
-	@Override
-	public void interrupt() {
-		running = false;
-	}
-
-	@Override
-	public void run() {
-		running = true;
-
-		try {
-			while(running) {
-				byte[] sourceBuffer = new byte[codec.getIncomingDecodedFrameSize()];
-				RtpPacket rtpPacket = new RtpPacket(sourceBuffer, 0);
-				rtpSocket.receive(rtpPacket);
-				byte[] destBuffer = new byte[rtpPacket.getLength() -  
rtpPacket.getHeaderLength()];
-				System.arraycopy(sourceBuffer, rtpPacket.getHeaderLength(),  
destBuffer, 0, destBuffer.length);
-				mediaReceiver.pushVideo(destBuffer, rtpPacket.getTimestamp(),  
codec.getCodecId());
-			}
-		} catch (Exception e) {
-			log.error("", e);
-		}
-		rtpSocket.close();
-	}
-
-}
=======================================
--- /branches/red5sip/src/java/org/red5/sip/app/SIPVideoLauncher.java	Tue  
Feb 19 11:33:08 2013
+++ /dev/null
@@ -1,39 +0,0 @@
-package org.red5.sip.app;
-
-import java.net.DatagramSocket;
-
-import org.red5.codecs.SIPCodec;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import local.ua.MediaLauncher;
-
-public class SIPVideoLauncher implements MediaLauncher {
-
-	protected static Logger log =  
LoggerFactory.getLogger(SIPVideoLauncher.class);
-	protected DatagramSocket socket;
-	protected RTPStreamVideoReceiver receiver;
-
-	public SIPVideoLauncher(int localPort, String remoteAddr, int remotePort,  
IMediaReceiver mediaReceiver, SIPCodec codec) {
-		try {
-			socket = new DatagramSocket(localPort);
-			receiver = new RTPStreamVideoReceiver(mediaReceiver, socket, codec);
-		} catch (Exception e) {
-			log.error("", e);
-		}
-	}
-
-	@Override
-	public boolean startMedia() {
-		log.debug("startMedia()");
-		receiver.start();
-		return true;
-	}
-
-	@Override
-	public boolean stopMedia() {
-		log.debug("stopMedia()");
-		return false;
-	}
-
-}
=======================================
--- /branches/red5sip/src/java/org/red5/codecs/SIPCodec.java	Tue Feb 19  
11:33:08 2013
+++ /branches/red5sip/src/java/org/red5/codecs/SIPCodec.java	Thu Feb 21  
09:13:01 2013
@@ -2,7 +2,7 @@


  /**
- * Interface for media codecs
+ * Interface for audio codecs
   * */
  public interface SIPCodec {

=======================================
--- /branches/red5sip/src/java/org/red5/codecs/SIPCodecFactory.java	Tue Feb  
19 11:33:08 2013
+++ /branches/red5sip/src/java/org/red5/codecs/SIPCodecFactory.java	Thu Feb  
21 09:13:01 2013
@@ -26,10 +26,8 @@
      // ----------------
      // Available video codecs

-    private static final int videoCodecH264 = 35;
+    private int[] availableVideoCodecsId = {};

-    private int[] availableVideoCodecsId = {videoCodecH264};
-

      private static SIPCodecFactory singletonSIPCodecFactory = new  
SIPCodecFactory();

@@ -45,7 +43,7 @@
       * Create a new instance of SIPCodec by codec id.
       * @return The codec associated with "codecId".
       * */
-    public SIPCodec getSIPMediaCodec( int codecId ) {
+    public SIPCodec getSIPAudioCodec( int codecId ) {

          SIPCodec sipCodec;

@@ -66,9 +64,6 @@
              case audioCodeciLBC:
                  sipCodec = new SIPCodeciLBC();
                  break;
-            case videoCodecH264:
-            	sipCodec = new SIPCodecH264();
-            	break;
              default:
                  sipCodec = null;
          }
@@ -95,7 +90,7 @@

          for ( int i = 0; i < availableAudioCodecsId.length; i++ ) {
              int codecId = availableAudioCodecsId[ i ];
-            SIPCodec codec = getSIPMediaCodec( codecId );
+            SIPCodec codec = getSIPAudioCodec( codecId );
              availableCodecs[i] = codec;
          }

@@ -115,7 +110,7 @@

          for ( int i = 0; i < availableVideoCodecsId.length; i++ ) {
              int codecId = availableVideoCodecsId[ i ];
-            SIPCodec codec = getSIPMediaCodec( codecId );
+            SIPCodec codec = getSIPAudioCodec( codecId );
              availableCodecs[i] = codec;
          }

@@ -148,7 +143,7 @@
              printLog( "getAvailableAudioCodecsWithPrecedence",
                      "codecId = [" + codecId + "]." );

-            SIPCodec sipCodec = getSIPMediaCodec(
+            SIPCodec sipCodec = getSIPAudioCodec(
                      Integer.valueOf( codecId ).intValue() );

              if ( sipCodec != null ) {
=======================================
--- /branches/red5sip/src/java/org/red5/sip/app/Application.java	Tue Feb 19  
11:33:08 2013
+++ /branches/red5sip/src/java/org/red5/sip/app/Application.java	Thu Feb 21  
09:13:01 2013
@@ -16,23 +16,21 @@
      private static final Logger log =  
LoggerFactory.getLogger(Application.class);
      private static final int SIP_START_PORT = 5070;
      private static final int SOUND_START_PORT = 3010;
-    private static final int VIDEO_START_PORT = 7010;
      private static int sipPort = SIP_START_PORT;
      private static int soundPort = SOUND_START_PORT;
-    private static int videoPort = VIDEO_START_PORT;
      private Properties props = null;
      private Map<Integer, SIPTransport> transportMap = new HashMap<Integer,  
SIPTransport>();
      private RTMPControlClient rtmpControlClient;

-    public SIPTransport createSIPTransport(Properties prop, int room_id) {
+    private SIPTransport createSIPTransport(Properties prop, int room_id) {
          log.info("Creating SIP trasport for room: " + room_id);
          RTPStreamSender.useASAO =  
prop.getProperty("red5.codec", "asao").equals("asao");
          RTMPRoomClient roomClient = new RTMPRoomClient(
  			prop.getProperty("red5.host")
  			, prop.getProperty("om.context", "openmeetings")
  			, room_id);
-
-        SIPTransport sipTransport = new SIPTransport(roomClient,  
sipPort++, soundPort++, videoPort++) {
+
+        SIPTransport sipTransport = new SIPTransport(roomClient,  
sipPort++, soundPort++) {
              public void onUaRegistrationSuccess(SIPRegisterAgent ra,  
NameAddress target, NameAddress contact, String result) {
                  log.info("Registered successfully");
                  this.roomClient.setSipNumberListener(this);
=======================================
--- /branches/red5sip/src/java/org/red5/sip/app/IMediaReceiver.java	Tue Feb  
19 11:33:08 2013
+++ /branches/red5sip/src/java/org/red5/sip/app/IMediaReceiver.java	Thu Feb  
21 09:13:01 2013
@@ -6,8 +6,6 @@

      void pushAudio( byte[] audio, long ts, int codec ) throws IOException;

-    void pushVideo( byte[] video, long ts, int codec ) throws IOException;
-
      void setSender( IMediaSender sender );

  }
=======================================
--- /branches/red5sip/src/java/org/red5/sip/app/PlayNetStream.java	Tue Feb  
19 11:33:08 2013
+++ /branches/red5sip/src/java/org/red5/sip/app/PlayNetStream.java	Thu Feb  
21 09:13:01 2013
@@ -17,8 +17,6 @@

      private int audioTs = 0;

-    private int videoTs = 0;
-
      private IMediaSender mediaSender;

      private IMediaStream mediaStream;
@@ -65,8 +63,8 @@
          }

          if (rtmpEvent instanceof VideoData) {
-             videoTs += rtmpEvent.getTimestamp();
-             //tag.setTimestamp(videoTs);
+            // videoTs += rtmpEvent.getTimestamp();
+            // tag.setTimestamp(videoTs);

          } else if (rtmpEvent instanceof AudioData) {
              audioTs = rtmpEvent.getTimestamp();
=======================================
--- /branches/red5sip/src/java/org/red5/sip/app/RTMPRoomClient.java	Wed Feb  
20 23:59:07 2013
+++ /branches/red5sip/src/java/org/red5/sip/app/RTMPRoomClient.java	Thu Feb  
21 09:13:01 2013
@@ -2,7 +2,6 @@

  import java.io.IOException;
  import java.lang.reflect.Field;
-import java.util.Arrays;
  import java.util.Collection;
  import java.util.HashMap;
  import java.util.HashSet;
@@ -28,7 +27,6 @@
  import org.red5.server.net.rtmp.codec.RTMP;
  import org.red5.server.net.rtmp.event.AudioData;
  import org.red5.server.net.rtmp.event.Notify;
-import org.red5.server.net.rtmp.event.VideoData;
  import org.red5.server.net.rtmp.message.Header;
  import org.red5.server.net.rtmp.status.StatusCodes;
  import org.red5.server.service.Call;
@@ -47,8 +45,7 @@
      private long broadCastId = -1;
      private RTMPConnection conn;
      private IMediaSender sender;
-    private IoBuffer audioBuffer;
-    private IoBuffer videoBuffer;
+    private IoBuffer buffer;
      private int kt = 0;
      private Integer publishStreamId = null;
      private boolean reconnect = true;
@@ -330,10 +327,8 @@
                      this.conn.close();
                  } else if("updateMuteStatus".equals(msgValue.get(0))) {
                      Client client = (Client)msgValue.get(1);
-                    if (this.publicSID.equals(client.getPublicSID())) {
-	                    log.info("Mic switched: " + client.getMicMuted());
-	                    this.micMuted = client.getMicMuted();
-                    }
+                    log.info("Mic switched: " + client.getMicMuted());
+                    this.micMuted = client.getMicMuted();
                  }
              } catch (Exception ignored) {}
          }
@@ -474,21 +469,21 @@
          if( publishStreamId == null) {
              return;
          }
-        if ( audioBuffer == null ) {
-            audioBuffer = IoBuffer.allocate( 1024 );
-            audioBuffer.setAutoExpand( true );
+        if ( buffer == null ) {
+            buffer = IoBuffer.allocate( 1024 );
+            buffer.setAutoExpand( true );
          }

-        audioBuffer.clear();
+        buffer.clear();

-        audioBuffer.put( (byte) codec ); // first byte 2 mono 5500; 6 mono  
11025; 22
+        buffer.put( (byte) codec ); // first byte 2 mono 5500; 6 mono  
11025; 22
          // mono 11025 adpcm 82 nellymoser 8000 178
          // speex 8000
-        audioBuffer.put( audio );
+        buffer.put( audio );

-        audioBuffer.flip();
+        buffer.flip();

-        AudioData audioData = new AudioData( audioBuffer );
+        AudioData audioData = new AudioData( buffer );
          audioData.setTimestamp( (int) ts );

          kt++;
@@ -500,28 +495,4 @@
          rtmpMsg.setBody( audioData );
          publishStreamData( publishStreamId, rtmpMsg );
      }
-
-	@Override
-	public void pushVideo(byte[] video, long ts, int codec) throws  
IOException {
-		if( publishStreamId == null) {
-            return;
-        }
-		if (videoBuffer == null || (videoBuffer.capacity() < video.length  
&& !videoBuffer.isAutoExpand())) {
-			videoBuffer = IoBuffer.allocate(video.length);
-			videoBuffer.setAutoExpand(true);
-		}
-
-		videoBuffer.clear();
-		//videoBuffer.put((byte) codec);
-		videoBuffer.put(video);
-		videoBuffer.flip();
-
-		VideoData videoData = new VideoData(videoBuffer);
-		videoData.setTimestamp((int) ts);
-
-		RTMPMessage message = new RTMPMessage();
-		message.setBody(videoData);
-
-		publishStreamData(publishStreamId, message);
-	}
  }
=======================================
--- /branches/red5sip/src/java/org/red5/sip/app/SIPTransport.java	Tue Feb  
19 11:33:08 2013
+++ /branches/red5sip/src/java/org/red5/sip/app/SIPTransport.java	Thu Feb  
21 09:13:01 2013
@@ -21,8 +21,7 @@
  	private String username;
  	private String password;
  	private int sipPort;
-	private int rtpAudioPort;
-	private int rtpVideoPort;
+	private int rtpPort;
  	private String proxy;
  	private String number;

@@ -30,11 +29,10 @@
  		log.debug(s);
  	}

-	public SIPTransport(RTMPRoomClient roomClient, int sipPort, int  
rtpAudioPort, int rtpVideoPort) {
+	public SIPTransport(RTMPRoomClient roomClient, int sipPort, int rtpPort) {
  		this.roomClient = roomClient;
  		this.sipPort = sipPort;
-		this.rtpAudioPort = rtpAudioPort;
-		this.rtpVideoPort = rtpVideoPort;
+		this.rtpPort = rtpPort;
  	}

  	public void login(String obproxy, String phone, String username,
@@ -58,8 +56,7 @@
  					.setOutboundProxy(new SocketAddress(opt_outbound_proxy));

  			user_profile = new SIPUserAgentProfile();
-			user_profile.audioPort = rtpAudioPort;
-			user_profile.videoPort = rtpVideoPort;
+			user_profile.audioPort = rtpPort;
  			user_profile.username = username;
  			user_profile.passwd = password;
  			user_profile.realm = realm;
=======================================
--- /branches/red5sip/src/java/org/red5/sip/app/SIPUserAgent.java	Tue Feb  
19 11:33:08 2013
+++ /branches/red5sip/src/java/org/red5/sip/app/SIPUserAgent.java	Thu Feb  
21 09:13:01 2013
@@ -79,11 +79,8 @@
      private IMediaReceiver mediaReceiver;

      /** Sip codec to be used on audio session */
-    private SIPCodec sipAudioCodec = null;
+    private SIPCodec sipCodec = null;

-    /** Sip codec to be used on video session */
-    private SIPCodec sipVideoCodec = null;
-

      // *********************** Startup Configuration  
***********************

@@ -472,13 +469,13 @@

              if ( audioApp == null ) {

-                if ( sipAudioCodec != null ) {
+                if ( sipCodec != null ) {

-                    audioApp = new SIPAudioLauncher( sipAudioCodec,  
localAudioPort,
+                    audioApp = new SIPAudioLauncher( sipCodec,  
localAudioPort,
                              remoteMediaAddress, remoteAudioPort,  
mediaReceiver);
                  }
                  else {
-                    printLog( "launchMediaApplication", "Audio SipCodec  
not initialized." );
+                    printLog( "launchMediaApplication", "SipCodec not  
initialized." );
                  }
              }

@@ -488,17 +485,15 @@
              }
          }
          if ( userProfile.video && localVideoPort != 0 &&  
remoteVideoPort != 0 ) {
-        	if (videoApp == null) {
-        		if (sipVideoCodec != null) {
-        			videoApp = new SIPVideoLauncher(localVideoPort,  
remoteMediaAddress, remoteAudioPort, mediaReceiver, sipVideoCodec);
-        		} else {
-        			printLog( "launchMediaApplication", "Video SipCodec not  
initialized." );
-        		}
-        	}
-
-            if (videoApp != null) {
-            	videoApp.startMedia();
+
+            if ( videoApp == null ) {
+
+                printLog( "launchMediaApplication",
+                        "No external video application nor JMF has been  
provided: Video not started." );
+                return;
              }
+
+            videoApp.startMedia();
          }
      }

@@ -555,10 +550,9 @@
              // attributes can be then matched.
              SessionDescriptor newSdp =  
SdpUtils.makeMediaPayloadsNegotiation(localSdp, remoteSdp);

-            // After we can create the correct audio and video codecs  
considering
-            // audio and video negotiations made above.
-            sipAudioCodec = SdpUtils.getNegotiatedAudioCodec( newSdp );
-            sipVideoCodec = SdpUtils.getNegotiatedVideoCodec( newSdp );
+            // After we can create the correct audio codec considering
+            // audio negotiation made above.
+            sipCodec = SdpUtils.getNegotiatedAudioCodec( newSdp );

              // Now we complete the SDP negotiation informing the selected
              // codec, so it can be internally updated during the process.
@@ -571,7 +565,7 @@
              // Finally, we use the "newSdp" and "remoteSdp" to initialize
              // the lasting codec informations.
              SIPCodecUtils.initSipAudioCodec(
-                    sipAudioCodec,
+                    sipCodec,
                      userProfile.audioDefaultPacketization,
                      userProfile.audioDefaultPacketization, newSdp,  
remoteSdp );
          }
@@ -653,8 +647,7 @@

          // After we can create the correct audio codec considering
          // audio negotiation made above.
-        sipAudioCodec = SdpUtils.getNegotiatedAudioCodec( newSdp );
-        sipVideoCodec = SdpUtils.getNegotiatedVideoCodec( newSdp );
+        sipCodec = SdpUtils.getNegotiatedAudioCodec( newSdp );

          // Now we complete the SDP negotiation informing the selected
          // codec, so it can be internally updated during the process.
@@ -667,7 +660,7 @@
          // Finally, we use the "newSdp" and "remoteSdp" to initialize
          // the lasting codec informations.
          SIPCodecUtils.initSipAudioCodec(
-                sipAudioCodec,
+                sipCodec,
                  userProfile.audioDefaultPacketization,
                  userProfile.audioDefaultPacketization, newSdp, remoteSdp );

=======================================
--- /branches/red5sip/src/java/org/red5/sip/app/SIPUserAgentProfile.java	 
Tue Feb 19 11:33:08 2013
+++ /branches/red5sip/src/java/org/red5/sip/app/SIPUserAgentProfile.java	 
Thu Feb 21 09:13:01 2013
@@ -128,7 +128,7 @@
      public boolean audio = true;

      /** Whether using video */
-    public boolean video = true;
+    public boolean video = false;

      /** Whether playing in receive only mode */
      public boolean recvOnly = false;
=======================================
--- /branches/red5sip/src/java/org/red5/sip/app/SdpUtils.java	Thu Feb 21  
01:11:26 2013
+++ /branches/red5sip/src/java/org/red5/sip/app/SdpUtils.java	Thu Feb 21  
09:13:01 2013
@@ -14,690 +14,759 @@

  public class SdpUtils {

-	protected static Logger log = LoggerFactory.getLogger(SdpUtils.class);
+    protected static Logger log = LoggerFactory.getLogger( SdpUtils.class  
);
+
+
+    /**
+     * @return Returns the audio codec to be used on current session.
+     */
+    public static SIPCodec getNegotiatedAudioCodec( SessionDescriptor  
negotiatedSDP )
+    {
+        int payloadId;
+        String rtpmap;
+        SIPCodec sipCodec = null;
+
+        printLog( "getNegotiatedAudioCodec", "Init..." );
+
+        rtpmap = negotiatedSDP.getMediaDescriptor(  
SIPCodec.MEDIA_TYPE_AUDIO ).
+                getAttribute( SIPCodec.ATTRIBUTE_RTPMAP  
).getAttributeValue();
+
+        printLog( "getNegotiatedAudioCodec", "rtpmap = [" + rtpmap + "]."  
);
+
+        if ( !rtpmap.isEmpty() ) {
+
+            payloadId = Integer.parseInt(
+                    rtpmap.substring(0, rtpmap.indexOf(" ")));
+
+            printLog( "getNegotiatedAudioCodec", "payloadId = [" +  
payloadId + "]." );
+
+            sipCodec = SIPCodecFactory.getInstance().getSIPAudioCodec(  
payloadId );
+
+            if ( sipCodec == null ) {
+
+                printLog( "getNegotiatedAudioCodec", "Error... codec not  
found." );
+            }
+            else {
+
+                printLog( "getNegotiatedAudioCodec",
+                        "payloadType = " + sipCodec.getCodecId() +
+                        ", payloadName = " + sipCodec.getCodecName() + "."  
);
+            }
+        }
+
+        printLog( "getNegotiatedAudioCodec", "End..." );
+
+        return sipCodec;
+    }
+
+
+    /**
+     *
+     * @param userName
+     * @param viaAddress
+     *
+     * @return Return the initial local SDP.
+     */
+    public static SessionDescriptor createInitialSdp(
+            String userName, String viaAddress, int audioPort,
+            int videoPort, String audioCodecsPrecedence ) {
+
+        SessionDescriptor initialDescriptor = null;
+
+        printLog( "createInitialSdp", "Init..." );
+
+        try {
+
+            printLog( "createInitialSdp",
+                    "userName = [" + userName + "], viaAddress = [" +  
viaAddress +
+                    "], audioPort = [" + audioPort + "], videoPort = [" +  
videoPort +
+                    "], audioCodecsPrecedence = [" + audioCodecsPrecedence  
+ "]." );
+
+            int audioCodecsNumber =  
SIPCodecFactory.getInstance().getAvailableAudioCodecsCount();
+            int videoCodecsNumber =  
SIPCodecFactory.getInstance().getAvailableVideoCodecsCount();
+
+            if ( ( audioCodecsNumber == 0 ) && ( videoCodecsNumber == 0 )  
) {
+
+                printLog( "createInitialSdp",
+                        "audioCodecsNumber = [" + audioCodecsNumber +
+                        "], videoCodecsNumber = [" + videoCodecsNumber  
+ "]." );
+
+                return null;
+            }
+
+            initialDescriptor = new SessionDescriptor( userName,  
viaAddress );
+
+            if ( audioCodecsNumber > 0 ) {
+
+                SIPCodec[] audioCodecs;
+                Vector<AttributeField> audioAttributes = new  
Vector<AttributeField>();
+
+                if ( audioCodecsPrecedence.isEmpty() ) {
+
+                    audioCodecs =  
SIPCodecFactory.getInstance().getAvailableAudioCodecs();
+                }
+                else {
+
+                    audioCodecs = SIPCodecFactory.getInstance().
+                            getAvailableAudioCodecsWithPrecedence(  
audioCodecsPrecedence );
+                }
+
+                for ( int audioIndex = 0; audioIndex < audioCodecsNumber;  
audioIndex++ ) {
+
+                    String payloadId = String.valueOf(  
audioCodecs[audioIndex].getCodecId() );
+                    String rtpmapParamValue = payloadId;
+                    rtpmapParamValue += " " +  
audioCodecs[audioIndex].getCodecName();
+                    rtpmapParamValue += "/" +  
audioCodecs[audioIndex].getSampleRate() + "/1";
+
+                    printLog( "createInitialSdp",
+                            "Adding rtpmap for payload [" + payloadId +
+                            "] with value = [" + rtpmapParamValue + "]." );
+
+                    audioAttributes.add( new AttributeField(
+                            SIPCodec.ATTRIBUTE_RTPMAP, rtpmapParamValue )  
);
+
+                    String[] codecMediaAttributes =
+                             
audioCodecs[audioIndex].getCodecMediaAttributes();
+
+                    if ( codecMediaAttributes != null ) {
+
+                        printLog( "createInitialSdp",
+                                "Adding " + codecMediaAttributes.length +
+                                " audio codec media attributes." );
+
+                        for ( int attribIndex = 0; attribIndex <  
codecMediaAttributes.length; attribIndex++ ) {
+
+                            printLog( "createInitialSdp",
+                                    "Adding audio media attribute [" +
+                                    codecMediaAttributes[attribIndex]  
+ "]." );
+
+                            AttributeField newAttribute =
+                                    parseAttributeField(  
codecMediaAttributes[attribIndex] );
+
+                            if ( newAttribute != null ) {
+
+                                audioAttributes.add( newAttribute );
+                            }
+                        }
+                    }
+                    else {
+
+                        printLog( "createInitialSdp",
+                                "Audio codec has no especific media  
attributes." );
+                    }
+                }
+
+                // Calculate the format list to be used on MediaDescriptor  
creation.
+                String formatList = getFormatList( audioAttributes );
+
+                for ( Enumeration<AttributeField> attributesEnum =  
audioAttributes.elements(); attributesEnum.hasMoreElements(); ) {
+
+                    AttributeField audioAttribute =  
attributesEnum.nextElement();
+
+                    if ( initialDescriptor.getMediaDescriptor(  
SIPCodec.MEDIA_TYPE_AUDIO ) == null ) {
+
+                        printLog( "createInitialSdp",
+                                "Creating audio media descriptor." );
+
+                        initialDescriptor.addMedia(
+                                new MediaField( SIPCodec.MEDIA_TYPE_AUDIO,  
audioPort, 0, "RTP/AVP", formatList ),
+                                audioAttribute );
+                    }
+                    else {
+
+                        printLog( "createInitialSdp",
+                                "Just adding attribute." );
+
+                        initialDescriptor.getMediaDescriptor(  
SIPCodec.MEDIA_TYPE_AUDIO ).
+                                addAttribute( audioAttribute );
+                    }
+                }
+
+                String[] commonAudioMediaAttributes =
+                         
SIPCodecFactory.getInstance().getCommonAudioMediaAttributes();
+
+                if ( commonAudioMediaAttributes != null ) {
+
+                    printLog( "createInitialSdp", "Adding " +
+                            commonAudioMediaAttributes.length + " common  
audio media attributes." );
+
+                    for ( int attribIndex = 0; attribIndex <  
commonAudioMediaAttributes.length; attribIndex++ ) {
+
+                        printLog( "createInitialSdp",
+                                "Adding common audio media attribute [" +
+                                commonAudioMediaAttributes[attribIndex]  
+ "]." );
+
+                        AttributeField newAttribute =
+                                parseAttributeField(  
commonAudioMediaAttributes[attribIndex] );
+
+                        if ( newAttribute != null ) {
+
+                            initialDescriptor.getMediaDescriptor(  
SIPCodec.MEDIA_TYPE_AUDIO ).
+                                    addAttribute( newAttribute );
+                        }
+                    }
+                }
+                else {
+
+                    printLog( "createInitialSdp", "No common audio media  
attributes." );
+                }
+            }
+
+            if ( videoCodecsNumber > 0 ) {
+
+                SIPCodec[] videoCodecs =  
SIPCodecFactory.getInstance().getAvailableVideoCodecs();
+                Vector<AttributeField> videoAttributes = new  
Vector<AttributeField>();
+
+                for ( int videoIndex = 0; videoIndex < audioCodecsNumber;  
videoIndex++ ) {
+
+                    String payloadId = String.valueOf(  
videoCodecs[videoIndex].getCodecId() );
+                    String rtpmapParamValue = payloadId;
+                    rtpmapParamValue += " " +  
videoCodecs[videoIndex].getCodecName();
+                    rtpmapParamValue += "/" +  
videoCodecs[videoIndex].getSampleRate() + "/1";
+
+                    printLog( "createInitialSdp",
+                            "Adding rtpmap for payload [" + payloadId +
+                            "] with value = [" + rtpmapParamValue + "]." );
+
+                    videoAttributes.add( new AttributeField(
+                            SIPCodec.ATTRIBUTE_RTPMAP, rtpmapParamValue )  
);
+
+                    String[] codecMediaAttributes =  
videoCodecs[videoIndex].getCodecMediaAttributes();
+
+                    if ( codecMediaAttributes != null ) {
+
+                        printLog( "createInitialSdp",
+                                "Adding " + codecMediaAttributes.length +
+                                " video codec media attributes." );
+
+                        for ( int attribIndex = 0; attribIndex <  
codecMediaAttributes.length; attribIndex++ ) {
+
+                            printLog( "createInitialSdp",
+                                    "Adding video media attribute [" +
+                                    codecMediaAttributes[attribIndex]  
+ "]." );
+
+                            AttributeField newAttribute =
+                                    parseAttributeField(  
codecMediaAttributes[attribIndex] );
+
+                            if ( newAttribute != null ) {
+
+                                videoAttributes.add( newAttribute );
+                            }
+                        }
+                    }
+                    else {
+
+                        printLog( "createInitialSdp",
+                                "Video codec has no especific media  
attributes." );
+                    }
+                }
+
+                // Calculate the format list to be used on MediaDescriptor  
creation.
+                String formatList = getFormatList( videoAttributes );
+
+                for ( Enumeration<AttributeField> attributesEnum =  
videoAttributes.elements(); attributesEnum.hasMoreElements(); ) {
+
+                    AttributeField videoAttribute =  
attributesEnum.nextElement();
+
+                    if ( initialDescriptor.getMediaDescriptor(  
SIPCodec.MEDIA_TYPE_VIDEO ) == null ) {
+
+                        initialDescriptor.addMedia(
+                                new MediaField( SIPCodec.MEDIA_TYPE_VIDEO,  
audioPort, 0, "RTP/AVP", formatList ),
+                                videoAttribute );
+                    }
+                    else {
+
+                        initialDescriptor.getMediaDescriptor(  
SIPCodec.MEDIA_TYPE_VIDEO ).
+                                addAttribute( videoAttribute );
+                    }
+                }
+
+                String[] commonVideoMediaAttributes =
+                         
SIPCodecFactory.getInstance().getCommonAudioMediaAttributes();
+
+                if ( commonVideoMediaAttributes != null ) {
+
+                    printLog( "createInitialSdp", "Adding " +
+                            commonVideoMediaAttributes.length + " common  
video media attributes." );
+
+                    for ( int attribIndex = 0; attribIndex <  
commonVideoMediaAttributes.length; attribIndex++ ) {
+
+                        printLog( "createInitialSdp",
+                                "Adding common video media attribute [" +
+                                commonVideoMediaAttributes[attribIndex]  
+ "]." );
+
+                        AttributeField newAttribute =
+                                parseAttributeField(  
commonVideoMediaAttributes[attribIndex] );
+
+                        if ( newAttribute != null ) {
+
+                            initialDescriptor.getMediaDescriptor(  
SIPCodec.MEDIA_TYPE_VIDEO ).
+                                    addAttribute( newAttribute );
+                        }
+                    }
+                }
+                else {
+
+                    printLog( "createInitialSdp", "No common video media  
attributes." );
+                }
+            }
+        }
+        catch ( Exception exception ) {
+
+            printLog( "createInitialSdp", "Failure creating initial SDP: "  
);
+            log.error("Exception", exception);
+        }
+
+        printLog( "createInitialSdp", "End..." );
+
+        return initialDescriptor;
+    }
+
+
+    private static String getFormatList( Vector<AttributeField>  
mediaAttributes ) {
+
+        AttributeField mediaAttribute = null;
+        String formatList = "";
+
+        printLog( "getFormatList", "Init..." );
+
+        for ( Enumeration<AttributeField> attributeEnum =  
mediaAttributes.elements(); attributeEnum.hasMoreElements(); ) {
+
+            mediaAttribute = (AttributeField) attributeEnum.nextElement();
+
+            if ( mediaAttribute.getAttributeName().equalsIgnoreCase(  
SIPCodec.ATTRIBUTE_RTPMAP ) ) {
+
+                if ( !formatList.isEmpty() ) {
+                    formatList += " ";
+                }
+
+                formatList += getPayloadIdFromAttribute( mediaAttribute );
+            }
+        }
+
+        printLog( "getFormatList", "formatList = [" + formatList + "]." );
+
+        printLog( "getFormatList", "End..." );
+
+        return formatList;
+    }
+
+
+    private static AttributeField parseAttributeField( String  
codecMediaAttribute ) {
+
+        AttributeField newAttribute = null;
+
+        printLog( "parseAttributeField", "Init..." );
+
+        printLog( "parseAttributeField",
+                "codecMediaAttribute = [" + codecMediaAttribute + "]." );
+
+        String attribName = codecMediaAttribute.substring(
+                0, codecMediaAttribute.indexOf( ":" ) );
+        String attribValue = codecMediaAttribute.substring(
+                codecMediaAttribute.indexOf( ":" ) + 1 );
+
+        printLog( "parseAttributeField",
+                "attribName = [" + attribName +
+                "] attribValue  = [" + attribValue + "]." );
+
+        if ( ( !attribName.isEmpty() ) && ( !attribValue.isEmpty() ) ) {
+
+            newAttribute = new AttributeField( attribName, attribValue );
+        }
+
+        printLog( "parseAttributeField", "End..." );
+
+        return newAttribute;
+    }
+
+
+    /**
+     * We must validate the existence of all remote "rtpmap" attributes
+     * on local SDP.
+     * If some exist, we add it to newSdp negotiated SDP result.
+     *
+     * @param localSdp
+     * @param remoteSdp
+     *
+     * @return Returns the new local descriptor as a result of media
+     *         payloads negotiation.
+     */
+    public static SessionDescriptor makeMediaPayloadsNegotiation(
+            SessionDescriptor localSdp, SessionDescriptor remoteSdp ) {
+
+        SessionDescriptor newSdp = null;
+
+        printLog( "makeMediaPayloadsNegotiation", "Init..." );
+
+        try {
+
+            newSdp = new SessionDescriptor( remoteSdp.getOrigin(),  
remoteSdp.getSessionName(),
+                    localSdp.getConnection(), localSdp.getTime() );
+
+            Vector<MediaDescriptor> remoteDescriptors =  
remoteSdp.getMediaDescriptors();
+
+            for ( Enumeration<MediaDescriptor> descriptorsEnum =  
remoteDescriptors.elements(); descriptorsEnum.hasMoreElements(); ) {
+
+                MediaDescriptor remoteDescriptor = (MediaDescriptor)  
descriptorsEnum.nextElement();
+                MediaDescriptor localDescriptor =  
localSdp.getMediaDescriptor(
+                        remoteDescriptor.getMedia().getMedia() );
+
+                if ( localDescriptor != null ) {
+
+                    Vector<AttributeField> remoteAttributes =  
remoteDescriptor.getAttributes( SIPCodec.ATTRIBUTE_RTPMAP );
+                    Vector<AttributeField> newSdpAttributes = new  
Vector<AttributeField>();
+
+                    for ( Enumeration<AttributeField> attributesEnum =  
remoteAttributes.elements(); attributesEnum.hasMoreElements(); ) {
+
+                        AttributeField remoteAttribute =  
attributesEnum.nextElement();
+
+                        String payloadId = getPayloadIdFromAttribute(  
remoteAttribute );
+
+                        if ( "".equals( payloadId ) ) {
+
+                            printLog( "makeMediaPayloadsNegotiation",
+                                    "Error! Payload id not found on  
attribute: Name = [" +
+                                    remoteAttribute.getAttributeName()  
+ "], Value = [" +
+                                    remoteAttribute.getAttributeValue()  
+ "]." );
+                        }
+                        else if ( findAttributeByPayloadId(
+                                remoteAttribute.getAttributeName(),  
payloadId,
+                                localDescriptor ) != null ) {
+
+                            newSdpAttributes.add( remoteAttribute );
+                        }
+                    }
+
+                    // Calculate the format list to be used on  
MediaDescriptor creation.
+                    String formatList = getFormatList( newSdpAttributes );
+
+                    for ( Enumeration<AttributeField> attributesEnum =  
newSdpAttributes.elements(); attributesEnum.hasMoreElements(); ) {
+
+                        AttributeField mediaAttribute =  
attributesEnum.nextElement();
+
+                        if ( newSdp.getMediaDescriptors().size() == 0 ) {
+
+                            newSdp.addMediaDescriptor( new MediaDescriptor(
+                                    new MediaField(  
localDescriptor.getMedia().getMedia(),
+                                             
localDescriptor.getMedia().getPort(),
+                                            0,
+                                             
localDescriptor.getMedia().getTransport(),
+                                            formatList ),
+                                    localDescriptor.getConnection() ) );
+                        }
+
+                        newSdp.getMediaDescriptor(  
localDescriptor.getMedia().getMedia() ).
+                                addAttribute( mediaAttribute );
+                    }
+                }
+            }
+        }
+        catch ( Exception exception ) {
+
+            printLog( "makeMediaPayloadsNegotiation", "Failure creating  
initial SDP: " );
+            log.error("Exception", exception);
+        }
+
+        printLog( "makeMediaPayloadsNegotiation", "End..." );
+
+        return newSdp;
+    }
+
+
+    /**
+     * Parameter "newSdp" must be the returning value from method's
+     * "makeMediaPayloadsNegotiation" execution.
+     * Here the pending attributes will be negotiated as well.
+     *
+     * @param newSdp
+     * @param localSdp
+     * @param remoteSdp
+     *
+     */
+    public static void completeSdpNegotiation(
+    		SessionDescriptor newSdp, SessionDescriptor localSdp,
+    		SessionDescriptor remoteSdp ) {
+
+        printLog( "makeSdpNegotiation", "Init..." );
+
+        try {
+
+            if ( newSdp.getMediaDescriptors().size() == 0 ) {
+
+                // Something is wrong.
+                // We should have at least a "audio" media descriptor with
+                // all audio payloads suported.
+
+                printLog( "completeSdpNegotiation",
+                        "Error! No media descriptors after  
\"makeMediaPayloadsNegotiation\"." );
+
+                return;
+            }
+
+            Vector<MediaDescriptor> remoteDescriptors =  
remoteSdp.getMediaDescriptors();
+
+            for ( Enumeration<MediaDescriptor> descriptorsEnum =  
remoteDescriptors.elements(); descriptorsEnum.hasMoreElements(); ) {
+
+                MediaDescriptor remoteDescriptor =  
descriptorsEnum.nextElement();
+                MediaDescriptor localDescriptor =  
localSdp.getMediaDescriptor(
+                        remoteDescriptor.getMedia().getMedia() );
+
+                if ( localDescriptor != null ) {
+
+                    // First we make the negotiation of remote attributes  
with
+                    // local ones to generate the new SDP "newSdp".
+
+                    Vector<AttributeField> remoteAttributes =  
remoteDescriptor.getAttributes();
+
+                    for ( Enumeration<AttributeField> atributesEnum =  
remoteAttributes.elements(); atributesEnum.hasMoreElements(); ) {
+
+                        AttributeField remoteAttribute =  
atributesEnum.nextElement();
+
+                        makeAttributeNegotiation( newSdp, localDescriptor,  
remoteAttribute );
+                    }
+
+                    // Now we add to "newSdp" all the local attributes that
+                    // were not negotiated yet.
+
+                    Vector<AttributeField> localAttributes =  
localDescriptor.getAttributes();
+
+                    for ( Enumeration<AttributeField> atributesEnum =  
localAttributes.elements(); atributesEnum.hasMoreElements(); ) {
+
+                        AttributeField localAttribute = (AttributeField)  
atributesEnum.nextElement();
+                        MediaDescriptor newLocalDescriptor =
+                                newSdp.getMediaDescriptor(  
localDescriptor.getMedia().getMedia() );
+
+                        if ( isPayloadRelatedAttribute( localAttribute ) )  
{
+
+                            String payloadId = getPayloadIdFromAttribute(  
localAttribute );
+
+                            if ( findAttributeByPayloadId(
+                                    localAttribute.getAttributeName(),
+                                    payloadId,
+                                    newLocalDescriptor) == null ) {
+
+                                newLocalDescriptor.addAttribute(  
localAttribute );
+                            }
+                        }
+                        else if ( newLocalDescriptor.getAttribute(
+                                localAttribute.getAttributeName() ) ==  
null ) {
+
+                            newLocalDescriptor.addAttribute(  
localAttribute );
+                        }
+                    }
+                }
+            }
+        }
+        catch ( Exception exception ) {
+
+            printLog( "completeSdpNegotiation", "Failure creating initial  
SDP: " );
+            log.error("Exception", exception);
+        }
+
+        printLog( "completeSdpNegotiation", "End..." );
+    }
+
+
+    /**
+     * Here we make the negotiation of all attributes besides "rtpmap" (
+     * these are negotiated on "makeMediaPayloadsNegotiation" method).
+     *
+     * @param newSdp
+     * @param localMedia
+     * @param remoteAttribute
+     */
+    private static void makeAttributeNegotiation(
+            SessionDescriptor newSdp, MediaDescriptor localMedia,  
AttributeField remoteAttribute ) {
+
+        printLog( "makeAttributeNegotiation", "Init..." );
+
+        try {
+
+            printLog( "makeAttributeNegotiation",
+                    "AttributeName = [" +  
remoteAttribute.getAttributeName() +
+                    "], AttributeValue = [" +  
remoteAttribute.getAttributeValue() + "].");
+
+            if ( remoteAttribute.getAttributeName().equals(  
SIPCodec.ATTRIBUTE_RTPMAP ) ) {
+
+                printLog( "makeAttributeNegotiation",
+                        "\"rtpmap\" attributes were already negotiated." );
+            }
+            else if ( !isPayloadRelatedAttribute( remoteAttribute ) ) {
+
+                // We do nothing with attributes that are not payload
+                // related, like: "ptime", "direction", etc.
+                // For now, we consider that they don't demand negotiation.
+
+                printLog( "makeAttributeNegotiation",
+                        "Attribute is not payload related. Do not  
negotiate it..." );
+            }
+            else {
+
+                String payloadId = getPayloadIdFromAttribute(  
remoteAttribute );
+
+                if ( "".equals( payloadId ) ) {
+
+                    printLog( "makeAttributeNegotiation",
+                            "Error! Payload id not found on attribute:  
Name = [" +
+                            remoteAttribute.getAttributeName() + "], Value  
= [" +
+                            remoteAttribute.getAttributeValue() + "]." );
+                }
+                // We must be sure this attribute is related with a payload
+                // already present on newSdp.
+                else if ( findAttributeByPayloadId(  
SIPCodec.ATTRIBUTE_RTPMAP, payloadId,
+                        newSdp.getMediaDescriptor(  
localMedia.getMedia().getMedia() ) ) != null ) {
+
+                    printLog( "makeAttributeNegotiation",
+                            "Payload " + payloadId + " present on newSdp."  
);
+
+                    AttributeField localAttribute =  
findAttributeByPayloadId(
+                            remoteAttribute.getAttributeName(), payloadId,  
localMedia );
+
+                    SIPCodec sipCodec =  
SIPCodecFactory.getInstance().getSIPAudioCodec(
+                            Integer.valueOf( payloadId ) );
+
+                    if ( sipCodec != null ) {
+
+                        String localAttibuteValue = "";
+
+                        if ( localAttribute != null ) {
+
+                            localAttibuteValue =  
localAttribute.getAttributeValue();
+                        }
+                        else {
+
+                            printLog( "makeAttributeNegotiation",
+                                    "Attribute not found on local media."  
);
+                        }
+
+                        String attributeValueResult =  
sipCodec.codecNegotiateAttribute(
+                                remoteAttribute.getAttributeName(),
+                                localAttibuteValue,
+                                remoteAttribute.getAttributeValue() );
+
+                        if ( ( attributeValueResult != null ) &&  
( !"".equals( attributeValueResult ) ) ) {
+
+                            newSdp.getMediaDescriptor(  
localMedia.getMedia().getMedia() ).
+                                    addAttribute( new AttributeField(
+                                             
remoteAttribute.getAttributeName(), attributeValueResult ) );
+                        }
+                    }
+                    else {
+
+                        printLog( "makeAttributeNegotiation", "Codec not  
found!" );
+                    }
+                }
+            }
+        }
+        catch ( Exception exception ) {
+
+            printLog( "makeAttributeNegotiation", "Failure creating  
initial SDP: " );
+            log.error("Exception", exception);
+        }
+
+        printLog( "makeAttributeNegotiation", "End..." );
+    }
+
+
+    private static AttributeField findAttributeByPayloadId(
+            String attributeName, String payloadId, MediaDescriptor  
mediaDescriptor ) {
+
+        printLog( "findAttributeByPayloadId", "Init..." );
+
+        AttributeField searchingMediaAttribute = null;
+
+        printLog( "findAttributeByPayloadId",
+                "attributeName = [" + attributeName +
+                "], payloadId = [" + payloadId + "]." );
+
+        Vector<AttributeField> mediaAttributes =  
mediaDescriptor.getAttributes( attributeName );
+
+        for ( Enumeration<AttributeField> attributesEnum =  
mediaAttributes.elements(); attributesEnum.hasMoreElements(); ) {
+
+            AttributeField mediaAttribute = (AttributeField)  
attributesEnum.nextElement();
+
+            printLog( "findAttributeByPayloadId",
+                    "Validating attribute with name = [" +  
mediaAttribute.getAttributeName() +
+                    "] and value = [" + mediaAttribute.getAttributeValue()  
+ "]." );
+
+            if ( getPayloadIdFromAttribute( mediaAttribute ).equals(  
payloadId ) ) {
+
+                searchingMediaAttribute = mediaAttribute;
+                break;
+            }
+        }
+
+        if ( searchingMediaAttribute != null ) {
+
+            printLog( "findAttributeByPayloadId",
+                    "Attribute found with name = [" +
+                    searchingMediaAttribute.getAttributeName() + "] and  
value = [" +
+                    searchingMediaAttribute.getAttributeValue() + "]." );
+        }
+        else {
+
+            printLog( "findAttributeByPayloadId",
+                    "Attribute with name [" + attributeName +
+                    "] and payloadId [" + payloadId + "] was not found." );
+        }
+
+        printLog( "findAttributeByPayloadId", "End..." );
+
+        return searchingMediaAttribute;
+    }
+
+
+    private static String getPayloadIdFromAttribute( AttributeField  
attribute ) {
+
+        String payloadId = "";
+
+        printLog( "getPayloadIdFromAttribute", "Init..." );
+
+        printLog( "getPayloadIdFromAttribute",
+                "AttributeName = [" + attribute.getAttributeName() +
+                "], AttributeValue = [" + attribute.getAttributeValue()  
+ "]." );
+
+        if ( isPayloadRelatedAttribute( attribute ) ) {
+
+            payloadId = attribute.getAttributeValue().substring( 0,
+                    attribute.getAttributeValue().indexOf( " " ) );
+        }
+
+        printLog( "getPayloadIdFromAttribute", "payloadId = " + payloadId  
);
+
+        printLog( "getPayloadIdFromAttribute", "End..." );
+
+        return payloadId;
+    }
+
+
+    private static boolean isPayloadRelatedAttribute( AttributeField  
attribute ) {
+
+        boolean isPayloadAttribute = false;
+
+        printLog( "isPayloadRelatedAttribute", "Init..." );
+
+        printLog( "isPayloadRelatedAttribute",
+                "AttributeName = [" + attribute.getAttributeName() +
+                "], AttributeValue = [" + attribute.getAttributeValue()  
+ "]." );
+
+        if ( ( attribute.getAttributeName().compareToIgnoreCase(  
SIPCodec.ATTRIBUTE_RTPMAP ) == 0 ) ||
+                ( attribute.getAttributeName().compareToIgnoreCase(  
SIPCodec.ATTRIBUTE_AS ) == 0 ) ||
+                ( attribute.getAttributeName().compareToIgnoreCase(  
SIPCodec.ATTRIBUTE_FMTP ) == 0 ) ) {
+
+            isPayloadAttribute = true;
+        }
+
+        printLog( "isPayloadRelatedAttribute", "isPayloadAttribute = " +  
isPayloadAttribute );
+
+        printLog( "isPayloadRelatedAttribute", "End..." );
+
+        return isPayloadAttribute;
+    }

-	public static SIPCodec getNegotiatedVideoCodec(SessionDescriptor  
negotiatedSDP) {
-		MediaDescriptor md =  
negotiatedSDP.getMediaDescriptor(SIPCodec.MEDIA_TYPE_VIDEO);
-		if (md == null) {
-			return null;
-		}
-		String rtpmap =  
md.getAttribute(SIPCodec.ATTRIBUTE_RTPMAP).getAttributeValue();
-		printLog("getNegotiatedVideoCodec", "rtpmap = [" + rtpmap + "].");
-		if (rtpmap == null || rtpmap.isEmpty()) {
-			return null;
-		}
-		int payloadId = Integer.parseInt(rtpmap.substring(0,  
rtpmap.indexOf(" ")));
-		SIPCodec sipCodec =  
SIPCodecFactory.getInstance().getSIPMediaCodec(payloadId);
-		if (sipCodec == null) {
-			printLog("getNegotiatedVideoCodec", "Error... codec not found.");
-		} else {
-			printLog("getNegotiatedVideoCodec", "payloadType = " +  
sipCodec.getCodecId() + ", payloadName = "
-					+ sipCodec.getCodecName() + ".");
-		}
-		return sipCodec;
-	}

-	/**
-	 * @return Returns the audio codec to be used on current session.
-	 */
-	public static SIPCodec getNegotiatedAudioCodec(SessionDescriptor  
negotiatedSDP) {
-		int payloadId;
-		String rtpmap;
-		SIPCodec sipCodec = null;
-
-		printLog("getNegotiatedAudioCodec", "Init...");
-
-		rtpmap =  
negotiatedSDP.getMediaDescriptor(SIPCodec.MEDIA_TYPE_AUDIO).getAttribute(SIPCodec.ATTRIBUTE_RTPMAP)
-				.getAttributeValue();
-
-		printLog("getNegotiatedAudioCodec", "rtpmap = [" + rtpmap + "].");
-
-		if (!rtpmap.isEmpty()) {
-
-			payloadId = Integer.parseInt(rtpmap.substring(0, rtpmap.indexOf(" ")));
-
-			printLog("getNegotiatedAudioCodec", "payloadId = [" + payloadId + "].");
-
-			sipCodec = SIPCodecFactory.getInstance().getSIPMediaCodec(payloadId);
-
-			if (sipCodec == null) {
-
-				printLog("getNegotiatedAudioCodec", "Error... codec not found.");
-			} else {
-
-				printLog("getNegotiatedAudioCodec", "payloadType = " +  
sipCodec.getCodecId() + ", payloadName = "
-						+ sipCodec.getCodecName() + ".");
-			}
-		}
-
-		printLog("getNegotiatedAudioCodec", "End...");
-
-		return sipCodec;
-	}
-
-	/**
-	 *
-	 * @param userName
-	 * @param viaAddress
-	 *
-	 * @return Return the initial local SDP.
-	 */
-	public static SessionDescriptor createInitialSdp(String userName, String  
viaAddress, int audioPort, int videoPort,
-			String audioCodecsPrecedence) {
-
-		SessionDescriptor initialDescriptor = null;
-
-		printLog("createInitialSdp", "Init...");
-
-		try {
-
-			printLog("createInitialSdp", "userName = [" + userName + "], viaAddress  
= [" + viaAddress
-					+ "], audioPort = [" + audioPort + "], videoPort = [" + videoPort  
+ "], audioCodecsPrecedence = ["
-					+ audioCodecsPrecedence + "].");
-
-			int audioCodecsNumber =  
SIPCodecFactory.getInstance().getAvailableAudioCodecsCount();
-			int videoCodecsNumber =  
SIPCodecFactory.getInstance().getAvailableVideoCodecsCount();
-
-			if ((audioCodecsNumber == 0) && (videoCodecsNumber == 0)) {
-
-				printLog("createInitialSdp", "audioCodecsNumber = [" +  
audioCodecsNumber + "], videoCodecsNumber = ["
-						+ videoCodecsNumber + "].");
-
-				return null;
-			}
-
-			initialDescriptor = new SessionDescriptor(userName, viaAddress);
-
-			if (audioCodecsNumber > 0) {
-
-				SIPCodec[] audioCodecs;
-				Vector<AttributeField> audioAttributes = new Vector<AttributeField>();
-
-				if (audioCodecsPrecedence.isEmpty()) {
-
-					audioCodecs = SIPCodecFactory.getInstance().getAvailableAudioCodecs();
-				} else {
-
-					audioCodecs =  
SIPCodecFactory.getInstance().getAvailableAudioCodecsWithPrecedence(
-							audioCodecsPrecedence);
-				}
-
-				for (int audioIndex = 0; audioIndex < audioCodecsNumber; audioIndex++)  
{
-
-					String payloadId =  
String.valueOf(audioCodecs[audioIndex].getCodecId());
-					String rtpmapParamValue = payloadId;
-					rtpmapParamValue += " " + audioCodecs[audioIndex].getCodecName();
-					rtpmapParamValue += "/" + audioCodecs[audioIndex].getSampleRate()  
+ "/1";
-
-					printLog("createInitialSdp", "Adding rtpmap for payload [" +  
payloadId + "] with value = ["
-							+ rtpmapParamValue + "].");
-
-					audioAttributes.add(new AttributeField(SIPCodec.ATTRIBUTE_RTPMAP,  
rtpmapParamValue));
-
-					String[] codecMediaAttributes =  
audioCodecs[audioIndex].getCodecMediaAttributes();
-
-					if (codecMediaAttributes != null) {
-
-						printLog("createInitialSdp", "Adding " + codecMediaAttributes.length
-								+ " audio codec media attributes.");
-
-						for (int attribIndex = 0; attribIndex < codecMediaAttributes.length;  
attribIndex++) {
-
-							printLog("createInitialSdp", "Adding audio media attribute ["
-									+ codecMediaAttributes[attribIndex] + "].");
-
-							AttributeField newAttribute =  
parseAttributeField(codecMediaAttributes[attribIndex]);
-
-							if (newAttribute != null) {
-
-								audioAttributes.add(newAttribute);
-							}
-						}
-					} else {
-
-						printLog("createInitialSdp", "Audio codec has no especific media  
attributes.");
-					}
-				}
-
-				// Calculate the format list to be used on MediaDescriptor
-				// creation.
-				String formatList = getFormatList(audioAttributes);
-
-				for (Enumeration<AttributeField> attributesEnum =  
audioAttributes.elements(); attributesEnum
-						.hasMoreElements();) {
-
-					AttributeField audioAttribute = attributesEnum.nextElement();
-
-					if (initialDescriptor.getMediaDescriptor(SIPCodec.MEDIA_TYPE_AUDIO)  
== null) {
-
-						printLog("createInitialSdp", "Creating audio media descriptor.");
-
-						initialDescriptor.addMedia(new MediaField(SIPCodec.MEDIA_TYPE_AUDIO,  
audioPort, 0, "RTP/AVP",
-								formatList), audioAttribute);
-					} else {
-
-						printLog("createInitialSdp", "Just adding attribute.");
-
-						 
initialDescriptor.getMediaDescriptor(SIPCodec.MEDIA_TYPE_AUDIO).addAttribute(audioAttribute);
-					}
-				}
-
-				String[] commonAudioMediaAttributes =  
SIPCodecFactory.getInstance().getCommonAudioMediaAttributes();
-
-				if (commonAudioMediaAttributes != null) {
-
-					printLog("createInitialSdp", "Adding " +  
commonAudioMediaAttributes.length
-							+ " common audio media attributes.");
-
-					for (int attribIndex = 0; attribIndex <  
commonAudioMediaAttributes.length; attribIndex++) {
-
-						printLog("createInitialSdp", "Adding common audio media attribute ["
-								+ commonAudioMediaAttributes[attribIndex] + "].");
-
-						AttributeField newAttribute =  
parseAttributeField(commonAudioMediaAttributes[attribIndex]);
-
-						if (newAttribute != null) {
-
-							 
initialDescriptor.getMediaDescriptor(SIPCodec.MEDIA_TYPE_AUDIO).addAttribute(newAttribute);
-						}
-					}
-				} else {
-
-					printLog("createInitialSdp", "No common audio media attributes.");
-				}
-			}
-
-			if (videoCodecsNumber > 0) {
-
-				SIPCodec[] videoCodecs =  
SIPCodecFactory.getInstance().getAvailableVideoCodecs();
-				Vector<AttributeField> videoAttributes = new Vector<AttributeField>();
-
-				for (int videoIndex = 0; videoIndex < videoCodecsNumber; videoIndex++)  
{
-
-					String payloadId =  
String.valueOf(videoCodecs[videoIndex].getCodecId());
-					String rtpmapParamValue = payloadId;
-					rtpmapParamValue += " " + videoCodecs[videoIndex].getCodecName();
-					rtpmapParamValue += "/" + videoCodecs[videoIndex].getSampleRate()  
+ "/1";
-
-					printLog("createInitialSdp", "Adding rtpmap for payload [" +  
payloadId + "] with value = ["
-							+ rtpmapParamValue + "].");
-
-					videoAttributes.add(new AttributeField(SIPCodec.ATTRIBUTE_RTPMAP,  
rtpmapParamValue));
-
-					String[] codecMediaAttributes =  
videoCodecs[videoIndex].getCodecMediaAttributes();
-
-					if (codecMediaAttributes != null) {
-
-						printLog("createInitialSdp", "Adding " + codecMediaAttributes.length
-								+ " video codec media attributes.");
-
-						for (int attribIndex = 0; attribIndex < codecMediaAttributes.length;  
attribIndex++) {
-
-							printLog("createInitialSdp", "Adding video media attribute ["
-									+ codecMediaAttributes[attribIndex] + "].");
-
-							AttributeField newAttribute =  
parseAttributeField(codecMediaAttributes[attribIndex]);
-
-							if (newAttribute != null) {
-
-								videoAttributes.add(newAttribute);
-							}
-						}
-					} else {
-
-						printLog("createInitialSdp", "Video codec has no especific media  
attributes.");
-					}
-				}
-
-				// Calculate the format list to be used on MediaDescriptor
-				// creation.
-				String formatList = getFormatList(videoAttributes);
-
-				for (Enumeration<AttributeField> attributesEnum =  
videoAttributes.elements(); attributesEnum
-						.hasMoreElements();) {
-
-					AttributeField videoAttribute = attributesEnum.nextElement();
-
-					if (initialDescriptor.getMediaDescriptor(SIPCodec.MEDIA_TYPE_VIDEO)  
== null) {
***The diff for this file has been truncated for email.***
=======================================
--- /branches/red5sip/src/java/org/zoolu/sdp/SessionDescriptor.java	Tue Feb  
19 11:33:08 2013
+++ /branches/red5sip/src/java/org/zoolu/sdp/SessionDescriptor.java	Thu Feb  
21 09:13:01 2013
@@ -157,20 +157,15 @@
        }
        // parse session attributes
        av=new Vector<AttributeField>();
-      while (par.hasMore()) {
-    	  if (par.startsWith("a=")) {
-	    	  AttributeField attribute=par.parseAttributeField();
-	          av.addElement(attribute);
-    	  } else par.goToNextLine();
-      }
-      par.setPos(0);
+      while (par.hasMore() && par.startsWith("a="))
+      {  AttributeField attribute=par.parseAttributeField();
+         av.addElement(attribute);
+      }
        // parse media descriptors
        media=new Vector<MediaDescriptor>();
-      while (par.hasMore()) {
-    	  if (par.startsWith("m=")) {
-		      MediaDescriptor md = par.parseMediaDescriptor();
-		      if (md != null) addMediaDescriptor(md);
-    	  } else par.goToNextLine();
+      MediaDescriptor md;
+      while ((md=par.parseMediaDescriptor())!=null)
+      {  addMediaDescriptor(md);
        }
     }