|
|
|
@ -40,6 +40,7 @@ static struct timerthread codec_timers_thread; |
|
|
|
static void rtp_payload_type_copy(struct rtp_payload_type *dst, const struct rtp_payload_type *src); |
|
|
|
static void codec_store_add_raw_order(struct codec_store *cs, struct rtp_payload_type *pt); |
|
|
|
static void __rtp_payload_type_add_name(GHashTable *, struct rtp_payload_type *pt); |
|
|
|
static void codec_calc_lost(struct ssrc_ctx *ssrc, uint16_t seq); |
|
|
|
|
|
|
|
|
|
|
|
static struct codec_handler codec_handler_stub = { |
|
|
|
@ -1329,8 +1330,10 @@ static int handler_func_passthrough(struct codec_handler *h, struct media_packet |
|
|
|
if (!handler_silence_block(h, mp)) |
|
|
|
return 0; |
|
|
|
|
|
|
|
if (mp->rtp) |
|
|
|
if (mp->rtp) { |
|
|
|
codec_calc_jitter(mp->ssrc_in, ntohl(mp->rtp->timestamp), h->source_pt.clock_rate, &mp->tv); |
|
|
|
codec_calc_lost(mp->ssrc_in, ntohs(mp->rtp->seq_num)); |
|
|
|
} |
|
|
|
codec_add_raw_packet(mp, h->source_pt.clock_rate); |
|
|
|
return 0; |
|
|
|
} |
|
|
|
@ -1949,8 +1952,10 @@ static int handler_func_passthrough_ssrc(struct codec_handler *h, struct media_p |
|
|
|
if (!handler_silence_block(h, mp)) |
|
|
|
return 0; |
|
|
|
|
|
|
|
if (mp->rtp) |
|
|
|
if (mp->rtp) { |
|
|
|
codec_calc_jitter(mp->ssrc_in, ntohl(mp->rtp->timestamp), h->source_pt.clock_rate, &mp->tv); |
|
|
|
codec_calc_lost(mp->ssrc_in, ntohs(mp->rtp->seq_num)); |
|
|
|
} |
|
|
|
|
|
|
|
// substitute out SSRC etc |
|
|
|
mp->rtp->ssrc = htonl(mp->ssrc_in->ssrc_map_out); |
|
|
|
@ -2830,6 +2835,60 @@ void codec_calc_jitter(struct ssrc_ctx *ssrc, unsigned long ts, unsigned int clo |
|
|
|
sec->jitter += d - ((sec->jitter + 8) >> 4); |
|
|
|
mutex_unlock(&sec->h.lock); |
|
|
|
} |
|
|
|
static void codec_calc_lost(struct ssrc_ctx *ssrc, uint16_t seq) { |
|
|
|
struct ssrc_entry_call *s = ssrc->parent; |
|
|
|
|
|
|
|
LOCK(&s->h.lock); |
|
|
|
|
|
|
|
// XXX shared code from kernel module |
|
|
|
|
|
|
|
uint32_t last_seq = s->last_seq_tracked; |
|
|
|
uint32_t new_seq = last_seq; |
|
|
|
|
|
|
|
// old seq or seq reset? |
|
|
|
uint16_t old_seq_trunc = last_seq & 0xffff; |
|
|
|
uint16_t seq_diff = seq - old_seq_trunc; |
|
|
|
if (seq_diff == 0 || seq_diff >= 0xfeff) // old/dup seq - ignore |
|
|
|
; |
|
|
|
else if (seq_diff > 0x100) { |
|
|
|
// reset seq and loss tracker |
|
|
|
new_seq = seq; |
|
|
|
s->last_seq_tracked = seq; |
|
|
|
s->lost_bits = -1; |
|
|
|
} |
|
|
|
else { |
|
|
|
// seq wrap? |
|
|
|
new_seq = (last_seq & 0xffff0000) | seq; |
|
|
|
while (new_seq < last_seq) { |
|
|
|
new_seq += 0x10000; |
|
|
|
if ((new_seq & 0xffff0000) == 0) // ext seq wrapped |
|
|
|
break; |
|
|
|
} |
|
|
|
seq_diff = new_seq - last_seq; |
|
|
|
s->last_seq_tracked = new_seq; |
|
|
|
|
|
|
|
// shift loss tracker bit field and count losses |
|
|
|
if (seq_diff >= (sizeof(s->lost_bits) * 8)) { |
|
|
|
// complete loss |
|
|
|
s->packets_lost += sizeof(s->lost_bits) * 8; |
|
|
|
s->lost_bits = -1; |
|
|
|
} |
|
|
|
else { |
|
|
|
while (seq_diff) { |
|
|
|
// shift out one bit and see if we lost it |
|
|
|
if ((s->lost_bits & 0x80000000) == 0) |
|
|
|
s->packets_lost++; |
|
|
|
s->lost_bits <<= 1; |
|
|
|
seq_diff--; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// track this frame as being seen |
|
|
|
seq_diff = (new_seq & 0xffff) - seq; |
|
|
|
if (seq_diff < (sizeof(s->lost_bits) * 8)) |
|
|
|
s->lost_bits |= (1 << seq_diff); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#ifdef WITH_TRANSCODING |
|
|
|
|