diff --git a/gst/rtpmanager/rtpsession.c b/gst/rtpmanager/rtpsession.c index bf8cfd0140..99ec2e5d37 100644 --- a/gst/rtpmanager/rtpsession.c +++ b/gst/rtpmanager/rtpsession.c @@ -369,9 +369,6 @@ rtp_session_finalize (GObject * object) for (i = 0; i < 32; i++) g_hash_table_destroy (sess->ssrcs[i]); - g_list_foreach (sess->conflicting_addresses, (GFunc) g_free, NULL); - g_list_free (sess->conflicting_addresses); - g_free (sess->bye_reason); g_hash_table_destroy (sess->cnames); @@ -972,44 +969,6 @@ static RTPSourceCallbacks callbacks = { (RTPSourceClockRate) source_clock_rate, }; -/** - * find_add_conflicting_addresses: - * @sess: The session to check in - * @arrival: The arrival stats for the buffer - * - * Checks if an address which has a conflict is already known, - * otherwise remembers it to prevent loops. - * - * Returns: TRUE if it was a known conflict, FALSE otherwise - */ - -static gboolean -find_add_conflicting_addresses (RTPSession * sess, RTPArrivalStats * arrival) -{ - GList *item; - RTPConflictingAddress *new_conflict; - - for (item = g_list_first (sess->conflicting_addresses); - item; item = g_list_next (item)) { - RTPConflictingAddress *known_conflict = item->data; - - if (gst_netaddress_equal (&arrival->address, &known_conflict->address)) { - known_conflict->time = arrival->current_time; - return TRUE; - } - } - - new_conflict = g_new0 (RTPConflictingAddress, 1); - - memcpy (&new_conflict->address, &arrival->address, sizeof (GstNetAddress)); - new_conflict->time = arrival->current_time; - - sess->conflicting_addresses = g_list_prepend (sess->conflicting_addresses, - new_conflict); - - return FALSE; -} - static gboolean check_collision (RTPSession * sess, RTPSource * source, RTPArrivalStats * arrival, gboolean rtp) @@ -1054,7 +1013,8 @@ check_collision (RTPSession * sess, RTPSource * source, } else { /* This is sending with our ssrc, is it an address we already know */ - if (find_add_conflicting_addresses (sess, arrival)) { + if (rtp_source_find_add_conflicting_address (source, &arrival->address, + arrival->current_time)) { /* Its a known conflict, its probably a loop, not a collision * lets just drop the incoming packet */ @@ -2466,7 +2426,6 @@ rtp_session_on_timeout (RTPSession * sess, GstClockTime current_time, guint64 ntpnstime, GstClockTime running_time) { GstFlowReturn result = GST_FLOW_OK; - GList *item; ReportData data; RTPSource *own; gboolean notify = FALSE; @@ -2526,21 +2485,9 @@ rtp_session_on_timeout (RTPSession * sess, GstClockTime current_time, } /* check for outdated collisions */ - GST_DEBUG ("checking collision list"); - item = g_list_first (sess->conflicting_addresses); - while (item) { - RTPConflictingAddress *known_conflict = item->data; - GList *next_item = g_list_next (item); - - if (known_conflict->time < current_time - (data.interval * - RTCP_INTERVAL_COLLISION_TIMEOUT)) { - sess->conflicting_addresses = - g_list_delete_link (sess->conflicting_addresses, item); - GST_DEBUG ("collision %p timed out", known_conflict); - g_free (known_conflict); - } - item = next_item; - } + GST_DEBUG ("Timing out collisions"); + rtp_source_timeout (sess->source, current_time, + data.interval * RTCP_INTERVAL_COLLISION_TIMEOUT); if (sess->change_ssrc) { GST_DEBUG ("need to change our SSRC (%08x)", own->ssrc); diff --git a/gst/rtpmanager/rtpsession.h b/gst/rtpmanager/rtpsession.h index ffced1a810..1a5909ae05 100644 --- a/gst/rtpmanager/rtpsession.h +++ b/gst/rtpmanager/rtpsession.h @@ -141,19 +141,6 @@ typedef struct { RTPSessionReconsider reconsider; } RTPSessionCallbacks; -/** - * RTPConflictingAddress: - * @address: #GstNetAddress which conflicted - * @last_conflict_time: time when the last conflict was seen - * - * This structure is used to account for addresses that have conflicted to find - * loops. - */ -typedef struct { - GstNetAddress address; - GstClockTime time; -} RTPConflictingAddress; - /** * RTPSession: * @lock: lock to protect the session @@ -165,7 +152,6 @@ typedef struct { * @callbacks: callbacks * @user_data: user data passed in callbacks * @stats: session statistics - * @conflicting_addresses: GList of conflicting addresses * * The RTP session manager object */ @@ -204,7 +190,6 @@ struct _RTPSession { RTPSessionStats stats; - GList *conflicting_addresses; gboolean change_ssrc; }; diff --git a/gst/rtpmanager/rtpsource.c b/gst/rtpmanager/rtpsource.c index 0b014b68f1..568811bca0 100644 --- a/gst/rtpmanager/rtpsource.c +++ b/gst/rtpmanager/rtpsource.c @@ -188,6 +188,9 @@ rtp_source_finalize (GObject * object) gst_caps_replace (&src->caps, NULL); + g_list_foreach (src->conflicting_addresses, (GFunc) g_free, NULL); + g_list_free (src->conflicting_addresses); + G_OBJECT_CLASS (rtp_source_parent_class)->finalize (object); } @@ -1582,3 +1585,76 @@ rtp_source_get_last_rb (RTPSource * src, guint8 * fractionlost, return TRUE; } + +/** + * rtp_source_find_add_conflicting_address: + * @src: The source the packet came in + * @address: address to check for + * @time: The time when the packet that is in conflict arrived + * + * Checks if an address which has a conflict is already known, + * otherwise remembers it to prevent loops. + * + * Returns: TRUE if it was a known conflict, FALSE otherwise + */ + +gboolean +rtp_source_find_add_conflicting_address (RTPSource * src, + GstNetAddress * address, GstClockTime time) +{ + GList *item; + RTPConflictingAddress *new_conflict; + + for (item = g_list_first (src->conflicting_addresses); + item; item = g_list_next (item)) { + RTPConflictingAddress *known_conflict = item->data; + + if (gst_netaddress_equal (address, &known_conflict->address)) { + known_conflict->time = time; + return TRUE; + } + } + + new_conflict = g_new0 (RTPConflictingAddress, 1); + + memcpy (&new_conflict->address, address, sizeof (GstNetAddress)); + new_conflict->time = time; + + src->conflicting_addresses = g_list_prepend (src->conflicting_addresses, + new_conflict); + + return FALSE; +} + +/** + * rtp_source_timeout: + * @src: The #RTPSource + * @current_time: The current time + * @collision_timeout: The amount of time after which a collision is timed out + * + * This is processed on each RTCP interval. It times out old collisions. + */ + +void +rtp_source_timeout (RTPSource * src, GstClockTime current_time, + GstClockTime collision_timeout) +{ + GList *item; + + item = g_list_first (src->conflicting_addresses); + while (item) { + RTPConflictingAddress *known_conflict = item->data; + GList *next_item = g_list_next (item); + + if (known_conflict->time < current_time - collision_timeout) { + gchar buf[40]; + + src->conflicting_addresses = + g_list_delete_link (src->conflicting_addresses, item); + gst_netaddress_to_string (&known_conflict->address, buf, 40); + GST_DEBUG ("collision %p timed out: %s", known_conflict, buf); + g_free (known_conflict); + } + item = next_item; + } +} diff --git a/gst/rtpmanager/rtpsource.h b/gst/rtpmanager/rtpsource.h index f15e862142..7cba4e3269 100644 --- a/gst/rtpmanager/rtpsource.h +++ b/gst/rtpmanager/rtpsource.h @@ -100,10 +100,25 @@ typedef struct { RTPSourceClockRate clock_rate; } RTPSourceCallbacks; +/** + * RTPConflictingAddress: + * @address: #GstNetAddress which conflicted + * @last_conflict_time: time when the last conflict was seen + * + * This structure is used to account for addresses that have conflicted to find + * loops. + */ +typedef struct { + GstNetAddress address; + GstClockTime time; +} RTPConflictingAddress; + /** * RTPSource: * * A source in the #RTPSession + * + * @conflicting_addresses: GList of conflicting addresses */ struct _RTPSource { GObject object; @@ -151,6 +166,8 @@ struct _RTPSource { gpointer user_data; RTPSourceStats stats; + + GList *conflicting_addresses; }; struct _RTPSourceClass { @@ -219,4 +236,13 @@ gboolean rtp_source_get_last_rb (RTPSource *src, guint8 *fraction void rtp_source_reset (RTPSource * src); +gboolean rtp_source_find_add_conflicting_address (RTPSource * src, + GstNetAddress *address, + GstClockTime time); + +void rtp_source_timeout (RTPSource * src, + GstClockTime current_time, + GstClockTime collision_timeout); + + #endif /* __RTP_SOURCE_H__ */