* #36737: switch back to svn repo, remove assert in sip_transaction.c
diff --git a/jni/pjproject-android/.svn/pristine/60/60834a41d22f39494185f3a6eea0a5da915f26b6.svn-base b/jni/pjproject-android/.svn/pristine/60/60834a41d22f39494185f3a6eea0a5da915f26b6.svn-base
new file mode 100644
index 0000000..4d15882
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/60/60834a41d22f39494185f3a6eea0a5da915f26b6.svn-base
@@ -0,0 +1,1596 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms oa the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 oa the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty oa
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy oa the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#include <pjmedia/sdp.h>
+#include <pjmedia/sdp_neg.h>
+#include "test.h"
+
+
+#define THIS_FILE   "sdp_neg_test.c"
+#define START_TEST  0
+
+enum session_type
+{
+    REMOTE_OFFER,
+    LOCAL_OFFER,
+};
+
+struct offer_answer
+{			
+    enum session_type type;	/*  LOCAL_OFFER:	REMOTE_OFFER:	*/
+    char *sdp1;			/* local offer		remote offer	*/
+    char *sdp2;			/* remote answer	initial local	*/
+    char *sdp3;			/* local active media	local answer	*/
+};
+
+static struct test
+{
+    const char		*title;
+    unsigned		 offer_answer_count;
+    struct offer_answer	 offer_answer[4];
+} test[] = 
+{
+    /* test 0: */
+    {
+	/*********************************************************************
+	 * RFC 3264 examples, section 10.1 (Alice's view)
+	 *
+	 * Difference from the example:
+	 *  - Bob's port number of the third media stream in the first answer
+	 *    is changed (make it different than Alice's)
+	 *  - in the second offer/answer exchange, Alice can't accept the
+	 *    additional line since she didn't specify the capability
+	 *    in the initial negotiator creation.
+	 */
+
+	"RFC 3264 example 10.1 (Alice's view)",
+	2,
+	{
+	  {
+	    LOCAL_OFFER,
+	    /* Alice sends offer: */
+	    "v=0\r\n"
+	    "o=alice 2890844526 2890844526 IN IP4 host.anywhere.com\r\n"
+	    "s= \r\n"
+	    "c=IN IP4 host.anywhere.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 49170 RTP/AVP 0\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "m=video 51372 RTP/AVP 31\r\n"
+	    "a=rtpmap:31 H261/90000\r\n"
+	    "m=video 53000 RTP/AVP 32\r\n"
+	    "a=rtpmap:32 MPV/90000\r\n",
+	    /* Received Bob's answer: */
+	    "v=0\r\n"
+	    "o=bob 2890844730 2890844730 IN IP4 host.example.com\r\n"
+	    "s= \r\n"
+	    "c=IN IP4 host.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 49920 RTP/AVP 0\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "m=video 0 RTP/AVP 31\r\n"
+	    "m=video 53002 RTP/AVP 32\r\n"
+	    "a=rtpmap:32 MPV/90000\r\n",
+	    /* Alice's SDP now: */
+	    "v=0\r\n"
+	    "o=alice 2890844526 2890844526 IN IP4 host.anywhere.com\r\n"
+	    "s= \r\n"
+	    "c=IN IP4 host.anywhere.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 49170 RTP/AVP 0\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "m=video 0 RTP/AVP 31\r\n"
+	    //"a=rtpmap:31 H261/90000\r\n"	/* <-- this is not necessary (port 0) */
+	    "m=video 53000 RTP/AVP 32\r\n"
+	    "a=rtpmap:32 MPV/90000\r\n"
+	  },
+	  {
+	    REMOTE_OFFER,
+	    /* Bob wants to change his local SDP 
+	     * (change local port for the first stream and add new stream)
+	     * Received SDP from Bob:
+	     */
+	    "v=0\r\n"
+	    "o=bob 2890844730 2890844731 IN IP4 host.example.com\r\n"
+	    "s=-\r\n"
+	    "c=IN IP4 host.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 65422 RTP/AVP 0\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "m=video 0 RTP/AVP 31\r\n"
+	    "m=video 53002 RTP/AVP 32\r\n"
+	    "a=rtpmap:32 MPV/90000\r\n"
+	    "m=audio 51434 RTP/AVP 110\r\n"
+	    "a=rtpmap:110 telephone-events/8000\r\n"
+	    "a=recvonly\r\n",
+	    NULL,
+	    /* Alice's SDP now */
+	    "v=0\r\n"
+	    "o=alice 2890844526 2890844527 IN IP4 host.anywhere.com\r\n"
+	    "s= \r\n"
+	    "c=IN IP4 host.anywhere.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 49170 RTP/AVP 0\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "m=video 0 RTP/AVP 31\r\n"
+	    //"a=rtpmap:31 H261/90000\r\n"	/* <-- this is not necessary (port 0) */
+	    "m=video 53000 RTP/AVP 32\r\n"
+	    "a=rtpmap:32 MPV/90000\r\n"
+	    "m=audio 0 RTP/AVP 110\r\n"
+	    /* <-- the following attributes are not necessary (port 0) */
+	    //"a=rtpmap:110 telephone-events/8000\r\n"
+	    //"a=sendonly\r\n"
+	  }
+	}
+    },
+
+    /* test 1: */
+    {
+	/*********************************************************************
+	 * RFC 3264 examples, section 10.1. (Bob's view)
+	 *
+	 * Difference:
+	 *  - the SDP version in Bob's capability is changed to ver-1.
+	 */
+
+	"RFC 3264 example 10.1 (Bob's view)",
+	2,
+	{
+	  {
+	    REMOTE_OFFER,
+	    /* Remote offer from Alice: */
+	    "v=0\r\n"
+	    "o=alice 2890844526 2890844526 IN IP4 host.anywhere.com\r\n"
+	    "s= \r\n"
+	    "c=IN IP4 host.anywhere.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 49170 RTP/AVP 0\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "m=video 51372 RTP/AVP 31\r\n"
+	    "a=rtpmap:31 H261/90000\r\n"
+	    "m=video 53000 RTP/AVP 32\r\n"
+	    "a=rtpmap:32 MPV/90000\r\n",
+	    /* Bob's capability: */
+	    "v=0\r\n"
+	    "o=bob 2890844730 2890844729 IN IP4 host.example.com\r\n"
+	    "s= \r\n"
+	    "c=IN IP4 host.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 49920 RTP/AVP 0\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "m=video 0 RTP/AVP 31\r\n"
+	    "m=video 53000 RTP/AVP 32\r\n"
+	    "a=rtpmap:32 MPV/90000\r\n",
+	    /* This's how Bob's answer should look like: */
+	    "v=0\r\n"
+	    "o=bob 2890844730 2890844730 IN IP4 host.example.com\r\n"
+	    "s= \r\n"
+	    "c=IN IP4 host.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 49920 RTP/AVP 0\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "m=video 0 RTP/AVP 31\r\n"
+	    "m=video 53000 RTP/AVP 32\r\n"
+	    "a=rtpmap:32 MPV/90000\r\n"
+	  },
+	  {
+	    LOCAL_OFFER,
+	    /* Bob wants to change his local SDP 
+	     * (change local port for the first stream and add new stream)
+	     */
+	    "v=0\r\n"
+	    "o=bob 2890844730 2890844731 IN IP4 host.example.com\r\n"
+	    "s=-\r\n"
+	    "c=IN IP4 host.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 65422 RTP/AVP 0\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "m=video 0 RTP/AVP 31\r\n"
+	    "m=video 53000 RTP/AVP 32\r\n"
+	    "a=rtpmap:32 MPV/90000\r\n"
+	    "m=audio 51434 RTP/AVP 110\r\n"
+	    "a=rtpmap:110 telephone-events/8000\r\n"
+	    "a=recvonly\r\n",
+	    /* Got answer from Alice */
+	    "v=0\r\n"
+	    "o=alice 2890844526 2890844527 IN IP4 host.anywhere.com\r\n"
+	    "s=-\r\n"
+	    "c=IN IP4 host.anywhere.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 49170 RTP/AVP 0\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "m=video 0 RTP/AVP 31\r\n"
+	    "a=rtpmap:31 H261/90000\r\n"
+	    "m=video 53000 RTP/AVP 32\r\n"
+	    "a=rtpmap:32 MPV/90000\r\n"
+	    "m=audio 53122 RTP/AVP 110\r\n"
+	    "a=rtpmap:110 telephone-events/8000\r\n"
+	    "a=sendonly\r\n",
+	    /* This is how Bob's SDP should look like after negotiation */
+	    "v=0\r\n"
+	    "o=bob 2890844730 2890844731 IN IP4 host.example.com\r\n"
+	    "s=-\r\n"
+	    "c=IN IP4 host.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 65422 RTP/AVP 0\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "m=video 0 RTP/AVP 31\r\n"
+	    "m=video 53000 RTP/AVP 32\r\n"
+	    "a=rtpmap:32 MPV/90000\r\n"
+	    "m=audio 51434 RTP/AVP 110\r\n"
+	    "a=rtpmap:110 telephone-events/8000\r\n"
+	    "a=recvonly\r\n"
+	  }
+	}
+    },
+
+    /* test 2: */
+    {
+	/*********************************************************************
+	 * RFC 3264 examples, section 10.2.
+	 * This is from Alice's point of view.
+	 */
+
+	"RFC 3264 example 10.2 (Alice's view)",
+	2,
+	{
+	  {
+	    LOCAL_OFFER,
+	    /* The initial offer from Alice to Bob indicates a single audio 
+	     * stream with the three audio codecs that are available in the 
+	     * DSP. The stream is marked as inactive, 
+	     */
+	    "v=0\r\n"
+	    "o=alice 2890844526 2890844526 IN IP4 host.anywhere.com\r\n"
+	    "s=-\r\n"
+	    "c=IN IP4 host.anywhere.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 62986 RTP/AVP 0 4 18\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "a=rtpmap:4 G723/8000\r\n"
+	    "a=rtpmap:18 G729/8000\r\n"
+	    "a=inactive\r\n",
+	    /* Bob can support dynamic switching between PCMU and G.723. So, 
+	     * he sends the following answer:
+	     */
+	    "v=0\r\n"
+	    "o=bob 2890844730 2890844731 IN IP4 host.example.com\r\n"
+	    "s=-\r\n"
+	    "c=IN IP4 host.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 54344 RTP/AVP 0 4\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "a=rtpmap:4 G723/8000\r\n"
+	    "a=inactive\r\n",
+	    /* This is how Alice's media should look like after negotiation */
+	    "v=0\r\n"
+	    "o=alice 2890844526 2890844526 IN IP4 host.anywhere.com\r\n"
+	    "s=-\r\n"
+	    "c=IN IP4 host.anywhere.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 62986 RTP/AVP 0 4\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "a=rtpmap:4 G723/8000\r\n"
+	    "a=inactive\r\n",
+	  },
+	  {
+	    LOCAL_OFFER,
+	    /* Alice sends an updated offer with a sendrecv stream: */
+	    "v=0\r\n"
+	    "o=alice 2890844526 2890844527 IN IP4 host.anywhere.com\r\n"
+	    "s=-\r\n"
+	    "c=IN IP4 host.anywhere.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 62986 RTP/AVP 4\r\n"
+	    "a=rtpmap:4 G723/8000\r\n"
+	    "a=sendrecv\r\n",
+	    /* Bob accepts the single codec: */
+	    "v=0\r\n"
+	    "o=bob 2890844730 2890844732 IN IP4 host.example.com\r\n"
+	    "s= \r\n"
+	    "c=IN IP4 host.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 54344 RTP/AVP 4\r\n"
+	    "a=rtpmap:4 G723/8000\r\n"
+	    "a=sendrecv\r\n",
+	    /* This is how Alice's media should look like after negotiation */
+	    "v=0\r\n"
+	    "o=alice 2890844526 2890844527 IN IP4 host.anywhere.com\r\n"
+	    "s=-\r\n"
+	    "c=IN IP4 host.anywhere.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 62986 RTP/AVP 4\r\n"
+	    "a=rtpmap:4 G723/8000\r\n"
+	    "a=sendrecv\r\n"
+	  }
+	}
+    },
+
+#if 0
+    // this test is commented, this causes error: 
+    // No suitable codec for remote offer (PJMEDIA_SDPNEG_NOANSCODEC),
+    // since currently the negotiator always answer with one codec, 
+    // PCMU in this case, while PCMU is not included in the second offer.
+
+    /* test 3: */
+    {
+	/*********************************************************************
+	 * RFC 3264 examples, section 10.2.
+	 * This is from Bob's point of view.
+	 *
+	 * Difference:
+	 *  - The SDP version number in Bob's initial capability is ver-1
+	 */
+
+	"RFC 3264 example 10.2 (Bob's view)",
+	2,
+	{
+	  {
+	    REMOTE_OFFER,
+	    /* Bob received offer from Alice:
+	     */
+	    "v=0\r\n"
+	    "o=alice 2890844526 2890844526 IN IP4 host.anywhere.com\r\n"
+	    "s=-\r\n"
+	    "c=IN IP4 host.anywhere.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 62986 RTP/AVP 0 4 18\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "a=rtpmap:4 G723/8000\r\n"
+	    "a=rtpmap:18 G729/8000\r\n"
+	    "a=inactive\r\n",
+	    /* Bob's capability:
+	     */
+	    "v=0\r\n"
+	    "o=bob 2890844730 2890844730 IN IP4 host.example.com\r\n"
+	    "s=-\r\n"
+	    "c=IN IP4 host.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 54344 RTP/AVP 0 4\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "a=rtpmap:4 G723/8000\r\n"
+	    "a=inactive\r\n",
+	    /* This is how Bob's media should look like after negotiation */
+	    "v=0\r\n"
+	    "o=bob 2890844730 2890844731 IN IP4 host.example.com\r\n"
+	    "s=-\r\n"
+	    "c=IN IP4 host.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 54344 RTP/AVP 0\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "a=inactive\r\n"
+	  },
+	  {
+	    REMOTE_OFFER,
+	    /* Received updated Alice's SDP: offer with a sendrecv stream: */
+	    "v=0\r\n"
+	    "o=alice 2890844526 2890844527 IN IP4 host.anywhere.com\r\n"
+	    "s=-\r\n"
+	    "c=IN IP4 host.anywhere.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 62986 RTP/AVP 4\r\n"
+	    "a=rtpmap:4 G723/8000\r\n"
+	    "a=sendrecv\r\n",
+	    /* Bob accepts the single codec: */
+	    NULL,
+	    /* This is how Bob's media should look like after negotiation */
+	    "v=0\r\n"
+	    "o=bob 2890844730 2890844732 IN IP4 host.example.com\r\n"
+	    "s=-\r\n"
+	    "c=IN IP4 host.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 54344 RTP/AVP 4\r\n"
+	    "a=rtpmap:4 G723/8000\r\n"
+	    "a=sendrecv\r\n",
+	  }
+	}
+    },
+#endif
+
+    /* test 4: */
+    {
+	/*********************************************************************
+	 * RFC 4317 Sample 2.1: Audio and Video 1 (Alice's view)
+	 *
+	 * This common scenario shows a video and audio session in which
+	 * multiple codecs are offered but only one is accepted.  As a result of
+	 * the exchange shown below, Alice and Bob may send only PCMU audio and
+	 * MPV video.  Note: Dynamic payload type 97 is used for iLBC codec
+	 */
+	"RFC 4317 section 2.1: Audio and Video 1 (Alice's view)",
+	1,
+	{
+	  {
+	    LOCAL_OFFER,
+	    /* Alice's local offer: */
+	    "v=0\r\n"
+	    "o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com\r\n"
+	    "s=-\r\n"
+	    "c=IN IP4 host.atlanta.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 49170 RTP/AVP 0 8 97\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "a=rtpmap:8 PCMA/8000\r\n"
+	    "a=rtpmap:97 iLBC/8000\r\n"
+	    "m=video 51372 RTP/AVP 31 32\r\n"
+	    "a=rtpmap:31 H261/90000\r\n"
+	    "a=rtpmap:32 MPV/90000\r\n",
+	    /* Received answer from Bob: */
+	    "v=0\r\n"
+	    "o=bob 2808844564 2808844564 IN IP4 host.biloxi.example.com\r\n"
+	    "s=-\r\n"
+	    "c=IN IP4 host.biloxi.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 49174 RTP/AVP 0\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "m=video 49170 RTP/AVP 32\r\n"
+	    "a=rtpmap:32 MPV/90000\r\n",
+	    /* This is how Alice's media should look like now: */
+	    "v=0\r\n"
+	    "o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com\r\n"
+	    "s=-\r\n"
+	    "c=IN IP4 host.atlanta.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 49170 RTP/AVP 0\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "m=video 51372 RTP/AVP 32\r\n"
+	    "a=rtpmap:32 MPV/90000\r\n"
+	  }
+	}
+    },
+
+    /* test 5: */
+    {
+	/*********************************************************************
+	 * RFC 4317 Sample 2.1: Audio and Video 1 (Bob's view)
+	 *
+	 * This common scenario shows a video and audio session in which
+	 * multiple codecs are offered but only one is accepted.  As a result of
+	 * the exchange shown below, Alice and Bob may send only PCMU audio and
+	 * MPV video.  Note: Dynamic payload type 97 is used for iLBC codec
+	 *
+	 * Difference:
+	 *  - Bob's initial capability version number
+	 */
+	"RFC 4317 section 2.1: Audio and Video 1 (Bob's view)",
+	1,
+	{
+	  {
+	    REMOTE_OFFER,
+	    /* Received Alice's local offer: */
+	    "v=0\r\n"
+	    "o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com\r\n"
+	    "s=-\r\n"
+	    "c=IN IP4 host.atlanta.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 49170 RTP/AVP 0 8 97\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "a=rtpmap:8 PCMA/8000\r\n"
+	    "a=rtpmap:97 iLBC/8000\r\n"
+	    "m=video 51372 RTP/AVP 31 32\r\n"
+	    "a=rtpmap:31 H261/90000\r\n"
+	    "a=rtpmap:32 MPV/90000\r\n",
+	    /* Bob's capability: */
+	    "v=0\r\n"
+	    "o=bob 2808844564 2808844563 IN IP4 host.biloxi.example.com\r\n"
+	    "s=-\r\n"
+	    "c=IN IP4 host.biloxi.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 49174 RTP/AVP 0\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "m=video 49170 RTP/AVP 32\r\n"
+	    "a=rtpmap:32 MPV/90000\r\n",
+	    /* This is how Bob's media should look like now: */
+	    "v=0\r\n"
+	    "o=bob 2808844564 2808844564 IN IP4 host.biloxi.example.com\r\n"
+	    "s=-\r\n"
+	    "c=IN IP4 host.biloxi.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 49174 RTP/AVP 0\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "m=video 49170 RTP/AVP 32\r\n"
+	    "a=rtpmap:32 MPV/90000\r\n"
+	  }
+	}
+    },
+
+    /* test 6: */
+    {
+	/*********************************************************************
+	 * RFC 4317 Sample 2.2: Audio and Video 2 (Alice's view)
+	 *
+	 * Difference:
+	 *  - Bob's initial capability version number
+	 */
+	"RFC 4317 section 2.2: Audio and Video 2 (Alice's view)",
+	2,
+	{
+	  {
+	    LOCAL_OFFER,
+	    /* Alice sends offer: */
+	    "v=0\r\n"
+	    "o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com\r\n"
+	    "s=alice\r\n"
+	    "c=IN IP4 host.atlanta.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 49170 RTP/AVP 0 8 97\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "a=rtpmap:8 PCMA/8000\r\n"
+	    "a=rtpmap:97 iLBC/8000\r\n"
+	    "m=video 51372 RTP/AVP 31 32\r\n"
+	    "a=rtpmap:31 H261/90000\r\n"
+	    "a=rtpmap:32 MPV/90000\r\n",
+	    /* Bob's answer: */
+	    "v=0\r\n"
+	    "o=bob 2808844564 2808844564 IN IP4 host.biloxi.example.com\r\n"
+	    "s=bob\r\n"
+	    "c=IN IP4 host.biloxi.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 49172 RTP/AVP 0 8\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "a=rtpmap:8 PCMA/8000\r\n"
+	    "m=video 0 RTP/AVP 31\r\n"
+	    "a=rtpmap:31 H261/90000\r\n",
+	    /* This is how Alice's media should look like now: */
+	    "v=0\r\n"
+	    "o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com\r\n"
+	    "s=alice\r\n"
+	    "c=IN IP4 host.atlanta.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 49170 RTP/AVP 0 8\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "a=rtpmap:8 PCMA/8000\r\n"
+	    // By #1088, the formats won't be negotiated when the media has port 0.
+	    //"m=video 0 RTP/AVP 31\r\n"
+	    "m=video 0 RTP/AVP 31 32\r\n"
+	    //"a=rtpmap:31 H261/90000\r\n"  /* <-- this is not necessary (port 0) */
+	  },
+	  {
+	    LOCAL_OFFER,
+	    /* Alice sends updated offer: */
+	    "v=0\r\n"
+	    "o=alice 2890844526 2890844527 IN IP4 host.atlanta.example.com\r\n"
+	    "s=alice\r\n"
+	    "c=IN IP4 host.atlanta.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 51372 RTP/AVP 0\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "m=video 0 RTP/AVP 31\r\n"
+	    "a=rtpmap:31 H261/90000\r\n",
+	    /* Bob's answer: */
+	    "v=0\r\n"
+	    "o=bob 2808844564 2808844565 IN IP4 host.biloxi.example.com\r\n"
+	    "s=bob\r\n"
+	    "c=IN IP4 host.biloxi.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 49172 RTP/AVP 0\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "m=video 0 RTP/AVP 31\r\n"
+	    "a=rtpmap:31 H261/90000\r\n",
+	    /* This is how Alice's SDP should look like: */
+	    "v=0\r\n"
+	    "o=alice 2890844526 2890844527 IN IP4 host.atlanta.example.com\r\n"
+	    "s=alice\r\n"
+	    "c=IN IP4 host.atlanta.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 51372 RTP/AVP 0\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "m=video 0 RTP/AVP 31\r\n"
+	    //"a=rtpmap:31 H261/90000\r\n"  /* <-- this is not necessary (port 0) */
+	  }
+	}
+    },
+
+    /* test 7: */
+    {
+	/*********************************************************************
+	 * RFC 4317 Sample 2.2: Audio and Video 2 (Bob's view)
+	 *
+	 * Difference:
+	 *  - Bob's initial capability version number
+	 */
+	"RFC 4317 section 2.2: Audio and Video 2 (Bob's view)",
+	2,
+	{
+	  {
+	    REMOTE_OFFER,
+	    /* Received offer from alice: */
+	    "v=0\r\n"
+	    "o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com\r\n"
+	    "s=alice\r\n"
+	    "c=IN IP4 host.atlanta.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 49170 RTP/AVP 0 8 97\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "a=rtpmap:8 PCMA/8000\r\n"
+	    "a=rtpmap:97 iLBC/8000\r\n"
+	    "m=video 51372 RTP/AVP 31 32\r\n"
+	    "a=rtpmap:31 H261/90000\r\n"
+	    "a=rtpmap:32 MPV/90000\r\n",
+	    /* Bob's initial capability: */
+	    "v=0\r\n"
+	    "o=bob 2808844564 2808844563 IN IP4 host.biloxi.example.com\r\n"
+	    "s=bob\r\n"
+	    "c=IN IP4 host.biloxi.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 49172 RTP/AVP 0 8\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "a=rtpmap:8 PCMA/8000\r\n"
+	    "m=video 0 RTP/AVP 31\r\n"
+	    "a=rtpmap:31 H261/90000\r\n",
+	    /* This is how Bob's answer should look like now: */
+	    "v=0\r\n"
+	    "o=bob 2808844564 2808844564 IN IP4 host.biloxi.example.com\r\n"
+	    "s=bob\r\n"
+	    "c=IN IP4 host.biloxi.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 49172 RTP/AVP 0\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "m=video 0 RTP/AVP 31\r\n"
+	    "a=rtpmap:31 H261/90000\r\n"
+	  },
+	  {
+	    REMOTE_OFFER,
+	    /* Received updated offer from Alice: */
+	    "v=0\r\n"
+	    "o=alice 2890844526 2890844527 IN IP4 host.atlanta.example.com\r\n"
+	    "s=alice\r\n"
+	    "c=IN IP4 host.atlanta.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 51372 RTP/AVP 0\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "m=video 0 RTP/AVP 31\r\n"
+	    "a=rtpmap:31 H261/90000\r\n",
+	    /* Bob's answer: */
+	    NULL,
+	    /* This is how Bob's answer should look like: */
+	    "v=0\r\n"
+	    "o=bob 2808844564 2808844565 IN IP4 host.biloxi.example.com\r\n"
+	    "s=bob\r\n"
+	    "c=IN IP4 host.biloxi.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 49172 RTP/AVP 0\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "m=video 0 RTP/AVP 31\r\n"
+	    //"a=rtpmap:31 H261/90000\r\n"  /* <-- this is not necessary (port 0) */
+	  }
+	}
+    },
+
+    /* test 8: */
+    {
+	/*********************************************************************
+	 * RFC 4317 Sample 2.4: Audio and Telephone-Events (Alice's view)
+	 *
+	 */
+
+	"RFC 4317 section 2.4: Audio and Telephone-Events (Alice's view)",
+	1,
+	{
+	  {
+	    LOCAL_OFFER,
+	    /* Alice sends offer: */
+	    "v=0\r\n"
+	    "o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com\r\n"
+	    "s=alice\r\n"
+	    "c=IN IP4 host.atlanta.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 49170 RTP/AVP 0 97\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "a=rtpmap:97 iLBC/8000\r\n"
+	    "m=audio 49172 RTP/AVP 98\r\n"
+	    "a=rtpmap:98 telephone-event/8000\r\n"
+	    "a=sendonly\r\n",
+	    /* Received Bob's answer: */
+	    "v=0\r\n"
+	    "o=bob 2808844564 2808844564 IN IP4 host.biloxi.example.com\r\n"
+	    "s=bob\r\n"
+	    "c=IN IP4 host.biloxi.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 49172 RTP/AVP 97\r\n"
+	    "a=rtpmap:97 iLBC/8000\r\n"
+	    "m=audio 49174 RTP/AVP 98\r\n"
+	    "a=rtpmap:98 telephone-event/8000\r\n"
+	    "a=recvonly\r\n",
+	    /* Alice's SDP now: */
+	    "v=0\r\n"
+	    "o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com\r\n"
+	    "s=alice\r\n"
+	    "c=IN IP4 host.atlanta.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 49170 RTP/AVP 97\r\n"
+	    "a=rtpmap:97 iLBC/8000\r\n"
+	    "m=audio 49172 RTP/AVP 98\r\n"
+	    "a=rtpmap:98 telephone-event/8000\r\n"
+	    "a=sendonly\r\n"
+	  }
+	}
+    },
+
+
+    /* test 9: */
+    {
+	/*********************************************************************
+	 * RFC 4317 Sample 2.4: Audio and Telephone-Events (Bob's view)
+	 *
+	 * Difference:
+	 *  - Bob's initial SDP version number
+	 *  - Bob's capability are added with more formats, and the
+	 *    stream order is interchanged to test the negotiator.
+	 */
+
+	"RFC 4317 section 2.4: Audio and Telephone-Events (Bob's view)",
+	1,
+	{
+	  {
+	    REMOTE_OFFER,
+	    /* Received Alice's offer: */
+	    "v=0\r\n"
+	    "o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com\r\n"
+	    "s=alice\r\n"
+	    "c=IN IP4 host.atlanta.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 49170 RTP/AVP 0 97\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "a=rtpmap:97 iLBC/8000\r\n"
+	    "m=audio 49172 RTP/AVP 98\r\n"
+	    "a=rtpmap:98 telephone-event/8000\r\n"
+	    "a=sendonly\r\n",
+	    /* Bob's initial capability: */
+	    "v=0\r\n"
+	    "o=bob 2808844564 2808844563 IN IP4 host.biloxi.example.com\r\n"
+	    "s=bob\r\n"
+	    "c=IN IP4 host.biloxi.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 49174 RTP/AVP 4 98\r\n"
+	    "a=rtpmap:98 telephone-event/8000\r\n"
+	    "m=audio 49172 RTP/AVP 97 8 99\r\n"
+	    "a=rtpmap:97 iLBC/8000\r\n"
+	    "a=rtpmap:99 telephone-event/8000\r\n",
+	    /* Bob's answer should be: */
+	    "v=0\r\n"
+	    "o=bob 2808844564 2808844564 IN IP4 host.biloxi.example.com\r\n"
+	    "s=bob\r\n"
+	    "c=IN IP4 host.biloxi.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 49172 RTP/AVP 97\r\n"
+	    "a=rtpmap:97 iLBC/8000\r\n"
+	    "m=audio 49174 RTP/AVP 98\r\n"
+	    "a=rtpmap:98 telephone-event/8000\r\n"
+	    "a=recvonly\r\n"
+	  }
+	}
+    },
+
+    /* test 10: */
+    {
+	/*********************************************************************
+	 * RFC 4317 Sample 2.6: Audio with Telephone-Events (Alice's view)
+	 *
+	 */
+
+	"RFC 4317 section 2.6: Audio with Telephone-Events (Alice's view)",
+	1,
+	{
+	  {
+	    LOCAL_OFFER,
+	    /* Alice sends offer: */
+	    "v=0\r\n"
+	    "o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com\r\n"
+	    "s=alice\r\n"
+	    "c=IN IP4 host.atlanta.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 49170 RTP/AVP 0\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "m=audio 51372 RTP/AVP 97 101\r\n"
+	    "a=rtpmap:97 iLBC/8000\r\n"
+	    "a=rtpmap:101 telephone-event/8000\r\n",
+	    /* Received bob's answer: */
+	    "v=0\r\n"
+	    "o=bob 2808844564 2808844564 IN IP4 host.biloxi.example.com\r\n"
+	    "s=bob\r\n"
+	    "c=IN IP4 host.biloxi.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 0 RTP/AVP 0\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "m=audio 49170 RTP/AVP 97 101\r\n"
+	    "a=rtpmap:97 iLBC/8000\r\n"
+	    "a=rtpmap:101 telephone-event/8000\r\n",
+	    /* Alice's local SDP should be: */
+	    "v=0\r\n"
+	    "o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com\r\n"
+	    "s=alice\r\n"
+	    "c=IN IP4 host.atlanta.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 0 RTP/AVP 0\r\n"
+	    //"a=rtpmap:0 PCMU/8000\r\n"	  /* <-- this is not necessary (port 0) */
+	    "m=audio 51372 RTP/AVP 97 101\r\n"
+	    "a=rtpmap:97 iLBC/8000\r\n"
+	    "a=rtpmap:101 telephone-event/8000\r\n"
+	  }
+	}
+    },
+
+    /* test 11: */
+    {
+	/*********************************************************************
+	 * RFC 4317 Sample 2.6: Audio with Telephone-Events (Bob's view)
+	 *
+	 * Difference:
+	 *  - Bob's SDP version number
+	 *  - Bob's initial capability are expanded with multiple m lines
+	 *    and more formats
+	 */
+
+	"RFC 4317 section 2.6: Audio with Telephone-Events (Bob's view)",
+	1,
+	{
+	  {
+	    REMOTE_OFFER,
+	    /* Received Alice's offer: */
+	    "v=0\r\n"
+	    "o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com\r\n"
+	    "s=alice\r\n"
+	    "c=IN IP4 host.atlanta.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 49170 RTP/AVP 0\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "m=audio 51372 RTP/AVP 97 101\r\n"
+	    "a=rtpmap:97 iLBC/8000\r\n"
+	    "a=rtpmap:101 telephone-event/8000\r\n",
+	    /* Bob's initial capability also has video: */
+	    "v=0\r\n"
+	    "o=bob 2808844564 2808844563 IN IP4 host.biloxi.example.com\r\n"
+	    "s=bob\r\n"
+	    "c=IN IP4 host.biloxi.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 49170 RTP/AVP 4 97 101\r\n"
+	    "a=rtpmap:4 G723/8000\r\n"
+	    "a=rtpmap:97 iLBC/8000\r\n"
+	    "a=rtpmap:101 telephone-event/8000\r\n"
+	    "m=video 1000 RTP/AVP 31\r\n"
+	    "a=rtpmap:31 H261/90000\r\n",
+	    /* Bob's answer should be: */
+	    "v=0\r\n"
+	    "o=bob 2808844564 2808844564 IN IP4 host.biloxi.example.com\r\n"
+	    "s=bob\r\n"
+	    "c=IN IP4 host.biloxi.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 0 RTP/AVP 0\r\n"
+	    //"a=rtpmap:0 PCMU/8000\r\n"      /* <-- this is not necessary (port 0) */
+	    "m=audio 49170 RTP/AVP 97 101\r\n"
+	    "a=rtpmap:97 iLBC/8000\r\n"
+	    "a=rtpmap:101 telephone-event/8000\r\n",
+	  }
+	}
+    },
+
+    /* test 12: */
+    {
+	/*********************************************************************
+	 * Ticket #527: More lenient SDP negotiator.
+	 */
+
+	"Ticket #527 scenario #1: Partial answer",
+	1,
+	{
+	  {
+	    LOCAL_OFFER,
+	    /* Alice sends offer audio and video: */
+	    "v=0\r\n"
+	    "o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com\r\n"
+	    "s=alice\r\n"
+	    "c=IN IP4 host.atlanta.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 49170 RTP/AVP 0\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "m=video 4000 RTP/AVP 31\r\n"
+	    "a=rtpmap:31 H261/90000\r\n",
+	    /* Receive Bob's answer only audio: */
+	    "v=0\r\n"
+	    "o=bob 2808844564 2808844563 IN IP4 host.biloxi.example.com\r\n"
+	    "s=bob\r\n"
+	    "c=IN IP4 host.biloxi.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 49170 RTP/AVP 0\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n",
+	    /* Alice's local SDP should be: */
+	    "v=0\r\n"
+	    "o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com\r\n"
+	    "s=alice\r\n"
+	    "c=IN IP4 host.atlanta.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 49170 RTP/AVP 0\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "m=video 0 RTP/AVP 31\r\n"
+	    //"a=rtpmap:31 H261/90000\r\n"    /* <-- this is not necessary (port 0) */
+	    "",
+	  }
+	}
+    },
+
+    /* test 13: */
+    {
+	/*********************************************************************
+	 * Ticket #527: More lenient SDP negotiator.
+	 */
+
+	"Ticket #527 scenario #1: Media mismatch in answer",
+	1,
+	{
+	  {
+	    LOCAL_OFFER,
+	    /* Alice sends offer audio and video: */
+	    "v=0\r\n"
+	    "o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com\r\n"
+	    "s=alice\r\n"
+	    "c=IN IP4 host.atlanta.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 3000 RTP/AVP 0\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "m=video 4000 RTP/AVP 31\r\n"
+	    "a=rtpmap:31 H261/90000\r\n",
+	    /* Receive Bob's answer two audio: */
+	    "v=0\r\n"
+	    "o=bob 2808844564 2808844563 IN IP4 host.biloxi.example.com\r\n"
+	    "s=bob\r\n"
+	    "c=IN IP4 host.biloxi.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 49170 RTP/AVP 0\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "m=audio 49172 RTP/AVP 0\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n",
+	    /* Alice's local SDP should be: */
+	    "v=0\r\n"
+	    "o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com\r\n"
+	    "s=alice\r\n"
+	    "c=IN IP4 host.atlanta.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 3000 RTP/AVP 0\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "m=video 0 RTP/AVP 31\r\n"
+	    //"a=rtpmap:31 H261/90000\r\n"    /* <-- this is not necessary (port 0) */
+	    "",
+	  }
+	}
+    },
+
+    /* test 14: */
+    {
+	/*********************************************************************
+	 * Ticket #527: More lenient SDP negotiator.
+	 */
+
+	"Ticket #527 scenario #2: Modify offer - partial streams",
+	2,
+	{
+	  {
+	    LOCAL_OFFER,
+	    /* Alice sends offer: */
+	    "v=0\r\n"
+	    "o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com\r\n"
+	    "s=alice\r\n"
+	    "c=IN IP4 host.atlanta.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 3000 RTP/AVP 0\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "m=audio 3100 RTP/AVP 0\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "m=video 3200 RTP/AVP 31\r\n"
+	    "a=rtpmap:31 H261/90000\r\n"
+	    "",
+	    /* Receive Bob's answer: */
+	    "v=0\r\n"
+	    "o=bob 2808844564 2808844563 IN IP4 host.biloxi.example.com\r\n"
+	    "s=bob\r\n"
+	    "c=IN IP4 host.biloxi.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 4000 RTP/AVP 0\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "m=audio 4100 RTP/AVP 0\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "m=video 4200 RTP/AVP 31\r\n"
+	    "a=rtpmap:31 H261/90000\r\n"
+	    "",
+	    /* Alice's local SDP should be: */
+	    "v=0\r\n"
+	    "o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com\r\n"
+	    "s=alice\r\n"
+	    "c=IN IP4 host.atlanta.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 3000 RTP/AVP 0\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "m=audio 3100 RTP/AVP 0\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "m=video 3200 RTP/AVP 31\r\n"
+	    "a=rtpmap:31 H261/90000\r\n"
+	    "",
+	  },
+	  {
+	    LOCAL_OFFER,
+	    /* Alice modifies offer with only specify one audio: */
+	    "v=0\r\n"
+	    "o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com\r\n"
+	    "s=alice\r\n"
+	    "c=IN IP4 host.atlanta.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 5200 RTP/AVP 0\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "",
+	    /* Receive Bob's answer: */
+	    "v=0\r\n"
+	    "o=bob 2808844564 2808844563 IN IP4 host.biloxi.example.com\r\n"
+	    "s=bob\r\n"
+	    "c=IN IP4 host.biloxi.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 7000 RTP/AVP 0\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "m=audio 0 RTP/AVP 0\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "m=video 0 RTP/AVP 31\r\n"
+	    "a=rtpmap:31 H261/90000\r\n"
+	    "",
+	    /* Alice's local SDP should be: */
+	    "v=0\r\n"
+	    "o=alice 2890844526 2890844527 IN IP4 host.atlanta.example.com\r\n"
+	    "s=alice\r\n"
+	    "c=IN IP4 host.atlanta.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 5200 RTP/AVP 0\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "m=audio 0 RTP/AVP 0\r\n"
+	    //"a=rtpmap:0 PCMU/8000\r\n"      /* <-- this is not necessary (port 0) */
+	    "m=video 0 RTP/AVP 31\r\n"
+	    //"a=rtpmap:31 H261/90000\r\n"    /* <-- this is not necessary (port 0) */
+	    "",
+	  }
+	}
+    },
+
+    /* test 15: */
+    {
+	/*********************************************************************
+	 * Ticket #527: More lenient SDP negotiator.
+	 */
+
+	"Ticket #527 scenario #2: Modify offer - unordered m= lines",
+	2,
+	{
+	  {
+	    LOCAL_OFFER,
+	    /* Alice sends offer: */
+	    "v=0\r\n"
+	    "o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com\r\n"
+	    "s=alice\r\n"
+	    "c=IN IP4 host.atlanta.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 3000 RTP/AVP 0\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "m=video 3200 RTP/AVP 31\r\n"
+	    "a=rtpmap:31 H261/90000\r\n"
+	    "",
+	    /* Receive Bob's answer: */
+	    "v=0\r\n"
+	    "o=bob 2808844564 2808844563 IN IP4 host.biloxi.example.com\r\n"
+	    "s=bob\r\n"
+	    "c=IN IP4 host.biloxi.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 4000 RTP/AVP 0\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "m=video 4200 RTP/AVP 31\r\n"
+	    "a=rtpmap:31 H261/90000\r\n"
+	    "",
+	    /* Alice's local SDP should be: */
+	    "v=0\r\n"
+	    "o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com\r\n"
+	    "s=alice\r\n"
+	    "c=IN IP4 host.atlanta.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 3000 RTP/AVP 0\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "m=video 3200 RTP/AVP 31\r\n"
+	    "a=rtpmap:31 H261/90000\r\n"
+	    "",
+	  },
+	  {
+	    LOCAL_OFFER,
+	    /* Alice modifies offer with unordered m= lines: */
+	    "v=0\r\n"
+	    "o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com\r\n"
+	    "s=alice\r\n"
+	    "c=IN IP4 host.atlanta.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=video 5000 RTP/AVP 31\r\n"
+	    "a=rtpmap:31 H261/90000\r\n"
+	    "m=audio 5200 RTP/AVP 0\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "",
+	    /* Receive Bob's answer: */
+	    "v=0\r\n"
+	    "o=bob 2808844564 2808844563 IN IP4 host.biloxi.example.com\r\n"
+	    "s=bob\r\n"
+	    "c=IN IP4 host.biloxi.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 7000 RTP/AVP 0\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "m=video 2000 RTP/AVP 31\r\n"
+	    "a=rtpmap:31 H261/90000\r\n"
+	    "",
+	    /* Alice's local SDP should be: */
+	    "v=0\r\n"
+	    "o=alice 2890844526 2890844527 IN IP4 host.atlanta.example.com\r\n"
+	    "s=alice\r\n"
+	    "c=IN IP4 host.atlanta.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 5200 RTP/AVP 0\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "m=video 5000 RTP/AVP 31\r\n"
+	    "a=rtpmap:31 H261/90000\r\n"
+	    "",
+	  }
+	}
+    },
+
+    /* test 16: */
+    {
+	/*********************************************************************
+	 * Ticket #527: More lenient SDP negotiator.
+	 */
+
+	"Ticket #527 scenario #2: Modify offer - partial & unordered streams",
+	2,
+	{
+	  {
+	    LOCAL_OFFER,
+	    /* Alice sends offer: */
+	    "v=0\r\n"
+	    "o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com\r\n"
+	    "s=alice\r\n"
+	    "c=IN IP4 host.atlanta.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 3000 RTP/AVP 0\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "m=audio 3200 RTP/AVP 0\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "m=video 3400 RTP/AVP 31\r\n"
+	    "a=rtpmap:31 H261/90000\r\n"
+	    "",
+	    /* Receive Bob's answer: */
+	    "v=0\r\n"
+	    "o=bob 2808844564 2808844563 IN IP4 host.biloxi.example.com\r\n"
+	    "s=bob\r\n"
+	    "c=IN IP4 host.biloxi.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 4000 RTP/AVP 0\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "m=audio 4200 RTP/AVP 0\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "m=video 4400 RTP/AVP 31\r\n"
+	    "a=rtpmap:31 H261/90000\r\n"
+	    "",
+	    /* Alice's local SDP should be: */
+	    "v=0\r\n"
+	    "o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com\r\n"
+	    "s=alice\r\n"
+	    "c=IN IP4 host.atlanta.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 3000 RTP/AVP 0\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "m=audio 3200 RTP/AVP 0\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "m=video 3400 RTP/AVP 31\r\n"
+	    "a=rtpmap:31 H261/90000\r\n"
+	    "",
+	  },
+	  {
+	    LOCAL_OFFER,
+	    /* Alice modifies offer by specifying partial and unordered media: */
+	    "v=0\r\n"
+	    "o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com\r\n"
+	    "s=alice\r\n"
+	    "c=IN IP4 host.atlanta.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=video 5000 RTP/AVP 31\r\n"
+	    "a=rtpmap:31 H261/90000\r\n"
+	    "m=audio 7000 RTP/AVP 0\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "",
+	    /* Receive Bob's answer: */
+	    "v=0\r\n"
+	    "o=bob 2808844564 2808844563 IN IP4 host.biloxi.example.com\r\n"
+	    "s=bob\r\n"
+	    "c=IN IP4 host.biloxi.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 4000 RTP/AVP 0\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "m=audio 0 RTP/AVP 0\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "m=video 4400 RTP/AVP 31\r\n"
+	    "a=rtpmap:31 H261/90000\r\n"
+	    "",
+	    /* Alice's local SDP should be: */
+	    "v=0\r\n"
+	    "o=alice 2890844526 2890844527 IN IP4 host.atlanta.example.com\r\n"
+	    "s=alice\r\n"
+	    "c=IN IP4 host.atlanta.example.com\r\n"
+	    "t=0 0\r\n"
+	    "m=audio 7000 RTP/AVP 0\r\n"
+	    "a=rtpmap:0 PCMU/8000\r\n"
+	    "m=audio 0 RTP/AVP 0\r\n"
+	    //"a=rtpmap:0 PCMU/8000\r\n"      /* <-- this is not necessary (port 0) */
+	    "m=video 5000 RTP/AVP 31\r\n"
+	    "a=rtpmap:31 H261/90000\r\n"
+	    "",
+	  }
+	}
+    },
+
+};
+
+static const char *find_diff(const char *s1, const char *s2,
+			     int *line)
+{
+    *line = 1;
+    while (*s2 && *s1) {
+	if (*s2 != *s1)
+	    return s2;
+	if (*s2 == '\n')
+	    ++*line;
+	++s2, ++s1;
+    }
+
+    return s2;
+}
+
+static int compare_sdp_string(const char *cmp_title,
+			      const char *title1,
+			      const pjmedia_sdp_session *sdp1,
+			      const char *title2,
+			      const pjmedia_sdp_session *sdp2,
+			      pj_status_t logical_cmp)
+{
+    char sdpbuf1[1024], sdpbuf2[1024];
+    pj_ssize_t len1, len2;
+
+    len1 = pjmedia_sdp_print(sdp1, sdpbuf1, sizeof(sdpbuf1));
+    if (len1 < 1) {
+	PJ_LOG(3,(THIS_FILE,"   error: printing sdp1"));
+	return -1;
+    }
+    sdpbuf1[len1] = '\0';
+
+    len2 = pjmedia_sdp_print(sdp2, sdpbuf2, sizeof(sdpbuf2));
+    if (len2 < 1) {
+	PJ_LOG(3,(THIS_FILE,"   error: printing sdp2"));
+	return -1;
+    }
+    sdpbuf2[len2] = '\0';
+
+    if (logical_cmp != PJ_SUCCESS) {
+	char errbuf[80];
+
+	pjmedia_strerror(logical_cmp, errbuf, sizeof(errbuf));
+
+	PJ_LOG(3,(THIS_FILE,"%s mismatch: %s\n"
+			    "%s:\n"
+			    "%s\n"
+			    "%s:\n"
+			    "%s\n",
+			    cmp_title,
+			    errbuf,
+			    title1, sdpbuf1, 
+			    title2, sdpbuf2));
+
+	return -1;
+
+    } else if (strcmp(sdpbuf1, sdpbuf2) != 0) {
+	int line;
+	const char *diff;
+
+	PJ_LOG(3,(THIS_FILE,"%s mismatch:\n"
+			    "%s:\n"
+			    "%s\n"
+			    "%s:\n"
+			    "%s\n",
+			    cmp_title,
+			    title1, sdpbuf1, 
+			    title2, sdpbuf2));
+
+	diff = find_diff(sdpbuf1, sdpbuf2, &line);
+	PJ_LOG(3,(THIS_FILE,"Difference: line %d:\n"
+			    "%s",
+			    line, diff));
+	return -1;
+
+    } else {
+	return 0;
+    }
+
+}
+
+static int offer_answer_test(pj_pool_t *pool, pjmedia_sdp_neg **p_neg,
+			     struct offer_answer *oa)
+{
+    pjmedia_sdp_session *sdp1;
+    pjmedia_sdp_neg *neg;
+    pj_status_t status;
+
+    status = pjmedia_sdp_parse(pool, oa->sdp1, pj_ansi_strlen(oa->sdp1),
+				&sdp1);
+    if (status != PJ_SUCCESS) {
+	app_perror(status, "   error: unexpected parse status for sdp1");
+	return -10;
+    }
+
+    status = pjmedia_sdp_validate(sdp1);
+    if (status != PJ_SUCCESS) {
+	app_perror(status, "   error: sdp1 validation failed");
+	return -15;
+    }
+
+    neg = *p_neg;
+
+    if (oa->type == LOCAL_OFFER) {
+	
+	/* 
+	 * Local creates offer first. 
+	 */
+	pjmedia_sdp_session *sdp2, *sdp3;
+	const pjmedia_sdp_session *active;
+
+	if (neg == NULL) {
+	    /* Create negotiator with local offer. */
+	    status = pjmedia_sdp_neg_create_w_local_offer(pool, sdp1, &neg);
+	    if (status != PJ_SUCCESS) {
+		app_perror(status, "   error: pjmedia_sdp_neg_create_w_local_offer");
+		return -20;
+	    }
+	    *p_neg = neg;
+
+	} else {
+	    /* Modify local offer */
+	    status = pjmedia_sdp_neg_modify_local_offer(pool, neg, sdp1);
+	    if (status != PJ_SUCCESS) {
+		app_perror(status, "   error: pjmedia_sdp_neg_modify_local_offer");
+		return -30;
+	    }
+	}
+
+	/* Parse and validate remote answer */
+	status = pjmedia_sdp_parse(pool, oa->sdp2, pj_ansi_strlen(oa->sdp2),
+				   &sdp2);
+	if (status != PJ_SUCCESS) {
+	    app_perror(status, "   error: parsing sdp2");
+	    return -40;
+	}
+
+	status = pjmedia_sdp_validate(sdp2);
+	if (status != PJ_SUCCESS) {
+	    app_perror(status, "   error: sdp2 validation failed");
+	    return -50;
+	}
+
+	/* Give the answer to negotiator. */
+	status = pjmedia_sdp_neg_set_remote_answer(pool, neg, sdp2);
+	if (status != PJ_SUCCESS) {
+	    app_perror(status, "   error: pjmedia_sdp_neg_rx_remote_answer");
+	    return -60;
+	}
+
+	/* Negotiate remote answer with local answer */
+	status = pjmedia_sdp_neg_negotiate(pool, neg, 0);
+	if (status != PJ_SUCCESS) {
+	    app_perror(status, "   error: pjmedia_sdp_neg_negotiate");
+	    return -70;
+	}
+
+	/* Get the local active media. */
+	status = pjmedia_sdp_neg_get_active_local(neg, &active);
+	if (status != PJ_SUCCESS) {
+	    app_perror(status, "   error: pjmedia_sdp_neg_get_local");
+	    return -80;
+	}
+
+	/* Parse and validate the correct active media. */
+	status = pjmedia_sdp_parse(pool, oa->sdp3, pj_ansi_strlen(oa->sdp3),
+				   &sdp3);
+	if (status != PJ_SUCCESS) {
+	    app_perror(status, "   error: parsing sdp3");
+	    return -90;
+	}
+
+	status = pjmedia_sdp_validate(sdp3);
+	if (status != PJ_SUCCESS) {
+	    app_perror(status, "   error: sdp3 validation failed");
+	    return -100;
+	}
+
+	/* Compare active with sdp3 */
+	status = pjmedia_sdp_session_cmp(active, sdp3, 0);
+	if (status != PJ_SUCCESS) {
+	    app_perror(status, "   error: active local comparison mismatch");
+	    compare_sdp_string("Logical cmp after negotiatin remote answer",
+			       "Active local sdp from negotiator", active,
+			       "The correct active local sdp", sdp3,
+			       status);
+	    return -110;
+	}
+
+	/* Compare the string representation oa both sdps */
+	status = compare_sdp_string("String cmp after negotiatin remote answer",
+				    "Active local sdp from negotiator", active,
+				    "The correct active local sdp", sdp3,
+				    PJ_SUCCESS);
+	if (status != 0)
+	    return -120;
+
+    } else {
+	/* 
+	 * Remote creates offer first. 
+	 */
+
+	pjmedia_sdp_session *sdp2 = NULL, *sdp3;
+	const pjmedia_sdp_session *answer;
+
+	if (oa->sdp2) {
+	    /* Parse and validate initial local capability */
+	    status = pjmedia_sdp_parse(pool, oa->sdp2, pj_ansi_strlen(oa->sdp2),
+				       &sdp2);
+	    if (status != PJ_SUCCESS) {
+		app_perror(status, "   error: parsing sdp2");
+		return -200;
+	    }
+
+	    status = pjmedia_sdp_validate(sdp2);
+	    if (status != PJ_SUCCESS) {
+		app_perror(status, "   error: sdp2 validation failed");
+		return -210;
+	    }
+	} else if (neg) {
+	    const pjmedia_sdp_session *lsdp;
+	    status = pjmedia_sdp_neg_get_active_local(neg, &lsdp);
+	    if (status != PJ_SUCCESS) {
+		app_perror(status, 
+			   "   error: pjmedia_sdp_neg_get_active_local");
+		return -215;
+	    }
+	    sdp2 = (pjmedia_sdp_session*)lsdp;
+	}
+
+	if (neg == NULL) {
+	    /* Create negotiator with remote offer. */
+	    status = pjmedia_sdp_neg_create_w_remote_offer(pool, sdp2, sdp1, &neg);
+	    if (status != PJ_SUCCESS) {
+		app_perror(status, "   error: pjmedia_sdp_neg_create_w_remote_offer");
+		return -220;
+	    }
+	    *p_neg = neg;
+
+	} else {
+	    /* Received subsequent offer from remote. */
+	    status = pjmedia_sdp_neg_set_remote_offer(pool, neg, sdp1);
+	    if (status != PJ_SUCCESS) {
+		app_perror(status, "   error: pjmedia_sdp_neg_rx_remote_offer");
+		return -230;
+	    }
+
+	    status = pjmedia_sdp_neg_set_local_answer(pool, neg, sdp2);
+	    if (status != PJ_SUCCESS) {
+		app_perror(status, "   error: pjmedia_sdp_neg_set_local_answer");
+		return -235;
+	    }
+	}
+
+	/* Negotiate. */
+	status = pjmedia_sdp_neg_negotiate(pool, neg, 0);
+	if (status != PJ_SUCCESS) {
+	    app_perror(status, "   error: pjmedia_sdp_neg_negotiate");
+	    return -240;
+	}
+	
+	/* Get our answer. */
+	status = pjmedia_sdp_neg_get_active_local(neg, &answer);
+	if (status != PJ_SUCCESS) {
+	    app_perror(status, "   error: pjmedia_sdp_neg_get_local");
+	    return -250;
+	}
+
+	/* Parse the correct answer. */
+	status = pjmedia_sdp_parse(pool, oa->sdp3, pj_ansi_strlen(oa->sdp3),
+				   &sdp3);
+	if (status != PJ_SUCCESS) {
+	    app_perror(status, "   error: parsing sdp3");
+	    return -260;
+	}
+
+	/* Validate the correct answer. */
+	status = pjmedia_sdp_validate(sdp3);
+	if (status != PJ_SUCCESS) {
+	    app_perror(status, "   error: sdp3 validation failed");
+	    return -270;
+	}
+
+	/* Compare answer from negotiator and the correct answer */
+	status = pjmedia_sdp_session_cmp(sdp3, answer, 0);
+	if (status != PJ_SUCCESS) {
+	    compare_sdp_string("Logical cmp after negotiating remote offer",
+			       "Local answer from negotiator", answer,
+			       "The correct local answer", sdp3,
+			       status);
+
+	    return -280;
+	}
+
+	/* Compare the string representation oa both answers */
+	status = compare_sdp_string("String cmp after negotiating remote offer",
+				    "Local answer from negotiator", answer,
+				    "The correct local answer", sdp3,
+				    PJ_SUCCESS);
+	if (status != 0)
+	    return -290;
+
+    }
+
+    return 0;
+}
+
+static int perform_test(pj_pool_t *pool, int test_index)
+{
+    pjmedia_sdp_neg *neg = NULL;
+    unsigned i;
+    int rc;
+
+    for (i=0; i<test[test_index].offer_answer_count; ++i) {
+
+	rc = offer_answer_test(pool, &neg, &test[test_index].offer_answer[i]);
+	if (rc != 0) {
+	    PJ_LOG(3,(THIS_FILE, "  test %d offer answer %d failed with status %d",
+		      test_index, i, rc));
+	    return rc;
+	}
+    }
+
+    return 0;
+}
+
+int sdp_neg_test()
+{
+    unsigned i;
+    int status;
+
+    for (i=START_TEST; i<PJ_ARRAY_SIZE(test); ++i) {
+	pj_pool_t *pool;
+
+	pool = pj_pool_create(mem, "sdp_neg_test", 4000, 4000, NULL);
+	if (!pool)
+	    return PJ_ENOMEM;
+
+	PJ_LOG(3,(THIS_FILE,"  test %d: %s", i, test[i].title));
+	status = perform_test(pool, i);
+
+	pj_pool_release(pool);
+
+	if (status != 0) {
+	    return status;
+	}
+    }
+
+    return 0;
+}
+