diff --git a/src/mod/codecs/mod_opus/mod_opus.c b/src/mod/codecs/mod_opus/mod_opus.c index 96933e6ea59..21bf642c3f6 100644 --- a/src/mod/codecs/mod_opus/mod_opus.c +++ b/src/mod/codecs/mod_opus/mod_opus.c @@ -144,6 +144,7 @@ struct opus_context { enc_stats_t encoder_stats; codec_control_state_t control_state; switch_bool_t recreate_decoder; + uint32_t encoder_samplerate; }; struct { @@ -177,6 +178,11 @@ static switch_bool_t switch_opus_acceptable_rate(int rate) return SWITCH_TRUE; } +static inline uint32_t opus_ts_step(uint32_t ptime_ms, uint32_t enc_rate) +{ + return (ptime_ms * 48); /* 48 kHz RTP clock rate */ +} + static uint32_t switch_opus_encoder_set_audio_bandwidth(OpusEncoder *encoder_object,int enc_samplerate) { if (enc_samplerate == 8000) { /* Audio Bandwidth: 0-4000Hz Sampling Rate: 8000Hz */ @@ -618,6 +624,9 @@ static switch_status_t switch_opus_init(switch_codec_t *codec, switch_codec_flag return SWITCH_STATUS_GENERR; } + /* Store encoder sample rate for RTP timestamp scaling */ + context->encoder_samplerate = enc_samplerate; + /* https://tools.ietf.org/html/rfc7587 */ if (opus_codec_settings.maxaveragebitrate) { opus_encoder_ctl(context->encoder_object, OPUS_SET_BITRATE(opus_codec_settings.maxaveragebitrate)); @@ -680,6 +689,7 @@ static switch_status_t switch_opus_init(switch_codec_t *codec, switch_codec_flag if (opus_prefs.adjust_bitrate) { switch_set_flag(codec, SWITCH_CODEC_FLAG_HAS_ADJ_BITRATE); } + } if (decoding) { @@ -718,6 +728,19 @@ static switch_status_t switch_opus_init(switch_codec_t *codec, switch_codec_flag } } + /* Set RTP interval for RFC 7587 compliance */ + if (codec->session) { + switch_rtp_t *rtp = switch_core_media_get_rtp_session(codec->session, SWITCH_MEDIA_TYPE_AUDIO); + if (rtp) { + uint32_t ptime_ms = codec->implementation->microseconds_per_packet / 1000; + uint32_t step = opus_ts_step(ptime_ms, codec->implementation->actual_samples_per_second); + switch_rtp_set_interval(rtp, ptime_ms, step); + } + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, + "Opus codec initialized without session - RTP interval not configured\n"); + } + context->codec_settings = opus_codec_settings; codec->private_info = context; diff --git a/src/switch_core_media.c b/src/switch_core_media.c index de5d0eff74c..8b533fa50eb 100644 --- a/src/switch_core_media.c +++ b/src/switch_core_media.c @@ -5517,6 +5517,10 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s uint32_t bit_rate = imp->bits_per_second; uint32_t codec_rate = imp->samples_per_second; + if (!strcasecmp(map->rm_encoding, "opus")) { + codec_rate = imp->actual_samples_per_second; + } + if (imp->codec_type != SWITCH_CODEC_TYPE_AUDIO) { continue; }