|
|
|
@ -257,6 +257,8 @@ struct ice_wrap {
|
|
|
|
|
struct rtp_ssrc_mapping {
|
|
|
|
|
/*! \brief The received SSRC */
|
|
|
|
|
unsigned int ssrc;
|
|
|
|
|
/*! True if the SSRC is available. Otherwise, this is a placeholder mapping until the SSRC is set. */
|
|
|
|
|
unsigned int ssrc_valid;
|
|
|
|
|
/*! \brief The RTP instance this SSRC belongs to*/
|
|
|
|
|
struct ast_rtp_instance *instance;
|
|
|
|
|
};
|
|
|
|
@ -3344,7 +3346,7 @@ static int ast_rtp_new(struct ast_rtp_instance *instance,
|
|
|
|
|
* \return 0 if element does not match.
|
|
|
|
|
* \return Non-zero if element matches.
|
|
|
|
|
*/
|
|
|
|
|
#define SSRC_MAPPING_ELEM_CMP(elem, value) (elem.instance == value)
|
|
|
|
|
#define SSRC_MAPPING_ELEM_CMP(elem, value) ((elem).instance == (value))
|
|
|
|
|
|
|
|
|
|
/*! \pre instance is locked */
|
|
|
|
|
static int ast_rtp_destroy(struct ast_rtp_instance *instance)
|
|
|
|
@ -4788,18 +4790,26 @@ static struct ast_rtp_instance *rtp_find_instance_by_ssrc(struct ast_rtp_instanc
|
|
|
|
|
struct ast_rtp *rtp, unsigned int ssrc)
|
|
|
|
|
{
|
|
|
|
|
int index;
|
|
|
|
|
struct ast_rtp_instance *found = instance;
|
|
|
|
|
|
|
|
|
|
if (!AST_VECTOR_SIZE(&rtp->ssrc_mapping)) {
|
|
|
|
|
/* This instance is not bundled */
|
|
|
|
|
return instance;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Find the bundled child instance */
|
|
|
|
|
for (index = 0; index < AST_VECTOR_SIZE(&rtp->ssrc_mapping); ++index) {
|
|
|
|
|
struct rtp_ssrc_mapping *mapping = AST_VECTOR_GET_ADDR(&rtp->ssrc_mapping, index);
|
|
|
|
|
|
|
|
|
|
if (mapping->ssrc == ssrc) {
|
|
|
|
|
found = mapping->instance;
|
|
|
|
|
break;
|
|
|
|
|
if (mapping->ssrc_valid && mapping->ssrc == ssrc) {
|
|
|
|
|
return mapping->instance;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return found;
|
|
|
|
|
/* Does the SSRC match the bundled parent? */
|
|
|
|
|
if (rtp->themssrc_valid && rtp->themssrc == ssrc) {
|
|
|
|
|
return instance;
|
|
|
|
|
}
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const char *rtcp_payload_type2str(unsigned int pt)
|
|
|
|
@ -5040,7 +5050,7 @@ static struct ast_frame *ast_rtcp_interpret(struct ast_rtp_instance *instance, c
|
|
|
|
|
/* Determine the appropriate instance for this */
|
|
|
|
|
if (ssrc_valid) {
|
|
|
|
|
child = rtp_find_instance_by_ssrc(transport, transport_rtp, ssrc);
|
|
|
|
|
if (child != transport) {
|
|
|
|
|
if (child && child != transport) {
|
|
|
|
|
/*
|
|
|
|
|
* It is safe to hold the child lock while holding the parent lock.
|
|
|
|
|
* We guarantee that the locking order is always parent->child or
|
|
|
|
@ -5551,6 +5561,10 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc
|
|
|
|
|
|
|
|
|
|
/* Determine the appropriate instance for this */
|
|
|
|
|
child = rtp_find_instance_by_ssrc(instance, rtp, ssrc);
|
|
|
|
|
if (!child) {
|
|
|
|
|
/* Neither the bundled parent nor any child has this SSRC */
|
|
|
|
|
return &ast_null_frame;
|
|
|
|
|
}
|
|
|
|
|
if (child != instance) {
|
|
|
|
|
/* It is safe to hold the child lock while holding the parent lock, we guarantee that the locking order
|
|
|
|
|
* is always parent->child or that the child lock is not held when acquiring the parent lock.
|
|
|
|
@ -5726,39 +5740,42 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc
|
|
|
|
|
timestamp = ntohl(rtpheader[1]);
|
|
|
|
|
|
|
|
|
|
AST_LIST_HEAD_INIT_NOLOCK(&frames);
|
|
|
|
|
/* Force a marker bit and change SSRC if the SSRC changes */
|
|
|
|
|
if (rtp->themssrc_valid && rtp->themssrc != ssrc) {
|
|
|
|
|
struct ast_frame *f, srcupdate = {
|
|
|
|
|
AST_FRAME_CONTROL,
|
|
|
|
|
.subclass.integer = AST_CONTROL_SRCCHANGE,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (!mark) {
|
|
|
|
|
if (rtpdebug) {
|
|
|
|
|
ast_debug(1, "Forcing Marker bit, because SSRC has changed\n");
|
|
|
|
|
/* Only non-bundled instances can change/learn the remote's SSRC implicitly. */
|
|
|
|
|
if (!child && !AST_VECTOR_SIZE(&rtp->ssrc_mapping)) {
|
|
|
|
|
/* Force a marker bit and change SSRC if the SSRC changes */
|
|
|
|
|
if (rtp->themssrc_valid && rtp->themssrc != ssrc) {
|
|
|
|
|
struct ast_frame *f, srcupdate = {
|
|
|
|
|
AST_FRAME_CONTROL,
|
|
|
|
|
.subclass.integer = AST_CONTROL_SRCCHANGE,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (!mark) {
|
|
|
|
|
if (rtpdebug) {
|
|
|
|
|
ast_debug(1, "Forcing Marker bit, because SSRC has changed\n");
|
|
|
|
|
}
|
|
|
|
|
mark = 1;
|
|
|
|
|
}
|
|
|
|
|
mark = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
f = ast_frisolate(&srcupdate);
|
|
|
|
|
AST_LIST_INSERT_TAIL(&frames, f, frame_list);
|
|
|
|
|
f = ast_frisolate(&srcupdate);
|
|
|
|
|
AST_LIST_INSERT_TAIL(&frames, f, frame_list);
|
|
|
|
|
|
|
|
|
|
rtp->seedrxseqno = 0;
|
|
|
|
|
rtp->rxcount = 0;
|
|
|
|
|
rtp->rxoctetcount = 0;
|
|
|
|
|
rtp->cycles = 0;
|
|
|
|
|
rtp->lastrxseqno = 0;
|
|
|
|
|
rtp->last_seqno = 0;
|
|
|
|
|
rtp->last_end_timestamp = 0;
|
|
|
|
|
if (rtp->rtcp) {
|
|
|
|
|
rtp->rtcp->expected_prior = 0;
|
|
|
|
|
rtp->rtcp->received_prior = 0;
|
|
|
|
|
rtp->seedrxseqno = 0;
|
|
|
|
|
rtp->rxcount = 0;
|
|
|
|
|
rtp->rxoctetcount = 0;
|
|
|
|
|
rtp->cycles = 0;
|
|
|
|
|
rtp->lastrxseqno = 0;
|
|
|
|
|
rtp->last_seqno = 0;
|
|
|
|
|
rtp->last_end_timestamp = 0;
|
|
|
|
|
if (rtp->rtcp) {
|
|
|
|
|
rtp->rtcp->expected_prior = 0;
|
|
|
|
|
rtp->rtcp->received_prior = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rtp->themssrc = ssrc; /* Record their SSRC to put in future RR */
|
|
|
|
|
rtp->themssrc_valid = 1;
|
|
|
|
|
}
|
|
|
|
|
/* Bundled children cannot change/learn their SSRC implicitly. */
|
|
|
|
|
ast_assert(!child || (rtp->themssrc_valid && rtp->themssrc == ssrc));
|
|
|
|
|
rtp->themssrc = ssrc; /* Record their SSRC to put in future RR */
|
|
|
|
|
rtp->themssrc_valid = 1;
|
|
|
|
|
|
|
|
|
|
/* Remove any padding bytes that may be present */
|
|
|
|
|
if (padding) {
|
|
|
|
@ -6520,13 +6537,14 @@ static void ast_rtp_set_remote_ssrc(struct ast_rtp_instance *instance, unsigned
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rtp->themssrc = ssrc;
|
|
|
|
|
rtp->themssrc_valid = 1;
|
|
|
|
|
|
|
|
|
|
/* If this is bundled we need to update the SSRC mapping */
|
|
|
|
|
if (rtp->bundled) {
|
|
|
|
|
struct ast_rtp *bundled_rtp;
|
|
|
|
|
int index;
|
|
|
|
|
|
|
|
|
|
ast_assert(rtp->themssrc_valid);
|
|
|
|
|
|
|
|
|
|
ao2_unlock(instance);
|
|
|
|
|
|
|
|
|
|
/* The child lock can't be held while accessing the parent */
|
|
|
|
@ -6536,8 +6554,9 @@ static void ast_rtp_set_remote_ssrc(struct ast_rtp_instance *instance, unsigned
|
|
|
|
|
for (index = 0; index < AST_VECTOR_SIZE(&bundled_rtp->ssrc_mapping); ++index) {
|
|
|
|
|
struct rtp_ssrc_mapping *mapping = AST_VECTOR_GET_ADDR(&bundled_rtp->ssrc_mapping, index);
|
|
|
|
|
|
|
|
|
|
if (mapping->ssrc == rtp->themssrc) {
|
|
|
|
|
if (mapping->instance == instance) {
|
|
|
|
|
mapping->ssrc = ssrc;
|
|
|
|
|
mapping->ssrc_valid = 1;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -6546,9 +6565,6 @@ static void ast_rtp_set_remote_ssrc(struct ast_rtp_instance *instance, unsigned
|
|
|
|
|
|
|
|
|
|
ao2_lock(instance);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rtp->themssrc = ssrc;
|
|
|
|
|
rtp->themssrc_valid = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void ast_rtp_set_stream_num(struct ast_rtp_instance *instance, int stream_num)
|
|
|
|
@ -6601,8 +6617,8 @@ static int ast_rtp_bundle(struct ast_rtp_instance *child, struct ast_rtp_instanc
|
|
|
|
|
/* Children maintain a reference to the parent to guarantee that the transport doesn't go away on them */
|
|
|
|
|
child_rtp->bundled = ao2_bump(parent);
|
|
|
|
|
|
|
|
|
|
ast_assert(child_rtp->themssrc_valid);
|
|
|
|
|
mapping.ssrc = child_rtp->themssrc;
|
|
|
|
|
mapping.ssrc_valid = child_rtp->themssrc_valid;
|
|
|
|
|
mapping.instance = child;
|
|
|
|
|
|
|
|
|
|
ao2_unlock(child);
|
|
|
|
|