diff --git a/gst/rtpmanager/rtpsession.c b/gst/rtpmanager/rtpsession.c index 05dd6b5362..081de5070a 100644 --- a/gst/rtpmanager/rtpsession.c +++ b/gst/rtpmanager/rtpsession.c @@ -1579,6 +1579,27 @@ rtp_session_add_conflicting_address (RTPSession * sess, add_conflicting_address (sess->conflicting_addresses, address, time); } +static void +rtp_session_have_conflict (RTPSession * sess, RTPSource * source, + GSocketAddress * address, GstClockTime current_time) +{ + guint32 ssrc = rtp_source_get_ssrc (source); + + /* Its a new collision, lets change our SSRC */ + rtp_session_add_conflicting_address (sess, address, current_time); + + /* mark the source BYE */ + rtp_source_mark_bye (source, "SSRC Collision"); + /* if we were suggesting this SSRC, change to something else */ + if (sess->suggested_ssrc == ssrc) { + sess->suggested_ssrc = rtp_session_create_new_ssrc (sess); + sess->internal_ssrc_set = TRUE; + } + + on_ssrc_collision (sess, source); + + rtp_session_schedule_bye_locked (sess, current_time); +} static gboolean check_collision (RTPSession * sess, RTPSource * source, @@ -1672,22 +1693,11 @@ check_collision (RTPSession * sess, RTPSource * source, */ GST_DEBUG ("Our packets are being looped back to us, dropping"); } else { - /* Its a new collision, lets change our SSRC */ - rtp_session_add_conflicting_address (sess, pinfo->address, + GST_DEBUG ("Collision for SSRC %x from new incoming packet," + " change our sender ssrc", ssrc); + + rtp_session_have_conflict (sess, source, pinfo->address, pinfo->current_time); - - GST_DEBUG ("Collision for SSRC %x", ssrc); - /* mark the source BYE */ - rtp_source_mark_bye (source, "SSRC Collision"); - /* if we were suggesting this SSRC, change to something else */ - if (sess->suggested_ssrc == ssrc) { - sess->suggested_ssrc = rtp_session_create_new_ssrc (sess); - sess->internal_ssrc_set = TRUE; - } - - on_ssrc_collision (sess, source); - - rtp_session_schedule_bye_locked (sess, pinfo->current_time); } } @@ -3115,9 +3125,31 @@ rtp_session_send_rtp (RTPSession * sess, gpointer data, gboolean is_list, if (created) on_new_sender_ssrc (sess, source); - if (!source->internal) - /* FIXME: Send GstRTPCollision upstream */ - goto collision; + if (!source->internal) { + GSocketAddress *from; + + if (source->rtp_from) + from = source->rtp_from; + else + from = source->rtcp_from; + if (from) { + if (rtp_session_find_conflicting_address (sess, from, current_time)) { + /* Its a known conflict, its probably a loop, not a collision + * lets just drop the incoming packet + */ + GST_LOG ("Our packets are being looped back to us, ignoring collision"); + } else { + GST_DEBUG ("Collision for SSRC %x, change our sender ssrc", pinfo.ssrc); + + rtp_session_have_conflict (sess, source, from, current_time); + + goto collision; + } + } else { + GST_LOG ("Ignoring collision on sent SSRC %x because remote source" + " doesn't have an address", pinfo.ssrc); + } + } prevsender = RTP_SOURCE_IS_SENDER (source); oldrate = source->bitrate; diff --git a/tests/check/elements/rtpsession.c b/tests/check/elements/rtpsession.c index ab9d36aac1..0e9f8cfb4e 100644 --- a/tests/check/elements/rtpsession.c +++ b/tests/check/elements/rtpsession.c @@ -949,22 +949,36 @@ add_rtcp_sdes_packet (GstBuffer * gstbuf, guint32 ssrc, const char *cname) GST_START_TEST (test_ssrc_collision_when_sending) { SessionHarness *h = session_harness_new (); - GstBuffer *buf = gst_rtcp_buffer_new (1400); + GstBuffer *buf; + GstEvent *ev; + GSocketAddress *saddr; -/* Push SDES with identical SSRC as what we will use for sending RTP, - establishing this as a non-internal SSRC */ + /* Push SDES with identical SSRC as what we will use for sending RTP, + establishing this as a non-internal SSRC */ + buf = gst_rtcp_buffer_new (1400); add_rtcp_sdes_packet (buf, 0x12345678, "test@foo.bar"); + saddr = g_inet_socket_address_new_from_string ("127.0.0.1", 8080); + gst_buffer_add_net_address_meta (buf, saddr); + g_object_unref (saddr); session_harness_recv_rtcp (h, buf); + /* Push RTP buffer making our internal SSRC=0x12345678 */ - fail_unless_equals_int (GST_FLOW_OK, - session_harness_send_rtp (h, generate_test_buffer (0, 0x12345678))); + buf = generate_test_buffer (0, 0x12345678); + fail_unless_equals_int (GST_FLOW_OK, session_harness_send_rtp (h, buf)); /* Verify the packet we just sent is not being boomeranged back to us as a received packet! */ fail_unless_equals_int (0, gst_harness_buffers_in_queue (h->recv_rtp_h)); - /* FIXME: verify a Collision event coming upstream! */ + while ((ev = gst_harness_try_pull_upstream_event (h->send_rtp_h)) != NULL) { + if (GST_EVENT_CUSTOM_UPSTREAM == GST_EVENT_TYPE (ev) && + gst_event_has_name (ev, "GstRTPCollision")) + break; + gst_event_unref (ev); + } + fail_unless (ev != NULL); + gst_event_unref (ev); session_harness_free (h); }