mgcp: Move Annex A counting out of patch/count method

mgcp_patch_and_count has grown due supporting linearizing timestamps,
ssrc and other things for equipment like the ip.access nanoBTS. Fight
back and move the Annex A code into a dedicated method.

The result is updated as we now count after all the patching and for
the Annex A code no change in SSRC can be detected.
This commit is contained in:
Holger Hans Peter Freyther 2014-10-06 20:04:42 +02:00
parent 2a7ab868e3
commit a5a59c9a05
4 changed files with 113 additions and 86 deletions

View File

@ -54,17 +54,22 @@ struct mgcp_rtp_state {
uint32_t orig_ssrc;
uint16_t base_seq;
int seq_offset;
int cycles;
int32_t timestamp_offset;
uint32_t packet_duration;
uint32_t jitter;
int32_t transit;
struct mgcp_rtp_stream_state in_stream;
struct mgcp_rtp_stream_state out_stream;
/* jitter and packet loss calculation */
int stats_initialized;
uint16_t stats_base_seq;
uint16_t stats_max_seq;
uint32_t stats_ssrc;
uint32_t stats_jitter;
int32_t stats_transit;
int stats_cycles;
};
struct mgcp_rtp_codec {

View File

@ -331,6 +331,60 @@ void mgcp_get_net_downlink_format_default(struct mgcp_endpoint *endp,
*fmtp_extra = endp->bts_end.fmtp_extra;
}
void mgcp_rtp_annex_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *state,
const uint16_t seq, const int32_t transit,
const uint32_t ssrc)
{
uint16_t udelta;
int32_t d;
/* initialize or re-initialize */
if (!state->stats_initialized || state->stats_ssrc != ssrc) {
state->stats_initialized = 1;
state->stats_base_seq = seq;
state->stats_max_seq = seq - 1;
state->stats_ssrc = ssrc;
state->stats_jitter = 0;
state->stats_transit = transit;
state->stats_cycles = 0;
}
/*
* The below takes the shape of the validation of
* Appendix A. Check if there is something weird with
* the sequence number, otherwise check for a wrap
* around in the sequence number.
* It can't wrap during the initialization so let's
* skip it here. The Appendix A probably doesn't have
* this issue because of the probation.
*/
udelta = seq - state->stats_max_seq;
if (udelta < RTP_MAX_DROPOUT) {
if (seq < state->stats_max_seq)
state->stats_cycles += RTP_SEQ_MOD;
} else if (udelta <= RTP_SEQ_MOD - RTP_MAX_MISORDER) {
LOGP(DMGCP, LOGL_NOTICE,
"RTP seqno made a very large jump on 0x%x delta: %u\n",
ENDPOINT_NUMBER(endp), udelta);
}
/*
* Calculate the jitter between the two packages. The TS should be
* taken closer to the read function. This was taken from the
* Appendix A of RFC 3550. Timestamp and arrival_time have a 1/rate
* resolution.
*/
d = transit - state->stats_transit;
state->stats_transit = transit;
if (d < 0)
d = -d;
state->stats_jitter += d - ((state->stats_jitter + 8) >> 4);
state->stats_max_seq = seq;
}
/**
* The RFC 3550 Appendix A assumes there are multiple sources but
* some of the supported endpoints (e.g. the nanoBTS) can only handle
@ -344,8 +398,8 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *sta
char *data, int len)
{
uint32_t arrival_time;
int32_t transit, d;
uint16_t seq, udelta;
int32_t transit;
uint16_t seq;
uint32_t timestamp, ssrc;
struct rtp_hdr *rtp_hdr;
int payload = rtp_end->codec.payload_type;
@ -361,13 +415,10 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *sta
transit = arrival_time - timestamp;
if (!state->initialized) {
state->initialized = 1;
state->in_stream.last_seq = seq - 1;
state->in_stream.ssrc = state->orig_ssrc = ssrc;
state->in_stream.last_tsdelta = 0;
state->base_seq = seq;
state->initialized = 1;
state->jitter = 0;
state->transit = transit;
state->packet_duration = mgcp_rtp_packet_duration(endp, rtp_end);
state->out_stream = state->in_stream;
state->out_stream.last_timestamp = timestamp;
@ -398,8 +449,6 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *sta
endp->conn_mode);
state->in_stream.ssrc = ssrc;
state->jitter = 0;
state->transit = transit;
if (rtp_end->force_constant_ssrc) {
int16_t delta_seq;
@ -470,34 +519,7 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *sta
addr, seq, timestamp, "output",
&state->out_stream.last_tsdelta);
/*
* The below takes the shape of the validation from Appendix A. Check
* if there is something weird with the sequence number, otherwise check
* for a wrap around in the sequence number.
*
* Note that last_seq is used where the appendix mentions max_seq.
*/
udelta = seq - state->out_stream.last_seq;
if (udelta < RTP_MAX_DROPOUT) {
if (seq < state->out_stream.last_seq)
state->cycles += RTP_SEQ_MOD;
} else if (udelta <= RTP_SEQ_MOD - RTP_MAX_MISORDER) {
LOGP(DMGCP, LOGL_NOTICE,
"RTP seqno made a very large jump on 0x%x delta: %u\n",
ENDPOINT_NUMBER(endp), udelta);
}
/*
* Calculate the jitter between the two packages. The TS should be
* taken closer to the read function. This was taken from the
* Appendix A of RFC 3550. Timestamp and arrival_time have a 1/rate
* resolution.
*/
d = transit - state->transit;
state->transit = transit;
if (d < 0)
d = -d;
state->jitter += d - ((state->jitter + 8) >> 4);
mgcp_rtp_annex_count(endp, state, seq, transit, ssrc);
/* Save output values */
state->out_stream.last_seq = seq;
@ -998,10 +1020,10 @@ void mgcp_state_calc_loss(struct mgcp_rtp_state *state,
struct mgcp_rtp_end *end, uint32_t *expected,
int *loss)
{
*expected = state->cycles + state->out_stream.last_seq;
*expected = *expected - state->base_seq + 1;
*expected = state->stats_cycles + state->stats_max_seq;
*expected = *expected - state->stats_base_seq + 1;
if (!state->initialized) {
if (!state->stats_initialized) {
*expected = 0;
*loss = 0;
return;
@ -1023,7 +1045,7 @@ void mgcp_state_calc_loss(struct mgcp_rtp_state *state,
uint32_t mgcp_state_calc_jitter(struct mgcp_rtp_state *state)
{
if (!state->initialized)
if (!state->stats_initialized)
return 0;
return state->jitter >> 4;
return state->stats_jitter >> 4;
}

View File

@ -699,10 +699,10 @@ static void test_packet_loss_calc(void)
memset(&state, 0, sizeof(state));
memset(&rtp, 0, sizeof(rtp));
state.initialized = 1;
state.base_seq = pl_test_dat[i].base_seq;
state.out_stream.last_seq = pl_test_dat[i].max_seq;
state.cycles = pl_test_dat[i].cycles;
state.stats_initialized = 1;
state.stats_base_seq = pl_test_dat[i].base_seq;
state.stats_max_seq = pl_test_dat[i].max_seq;
state.stats_cycles = pl_test_dat[i].cycles;
rtp.packets = pl_test_dat[i].packets;
mgcp_state_calc_loss(&state, &rtp, &expected, &loss);
@ -921,7 +921,7 @@ static void test_packet_error_detection(int patch_ssrc, int patch_ts)
state.out_stream.err_ts_counter - last_out_ts_err_cnt);
printf("Stats: Jitter = %u, Transit = %d\n",
mgcp_state_calc_jitter(&state), state.transit);
mgcp_state_calc_jitter(&state), state.stats_transit);
last_in_ts_err_cnt = state.in_stream.err_ts_counter;
last_out_ts_err_cnt = state.out_stream.err_ts_counter;

View File

@ -142,58 +142,58 @@ Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0
Stats: Jitter = 15, Transit = 40
In TS: 34688, dTS: 0, Seq: 12
Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0
Stats: Jitter = 0, Transit = -32768
Stats: Jitter = 2065, Transit = -32768
In TS: 34848, dTS: 160, Seq: 13
Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0
Stats: Jitter = 0, Transit = -32768
Stats: Jitter = 1935, Transit = -32768
In TS: 35008, dTS: 160, Seq: 14
Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0
Stats: Jitter = 0, Transit = -32768
Stats: Jitter = 1814, Transit = -32768
In TS: 35128, dTS: 120, Seq: 15
Out TS change: 120, dTS: 120, Seq change: 1, TS Err change: in +1, out +1
Stats: Jitter = 2, Transit = -32728
Stats: Jitter = 1704, Transit = -32728
In TS: 35288, dTS: 160, Seq: 16
Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0
Stats: Jitter = 2, Transit = -32728
Stats: Jitter = 1597, Transit = -32728
In TS: 35448, dTS: 160, Seq: 17
Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0
Stats: Jitter = 2, Transit = -32728
Stats: Jitter = 1497, Transit = -32728
In TS: 35768, dTS: 160, Seq: 19
Out TS change: 320, dTS: 160, Seq change: 2, TS Err change: in +0, out +0
Stats: Jitter = 12, Transit = -32888
Stats: Jitter = 1414, Transit = -32888
In TS: 35928, dTS: 160, Seq: 20
Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0
Stats: Jitter = 11, Transit = -32888
Stats: Jitter = 1325, Transit = -32888
In TS: 36088, dTS: 160, Seq: 21
Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0
Stats: Jitter = 20, Transit = -33048
Stats: Jitter = 1252, Transit = -33048
In TS: 36088, dTS: 160, Seq: 21
Out TS change: 0, dTS: 160, Seq change: 0, TS Err change: in +0, out +0
Stats: Jitter = 29, Transit = -32888
Stats: Jitter = 1184, Transit = -32888
In TS: 36248, dTS: 160, Seq: 22
Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0
Stats: Jitter = 27, Transit = -32888
Stats: Jitter = 1110, Transit = -32888
In TS: 36408, dTS: 160, Seq: 23
Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0
Stats: Jitter = 25, Transit = -32888
Stats: Jitter = 1041, Transit = -32888
In TS: 36568, dTS: 160, Seq: 23
Out TS change: 160, dTS: 160, Seq change: 0, TS Err change: in +1, out +1
Stats: Jitter = 24, Transit = -32888
Stats: Jitter = 976, Transit = -32888
In TS: 36728, dTS: 160, Seq: 24
Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0
Stats: Jitter = 22, Transit = -32888
Stats: Jitter = 915, Transit = -32888
In TS: 36888, dTS: 160, Seq: 25
Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0
Stats: Jitter = 21, Transit = -32888
Stats: Jitter = 857, Transit = -32888
In TS: 160000, dTS: 0, Seq: 1000
Out TS change: 12000, dTS: 12000, Seq change: 1, TS Err change: in +0, out +0
Stats: Jitter = 0, Transit = -144000
Stats: Jitter = 7748, Transit = -144000
In TS: 160160, dTS: 160, Seq: 1001
Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0
Stats: Jitter = 0, Transit = -144000
Stats: Jitter = 7264, Transit = -144000
In TS: 160320, dTS: 160, Seq: 1002
Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0
Stats: Jitter = 0, Transit = -144000
Stats: Jitter = 6810, Transit = -144000
Testing packet error detection.
Output SSRC changed to 11223344
In TS: 0, dTS: 0, Seq: 0
@ -422,57 +422,57 @@ Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0
Stats: Jitter = 15, Transit = 40
In TS: 34688, dTS: 0, Seq: 12
Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0
Stats: Jitter = 0, Transit = -32768
Stats: Jitter = 2065, Transit = -32768
In TS: 34848, dTS: 160, Seq: 13
Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0
Stats: Jitter = 0, Transit = -32768
Stats: Jitter = 1935, Transit = -32768
In TS: 35008, dTS: 160, Seq: 14
Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0
Stats: Jitter = 0, Transit = -32768
Stats: Jitter = 1814, Transit = -32768
In TS: 35128, dTS: 120, Seq: 15
Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +1, out +0
Stats: Jitter = 2, Transit = -32728
Stats: Jitter = 1704, Transit = -32728
In TS: 35288, dTS: 160, Seq: 16
Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0
Stats: Jitter = 2, Transit = -32728
Stats: Jitter = 1597, Transit = -32728
In TS: 35448, dTS: 160, Seq: 17
Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0
Stats: Jitter = 2, Transit = -32728
Stats: Jitter = 1497, Transit = -32728
In TS: 35768, dTS: 160, Seq: 19
Out TS change: 320, dTS: 160, Seq change: 2, TS Err change: in +0, out +0
Stats: Jitter = 12, Transit = -32888
Stats: Jitter = 1414, Transit = -32888
In TS: 35928, dTS: 160, Seq: 20
Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0
Stats: Jitter = 11, Transit = -32888
Stats: Jitter = 1325, Transit = -32888
In TS: 36088, dTS: 160, Seq: 21
Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0
Stats: Jitter = 20, Transit = -33048
Stats: Jitter = 1252, Transit = -33048
In TS: 36088, dTS: 160, Seq: 21
Out TS change: 0, dTS: 160, Seq change: 0, TS Err change: in +0, out +0
Stats: Jitter = 29, Transit = -32888
Stats: Jitter = 1184, Transit = -32888
In TS: 36248, dTS: 160, Seq: 22
Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0
Stats: Jitter = 27, Transit = -32888
Stats: Jitter = 1110, Transit = -32888
In TS: 36408, dTS: 160, Seq: 23
Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0
Stats: Jitter = 25, Transit = -32888
Stats: Jitter = 1041, Transit = -32888
In TS: 36568, dTS: 160, Seq: 23
Out TS change: 160, dTS: 160, Seq change: 0, TS Err change: in +1, out +1
Stats: Jitter = 24, Transit = -32888
Stats: Jitter = 976, Transit = -32888
In TS: 36728, dTS: 160, Seq: 24
Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0
Stats: Jitter = 22, Transit = -32888
Stats: Jitter = 915, Transit = -32888
In TS: 36888, dTS: 160, Seq: 25
Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0
Stats: Jitter = 21, Transit = -32888
Stats: Jitter = 857, Transit = -32888
In TS: 160000, dTS: 0, Seq: 1000
Out TS change: 12000, dTS: 12000, Seq change: 1, TS Err change: in +0, out +0
Stats: Jitter = 0, Transit = -144000
Stats: Jitter = 7748, Transit = -144000
In TS: 160160, dTS: 160, Seq: 1001
Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0
Stats: Jitter = 0, Transit = -144000
Stats: Jitter = 7264, Transit = -144000
In TS: 160320, dTS: 160, Seq: 1002
Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0
Stats: Jitter = 0, Transit = -144000
Stats: Jitter = 6810, Transit = -144000
Testing multiple payload types
Done