rtp seq checksum

rtp rfc document link

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

Guess you like

Origin blog.csdn.net/zjoops1314/article/details/125305413
RTP