TT#136957 use separate sequencer per sink/destination

Change-Id: Ib960108003d5aa13ba1732d7a5e8c6720feca5c0
pull/1487/head
Richard Fuchs 4 years ago
parent c0d9f84e49
commit 2240921ab3

@ -398,7 +398,9 @@ static void __make_passthrough_ssrc(struct codec_handler *handler) {
static void __reset_sequencer(void *p, void *dummy) {
struct ssrc_entry_call *s = p;
s->sequencer.seq = -1;
if (s->sequencers)
g_hash_table_destroy(s->sequencers);
s->sequencers = NULL;
}
static void __make_transcoder(struct codec_handler *handler, struct rtp_payload_type *dest,
GHashTable *output_transcoders, int dtmf_payload_type, bool pcm_dtmf_detect,
@ -1535,6 +1537,12 @@ static void __ssrc_unlock_both(struct media_packet *mp) {
mutex_unlock(&ssrc_out_p->h.lock);
}
static void __seq_free(void *p) {
packet_sequencer_t *seq = p;
packet_sequencer_destroy(seq);
g_slice_free1(sizeof(*seq), seq);
}
static int __handler_func_sequencer(struct media_packet *mp, struct transcode_packet *packet)
{
struct codec_handler *h = packet->handler;
@ -1588,10 +1596,18 @@ static int __handler_func_sequencer(struct media_packet *mp, struct transcode_pa
__ssrc_lock_both(mp);
packet_sequencer_init(&ssrc_in_p->sequencer, (GDestroyNotify) __transcode_packet_free);
// get sequencer appropriate for our output
if (!ssrc_in_p->sequencers)
ssrc_in_p->sequencers = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, __seq_free);
packet_sequencer_t *seq = g_hash_table_lookup(ssrc_in_p->sequencers, mp->media_out);
if (!seq) {
seq = g_slice_alloc0(sizeof(*seq));
packet_sequencer_init(seq, (GDestroyNotify) __transcode_packet_free);
g_hash_table_insert(ssrc_in_p->sequencers, mp->media_out, seq);
}
uint16_t seq_ori = ssrc_in_p->sequencer.seq;
int seq_ret = packet_sequencer_insert(&ssrc_in_p->sequencer, &packet->p);
uint16_t seq_ori = seq->seq;
int seq_ret = packet_sequencer_insert(seq, &packet->p);
if (seq_ret < 0) {
// dupe
int func_ret = 0;
@ -1610,7 +1626,7 @@ static int __handler_func_sequencer(struct media_packet *mp, struct transcode_pa
while (1) {
int func_ret = 0;
packet = packet_sequencer_next_packet(&ssrc_in_p->sequencer);
packet = packet_sequencer_next_packet(seq);
if (G_UNLIKELY(!packet)) {
if (!ch || !h->dest_pt.clock_rate || !ch->handler
|| !h->dest_pt.codec_def)
@ -1627,7 +1643,7 @@ static int __handler_func_sequencer(struct media_packet *mp, struct transcode_pa
unsigned long long ts_diff_us =
(unsigned long long) ts_diff * 1000000 / h->dest_pt.clock_rate;
if (ts_diff_us >= 60000) { // arbitrary value
packet = packet_sequencer_force_next_packet(&ssrc_in_p->sequencer);
packet = packet_sequencer_force_next_packet(seq);
if (!packet)
break;
ilogs(transcoding, LOG_DEBUG, "Timestamp difference too large (%llu ms) after lost packet, "
@ -1672,8 +1688,8 @@ static int __handler_func_sequencer(struct media_packet *mp, struct transcode_pa
goto next;
}
ssrc_in_p->packets_lost = ssrc_in_p->sequencer.lost_count;
atomic64_set(&ssrc_in->last_seq, ssrc_in_p->sequencer.ext_seq);
ssrc_in_p->packets_lost = seq->lost_count;
atomic64_set(&ssrc_in->last_seq, seq->ext_seq);
ilogs(transcoding, LOG_DEBUG, "Processing RTP packet: seq %u, TS %lu",
packet->p.seq, packet->ts);

@ -490,6 +490,9 @@ static const char *dtmf_inject_pcm(struct call_media *media, struct call_media *
struct sink_handler *sh = l->data;
struct packet_stream *sink_ps = sh->sink;
struct call_monologue *sink_ml = sink_ps->media->monologue;
packet_sequencer_t *seq = g_hash_table_lookup(ssrc_in->parent->sequencers, sink_ps->media);
if (!seq)
continue;
struct ssrc_ctx *ssrc_out = get_ssrc_ctx(ssrc_in->ssrc_map_out,
sink_ml->ssrc_hash, SSRC_DIR_OUTPUT,
@ -511,7 +514,7 @@ static const char *dtmf_inject_pcm(struct call_media *media, struct call_media *
struct rtp_header rtp = {
.m_pt = 0xff,
.timestamp = 0,
.seq_num = htons(ssrc_in->parent->sequencer.seq),
.seq_num = htons(seq->seq),
.ssrc = htonl(ssrc_in->parent->h.ssrc),
};
struct media_packet packet = {
@ -535,7 +538,7 @@ static const char *dtmf_inject_pcm(struct call_media *media, struct call_media *
// insert pause
tep.event = 0xff;
tep.duration = htons(pause_samples);
rtp.seq_num = htons(ssrc_in->parent->sequencer.seq);
rtp.seq_num = htons(seq->seq);
ch->dtmf_injector->handler_func(ch->dtmf_injector, &packet);

@ -53,7 +53,8 @@ static void __free_ssrc_entry_call(void *ep) {
g_queue_clear_full(&e->sender_reports, (GDestroyNotify) free_sender_report);
g_queue_clear_full(&e->rr_time_reports, (GDestroyNotify) free_rr_time);
g_queue_clear_full(&e->stats_blocks, (GDestroyNotify) free_stats_block);
packet_sequencer_destroy(&e->sequencer);
if (e->sequencers)
g_hash_table_destroy(e->sequencers);
}
static void ssrc_entry_put(void *ep) {
struct ssrc_entry_call *e = ep;

@ -118,7 +118,7 @@ struct ssrc_entry_call {
// for transcoding
// input only
packet_sequencer_t sequencer;
GHashTable *sequencers;
uint32_t jitter, transit;
// output only
uint16_t seq_diff;

@ -16,7 +16,7 @@ autotest_start(qw(--config-file=none -t -1 -i 203.0.113.1 -i 2001:db8:4321::1
my ($sock_a, $sock_b, $sock_c, $sock_d, $port_a, $port_b, $port_c, $ssrc_a, $ssrc_b, $resp,
$sock_ax, $sock_bx, $port_ax, $port_bx, $port_d,
$sock_ax, $sock_bx, $port_ax, $port_bx, $port_d, $sock_e, $port_e,
$srtp_ctx_a, $srtp_ctx_b, $srtp_ctx_a_rev, $srtp_ctx_b_rev, $ufrag_a, $ufrag_b,
@ret1, @ret2, @ret3, @ret4, $srtp_key_a, $srtp_key_b, $ts, $seq, $tag_medias, $media_labels,
$ftr, $ttr, $fts, $ttr2);
@ -1622,6 +1622,181 @@ rcv($sock_c, $port_c, rtpm(0, 4001, 7160, $ssrc_b, "\x00" x 160));
($sock_a, $sock_b, $sock_c, $sock_d, $sock_e) =
new_call([qw(198.51.100.14 6132)],
[qw(198.51.100.14 6134)],
[qw(198.51.100.14 6136)],
[qw(198.51.100.14 6138)],
[qw(198.51.100.14 6140)]);
($port_a) = offer('multi subs w diff codecs',
{ }, <<SDP);
v=0
o=- 1545997027 1 IN IP4 198.51.100.1
s=tester
t=0 0
m=audio 6132 RTP/AVP 0
c=IN IP4 198.51.100.14
a=sendrecv
----------------------------------
v=0
o=- 1545997027 1 IN IP4 198.51.100.1
s=tester
t=0 0
m=audio PORT RTP/AVP 0
c=IN IP4 203.0.113.1
a=rtpmap:0 PCMU/8000
a=sendrecv
a=rtcp:PORT
SDP
($port_b) = answer('multi subs w diff codecs',
{ }, <<SDP);
v=0
o=- 1545997027 1 IN IP4 198.51.100.1
s=tester
t=0 0
m=audio 6134 RTP/AVP 0
c=IN IP4 198.51.100.14
a=sendrecv
----------------------------------
v=0
o=- 1545997027 1 IN IP4 198.51.100.1
s=tester
t=0 0
m=audio PORT RTP/AVP 0
c=IN IP4 203.0.113.1
a=rtpmap:0 PCMU/8000
a=sendrecv
a=rtcp:PORT
SDP
snd($sock_b, $port_a, rtp(0, 2000, 4000, 0x3456, "\x00" x 160));
($ssrc_a) = rcv($sock_a, $port_b, rtpm(0, 2000, 4000, -1, "\x00" x 160));
snd($sock_a, $port_b, rtp(0, 4000, 7000, 0x6543, "\x00" x 160));
($ssrc_b) = rcv($sock_b, $port_a, rtpm(0, 4000, 7000, -1, "\x00" x 160));
($ftr, $ttr, undef, undef, undef, $port_c) = subscribe_request('multi subs w diff codecs',
{ 'from-tag' => ft(), codec => {transcode => ['PCMA', 'G722', 'G723'] } }, <<SDP);
v=0
o=- 1545997027 1 IN IP4 198.51.100.1
s=tester
t=0 0
m=audio PORT RTP/AVP 0 8 9 4
c=IN IP4 203.0.113.1
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:9 G722/8000
a=rtpmap:4 G723/8000
a=sendonly
a=rtcp:PORT
SDP
is $ftr, ft(), 'from-tag matches';
subscribe_answer('multi subs w diff codecs',
{ 'to-tag' => $ttr }, <<SDP);
v=0
o=- 1545997027 1 IN IP4 198.51.100.1
s=tester
t=0 0
m=audio 6136 RTP/AVP 0
c=IN IP4 198.51.100.14
a=recvonly
SDP
snd($sock_b, $port_a, rtp(0, 2001, 4160, 0x3456, "\x00" x 160));
rcv($sock_a, $port_b, rtpm(0, 2001, 4160, $ssrc_a, "\x00" x 160));
snd($sock_a, $port_b, rtp(0, 4001, 7160, 0x6543, "\x00" x 160));
rcv($sock_b, $port_a, rtpm(0, 4001, 7160, $ssrc_b, "\x00" x 160));
rcv($sock_c, $port_c, rtpm(0, 4001, 7160, $ssrc_b, "\x00" x 160));
($ftr, $ttr, undef, undef, undef, $port_d) = subscribe_request('multi subs w diff codecs',
{ 'from-tag' => ft(), codec => {transcode => ['PCMA', 'G722', 'G723'] } }, <<SDP);
v=0
o=- 1545997027 1 IN IP4 198.51.100.1
s=tester
t=0 0
m=audio PORT RTP/AVP 0 8 9 4
c=IN IP4 203.0.113.1
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:9 G722/8000
a=rtpmap:4 G723/8000
a=sendonly
a=rtcp:PORT
SDP
is $ftr, ft(), 'from-tag matches';
subscribe_answer('multi subs w diff codecs',
{ 'to-tag' => $ttr, flags => ['allow transcoding'] }, <<SDP);
v=0
o=- 1545997027 1 IN IP4 198.51.100.1
s=tester
t=0 0
m=audio 6138 RTP/AVP 8
c=IN IP4 198.51.100.14
a=recvonly
SDP
snd($sock_b, $port_a, rtp(0, 2002, 4320, 0x3456, "\x00" x 160));
rcv($sock_a, $port_b, rtpm(0, 2002, 4320, $ssrc_a, "\x00" x 160));
snd($sock_a, $port_b, rtp(0, 4002, 7320, 0x6543, "\x00" x 160));
rcv($sock_b, $port_a, rtpm(0, 4002, 7320, $ssrc_b, "\x00" x 160));
rcv($sock_c, $port_c, rtpm(0, 4002, 7320, $ssrc_b, "\x00" x 160));
rcv($sock_d, $port_d, rtpm(8, 4002, 7320, $ssrc_b, "\x2a" x 160));
($ftr, $ttr, undef, undef, undef, $port_e) = subscribe_request('multi subs w diff codecs',
{ 'from-tag' => ft(), codec => {transcode => ['PCMA', 'G722', 'G723'] } }, <<SDP);
v=0
o=- 1545997027 1 IN IP4 198.51.100.1
s=tester
t=0 0
m=audio PORT RTP/AVP 0 8 9 4
c=IN IP4 203.0.113.1
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:9 G722/8000
a=rtpmap:4 G723/8000
a=sendonly
a=rtcp:PORT
SDP
is $ftr, ft(), 'from-tag matches';
subscribe_answer('multi subs w diff codecs',
{ 'to-tag' => $ttr, flags => ['allow transcoding'] }, <<SDP);
v=0
o=- 1545997027 1 IN IP4 198.51.100.1
s=tester
t=0 0
m=audio 6140 RTP/AVP 9
c=IN IP4 198.51.100.14
a=recvonly
SDP
snd($sock_b, $port_a, rtp(0, 2003, 4480, 0x3456, "\x00" x 160));
rcv($sock_a, $port_b, rtpm(0, 2003, 4480, $ssrc_a, "\x00" x 160));
snd($sock_a, $port_b, rtp(0, 4003, 7480, 0x6543, "\x00" x 160));
rcv($sock_b, $port_a, rtpm(0, 4003, 7480, $ssrc_b, "\x00" x 160));
rcv($sock_c, $port_c, rtpm(0, 4003, 7480, $ssrc_b, "\x00" x 160));
rcv($sock_d, $port_d, rtpm(8, 4003, 7480, $ssrc_b, "\x2a" x 160));
rcv_no($sock_e); # resample/codec buffer
snd($sock_b, $port_a, rtp(0, 2004, 4640, 0x3456, "\x00" x 160));
rcv($sock_a, $port_b, rtpm(0, 2004, 4640, $ssrc_a, "\x00" x 160));
snd($sock_a, $port_b, rtp(0, 4004, 7640, 0x6543, "\x00" x 160));
rcv($sock_b, $port_a, rtpm(0, 4004, 7640, $ssrc_b, "\x00" x 160));
rcv($sock_c, $port_c, rtpm(0, 4004, 7640, $ssrc_b, "\x00" x 160));
rcv($sock_d, $port_d, rtpm(8, 4004, 7640, $ssrc_b, "\x2a" x 160));
rcv($sock_e, $port_e, rtpm(9, 4003, 7480, $ssrc_b, "\x23\x84\x20\x84\x20\x84\x04\x84\x04\x84\x44\x44\xc4\xc4\xc4\xc5\xc5\xc6\xc6\xc7\x88\xc8\xc8\xc9\xc9\xc9\xca\xcb\xcc\xcc\xcb\xcd\xcd\xcd\xcd\xce\xcf\x8f\xd0\xd0\xcf\x91\xd1\xd0\xd0\x90\xd1\xd1\xd2\xd3\x94\xd2\xd4\xd2\x94\xd2\xd4\xd3\xd5\x95\xd4\xd4\xd3\x96\xd5\xd5\xd5\x96\xd7\xd6\xd6\xd6\x97\xd8\xd5\xd6\x97\xd8\xd4\xd5\x98\xd6\xd7\xd9\xd7\x99\xd6\xd9\xd6\x97\xdb\x98\xd6\x98\xd7\xd9\xd5\x98\xd7\xdb\xd9\xd6\xd9\xd6\xda\xd7\x9b\xda\x97\xdc\x93\x5e\xd6\xd9\xd9\x95\x5c\x92\xde\xd7\xdb\xdb\xd8\xd7\xd9\xd8\xd4\x98\xd7\xbe\xd2\x9c\xd6\xd9\xd7\xdb\xdf\xd5\xd9\xd7\x9d\xd3\xbe\xd7\xdb\xdb\xd8\xd6\xd7\xbf\x55\x97\xbe\xd5\xd6\xd9\x9b\x1c\xd2\xbc"));
($sock_a, $sock_b, $sock_c) =
new_call([qw(198.51.100.14 6000)], [qw(198.51.100.14 6002)], [qw(198.51.100.14 6004)]);

Loading…
Cancel
Save