diff options
Diffstat (limited to 'res')
-rw-r--r-- | res/res_pjsip_session.c | 6 | ||||
-rw-r--r-- | res/res_rtp_asterisk.c | 60 |
2 files changed, 59 insertions, 7 deletions
diff --git a/res/res_pjsip_session.c b/res/res_pjsip_session.c index fe3680f3b..0ad2c8f30 100644 --- a/res/res_pjsip_session.c +++ b/res/res_pjsip_session.c @@ -785,6 +785,12 @@ static int handle_negotiated_sdp(struct ast_sip_session *session, const pjmedia_ * we remove it as a result of the stream limit being reached. */ if (ast_stream_get_state(stream) == AST_STREAM_STATE_REMOVED) { + /* This stream is no longer being used so release any resources the handler + * may have on it. + */ + if (session_media->handler) { + session_media_set_handler(session_media, NULL); + } continue; } diff --git a/res/res_rtp_asterisk.c b/res/res_rtp_asterisk.c index a2e63ec0b..70561d0b6 100644 --- a/res/res_rtp_asterisk.c +++ b/res/res_rtp_asterisk.c @@ -266,7 +266,8 @@ struct ast_rtp { unsigned int lastitexttimestamp; unsigned int lastotexttimestamp; unsigned int lasteventseqn; - int lastrxseqno; /*!< Last received sequence number */ + int lastrxseqno; /*!< Last received sequence number, from the network */ + int expectedseqno; /*!< Next expected sequence number, from the core */ unsigned short seedrxseqno; /*!< What sequence number did they start with?*/ unsigned int seedrxts; /*!< What RTP timestamp did they start with? */ unsigned int rxcount; /*!< How many packets have we received? */ @@ -3245,6 +3246,7 @@ static int ast_rtp_new(struct ast_rtp_instance *instance, rtp->ssrc = ast_random(); ast_uuid_generate_str(rtp->cname, sizeof(rtp->cname)); rtp->seqno = ast_random() & 0x7fff; + rtp->expectedseqno = -1; rtp->sched = sched; ast_sockaddr_copy(&rtp->bind_address, addr); @@ -3274,7 +3276,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).ssrc == (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) @@ -3289,7 +3291,7 @@ static int ast_rtp_destroy(struct ast_rtp_instance *instance) ao2_lock(rtp->bundled); bundled_rtp = ast_rtp_instance_get_data(rtp->bundled); - AST_VECTOR_REMOVE_CMP_UNORDERED(&bundled_rtp->ssrc_mapping, rtp->themssrc, SSRC_MAPPING_ELEM_CMP, AST_VECTOR_ELEM_CLEANUP_NOOP); + AST_VECTOR_REMOVE_CMP_UNORDERED(&bundled_rtp->ssrc_mapping, instance, SSRC_MAPPING_ELEM_CMP, AST_VECTOR_ELEM_CLEANUP_NOOP); ao2_unlock(rtp->bundled); ao2_lock(instance); @@ -3897,6 +3899,7 @@ static int rtp_raw_write(struct ast_rtp_instance *instance, struct ast_frame *fr unsigned int ms = calc_txstamp(rtp, &frame->delivery); struct ast_sockaddr remote_address = { {0,} }; int rate = rtp_get_rate(frame->subclass.format) / 1000; + unsigned int seqno; if (ast_format_cmp(frame->subclass.format, ast_format_g722) == AST_FORMAT_CMP_EQUAL) { frame->samples /= 2; @@ -3963,6 +3966,40 @@ static int rtp_raw_write(struct ast_rtp_instance *instance, struct ast_frame *fr rtp->lastdigitts = rtp->lastts; } + /* Assume that the sequence number we expect to use is what will be used until proven otherwise */ + seqno = rtp->seqno; + + /* If the frame contains sequence number information use it to influence our sequence number */ + if (ast_test_flag(frame, AST_FRFLAG_HAS_SEQUENCE_NUMBER)) { + if (rtp->expectedseqno != -1) { + /* Determine where the frame from the core is in relation to where we expected */ + int difference = frame->seqno - rtp->expectedseqno; + + /* If there is a substantial difference then we've either got packets really out + * of order, or the source is RTP and it has cycled. If this happens we resync + * the sequence number adjustments to this frame. If we also have packet loss + * things won't be reflected correctly but it will sort itself out after a bit. + */ + if (abs(difference) > 100) { + difference = 0; + } + + /* Adjust the sequence number being used for this packet accordingly */ + seqno += difference; + + if (difference >= 0) { + /* This frame is on time or in the future */ + rtp->expectedseqno = frame->seqno + 1; + rtp->seqno += difference; + } + } else { + /* This is the first frame with sequence number we've seen, so start keeping track */ + rtp->expectedseqno = frame->seqno + 1; + } + } else { + rtp->expectedseqno = -1; + } + if (ast_test_flag(frame, AST_FRFLAG_HAS_TIMING_INFO)) { rtp->lastts = frame->ts * rate; } @@ -3974,7 +4011,7 @@ static int rtp_raw_write(struct ast_rtp_instance *instance, struct ast_frame *fr int hdrlen = 12, res, ice; unsigned char *rtpheader = (unsigned char *)(frame->data.ptr - hdrlen); - put_unaligned_uint32(rtpheader, htonl((2 << 30) | (codec << 16) | (rtp->seqno) | (mark << 23))); + put_unaligned_uint32(rtpheader, htonl((2 << 30) | (codec << 16) | (seqno) | (mark << 23))); put_unaligned_uint32(rtpheader + 4, htonl(rtp->lastts)); put_unaligned_uint32(rtpheader + 8, htonl(rtp->ssrc)); @@ -4011,7 +4048,13 @@ static int rtp_raw_write(struct ast_rtp_instance *instance, struct ast_frame *fr } } - rtp->seqno++; + /* If the sequence number that has been used doesn't match what we expected then this is an out of + * order late packet, so we don't need to increment as we haven't yet gotten the expected frame from + * the core. + */ + if (seqno == rtp->seqno) { + rtp->seqno++; + } return 0; } @@ -5474,6 +5517,7 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc rtp->f.datalen = res - hdrlen; rtp->f.data.ptr = read_area + hdrlen; rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET; + ast_set_flag(&rtp->f, AST_FRFLAG_HAS_SEQUENCE_NUMBER); rtp->f.seqno = seqno; rtp->f.stream_num = rtp->stream_num; @@ -6082,7 +6126,7 @@ static void ast_rtp_set_stream_num(struct ast_rtp_instance *instance, int stream static int ast_rtp_bundle(struct ast_rtp_instance *child, struct ast_rtp_instance *parent) { struct ast_rtp *child_rtp = ast_rtp_instance_get_data(child); - struct ast_rtp *parent_rtp = ast_rtp_instance_get_data(parent); + struct ast_rtp *parent_rtp; struct rtp_ssrc_mapping mapping; struct ast_sockaddr them = { { 0, } }; @@ -6099,7 +6143,7 @@ static int ast_rtp_bundle(struct ast_rtp_instance *child, struct ast_rtp_instanc /* The child lock can't be held while accessing the parent */ ao2_lock(child_rtp->bundled); bundled_rtp = ast_rtp_instance_get_data(child_rtp->bundled); - AST_VECTOR_REMOVE_CMP_UNORDERED(&bundled_rtp->ssrc_mapping, child_rtp->themssrc, SSRC_MAPPING_ELEM_CMP, AST_VECTOR_ELEM_CLEANUP_NOOP); + AST_VECTOR_REMOVE_CMP_UNORDERED(&bundled_rtp->ssrc_mapping, child, SSRC_MAPPING_ELEM_CMP, AST_VECTOR_ELEM_CLEANUP_NOOP); ao2_unlock(child_rtp->bundled); ao2_lock(child); @@ -6113,6 +6157,8 @@ static int ast_rtp_bundle(struct ast_rtp_instance *child, struct ast_rtp_instanc return 0; } + parent_rtp = ast_rtp_instance_get_data(parent); + /* We no longer need any transport related resources as we will use our parent RTP instance instead */ rtp_deallocate_transport(child, child_rtp); |