Index: pjproject/trunk/pjmedia/src/pjmedia/sdp_neg.c
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia/sdp_neg.c	(revision 1949)
+++ pjproject/trunk/pjmedia/src/pjmedia/sdp_neg.c	(revision 1950)
@@ -225,4 +225,10 @@
 				    const pjmedia_sdp_session *local)
 {
+    pjmedia_sdp_session *new_offer;
+    pjmedia_sdp_session *old_offer;
+    char media_used[PJMEDIA_MAX_SDP_MEDIA];
+    unsigned oi; /* old offer media index */
+    pj_status_t status;
+
     /* Check arguments are valid. */
     PJ_ASSERT_RETURN(pool && neg && local, PJ_EINVAL);
@@ -232,8 +238,74 @@
 		     PJMEDIA_SDPNEG_EINSTATE);
 
+    /* Validate the new offer */
+    status = pjmedia_sdp_validate(local);
+    if (status != PJ_SUCCESS)
+	return status;
+
     /* Change state to STATE_LOCAL_OFFER */
     neg->state = PJMEDIA_SDP_NEG_STATE_LOCAL_OFFER;
-    neg->initial_sdp = pjmedia_sdp_session_clone(pool, local);
-    neg->neg_local_sdp = pjmedia_sdp_session_clone(pool, local);
+
+    /* Init vars */
+    pj_bzero(media_used, sizeof(media_used));
+    old_offer = neg->active_local_sdp;
+    new_offer = pjmedia_sdp_session_clone(pool, local);
+
+    /* RFC 3264 Section 8: When issuing an offer that modifies the session,
+     * the "o=" line of the new SDP MUST be identical to that in the
+     * previous SDP, except that the version in the origin field MUST
+     * increment by one from the previous SDP.
+     */
+    pj_strdup(pool, &new_offer->origin.user, &old_offer->origin.user);
+    new_offer->origin.id = old_offer->origin.id;
+    new_offer->origin.version = old_offer->origin.version + 1;
+    pj_strdup(pool, &new_offer->origin.net_type, &old_offer->origin.net_type);
+    pj_strdup(pool, &new_offer->origin.addr_type,&old_offer->origin.addr_type);
+    pj_strdup(pool, &new_offer->origin.addr, &old_offer->origin.addr);
+
+    /* Generating the new offer, in the case media lines doesn't match the
+     * active SDP (e.g. current/active SDP's have m=audio and m=video lines, 
+     * and the new offer only has m=audio line), the negotiator will fix 
+     * the new offer by reordering and adding the missing media line with 
+     * port number set to zero.
+     */
+    for (oi = 0; oi < old_offer->media_count; ++oi) {
+	pjmedia_sdp_media *om;
+	pjmedia_sdp_media *nm;
+	unsigned ni; /* new offer media index */
+	pj_bool_t found = PJ_FALSE;
+
+	om = old_offer->media[oi];
+	for (ni = oi; ni < new_offer->media_count; ++ni) {
+	    nm = new_offer->media[ni];
+	    if (pj_strcmp(&nm->desc.media, &om->desc.media) == 0) {
+		if (ni != oi) {
+		    /* The same media found but the position unmatched to the 
+		     * old offer, so let's put this media in the right place, 
+		     * and keep the order of the rest.
+		     */
+		    pj_array_insert(new_offer->media,		 /* array    */
+				    sizeof(new_offer->media[0]), /* elmt size*/
+				    ni,				 /* count    */
+				    oi,				 /* pos      */
+				    &nm);			 /* new elmt */
+		}
+		found = PJ_TRUE;
+		break;
+	    }
+	}
+	if (!found) {
+	    pjmedia_sdp_media *m;
+
+	    m = pjmedia_sdp_media_clone(pool, om);
+	    m->desc.port = 0;
+
+	    pj_array_insert(new_offer->media, sizeof(new_offer->media[0]),
+			    new_offer->media_count++, oi, &m);
+	}
+    }
+
+    /* New_offer fixed */
+    neg->initial_sdp = new_offer;
+    neg->neg_local_sdp = pjmedia_sdp_session_clone(pool, new_offer);
 
     return PJ_SUCCESS;
@@ -649,5 +721,6 @@
 				  pjmedia_sdp_session **p_active)
 {
-    unsigned mi;
+    unsigned omi = 0; /* Offer media index */
+    unsigned ami = 0; /* Answer media index */
     pj_bool_t has_active = PJ_FALSE;
     pj_status_t status;
@@ -657,16 +730,33 @@
 
     /* Check that media count match between offer and answer */
-    if (offer->media_count != answer->media_count)
-	return PJMEDIA_SDPNEG_EMISMEDIA;
+    // Ticket #527, different media count is allowed for more interoperability,
+    // however, the media order must be same between offer and answer.
+    // if (offer->media_count != answer->media_count)
+    //	   return PJMEDIA_SDPNEG_EMISMEDIA;
 
     /* Now update each media line in the offer with the answer. */
-    for (mi=0; mi<offer->media_count; ++mi) {
-	status = process_m_answer(pool, offer->media[mi], answer->media[mi],
+    for (; omi<offer->media_count; ++omi) {
+	if (ami == answer->media_count) {
+	    /* No answer media to be negotiated */
+	    offer->media[omi]->desc.port = 0;
+	    continue;
+	}
+
+	status = process_m_answer(pool, offer->media[omi], answer->media[ami],
 				  allow_asym);
+
+	/* If media type is mismatched, just disable the media. */
+	if (status == PJMEDIA_SDPNEG_EINVANSMEDIA) {
+	    offer->media[omi]->desc.port = 0;
+	    continue;
+	}
+
 	if (status != PJ_SUCCESS)
 	    return status;
 
-	if (offer->media[mi]->desc.port != 0)
+	if (offer->media[omi]->desc.port != 0)
 	    has_active = PJ_TRUE;
+
+	++ami;
     }
 
@@ -946,5 +1036,5 @@
 	     * Reject the offer by setting the port to zero in the answer.
 	     */
-	    pjmedia_sdp_attr *a;
+	    //pjmedia_sdp_attr *a;
 
 	    /* For simplicity in the construction of the answer, we'll
@@ -956,9 +1046,12 @@
 	    am->desc.port = 0;
 
+	    // Just set port zero to disable stream without set it to inactive.
 	    /* Remove direction attribute, and replace with inactive */
 	    remove_all_media_directions(am);
-
-	    a = pjmedia_sdp_attr_create(pool, "inactive", NULL);
-	    pjmedia_sdp_media_add_attr(am, a);
+	    //a = pjmedia_sdp_attr_create(pool, "inactive", NULL);
+	    //pjmedia_sdp_media_add_attr(am, a);
+
+	    /* Then update direction */
+	    update_media_direction(pool, om, am);
 
 	} else {
Index: pjproject/trunk/pjmedia/src/test/sdp_neg_test.c
===================================================================
--- pjproject/trunk/pjmedia/src/test/sdp_neg_test.c	(revision 1949)
+++ pjproject/trunk/pjmedia/src/test/sdp_neg_test.c	(revision 1950)
@@ -321,4 +321,10 @@
     },
 
+#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: */
     {
@@ -394,4 +400,5 @@
 	}
     },
+#endif
 
     /* test 4: */
@@ -752,6 +759,5 @@
 	    "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"
-	    "a=recvonly\r\n",
+	    "a=rtpmap:99 telephone-event/8000\r\n",
 	    /* Bob's answer should be: */
 	    "v=0\r\n"
@@ -868,4 +874,364 @@
 	    "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"
+	    "",
+	  }
+	}
+    },
+
+    /* 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"
+	    "",
+	  }
+	}
+    },
+
+    /* 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"
+	    "m=video 0 RTP/AVP 31\r\n"
+	    "a=rtpmap:31 H261/90000\r\n"
+	    "",
+	  }
+	}
+    },
+
+    /* 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"
+	    "m=video 5000 RTP/AVP 31\r\n"
+	    "a=rtpmap:31 H261/90000\r\n"
+	    "",
 	  }
 	}
@@ -1076,8 +1442,8 @@
 	 */
 
-	pjmedia_sdp_session *sdp2, *sdp3;
+	pjmedia_sdp_session *sdp2 = NULL, *sdp3;
 	const pjmedia_sdp_session *answer;
 
-	if (neg == NULL) {
+	if (oa->sdp2) {
 	    /* Parse and validate initial local capability */
 	    status = pjmedia_sdp_parse(pool, oa->sdp2, pj_native_strlen(oa->sdp2),
@@ -1093,5 +1459,14 @@
 		return -210;
 	    }
-
+	} else if (neg) {
+	    status = pjmedia_sdp_neg_get_active_local(neg, &sdp2);
+	    if (status != PJ_SUCCESS) {
+		app_perror(status, 
+			   "   error: pjmedia_sdp_neg_get_active_local");
+		return -215;
+	    }
+	}
+
+	if (neg == NULL) {
 	    /* Create negotiator with remote offer. */
 	    status = pjmedia_sdp_neg_create_w_remote_offer(pool, sdp2, sdp1, &neg);
@@ -1109,4 +1484,10 @@
 		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;
+	    }
 	}
 
Index: pjproject/trunk/pjmedia/src/test/test.c
===================================================================
--- pjproject/trunk/pjmedia/src/test/test.c	(revision 1949)
+++ pjproject/trunk/pjmedia/src/test/test.c	(revision 1950)
@@ -55,9 +55,9 @@
     mem = &caching_pool.factory;
 
-    //DO_TEST(sdp_neg_test());
+    sdp_neg_test();
     //sdp_test (&caching_pool.factory);
     //rtp_test(&caching_pool.factory);
     //session_test (&caching_pool.factory);
-    jbuf_main();
+    //jbuf_main();
 
     PJ_LOG(3,(THIS_FILE," "));
