PJ_DEF(void) pjmedia_rtp_session_update2( pjmedia_rtp_session *ses, const pjmedia_rtp_hdr *hdr, pjmedia_rtp_status *p_seq_st, pj_bool_t check_pt) { pjmedia_rtp_status seq_st; /* for now check_pt MUST be either PJ_TRUE or PJ_FALSE. * In the future we might change check_pt from boolean to * unsigned integer to accommodate more flags. */ pj_assert(check_pt==PJ_TRUE || check_pt==PJ_FALSE); /* Init status */ seq_st.status.value = 0; seq_st.diff = 0; /* Check SSRC. */ if (!ses->has_peer_ssrc && ses->peer_ssrc == 0) ses->peer_ssrc = pj_ntohl(hdr->ssrc); if (pj_ntohl(hdr->ssrc) != ses->peer_ssrc) { seq_st.status.flag.badssrc = 1; if (!ses->has_peer_ssrc) ses->peer_ssrc = pj_ntohl(hdr->ssrc); } /* Check payload type. */ if (check_pt && hdr->pt != ses->out_pt) { if (p_seq_st) { p_seq_st->status.value = seq_st.status.value; p_seq_st->status.flag.bad = 1; p_seq_st->status.flag.badpt = 1; } return; } /* Initialize sequence number on first packet received. */ if (ses->received == 0) pjmedia_rtp_seq_init( &ses->seq_ctrl, pj_ntohs(hdr->seq) ); /* Check sequence number to see if remote session has been restarted. */ pjmedia_rtp_seq_update( &ses->seq_ctrl, pj_ntohs(hdr->seq), &seq_st); if (seq_st.status.flag.restart) { ++ses->received; } else if (!seq_st.status.flag.bad) { ++ses->received; } if (p_seq_st) { p_seq_st->status.value = seq_st.status.value; p_seq_st->diff = seq_st.diff; } }
PJ_DEF(void) pjmedia_rtcp_rx_rtp2(pjmedia_rtcp_session *sess, unsigned seq, unsigned rtp_ts, unsigned payload, pj_bool_t discarded) { pj_timestamp ts; pj_uint32_t arrival; pj_int32_t transit; pjmedia_rtp_status seq_st; unsigned last_seq; #if !defined(PJMEDIA_HAS_RTCP_XR) || (PJMEDIA_HAS_RTCP_XR == 0) PJ_UNUSED_ARG(discarded); #endif if (sess->stat.rx.pkt == 0) { /* Init sequence for the first time. */ pjmedia_rtp_seq_init(&sess->seq_ctrl, (pj_uint16_t)seq); } sess->stat.rx.pkt++; sess->stat.rx.bytes += payload; /* Process the RTP packet. */ last_seq = sess->seq_ctrl.max_seq; pjmedia_rtp_seq_update(&sess->seq_ctrl, (pj_uint16_t)seq, &seq_st); if (seq_st.status.flag.restart) { rtcp_init_seq(sess); } if (seq_st.status.flag.dup) { sess->stat.rx.dup++; TRACE_((sess->name, "Duplicate packet detected")); } if (seq_st.status.flag.outorder && !seq_st.status.flag.probation) { sess->stat.rx.reorder++; TRACE_((sess->name, "Out-of-order packet detected")); } if (seq_st.status.flag.bad) { sess->stat.rx.discard++; #if defined(PJMEDIA_HAS_RTCP_XR) && (PJMEDIA_HAS_RTCP_XR != 0) pjmedia_rtcp_xr_rx_rtp(&sess->xr_session, seq, -1, /* lost */ (seq_st.status.flag.dup? 1:0), /* dup */ (!seq_st.status.flag.dup? 1:-1), /* discard */ -1, /* jitter */ -1, 0); /* toh */ #endif TRACE_((sess->name, "Bad packet discarded")); return; } /* Only mark "good" packets */ ++sess->received; /* Calculate loss periods. */ if (seq_st.diff > 1) { unsigned count = seq_st.diff - 1; unsigned period; period = count * sess->pkt_size * 1000 / sess->clock_rate; period *= 1000; /* Update packet lost. * The packet lost number will also be updated when we're sending * outbound RTCP RR. */ sess->stat.rx.loss += (seq_st.diff - 1); TRACE_((sess->name, "%d packet(s) lost", seq_st.diff - 1)); /* Update loss period stat */ pj_math_stat_update(&sess->stat.rx.loss_period, period); } /* * Calculate jitter only when sequence is good (see RFC 3550 section A.8), * AND only when the timestamp is different than the last packet * (see RTP FAQ). */ if (seq_st.diff == 1 && rtp_ts != sess->rtp_last_ts) { /* Get arrival time and convert timestamp to samples */ pj_get_timestamp(&ts); ts.u64 = ts.u64 * sess->clock_rate / sess->ts_freq.u64; arrival = ts.u32.lo; transit = arrival - rtp_ts; /* Ignore the first N packets as they normally have bad jitter * due to other threads working to establish the call */ if (sess->transit == 0 || sess->received < PJMEDIA_RTCP_IGNORE_FIRST_PACKETS) { sess->transit = transit; sess->stat.rx.jitter.min = (unsigned)-1; } else { pj_int32_t d; pj_uint32_t jitter; d = transit - sess->transit; sess->transit = transit; if (d < 0) d = -d; sess->jitter += d - ((sess->jitter + 8) >> 4); /* Get jitter in usec */ if (d < 4294) jitter = d * 1000000 / sess->clock_rate; else { jitter = d * 1000 / sess->clock_rate; jitter *= 1000; } /* Update jitter stat */ pj_math_stat_update(&sess->stat.rx.jitter, jitter); #if defined(PJMEDIA_HAS_RTCP_XR) && (PJMEDIA_HAS_RTCP_XR != 0) pjmedia_rtcp_xr_rx_rtp(&sess->xr_session, seq, 0, /* lost */ 0, /* dup */ discarded, /* discard */ (sess->jitter >> 4), /* jitter */ -1, 0); /* toh */ #endif } #if defined(PJMEDIA_HAS_RTCP_XR) && (PJMEDIA_HAS_RTCP_XR != 0) } else if (seq_st.diff > 1) {