rtpsession: Move SSRC conflicts lists into RTPSource

We will also need to track SSRC conflicts in remote sources.

See #607615
This commit is contained in:
Olivier Crête 2010-03-05 15:46:48 +01:00 committed by Wim Taymans
parent 38f2b4735d
commit f336ea283f
4 changed files with 107 additions and 73 deletions

View file

@ -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);

View file

@ -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;
};

View file

@ -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;
}
}

View file

@ -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__ */