void pjmedia_rtp_seq_update( pjmedia_rtp_seq_session *sess, 
			     pj_uint16_t seq,
			     pjmedia_rtp_status *seq_status)
{
    pj_uint16_t udelta = (pj_uint16_t) (seq - sess->max_seq);
    pjmedia_rtp_status st;
    
    /* Init status */
    st.status.value = 0;
    st.diff = 0;

    /*
     * Source is not valid until MIN_SEQUENTIAL packets with
     * sequential sequence numbers have been received.
     */
    if (sess->probation) {

	st.status.flag.probation = 1;
	
        if (seq == sess->max_seq+ 1) {
	    /* packet is in sequence */
	    st.diff = 1;
	    sess->probation--;
            sess->max_seq = seq;
            if (sess->probation == 0) {
		st.status.flag.probation = 0;
            }
	} else {

	    st.diff = 0;

	    st.status.flag.bad = 1;
	    if (seq == sess->max_seq)
		st.status.flag.dup = 1;
	    else
		st.status.flag.outorder = 1;

	    sess->probation = MIN_SEQUENTIAL - 1;
	    sess->max_seq = seq;
        }


    } else if (udelta == 0) {

	st.status.flag.dup = 1;

    } else if (udelta < MAX_DROPOUT) {
	/* in order, with permissible gap */
	if (seq < sess->max_seq) {
	    /* Sequence number wrapped - count another 64K cycle. */
	    sess->cycles += RTP_SEQ_MOD;
        }
        sess->max_seq = seq;

	st.diff = udelta;

    } else if (udelta <= (RTP_SEQ_MOD - MAX_MISORDER)) {
	/* the sequence number made a very large jump */
        if (seq == sess->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).
	     */
	    pjmedia_rtp_seq_restart(sess, seq);
	    st.status.flag.restart = 1;
	    st.status.flag.probation = 1;
	    st.diff = 1;
	}
        else {
	    sess->bad_seq = (seq + 1) & (RTP_SEQ_MOD-1);
            st.status.flag.bad = 1;
	    st.status.flag.outorder = 1;
        }
    } else {
	/* old duplicate or reordered packet.
	 * Not necessarily bad packet (?)
	 */
	st.status.flag.outorder = 1;
    }
    

    if (seq_status) {
	seq_status->diff = st.diff;
	seq_status->status.value = st.status.value;
    }
}
void pjmedia_rtp_seq_update( pjmedia_rtp_seq_session *sess, 
			     pj_uint16_t seq,
			     pjmedia_rtp_status *seq_status)
{
    pj_uint16_t udelta = (pj_uint16_t) (seq - sess->max_seq);
    pjmedia_rtp_status st;
    
     
    st.status.value = 0;
    st.diff = 0;

     
    if (sess->probation) {

	st.status.flag.probation = 1;
	
        if (seq == sess->max_seq+ 1) {
	     
	    st.diff = 1;
	    sess->probation--;
            sess->max_seq = seq;
            if (sess->probation == 0) {
		st.status.flag.probation = 0;
            }
	} else {

	    st.diff = 0;

	    st.status.flag.bad = 1;
	    if (seq == sess->max_seq)
		st.status.flag.dup = 1;
	    else
		st.status.flag.outorder = 1;

	    sess->probation = MIN_SEQUENTIAL - 1;
	    sess->max_seq = seq;
        }


    } else if (udelta == 0) {

	st.status.flag.dup = 1;

    } else if (udelta < MAX_DROPOUT) {
	 
	if (seq < sess->max_seq) {
	     
	    sess->cycles += RTP_SEQ_MOD;
        }
        sess->max_seq = seq;

	st.diff = udelta;

    } else if (udelta <= (RTP_SEQ_MOD - MAX_MISORDER)) {
	 
        if (seq == sess->bad_seq) {
	     
	    pjmedia_rtp_seq_restart(sess, seq);
	    st.status.flag.restart = 1;
	    st.status.flag.probation = 1;
	    st.diff = 1;
	}
        else {
	    sess->bad_seq = (seq + 1) & (RTP_SEQ_MOD-1);
            st.status.flag.bad = 1;
	    st.status.flag.outorder = 1;
        }
    } else {
	 
	st.status.flag.outorder = 1;
    }
    

    if (seq_status) {
	seq_status->diff = st.diff;
	seq_status->status.value = st.status.value;
    }
}