Revision: 94
Author:   [email protected]
Date:     Tue Feb 19 11:33:08 2013
Log:      Video support: initial code is commited
http://code.google.com/p/red5phone/source/detail?r=94

Added:
 /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

=======================================
--- /dev/null
+++ /branches/red5sip/src/java/org/red5/codecs/SIPCodecH264.java Tue Feb 19 11:33:08 2013
@@ -0,0 +1,114 @@
+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;
+       }
+
+}
=======================================
--- /dev/null
+++ /branches/red5sip/src/java/org/red5/sip/app/RTPStreamVideoReceiver.java Tue Feb 19 11:33:08 2013
@@ -0,0 +1,50 @@
+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();
+       }
+
+}
=======================================
--- /dev/null
+++ /branches/red5sip/src/java/org/red5/sip/app/SIPVideoLauncher.java Tue Feb 19 11:33:08 2013
@@ -0,0 +1,39 @@
+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 Fri Feb 10 07:37:46 2012 +++ /branches/red5sip/src/java/org/red5/codecs/SIPCodec.java Tue Feb 19 11:33:08 2013
@@ -2,7 +2,7 @@


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

=======================================
--- /branches/red5sip/src/java/org/red5/codecs/SIPCodecFactory.java Sun Feb 17 19:49:41 2013 +++ /branches/red5sip/src/java/org/red5/codecs/SIPCodecFactory.java Tue Feb 19 11:33:08 2013
@@ -26,8 +26,10 @@
     // ----------------
     // Available video codecs

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

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

private static SIPCodecFactory singletonSIPCodecFactory = new SIPCodecFactory();

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

         SIPCodec sipCodec;

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

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

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

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

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

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

             if ( sipCodec != null ) {
=======================================
--- /branches/red5sip/src/java/org/red5/sip/app/Application.java Mon Feb 18 02:34:27 2013 +++ /branches/red5sip/src/java/org/red5/sip/app/Application.java Tue Feb 19 11:33:08 2013
@@ -16,21 +16,23 @@
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;

-    private SIPTransport createSIPTransport(Properties prop, int room_id) {
+    public 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++) {
+
+ SIPTransport sipTransport = new SIPTransport(roomClient, sipPort++, soundPort++, videoPort++) { 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 Fri Feb 10 07:37:46 2012 +++ /branches/red5sip/src/java/org/red5/sip/app/IMediaReceiver.java Tue Feb 19 11:33:08 2013
@@ -6,6 +6,8 @@

     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 Sun Feb 17 19:49:41 2013 +++ /branches/red5sip/src/java/org/red5/sip/app/PlayNetStream.java Tue Feb 19 11:33:08 2013
@@ -17,6 +17,8 @@

     private int audioTs = 0;

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

     private IMediaStream mediaStream;
@@ -63,8 +65,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 Mon Feb 18 21:27:45 2013 +++ /branches/red5sip/src/java/org/red5/sip/app/RTMPRoomClient.java Tue Feb 19 11:33:08 2013
@@ -2,6 +2,7 @@

 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;
@@ -27,6 +28,7 @@
 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;
@@ -45,7 +47,8 @@
     private long broadCastId = -1;
     private RTMPConnection conn;
     private IMediaSender sender;
-    private IoBuffer buffer;
+    private IoBuffer audioBuffer;
+    private IoBuffer videoBuffer;
     private int kt = 0;
     private Integer publishStreamId = null;
     private boolean reconnect = true;
@@ -469,21 +472,21 @@
         if( publishStreamId == null) {
             return;
         }
-        if ( buffer == null ) {
-            buffer = IoBuffer.allocate( 1024 );
-            buffer.setAutoExpand( true );
+        if ( audioBuffer == null ) {
+            audioBuffer = IoBuffer.allocate( 1024 );
+            audioBuffer.setAutoExpand( true );
         }

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

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

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

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

         kt++;
@@ -495,4 +498,28 @@
         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 Mon Feb 18 21:27:45 2013 +++ /branches/red5sip/src/java/org/red5/sip/app/SIPTransport.java Tue Feb 19 11:33:08 2013
@@ -21,7 +21,8 @@
        private String username;
        private String password;
        private int sipPort;
-       private int rtpPort;
+       private int rtpAudioPort;
+       private int rtpVideoPort;
        private String proxy;
        private String number;

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

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

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

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

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

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

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

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

             if ( audioApp == null ) {

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

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

@@ -485,15 +488,17 @@
             }
         }
if ( userProfile.video && localVideoPort != 0 && remoteVideoPort != 0 ) {
-
-            if ( videoApp == null ) {
-
-                printLog( "launchMediaApplication",
- "No external video application nor JMF has been provided: Video not started." );
-                return;
+               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();
             }
-
-            videoApp.startMedia();
         }
     }

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

-            // After we can create the correct audio codec considering
-            // audio negotiation made above.
-            sipCodec = SdpUtils.getNegotiatedAudioCodec( newSdp );
+ // 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 );

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

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

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

=======================================
--- /branches/red5sip/src/java/org/red5/sip/app/SIPUserAgentProfile.java Fri Feb 10 07:37:46 2012 +++ /branches/red5sip/src/java/org/red5/sip/app/SIPUserAgentProfile.java Tue Feb 19 11:33:08 2013
@@ -128,7 +128,7 @@
     public boolean audio = true;

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

     /** Whether playing in receive only mode */
     public boolean recvOnly = false;
=======================================
--- /branches/red5sip/src/java/org/red5/sip/app/SdpUtils.java Sun Feb 17 20:38:26 2013 +++ /branches/red5sip/src/java/org/red5/sip/app/SdpUtils.java Tue Feb 19 11:33:08 2013
@@ -17,6 +17,26 @@
protected static Logger log = LoggerFactory.getLogger( SdpUtils.class );


+ public static SIPCodec getNegotiatedVideoCodec(SessionDescriptor negotiatedSDP) { + String rtpmap = negotiatedSDP.getMediaDescriptor(SIPCodec.MEDIA_TYPE_VIDEO).
+                       
getAttribute(SIPCodec.ATTRIBUTE_RTPMAP).getAttributeValue();
+       printLog( "getNegotiatedVideoCodec", "rtpmap = [" + rtpmap + "]." );
+       if (rtpmap.isEmpty()) return null;
+ int payloadId = Integer.parseInt(rtpmap.substring(0, rtpmap.indexOf(" "))); + SIPCodec sipCodec = SIPCodecFactory.getInstance().getSIPMediaCodec(payloadId);
+       if ( sipCodec == null ) {
+
+ printLog( "getNegotiatedAudioCodec", "Error... codec not found." );
+        }
+        else {
+
+            printLog( "getNegotiatedAudioCodec",
+                    "payloadType = " + sipCodec.getCodecId() +
+                    ", payloadName = " + sipCodec.getCodecName() + "." );
+        }
+       return sipCodec;
+    }
+
     /**
      * @return Returns the audio codec to be used on current session.
      */
@@ -40,7 +60,7 @@

printLog( "getNegotiatedAudioCodec", "payloadId = [" + payloadId + "]." );

- sipCodec = SIPCodecFactory.getInstance().getSIPAudioCodec( payloadId ); + sipCodec = SIPCodecFactory.getInstance().getSIPMediaCodec( payloadId );

             if ( sipCodec == null ) {

@@ -217,7 +237,7 @@
SIPCodec[] videoCodecs = SIPCodecFactory.getInstance().getAvailableVideoCodecs(); Vector<AttributeField> videoAttributes = new Vector<AttributeField>();

- for ( int videoIndex = 0; videoIndex < audioCodecsNumber; videoIndex++ ) { + for ( int videoIndex = 0; videoIndex < videoCodecsNumber; videoIndex++ ) {

String payloadId = String.valueOf( videoCodecs[videoIndex].getCodecId() );
                     String rtpmapParamValue = payloadId;
@@ -271,7 +291,7 @@
if ( initialDescriptor.getMediaDescriptor( SIPCodec.MEDIA_TYPE_VIDEO ) == null ) {

                         initialDescriptor.addMedia(
- new MediaField( SIPCodec.MEDIA_TYPE_VIDEO, audioPort, 0, "RTP/AVP", formatList ), + new MediaField( SIPCodec.MEDIA_TYPE_VIDEO, videoPort, 0, "RTP/AVP", formatList ),
                                 videoAttribute );
                     }
                     else {
@@ -282,7 +302,7 @@
                 }

                 String[] commonVideoMediaAttributes =
- SIPCodecFactory.getInstance().getCommonAudioMediaAttributes(); + SIPCodecFactory.getInstance().getCommonVideoMediaAttributes();

                 if ( commonVideoMediaAttributes != null ) {

@@ -444,18 +464,15 @@
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.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 );
                     }
@@ -623,7 +640,7 @@
AttributeField localAttribute = findAttributeByPayloadId( remoteAttribute.getAttributeName(), payloadId, localMedia );

- SIPCodec sipCodec = SIPCodecFactory.getInstance().getSIPAudioCodec( + SIPCodec sipCodec = SIPCodecFactory.getInstance().getSIPMediaCodec(
                             Integer.valueOf( payloadId ) );

                     if ( sipCodec != null ) {
=======================================
--- /branches/red5sip/src/java/org/zoolu/sdp/SessionDescriptor.java Sun Feb 17 19:49:41 2013 +++ /branches/red5sip/src/java/org/zoolu/sdp/SessionDescriptor.java Tue Feb 19 11:33:08 2013
@@ -157,15 +157,20 @@
       }
       // parse session attributes
       av=new Vector<AttributeField>();
-      while (par.hasMore() && par.startsWith("a="))
-      {  AttributeField attribute=par.parseAttributeField();
-         av.addElement(attribute);
-      }
+      while (par.hasMore()) {
+         if (par.startsWith("a=")) {
+                 AttributeField attribute=par.parseAttributeField();
+                 av.addElement(attribute);
+         } else par.goToNextLine();
+      }
+      par.setPos(0);
       // parse media descriptors
       media=new Vector<MediaDescriptor>();
-      MediaDescriptor md;
-      while ((md=par.parseMediaDescriptor())!=null)
-      {  addMediaDescriptor(md);
+      while (par.hasMore()) {
+         if (par.startsWith("m=")) {
+                     MediaDescriptor md = par.parseMediaDescriptor();
+                     if (md != null) addMediaDescriptor(md);
+         } else par.goToNextLine();
       }
    }

Reply via email to