From ed2a7e3eafd2ead9ed3db5adf3f201fb4fe085dd Mon Sep 17 00:00:00 2001 From: Paulo Vicentini <paulo.vicentini@gmail.com> Date: Wed, 26 Feb 2020 01:30:04 +0100 Subject: [PATCH] chan_pjsip: Check audio frame when remote SSRC changes. If the SSRC of a received RTP packet differed from the previous SSRC an SSRC change control frame would be queued ahead of the media frame. In the case of audio this would result in the format of the audio frame not being checked, and if it differed or was not allowed then it could cause the call to drop due to failure to set up a translation path. The chan_pjsip module will now no longer assume the first frame will be the audio frame and instead goes through the complete list to find it. ASTERISK-28759 Change-Id: I6d854cc523f343e299a615636fc65bdbd5f809ec --- channels/chan_pjsip.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/channels/chan_pjsip.c b/channels/chan_pjsip.c index 0e43373c9a..0ec17915f7 100644 --- a/channels/chan_pjsip.c +++ b/channels/chan_pjsip.c @@ -829,6 +829,7 @@ static struct ast_frame *chan_pjsip_read_stream(struct ast_channel *ast) struct ast_sip_session_media_read_callback_state *callback_state; struct ast_frame *f; int fdno = ast_channel_fdno(ast) - AST_EXTENDED_FDS; + struct ast_frame *cur; if (fdno >= AST_VECTOR_SIZE(&session->active_media_state->read_callbacks)) { return &ast_null_frame; @@ -841,8 +842,13 @@ static struct ast_frame *chan_pjsip_read_stream(struct ast_channel *ast) return f; } - if (f->frametype != AST_FRAME_VOICE || - callback_state->session != session->active_media_state->default_session[callback_state->session->type]) { + for (cur = f; cur; cur = AST_LIST_NEXT(cur, frame_list)) { + if (cur->frametype == AST_FRAME_VOICE) { + break; + } + } + + if (!cur || callback_state->session != session->active_media_state->default_session[callback_state->session->type]) { return f; } @@ -854,36 +860,36 @@ static struct ast_frame *chan_pjsip_read_stream(struct ast_channel *ast) * raw read format BEFORE the native format check */ if (!session->endpoint->asymmetric_rtp_codec && - ast_format_cmp(ast_channel_rawwriteformat(ast), f->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL && - is_compatible_format(session, f)) { + ast_format_cmp(ast_channel_rawwriteformat(ast), cur->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL && + is_compatible_format(session, cur)) { struct ast_format_cap *caps; /* For maximum compatibility we ensure that the formats match that of the received media */ ast_debug(1, "Oooh, got a frame with format of %s on channel '%s' when we're sending '%s', switching to match\n", - ast_format_get_name(f->subclass.format), ast_channel_name(ast), + ast_format_get_name(cur->subclass.format), ast_channel_name(ast), ast_format_get_name(ast_channel_rawwriteformat(ast))); caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); if (caps) { ast_format_cap_append_from_cap(caps, ast_channel_nativeformats(ast), AST_MEDIA_TYPE_UNKNOWN); ast_format_cap_remove_by_type(caps, AST_MEDIA_TYPE_AUDIO); - ast_format_cap_append(caps, f->subclass.format, 0); + ast_format_cap_append(caps, cur->subclass.format, 0); ast_channel_nativeformats_set(ast, caps); ao2_ref(caps, -1); } - ast_set_write_format_path(ast, ast_channel_writeformat(ast), f->subclass.format); - ast_set_read_format_path(ast, ast_channel_readformat(ast), f->subclass.format); + ast_set_write_format_path(ast, ast_channel_writeformat(ast), cur->subclass.format); + ast_set_read_format_path(ast, ast_channel_readformat(ast), cur->subclass.format); if (ast_channel_is_bridged(ast)) { ast_channel_set_unbridged_nolock(ast, 1); } } - if (ast_format_cap_iscompatible_format(ast_channel_nativeformats(ast), f->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) { + if (ast_format_cap_iscompatible_format(ast_channel_nativeformats(ast), cur->subclass.format) + == AST_FORMAT_CMP_NOT_EQUAL) { ast_debug(1, "Oooh, got a frame with format of %s on channel '%s' when it has not been negotiated\n", - ast_format_get_name(f->subclass.format), ast_channel_name(ast)); - + ast_format_get_name(cur->subclass.format), ast_channel_name(ast)); ast_frfree(f); return &ast_null_frame; } -- GitLab