Skip to content

Commit 16f8356

Browse files
mbradeengtjoseph
authored andcommitted
rtp_engine: add support for multirate 2833 DRAFT
DRAFT PR - demonstrate a method for handling non 8K 2833 digit sdp offers. Changes to the engine itself limited to adding the 48/24K types. res_pjsip_sdp_rtp is changed to note the number of incoming codecs and add an associated offer
1 parent 183954b commit 16f8356

File tree

4 files changed

+204
-17
lines changed

4 files changed

+204
-17
lines changed

include/asterisk/rtp_engine.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,8 @@ struct ast_rtp_payload_type {
311311
unsigned int primary_mapping:1;
312312
/*! When the payload type became non-primary. */
313313
struct timeval when_retired;
314+
/*! Bitrate to over-ride mime type defaults */
315+
int bitrate;
314316
};
315317

316318
/* Common RTCP report types */
@@ -1788,6 +1790,21 @@ int ast_rtp_codecs_payload_code(struct ast_rtp_codecs *codecs, int asterisk_form
17881790
*/
17891791
int ast_rtp_codecs_payload_set_rx(struct ast_rtp_codecs *codecs, int code, struct ast_format *format);
17901792

1793+
/*!
1794+
* \brief Set a payload code with bitrate for use with a specific Asterisk format
1795+
*
1796+
* \param codecs Codecs structure to manipulate
1797+
* \param code The payload code
1798+
* \param format Asterisk format
1799+
* \param bitrate Bitrate of the format, 0 to use the format's default
1800+
*
1801+
* \retval 0 Payload was set to the given format
1802+
* \retval -1 Payload was in use or could not be set
1803+
*
1804+
* \since 20.0.0
1805+
*/
1806+
int ast_rtp_codecs_payload_set_rx_bitrate(struct ast_rtp_codecs *codecs, int code, struct ast_format *format, int bitrate);
1807+
17911808
/*!
17921809
* \brief Retrieve a tx mapped payload type based on whether it is an Asterisk format and the code
17931810
* \since 14.0.0
@@ -1802,6 +1819,21 @@ int ast_rtp_codecs_payload_set_rx(struct ast_rtp_codecs *codecs, int code, struc
18021819
*/
18031820
int ast_rtp_codecs_payload_code_tx(struct ast_rtp_codecs *codecs, int asterisk_format, const struct ast_format *format, int code);
18041821

1822+
/*!
1823+
* \brief Retrieve a tx mapped payload type based on whether it is an Asterisk format and the code
1824+
* \since 20.0.0
1825+
*
1826+
* \param codecs Codecs structure to look in
1827+
* \param asterisk_format Non-zero if the given Asterisk format is present
1828+
* \param format Asterisk format to look for
1829+
* \param code The format to look for
1830+
* \param bitrate The bitrate to look for, zero if we don't care
1831+
*
1832+
* \return Numerical payload type
1833+
* \retval -1 if not found.
1834+
*/
1835+
int ast_rtp_codecs_payload_code_tx_bitrate(struct ast_rtp_codecs *codecs, int asterisk_format, const struct ast_format *format, int code, int bitrate);
1836+
18051837
/*!
18061838
* \brief Search for the tx payload type in the ast_rtp_codecs structure
18071839
*

main/rtp_engine.c

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1380,6 +1380,8 @@ int ast_rtp_codecs_payloads_set_rtpmap_type_rate(struct ast_rtp_codecs *codecs,
13801380
continue;
13811381
}
13821382

1383+
ast_log(LOG_DEBUG, "Comparing %d %s %s with %d %s %s", pt, mimetype, mimesubtype, t->payload_type.rtp_code, t->type, t->subtype);
1384+
13831385
/* if both sample rates have been supplied, and they don't match,
13841386
* then this not a match; if one has not been supplied, then the
13851387
* rates are not compared */
@@ -1399,6 +1401,7 @@ int ast_rtp_codecs_payloads_set_rtpmap_type_rate(struct ast_rtp_codecs *codecs,
13991401
new_type->rtp_code = t->payload_type.rtp_code;
14001402
new_type->payload = pt;
14011403
new_type->primary_mapping = 1;
1404+
new_type->bitrate = sample_rate;
14021405
if (t->payload_type.asterisk_format
14031406
&& ast_format_cmp(t->payload_type.format, ast_format_g726) == AST_FORMAT_CMP_EQUAL
14041407
&& (options & AST_RTP_OPT_G726_NONSTANDARD)) {
@@ -1825,7 +1828,7 @@ static int rtp_codecs_find_non_primary_dynamic_rx(struct ast_rtp_codecs *codecs)
18251828
* \return Numerical payload type
18261829
* \retval -1 if could not assign.
18271830
*/
1828-
static int rtp_codecs_assign_payload_code_rx(struct ast_rtp_codecs *codecs, int asterisk_format, struct ast_format *format, int code, int explicit)
1831+
static int rtp_codecs_assign_payload_code_rx(struct ast_rtp_codecs *codecs, int asterisk_format, struct ast_format *format, int code, int explicit, int bitrate)
18291832
{
18301833
int payload = code;
18311834
struct ast_rtp_payload_type *new_type;
@@ -1844,8 +1847,13 @@ static int rtp_codecs_assign_payload_code_rx(struct ast_rtp_codecs *codecs, int
18441847
}
18451848

18461849
ast_rwlock_wrlock(&codecs->codecs_lock);
1850+
1851+
new_type->bitrate = bitrate;
1852+
18471853
if (payload > -1 && (payload < AST_RTP_PT_FIRST_DYNAMIC
18481854
|| AST_VECTOR_SIZE(&codecs->payload_mapping_rx) <= payload
1855+
// test if this is needed
1856+
//|| (explicit || !AST_VECTOR_GET(&codecs->payload_mapping_rx, payload)))) {
18491857
|| !AST_VECTOR_GET(&codecs->payload_mapping_rx, payload))) {
18501858
/*
18511859
* The payload type is a static assignment
@@ -1926,7 +1934,7 @@ int ast_rtp_codecs_payload_code(struct ast_rtp_codecs *codecs, int asterisk_form
19261934

19271935
if (payload < 0) {
19281936
payload = rtp_codecs_assign_payload_code_rx(codecs, asterisk_format, format,
1929-
code, 0);
1937+
code, 0, 0);
19301938
}
19311939
ast_rwlock_unlock(&static_RTP_PT_lock);
19321940

@@ -1935,10 +1943,15 @@ int ast_rtp_codecs_payload_code(struct ast_rtp_codecs *codecs, int asterisk_form
19351943

19361944
int ast_rtp_codecs_payload_set_rx(struct ast_rtp_codecs *codecs, int code, struct ast_format *format)
19371945
{
1938-
return rtp_codecs_assign_payload_code_rx(codecs, 1, format, code, 1);
1946+
return rtp_codecs_assign_payload_code_rx(codecs, 1, format, code, 1, 0);
19391947
}
19401948

1941-
int ast_rtp_codecs_payload_code_tx(struct ast_rtp_codecs *codecs, int asterisk_format, const struct ast_format *format, int code)
1949+
int ast_rtp_codecs_payload_set_rx_bitrate(struct ast_rtp_codecs *codecs, int code, struct ast_format *format, int bitrate)
1950+
{
1951+
return rtp_codecs_assign_payload_code_rx(codecs, 1, format, code, 0, bitrate);
1952+
}
1953+
1954+
int ast_rtp_codecs_payload_code_tx_bitrate(struct ast_rtp_codecs *codecs, int asterisk_format, const struct ast_format *format, int code, int bitrate)
19421955
{
19431956
struct ast_rtp_payload_type *type;
19441957
int idx;
@@ -1953,7 +1966,8 @@ int ast_rtp_codecs_payload_code_tx(struct ast_rtp_codecs *codecs, int asterisk_f
19531966
}
19541967

19551968
if (!type->asterisk_format
1956-
&& type->rtp_code == code) {
1969+
&& type->rtp_code == code
1970+
&& (!bitrate || type->bitrate == bitrate)) {
19571971
payload = idx;
19581972
break;
19591973
}
@@ -1985,6 +1999,11 @@ int ast_rtp_codecs_payload_code_tx(struct ast_rtp_codecs *codecs, int asterisk_f
19851999
return payload;
19862000
}
19872001

2002+
int ast_rtp_codecs_payload_code_tx(struct ast_rtp_codecs *codecs, int asterisk_format, const struct ast_format *format, int code)
2003+
{
2004+
return ast_rtp_codecs_payload_code_tx_bitrate(codecs, asterisk_format, format, code, 0);
2005+
}
2006+
19882007
int ast_rtp_codecs_find_payload_code(struct ast_rtp_codecs *codecs, int payload)
19892008
{
19902009
struct ast_rtp_payload_type *type;
@@ -3700,7 +3719,11 @@ int ast_rtp_engine_init(void)
37003719
/* this is the sample rate listed in the RTP profile for the G.722 codec, *NOT* the actual sample rate of the media stream */
37013720
set_next_mime_type(ast_format_g722, 0, "audio", "G722", 8000);
37023721
set_next_mime_type(ast_format_g726_aal2, 0, "audio", "AAL2-G726-32", 8000);
3722+
/* we need all 4 of these or ast_rtp_codecs_payloads_set_rtpmap_type_rate will not examine it */
37033723
set_next_mime_type(NULL, AST_RTP_DTMF, "audio", "telephone-event", 8000);
3724+
set_next_mime_type(NULL, AST_RTP_DTMF, "audio", "telephone-event", 16000);
3725+
set_next_mime_type(NULL, AST_RTP_DTMF, "audio", "telephone-event", 48000);
3726+
set_next_mime_type(NULL, AST_RTP_DTMF, "audio", "telephone-event", 24000);
37043727
set_next_mime_type(NULL, AST_RTP_CISCO_DTMF, "audio", "cisco-telephone-event", 8000);
37053728
set_next_mime_type(NULL, AST_RTP_CN, "audio", "CN", 8000);
37063729
set_next_mime_type(ast_format_jpeg, 0, "video", "JPEG", 90000);

res/res_pjsip_sdp_rtp.c

Lines changed: 111 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -650,6 +650,43 @@ static pjmedia_sdp_attr* generate_rtpmap_attr(struct ast_sip_session *session, p
650650
return attr;
651651
}
652652

653+
654+
static pjmedia_sdp_attr* generate_rtpmap_attr2(struct ast_sip_session *session, pjmedia_sdp_media *media, pj_pool_t *pool,
655+
int rtp_code, int asterisk_format, struct ast_format *format, int code, int sample_rate)
656+
{
657+
#ifndef HAVE_PJSIP_ENDPOINT_COMPACT_FORM
658+
extern pj_bool_t pjsip_use_compact_form;
659+
#else
660+
pj_bool_t pjsip_use_compact_form = pjsip_cfg()->endpt.use_compact_form;
661+
#endif
662+
pjmedia_sdp_rtpmap rtpmap;
663+
pjmedia_sdp_attr *attr = NULL;
664+
char tmp[64];
665+
enum ast_rtp_options options = session->endpoint->media.g726_non_standard ?
666+
AST_RTP_OPT_G726_NONSTANDARD : 0;
667+
668+
snprintf(tmp, sizeof(tmp), "%d", rtp_code);
669+
pj_strdup2(pool, &media->desc.fmt[media->desc.fmt_count++], tmp);
670+
671+
if (rtp_code <= AST_RTP_PT_LAST_STATIC && pjsip_use_compact_form) {
672+
return NULL;
673+
}
674+
675+
rtpmap.pt = media->desc.fmt[media->desc.fmt_count - 1];
676+
rtpmap.clock_rate = sample_rate;
677+
ast_log(LOG_ERROR, "Generating rtpmap attribute with clock rate: %d\n", rtpmap.clock_rate);
678+
pj_strdup2(pool, &rtpmap.enc_name, ast_rtp_lookup_mime_subtype2(asterisk_format, format, code, options));
679+
if (!pj_stricmp2(&rtpmap.enc_name, "opus")) {
680+
pj_cstr(&rtpmap.param, "2");
681+
} else {
682+
pj_cstr(&rtpmap.param, NULL);
683+
}
684+
685+
pjmedia_sdp_rtpmap_to_attr(pool, &rtpmap, &attr);
686+
687+
return attr;
688+
}
689+
653690
static pjmedia_sdp_attr* generate_fmtp_attr(pj_pool_t *pool, struct ast_format *format, int rtp_code)
654691
{
655692
struct ast_str *fmtp0 = ast_str_alloca(256);
@@ -1749,6 +1786,11 @@ static int create_outgoing_sdp_stream(struct ast_sip_session *session, struct as
17491786
pj_sockaddr ip;
17501787
int direct_media_enabled = !ast_sockaddr_isnull(&session_media->direct_media_addr) &&
17511788
ast_format_cap_count(session->direct_media_cap);
1789+
1790+
int bitRates[4] = { 0, 0, 0, 0 };
1791+
int added_rtp_type = 0;
1792+
struct ast_rtp_codecs *zcodecs;
1793+
17521794
SCOPE_ENTER(1, "%s Type: %s %s\n", ast_sip_session_get_name(session),
17531795
ast_codec_media_type2str(media_type), ast_str_tmp(128, ast_stream_to_str(stream, &STR_TMP)));
17541796

@@ -1938,7 +1980,27 @@ static int create_outgoing_sdp_stream(struct ast_sip_session *session, struct as
19381980
}
19391981

19401982
if ((attr = generate_rtpmap_attr(session, media, pool, rtp_code, 1, format, 0))) {
1983+
int newrate = ast_rtp_lookup_sample_rate2(1, format, 0);
19411984
media->attr[media->attr_count++] = attr;
1985+
// lolcode
1986+
if (bitRates[0] == 0) {
1987+
bitRates[0] = newrate;
1988+
}
1989+
else if ((newrate != bitRates[0])) {
1990+
if (bitRates[1] == 0) {
1991+
bitRates[1] = newrate;
1992+
}
1993+
else if ((newrate != bitRates[1])) {
1994+
if (bitRates[2] == 0) {
1995+
bitRates[2] = newrate;
1996+
}
1997+
else if ((newrate != bitRates[2])) {
1998+
if (bitRates[3] == 0) {
1999+
bitRates[3] = newrate;
2000+
}
2001+
}
2002+
}
2003+
}
19422004
}
19432005

19442006
if ((attr = generate_fmtp_attr(pool, format, rtp_code))) {
@@ -1956,6 +2018,38 @@ static int create_outgoing_sdp_stream(struct ast_sip_session *session, struct as
19562018
}
19572019
}
19582020

2021+
/* Copy any non asterisk formats to the rx side */
2022+
zcodecs = ast_rtp_instance_get_codecs(session_media->rtp);
2023+
for (int idx = 0; idx < AST_VECTOR_SIZE(&zcodecs->payload_mapping_tx); ++idx) {
2024+
struct ast_rtp_payload_type *type;
2025+
type = AST_VECTOR_GET(&zcodecs->payload_mapping_tx, idx);
2026+
if (!type) {
2027+
continue;
2028+
}
2029+
if (!type->asterisk_format && type->primary_mapping) {
2030+
ast_rtp_codecs_payload_set_rx_bitrate(ast_rtp_instance_get_codecs(session_media->rtp), idx, type->format, type->bitrate);
2031+
}
2032+
}
2033+
/* Use the rx list of non asterisk formats to build the sdp attributes */
2034+
for (int idx = 0; idx < AST_VECTOR_SIZE(&zcodecs->payload_mapping_rx); ++idx) {
2035+
struct ast_rtp_payload_type *type;
2036+
type = AST_VECTOR_GET(&zcodecs->payload_mapping_rx, idx);
2037+
if (!type) {
2038+
continue;
2039+
}
2040+
if (!type->asterisk_format && type->primary_mapping) {
2041+
int newrate = type->bitrate;
2042+
if ((attr = generate_rtpmap_attr2(session, media, pool, idx, 0, NULL, AST_RTP_DTMF, newrate))) {
2043+
/* note that we are adding attributes based on an existing offer so they don't need to be made from scratch */
2044+
added_rtp_type = 1;
2045+
media->attr[media->attr_count++] = attr;
2046+
snprintf(tmp, sizeof(tmp), "%d 0-16", (idx));
2047+
attr = pjmedia_sdp_attr_create(pool, "fmtp", pj_cstr(&stmp, tmp));
2048+
media->attr[media->attr_count++] = attr;
2049+
}
2050+
}
2051+
}
2052+
19592053
/* Add non-codec formats */
19602054
if (ast_sip_session_is_pending_stream_default(session, stream) && media_type != AST_MEDIA_TYPE_VIDEO
19612055
&& media->desc.fmt_count < PJMEDIA_MAX_SDP_FMT) {
@@ -1969,14 +2063,24 @@ static int create_outgoing_sdp_stream(struct ast_sip_session *session, struct as
19692063
continue;
19702064
}
19712065

1972-
if ((attr = generate_rtpmap_attr(session, media, pool, rtp_code, 0, NULL, index))) {
1973-
media->attr[media->attr_count++] = attr;
2066+
if (index != AST_RTP_DTMF) {
2067+
if ((attr = generate_rtpmap_attr(session, media, pool, rtp_code, 0, NULL, index))) {
2068+
media->attr[media->attr_count++] = attr;
2069+
}
19742070
}
1975-
1976-
if (index == AST_RTP_DTMF) {
1977-
snprintf(tmp, sizeof(tmp), "%d 0-16", rtp_code);
1978-
attr = pjmedia_sdp_attr_create(pool, "fmtp", pj_cstr(&stmp, tmp));
1979-
media->attr[media->attr_count++] = attr;
2071+
else if (!added_rtp_type) {
2072+
/* If we aren't going based off an existing offer, walk through the possible bitrates for the
2073+
2833/4733 digits and add them manually */
2074+
for (int i=0; i<4; i++) {
2075+
if(bitRates[i] != 0 ) {
2076+
if ((attr = generate_rtpmap_attr2(session, media, pool, (rtp_code+i), 0, NULL, index, bitRates[i]))) {
2077+
media->attr[media->attr_count++] = attr;
2078+
}
2079+
snprintf(tmp, sizeof(tmp), "%d 0-16", (rtp_code+i));
2080+
attr = pjmedia_sdp_attr_create(pool, "fmtp", pj_cstr(&stmp, tmp));
2081+
media->attr[media->attr_count++] = attr;
2082+
}
2083+
}
19802084
}
19812085

19822086
if (media->desc.fmt_count == PJMEDIA_MAX_SDP_FMT) {
@@ -1985,7 +2089,6 @@ static int create_outgoing_sdp_stream(struct ast_sip_session *session, struct as
19852089
}
19862090
}
19872091

1988-
19892092
/* If no formats were actually added to the media stream don't add it to the SDP */
19902093
if (!media->desc.fmt_count) {
19912094
SCOPE_EXIT_RTN_VALUE(1, "No formats added to stream\n");

res/res_rtp_asterisk.c

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4230,7 +4230,7 @@ static int ast_rtp_dtmf_begin(struct ast_rtp_instance *instance, char digit)
42304230
{
42314231
struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
42324232
struct ast_sockaddr remote_address = { {0,} };
4233-
int hdrlen = 12, res = 0, i = 0, payload = 101;
4233+
int hdrlen = 12, res = 0, i = 0, payload = 101, sample_rate = 8000;
42344234
char data[256];
42354235
unsigned int *rtpheader = (unsigned int*)data;
42364236

@@ -4257,12 +4257,41 @@ static int ast_rtp_dtmf_begin(struct ast_rtp_instance *instance, char digit)
42574257
return -1;
42584258
}
42594259

4260-
/* Grab the payload that they expect the RFC2833 packet to be received in */
4261-
payload = ast_rtp_codecs_payload_code_tx(ast_rtp_instance_get_codecs(instance), 0, NULL, AST_RTP_DTMF);
4260+
if (rtp->lasttxformat == ast_format_none) {
4261+
/* we haven't sent any audio yet so we have to lookup both the payload type and
4262+
bitrate. This should get us the first stored dtmf type. */
4263+
struct ast_rtp_payload_type *type;
4264+
int idx;
4265+
struct ast_rtp_codecs *codecs = ast_rtp_instance_get_codecs(instance);
4266+
ast_rwlock_rdlock(&codecs->codecs_lock);
4267+
for (idx = 0; idx < AST_VECTOR_SIZE(&codecs->payload_mapping_tx); ++idx) {
4268+
type = AST_VECTOR_GET(&codecs->payload_mapping_tx, idx);
4269+
if (!type) {
4270+
continue;
4271+
}
4272+
if (type->rtp_code == AST_RTP_DTMF) {
4273+
payload = idx;
4274+
sample_rate = type->bitrate;
4275+
break;
4276+
}
4277+
}
4278+
ast_rwlock_unlock(&codecs->codecs_lock);
4279+
} else {
4280+
/* If we get 0 back that can be ok, provided a default rate is set */
4281+
sample_rate = ast_format_get_codec(rtp->lasttxformat)->sample_rate;
4282+
/* Grab the payload that they expect the RFC2833 packet to be received in */
4283+
payload = ast_rtp_codecs_payload_code_tx_bitrate(ast_rtp_instance_get_codecs(instance), 0, NULL, AST_RTP_DTMF, sample_rate);
4284+
}
4285+
/* If this returns -1, we are being asked to send digits for a sample rate that is outside
4286+
what was negotiated for. Fall back if possible. */
4287+
if (payload == -1) {
4288+
return -1;
4289+
}
4290+
ast_log(LOG_DEBUG, "Sending digit '%d' at rate %d\n", digit, sample_rate);
42624291

42634292
rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
42644293
rtp->send_duration = 160;
4265-
rtp->lastts += calc_txstamp(rtp, NULL) * DTMF_SAMPLE_RATE_MS;
4294+
rtp->lastts += calc_txstamp(rtp, NULL) * (sample_rate/1000);
42664295
rtp->lastdigitts = rtp->lastts + rtp->send_duration;
42674296

42684297
/* Create the actual packet that we will be sending */

0 commit comments

Comments
 (0)