1. rtp source structure information
/*
* Per-source state information
*/
typedef struct {
u_int16 max_seq; /* highest seq. number seen */
u_int32 cycles; /* shifted count of seq. number cycles */
u_int32 base_seq; /* base seq number */
u_int32 bad_seq; /* last ’bad’ seq number + 1 */
u_int32 probation; /* sequ. packets till source is valid */
u_int32 received; /* packets received */
u_int32 expected_prior; /* packet expected at last interval */
u_int32 received_prior; /* packet received at last interval */
u_int32 transit; /* relative trans time for prev pkt */
u_int32 jitter; /* estimated jitter */
/* ... */
} source;
2. Initialize source
init_seq(s, seq);
s->max_seq = seq - 1;
s->probation = MIN_SEQUENTIAL;
3. Initialize the seq function
void init_seq(source *s, u_int16 seq)
{
s->base_seq = seq;
s->max_seq = seq;
s->bad_seq = RTP_SEQ_MOD + 1; /* so seq == bad_seq is false */
s->cycles = 0;
s->received = 0;
s->received_prior = 0;
s->expected_prior = 0;
/* other initialization */
}
4. seq update function
int update_seq(source *s, u_int16 seq)
{
u_int16 udelta = seq - s->max_seq;
const int MAX_DROPOUT = 3000;
const int MAX_MISORDER = 100;
const int MIN_SEQUENTIAL = 2;
/*
* Source is not valid until MIN_SEQUENTIAL packets with
* sequential sequence numbers have been received.
*/
/* 通过连续probation个变量,确定base_seq */
if (s->probation) {
/* packet is in sequence */
if (seq == s->max_seq + 1) {
s->probation--;
s->max_seq = seq;
if (s->probation == 0) {
init_seq(s, seq);
s->received++;
return 1;
}
}
else {
s->probation = MIN_SEQUENTIAL - 1;
s->max_seq = seq;
}
return 0;
} else if (udelta < MAX_DROPOUT) {
// 当前max_seq 向后MAX_DROPOUT内个seq
/* in order, with permissible gap */
if (seq < s->max_seq) {
// 如果seq < s->max_seq 表示又一次循环
/*
* Sequence number wrapped - count another 64K cycle.
*/
s->cycles += RTP_SEQ_MOD;
}
s->max_seq = seq;
} else if (udelta <= RTP_SEQ_MOD - MAX_MISORDER) {
// 向前超过MAX_MISORDER个seq
/* the sequence number made a very large jump */
if (seq == s->bad_seq) {
/*
* Two sequential packets -- assume that the other side
* restarted without telling us so just re-sync
* (i.e., pretend this was the first packet).
*/
init_seq(s, seq);
} else {
// 设置seq + 1为bad_seq,如果下一个seq == s->bad_seq, 则重新初始化seq
s->bad_seq = (seq + 1) & (RTP_SEQ_MOD - 1);
return 0;
}
}
else {
/* duplicate or reordered packet */
}
s->received++;
return 1;
}
update_seq mainly includes three parts:
- Because the initial seq in rtp is uncertain, the benchmark seq is determined by receiving consecutive prodation seq
- udelta < MAX_DROPOUT means backward jump, cannot exceed MAX_DROPOUT
- udelta <= RTP_SEQ_MOD - MAX_MISORDER jump forward, beyond MAX_MISORDER
Use the update_seq function to check whether the current seq is valid