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
This commit is contained in:
parent
1522c4467c
commit
4495e64b7c
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue