mirror of
https://github.com/asterisk/asterisk.git
synced 2025-10-09 06:28:14 +00:00
res_pjsip: Add option to force G.726 to be treated as AAL2 packed.
Some phones send g.726 audio packed for AAL2, which differs from what is recommended by RFC 3351. If Asterisk receives audio formatted as such when negotiating g.726 then it sounds a bit distorted. Added an option to res_pjsip_endpoint that allows g.726 negotiated audio to be treated as g.726 AAL2 packed. ASTERISK-25158 #close Reported by: Steve Pitts Change-Id: Ie7e21f75493d7fe53e75e12c971e72f5afa33615
This commit is contained in:
6
CHANGES
6
CHANGES
@@ -17,6 +17,12 @@ AMI
|
|||||||
* A new ContactStatus event has been added that reflects res_pjsip contact
|
* A new ContactStatus event has been added that reflects res_pjsip contact
|
||||||
lifecycle changes: Created, Removed, Reachable, Unreachable, Unknown.
|
lifecycle changes: Created, Removed, Reachable, Unreachable, Unknown.
|
||||||
|
|
||||||
|
res_pjsip
|
||||||
|
------------------
|
||||||
|
* A new 'g726_non_standard' endpoint option has been added that, when set to
|
||||||
|
'yes' and g.726 audio is negotiated, forces the codec to be treated as if it
|
||||||
|
is AAL2 packed on the channel.
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
--- Functionality changes from Asterisk 13.3.0 to Asterisk 13.4.0 ------------
|
--- Functionality changes from Asterisk 13.3.0 to Asterisk 13.4.0 ------------
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
@@ -656,6 +656,11 @@
|
|||||||
; "no")
|
; "no")
|
||||||
;media_encryption_optimistic=no ; Use encryption if possible but don't fail the call
|
;media_encryption_optimistic=no ; Use encryption if possible but don't fail the call
|
||||||
; if not possible.
|
; if not possible.
|
||||||
|
;g726_non_standard=no ; When set to "yes" and an endpoint negotiates g.726
|
||||||
|
; audio then g.726 for AAL2 packing order is used contrary
|
||||||
|
; to what is recommended in RFC3551. Note, 'g726aal2' also
|
||||||
|
; needs to be specified in the codec allow list
|
||||||
|
; (default: "no")
|
||||||
;inband_progress=no ; Determines whether chan_pjsip will indicate ringing
|
;inband_progress=no ; Determines whether chan_pjsip will indicate ringing
|
||||||
; using inband progress (default: "no")
|
; using inband progress (default: "no")
|
||||||
;call_group= ; The numeric pickup groups for a channel (default: "")
|
;call_group= ; The numeric pickup groups for a channel (default: "")
|
||||||
|
@@ -0,0 +1,30 @@
|
|||||||
|
"""add g726_non_standard
|
||||||
|
|
||||||
|
Revision ID: 28b8e71e541f
|
||||||
|
Revises: a541e0b5e89
|
||||||
|
Create Date: 2015-06-12 16:07:08.609628
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '28b8e71e541f'
|
||||||
|
down_revision = 'a541e0b5e89'
|
||||||
|
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
from sqlalchemy.dialects.postgresql import ENUM
|
||||||
|
|
||||||
|
YESNO_NAME = 'yesno_values'
|
||||||
|
YESNO_VALUES = ['yes', 'no']
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
############################# Enums ##############################
|
||||||
|
|
||||||
|
# yesno_values have already been created, so use postgres enum object
|
||||||
|
# type to get around "already created" issue - works okay with mysql
|
||||||
|
yesno_values = ENUM(*YESNO_VALUES, name=YESNO_NAME, create_type=False)
|
||||||
|
op.add_column('ps_endpoints', sa.Column('g726_non_standard', yesno_values))
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
op.drop_column('ps_endpoints', 'g726_non_standard')
|
@@ -555,6 +555,8 @@ struct ast_sip_endpoint_media_configuration {
|
|||||||
unsigned int tos_video;
|
unsigned int tos_video;
|
||||||
/*! Priority for video streams */
|
/*! Priority for video streams */
|
||||||
unsigned int cos_video;
|
unsigned int cos_video;
|
||||||
|
/*! Is g.726 packed in a non standard way */
|
||||||
|
unsigned int g726_non_standard;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@@ -471,6 +471,15 @@
|
|||||||
set to <literal>sdes</literal> or <literal>dtls</literal>.
|
set to <literal>sdes</literal> or <literal>dtls</literal>.
|
||||||
</para></description>
|
</para></description>
|
||||||
</configOption>
|
</configOption>
|
||||||
|
<configOption name="g726_non_standard" default="no">
|
||||||
|
<synopsis>Force g.726 to use AAL2 packing order when negotiating g.726 audio</synopsis>
|
||||||
|
<description><para>
|
||||||
|
When set to "yes" and an endpoint negotiates g.726 audio then use g.726 for AAL2
|
||||||
|
packing order instead of what is recommended by RFC3551. Since this essentially
|
||||||
|
replaces the underlying 'g726' codec with 'g726aal2' then 'g726aal2' needs to be
|
||||||
|
specified in the endpoint's allowed codec list.
|
||||||
|
</para></description>
|
||||||
|
</configOption>
|
||||||
<configOption name="inband_progress" default="no">
|
<configOption name="inband_progress" default="no">
|
||||||
<synopsis>Determines whether chan_pjsip will indicate ringing using inband
|
<synopsis>Determines whether chan_pjsip will indicate ringing using inband
|
||||||
progress.</synopsis>
|
progress.</synopsis>
|
||||||
|
@@ -1922,6 +1922,7 @@ int ast_res_pjsip_initialize_configuration(const struct ast_module_info *ast_mod
|
|||||||
ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtls_fingerprint", "", dtls_handler, dtlsfingerprint_to_str, NULL, 0, 0);
|
ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "dtls_fingerprint", "", dtls_handler, dtlsfingerprint_to_str, NULL, 0, 0);
|
||||||
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "srtp_tag_32", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtp.srtp_tag_32));
|
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "srtp_tag_32", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtp.srtp_tag_32));
|
||||||
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "media_encryption_optimistic", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtp.encryption_optimistic));
|
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "media_encryption_optimistic", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtp.encryption_optimistic));
|
||||||
|
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "g726_non_standard", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.g726_non_standard));
|
||||||
ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "redirect_method", "user", redirect_handler, NULL, NULL, 0, 0);
|
ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "redirect_method", "user", redirect_handler, NULL, NULL, 0, 0);
|
||||||
ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "set_var", "", set_var_handler, set_var_to_str, set_var_to_vl, 0, 0);
|
ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "set_var", "", set_var_handler, set_var_to_str, set_var_to_vl, 0, 0);
|
||||||
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "message_context", "", OPT_STRINGFIELD_T, 1, STRFLDSET(struct ast_sip_endpoint, message_context));
|
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "message_context", "", OPT_STRINGFIELD_T, 1, STRFLDSET(struct ast_sip_endpoint, message_context));
|
||||||
|
@@ -155,6 +155,8 @@ static void get_codecs(struct ast_sip_session *session, const struct pjmedia_sdp
|
|||||||
char name[256];
|
char name[256];
|
||||||
char media[20];
|
char media[20];
|
||||||
char fmt_param[256];
|
char fmt_param[256];
|
||||||
|
enum ast_rtp_options options = session->endpoint->media.g726_non_standard ?
|
||||||
|
AST_RTP_OPT_G726_NONSTANDARD : 0;
|
||||||
|
|
||||||
ast_rtp_codecs_payloads_initialize(codecs);
|
ast_rtp_codecs_payloads_initialize(codecs);
|
||||||
|
|
||||||
@@ -176,9 +178,10 @@ static void get_codecs(struct ast_sip_session *session, const struct pjmedia_sdp
|
|||||||
if (strcmp(name,"telephone-event") == 0) {
|
if (strcmp(name,"telephone-event") == 0) {
|
||||||
tel_event++;
|
tel_event++;
|
||||||
}
|
}
|
||||||
|
|
||||||
ast_copy_pj_str(media, (pj_str_t*)&stream->desc.media, sizeof(media));
|
ast_copy_pj_str(media, (pj_str_t*)&stream->desc.media, sizeof(media));
|
||||||
ast_rtp_codecs_payloads_set_rtpmap_type_rate(codecs, NULL, pj_strtoul(&stream->desc.fmt[i]),
|
ast_rtp_codecs_payloads_set_rtpmap_type_rate(codecs, NULL, pj_strtoul(&stream->desc.fmt[i]),
|
||||||
media, name, 0, rtpmap->clock_rate);
|
media, name, options, rtpmap->clock_rate);
|
||||||
/* Look for an optional associated fmtp attribute */
|
/* Look for an optional associated fmtp attribute */
|
||||||
if (!(attr = pjmedia_sdp_media_find_attr2(stream, "fmtp", &rtpmap->pt))) {
|
if (!(attr = pjmedia_sdp_media_find_attr2(stream, "fmtp", &rtpmap->pt))) {
|
||||||
continue;
|
continue;
|
||||||
@@ -304,18 +307,20 @@ static int set_caps(struct ast_sip_session *session, struct ast_sip_session_medi
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static pjmedia_sdp_attr* generate_rtpmap_attr(pjmedia_sdp_media *media, pj_pool_t *pool, int rtp_code,
|
static pjmedia_sdp_attr* generate_rtpmap_attr(struct ast_sip_session *session, pjmedia_sdp_media *media, pj_pool_t *pool,
|
||||||
int asterisk_format, struct ast_format *format, int code)
|
int rtp_code, int asterisk_format, struct ast_format *format, int code)
|
||||||
{
|
{
|
||||||
pjmedia_sdp_rtpmap rtpmap;
|
pjmedia_sdp_rtpmap rtpmap;
|
||||||
pjmedia_sdp_attr *attr = NULL;
|
pjmedia_sdp_attr *attr = NULL;
|
||||||
char tmp[64];
|
char tmp[64];
|
||||||
|
enum ast_rtp_options options = session->endpoint->media.g726_non_standard ?
|
||||||
|
AST_RTP_OPT_G726_NONSTANDARD : 0;
|
||||||
|
|
||||||
snprintf(tmp, sizeof(tmp), "%d", rtp_code);
|
snprintf(tmp, sizeof(tmp), "%d", rtp_code);
|
||||||
pj_strdup2(pool, &media->desc.fmt[media->desc.fmt_count++], tmp);
|
pj_strdup2(pool, &media->desc.fmt[media->desc.fmt_count++], tmp);
|
||||||
rtpmap.pt = media->desc.fmt[media->desc.fmt_count - 1];
|
rtpmap.pt = media->desc.fmt[media->desc.fmt_count - 1];
|
||||||
rtpmap.clock_rate = ast_rtp_lookup_sample_rate2(asterisk_format, format, code);
|
rtpmap.clock_rate = ast_rtp_lookup_sample_rate2(asterisk_format, format, code);
|
||||||
pj_strdup2(pool, &rtpmap.enc_name, ast_rtp_lookup_mime_subtype2(asterisk_format, format, code, 0));
|
pj_strdup2(pool, &rtpmap.enc_name, ast_rtp_lookup_mime_subtype2(asterisk_format, format, code, options));
|
||||||
rtpmap.param.slen = 0;
|
rtpmap.param.slen = 0;
|
||||||
rtpmap.param.ptr = NULL;
|
rtpmap.param.ptr = NULL;
|
||||||
|
|
||||||
@@ -1050,7 +1055,7 @@ static int create_outgoing_sdp_stream(struct ast_sip_session *session, struct as
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(attr = generate_rtpmap_attr(media, pool, rtp_code, 1, format, 0))) {
|
if (!(attr = generate_rtpmap_attr(session, media, pool, rtp_code, 1, format, 0))) {
|
||||||
ao2_ref(format, -1);
|
ao2_ref(format, -1);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -1075,7 +1080,7 @@ static int create_outgoing_sdp_stream(struct ast_sip_session *session, struct as
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(attr = generate_rtpmap_attr(media, pool, rtp_code, 0, NULL, index))) {
|
if (!(attr = generate_rtpmap_attr(session, media, pool, rtp_code, 0, NULL, index))) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user