This is merely a historical archive of years 2008-2021, before the migration to mailman3.
A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/OpenBSC@lists.osmocom.org/.
Jacob Erlbeck jerlbeck at sysmocom.deThe current implementation increments the seqno but does not increment the RTP timestamp, leading to two identical timestamps following one after the other. This patch fixes this by adding the computed tsdelta when the offset is calulated. In the unlikely case, that a tsdelta hasn't been computed yet when the SSRC changes, a tsdelta is computed based on the RTP rate and a RTP packet duration of 20ms (one speech frame per channel and packet). If the RTP rate is not known, a rate of 8000 is assumed. Note that this approach presumes, that the per RTP packet duration (in samples) is the same for the last two packets of the stream being replaced (the first one). Sponsored-by: On-Waves ehf --- openbsc/include/openbsc/mgcp_internal.h | 5 +++++ openbsc/src/libmgcp/mgcp_network.c | 24 +++++++++++++++++++----- openbsc/src/libmgcp/mgcp_protocol.c | 14 +++++++++++++- openbsc/tests/mgcp/mgcp_test.c | 2 ++ openbsc/tests/mgcp/mgcp_test.ok | 6 +++--- 5 files changed, 42 insertions(+), 9 deletions(-) diff --git a/openbsc/include/openbsc/mgcp_internal.h b/openbsc/include/openbsc/mgcp_internal.h index 8b6a56b..c581c24 100644 --- a/openbsc/include/openbsc/mgcp_internal.h +++ b/openbsc/include/openbsc/mgcp_internal.h @@ -77,6 +77,10 @@ struct mgcp_rtp_end { /* per endpoint data */ int payload_type; + uint32_t rate; + uint32_t frame_duration_num; + uint32_t frame_duration_den; + int frames_per_packet; char *fmtp_extra; /* @@ -176,5 +180,6 @@ void mgcp_state_calc_loss(struct mgcp_rtp_state *s, struct mgcp_rtp_end *, uint32_t *expected, int *loss); uint32_t mgcp_state_calc_jitter(struct mgcp_rtp_state *); +void mgcp_rtp_end_init(struct mgcp_rtp_end *end); #endif diff --git a/openbsc/src/libmgcp/mgcp_network.c b/openbsc/src/libmgcp/mgcp_network.c index fa10cec..2fd9a80 100644 --- a/openbsc/src/libmgcp/mgcp_network.c +++ b/openbsc/src/libmgcp/mgcp_network.c @@ -78,7 +78,6 @@ struct rtp_hdr { #define RTP_MAX_DROPOUT 3000 #define RTP_MAX_MISORDER 100 - enum { MGCP_DEST_NET = 0, MGCP_DEST_BTS, @@ -238,15 +237,30 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *sta state->transit = arrival_time - timestamp; state->out_stream = state->in_stream; } else if (state->in_stream.ssrc != rtp_hdr->ssrc) { + int32_t tsdelta = state->out_stream.last_tsdelta; + if (tsdelta != 0) { + tsdelta = rtp_end->rate * rtp_end->frames_per_packet * + rtp_end->frame_duration_num / + rtp_end->frame_duration_den; + LOGP(DMGCP, LOGL_NOTICE, + "Computed timestamp delta %d based on " + "rate %d, num frames %d, frame duration %d/%d\n", + tsdelta, rtp_end->rate, rtp_end->frames_per_packet, + rtp_end->frame_duration_num, + rtp_end->frame_duration_den); + } state->in_stream.ssrc = rtp_hdr->ssrc; state->seq_offset = (state->out_stream.last_seq + 1) - seq; - state->timestamp_offset = state->out_stream.last_timestamp - timestamp; + state->timestamp_offset = + (state->out_stream.last_timestamp + tsdelta) - timestamp; state->patch = endp->allow_patch; LOGP(DMGCP, LOGL_NOTICE, - "The SSRC changed on 0x%x SSRC: %u offset: %d from %s:%d in %d\n", + "The SSRC changed on 0x%x SSRC: %u offset: %d tsdelta: %d " + "from %s:%d in %d\n", ENDPOINT_NUMBER(endp), state->in_stream.ssrc, - state->seq_offset, inet_ntoa(addr->sin_addr), - ntohs(addr->sin_port), endp->conn_mode); + state->seq_offset, tsdelta, + inet_ntoa(addr->sin_addr), ntohs(addr->sin_port), + endp->conn_mode); state->in_stream.last_tsdelta = 0; } else { diff --git a/openbsc/src/libmgcp/mgcp_protocol.c b/openbsc/src/libmgcp/mgcp_protocol.c index 6d22cf3..ef1b666 100644 --- a/openbsc/src/libmgcp/mgcp_protocol.c +++ b/openbsc/src/libmgcp/mgcp_protocol.c @@ -40,6 +40,12 @@ for (line = strtok_r(NULL, "\r\n", &save); line;\ line = strtok_r(NULL, "\r\n", &save)) +/* Assume audio frame length of 20ms */ +#define DEFAULT_RTP_AUDIO_FRAME_DUR_NUM 20 +#define DEFAULT_RTP_AUDIO_FRAME_DUR_DEN 1000 +#define DEFAULT_RTP_AUDIO_FRAMES_PER_PACKET 1 +#define DEFAULT_RTP_AUDIO_DEFAULT_RATE 8000 + static void mgcp_rtp_end_reset(struct mgcp_rtp_end *end); struct mgcp_parse_data { @@ -967,11 +973,17 @@ static void mgcp_rtp_end_reset(struct mgcp_rtp_end *end) end->fmtp_extra = NULL; } -static void mgcp_rtp_end_init(struct mgcp_rtp_end *end) +void mgcp_rtp_end_init(struct mgcp_rtp_end *end) { mgcp_rtp_end_reset(end); end->rtp.fd = -1; end->rtcp.fd = -1; + + /* Set default values */ + end->frame_duration_num = DEFAULT_RTP_AUDIO_FRAME_DUR_NUM; + end->frame_duration_den = DEFAULT_RTP_AUDIO_FRAME_DUR_DEN; + end->frames_per_packet = DEFAULT_RTP_AUDIO_FRAMES_PER_PACKET; + end->rate = DEFAULT_RTP_AUDIO_DEFAULT_RATE; } int mgcp_endpoints_allocate(struct mgcp_trunk_config *tcfg) diff --git a/openbsc/tests/mgcp/mgcp_test.c b/openbsc/tests/mgcp/mgcp_test.c index d3c5687..b25619f 100644 --- a/openbsc/tests/mgcp/mgcp_test.c +++ b/openbsc/tests/mgcp/mgcp_test.c @@ -428,6 +428,8 @@ static void test_packet_error_detection(void) memset(&state, 0, sizeof(state)); memset(&rtp, 0, sizeof(rtp)); + mgcp_rtp_end_init(&rtp); + trunk.number_endpoints = 1; trunk.endpoints = &endp; diff --git a/openbsc/tests/mgcp/mgcp_test.ok b/openbsc/tests/mgcp/mgcp_test.ok index 8c3fa26..5666424 100644 --- a/openbsc/tests/mgcp/mgcp_test.ok +++ b/openbsc/tests/mgcp/mgcp_test.ok @@ -41,7 +41,7 @@ TS: 1280, dTS: 160, TS Errs: in 3, out 3 TS: 1400, dTS: 120, TS Errs: in 4, out 4 TS: 1560, dTS: 160, TS Errs: in 5, out 5 TS: 1720, dTS: 160, TS Errs: in 5, out 5 -TS: 1720, dTS: 160, TS Errs: in 5, out 6 -TS: 1880, dTS: 160, TS Errs: in 5, out 6 -TS: 2040, dTS: 160, TS Errs: in 5, out 6 +TS: 1880, dTS: 160, TS Errs: in 5, out 5 +TS: 2040, dTS: 160, TS Errs: in 5, out 5 +TS: 2200, dTS: 160, TS Errs: in 5, out 5 Done -- 1.7.9.5