TT#28163 abstractize SSRC hash

Change-Id: I2f28854070ad5a7567870ef7585e67729154b0e3
changes/98/18598/10
Richard Fuchs 7 years ago
parent a967f9dcbb
commit b9206a49bc

@ -18,6 +18,7 @@ flags = [
'-fno-strict-aliasing',
'-I/usr/include/glib-2.0',
'-I/usr/lib/x86_64-linux-gnu/glib-2.0/include',
'-I/usr/include/json-glib-1.0',
'-pthread',
'-I../kernel-module/',
'-I../lib/',

@ -594,7 +594,7 @@ static void call_timer(void *ptr) {
if (sink) {
mutex_lock(&sink->out_lock);
if (sink->crypto.params.crypto_suite && sink->ssrc_out
&& ke->target.ssrc == sink->ssrc_out->parent->ssrc
&& ke->target.ssrc == sink->ssrc_out->parent->h.ssrc
&& ke->target.encrypt.last_index - sink->ssrc_out->srtp_index > 0x4000)
{
sink->ssrc_out->srtp_index = ke->target.encrypt.last_index;
@ -605,7 +605,7 @@ static void call_timer(void *ptr) {
mutex_lock(&ps->in_lock);
if (sfd->crypto.params.crypto_suite && ps->ssrc_in
&& ke->target.ssrc == ps->ssrc_in->parent->ssrc
&& ke->target.ssrc == ps->ssrc_in->parent->h.ssrc
&& ke->target.decrypt.last_index - ps->ssrc_in->srtp_index > 0x4000)
{
ps->ssrc_in->srtp_index = ke->target.decrypt.last_index;
@ -652,8 +652,8 @@ int call_init() {
void __payload_type_free(void *p) {
g_slice_free1(sizeof(struct rtp_payload_type), p);
void payload_type_free(struct rtp_payload_type *p) {
g_slice_free1(sizeof(*p), p);
}
static struct call_media *__get_media(struct call_monologue *ml, GList **it, const struct stream_params *sp) {
@ -683,7 +683,7 @@ static struct call_media *__get_media(struct call_monologue *ml, GList **it, con
med->call = ml->call;
med->index = sp->index;
call_str_cpy(ml->call, &med->type, &sp->type);
med->codecs = g_hash_table_new_full(g_int_hash, g_int_equal, NULL, __payload_type_free);
med->codecs = g_hash_table_new_full(g_int_hash, g_int_equal, NULL, (GDestroyNotify) payload_type_free);
med->codec_names = g_hash_table_new_full(str_hash, str_equal, NULL, (void (*)(void*)) g_queue_free);
g_queue_push_tail(&ml->medias, med);
@ -1853,7 +1853,7 @@ void call_destroy(struct call *c) {
(unsigned int) (ps->selected_sfd ? ps->selected_sfd->socket.local.port : 0),
addr, ps->endpoint.port,
(!PS_ISSET(ps, RTP) && PS_ISSET(ps, RTCP)) ? " (RTCP)" : "",
ps->ssrc_in ? ps->ssrc_in->parent->ssrc : 0,
ps->ssrc_in ? ps->ssrc_in->parent->h.ssrc : 0,
atomic64_get(&ps->stats.packets),
atomic64_get(&ps->stats.bytes),
atomic64_get(&ps->stats.errors),
@ -1869,12 +1869,12 @@ void call_destroy(struct call *c) {
k = g_hash_table_get_values(c->ssrc_hash->ht);
for (l = k; l; l = l->next) {
struct ssrc_entry *se = l->data;
struct ssrc_entry_call *se = l->data;
if (!se->stats_blocks.length || !se->lowest_mos || !se->highest_mos)
continue;
ilog(LOG_INFO, "--- SSRC %" PRIu32 "", se->ssrc);
ilog(LOG_INFO, "--- SSRC %" PRIu32 "", se->h.ssrc);
ilog(LOG_INFO, "------ Average MOS %" PRIu64 ".%" PRIu64 ", "
"lowest MOS %" PRIu64 ".%" PRIu64 " (at %u:%02u), "
"highest MOS %" PRIu64 ".%" PRIu64 " (at %u:%02u)",
@ -1986,7 +1986,7 @@ static void __call_free(void *p) {
g_hash_table_destroy(md->codecs);
g_hash_table_destroy(md->codec_names);
g_queue_clear(&md->codecs_prefs_recv);
g_queue_clear_full(&md->codecs_prefs_send, __payload_type_free);
g_queue_clear_full(&md->codecs_prefs_send, (GDestroyNotify) payload_type_free);
codec_handlers_free(md);
g_slice_free1(sizeof(*md), md);
}
@ -2027,7 +2027,7 @@ static struct call *call_create(const str *callid) {
c->created = rtpe_now;
c->dtls_cert = dtls_cert();
c->tos = rtpe_config.default_tos;
c->ssrc_hash = create_ssrc_hash();
c->ssrc_hash = create_ssrc_hash_call();
return c;
}

@ -201,6 +201,7 @@ struct call_monologue;
struct ice_agent;
struct ssrc_hash;
struct codec_handler;
struct rtp_payload_type;
typedef bencode_buffer_t call_buffer_t;
@ -426,7 +427,7 @@ int call_stream_address46(char *o, struct packet_stream *ps, enum stream_address
const struct transport_protocol *transport_protocol(const str *s);
void add_total_calls_duration_in_interval(struct timeval *interval_tv);
void __payload_type_free(void *p);
void payload_type_free(struct rtp_payload_type *p);
void __rtp_stats_update(GHashTable *dst, GHashTable *src);
const struct rtp_payload_type *__rtp_stats_codec(struct call_media *m);

@ -989,7 +989,7 @@ static void ng_stats_stream(bencode_item_t *list, const struct packet_stream *ps
BF_PS("ICE", ICE);
if (ps->ssrc_in)
bencode_dictionary_add_integer(dict, "SSRC", ps->ssrc_in->parent->ssrc);
bencode_dictionary_add_integer(dict, "SSRC", ps->ssrc_in->parent->h.ssrc);
stats:
if (totals->last_packet < atomic64_get(&ps->last_packet))
@ -1109,9 +1109,9 @@ static void ng_stats_ssrc(bencode_item_t *dict, struct ssrc_hash *ht) {
GList *ll = g_hash_table_get_values(ht->ht);
for (GList *l = ll; l; l = l->next) {
struct ssrc_entry *se = l->data;
struct ssrc_entry_call *se = l->data;
char *tmp = bencode_buffer_alloc(dict->buffer, 12);
snprintf(tmp, 12, "%" PRIu32, se->ssrc);
snprintf(tmp, 12, "%" PRIu32, se->h.ssrc);
bencode_item_t *ent = bencode_dictionary_add_dictionary(dict, tmp);
if (!se->stats_blocks.length || !se->lowest_mos || !se->highest_mos)

@ -210,7 +210,7 @@ static struct rtp_payload_type *codec_add_payload_type(const str *codec, struct
ilog(LOG_WARN, "Ran out of RTP payload type numbers while adding codec '"
STR_FORMAT "' for transcoding",
STR_FMT(codec));
__payload_type_free(pt);
payload_type_free(pt);
return NULL;
}
}
@ -239,7 +239,7 @@ static struct rtp_payload_type *__rtp_payload_type_add_recv(struct call_media *m
struct rtp_payload_type *existing_pt;
if ((existing_pt = g_hash_table_lookup(media->codecs, &pt->payload_type))) {
// collision/duplicate - ignore
__payload_type_free(pt);
payload_type_free(pt);
return existing_pt;
}
g_hash_table_replace(media->codecs, &pt->payload_type, pt);
@ -275,7 +275,7 @@ static void __rtp_payload_type_add(struct call_media *media, struct call_media *
static void __payload_queue_free(void *qq) {
GQueue *q = qq;
g_queue_free_full(q, __payload_type_free);
g_queue_free_full(q, (GDestroyNotify) payload_type_free);
}
static int __revert_codec_strip(GHashTable *removed, const str *codec,
struct call_media *media, struct call_media *other_media) {
@ -305,7 +305,7 @@ void codec_rtp_payload_types(struct call_media *media, struct call_media *other_
// start fresh
g_queue_clear(&media->codecs_prefs_recv);
g_queue_clear_full(&other_media->codecs_prefs_send, __payload_type_free);
g_queue_clear_full(&other_media->codecs_prefs_send, (GDestroyNotify) payload_type_free);
g_hash_table_remove_all(media->codecs);
g_hash_table_remove_all(media->codec_names);

@ -1028,7 +1028,7 @@ void kernelize(struct packet_stream *stream) {
__re_address_translate_ep(&reti.dst_addr, &sink->endpoint);
__re_address_translate_ep(&reti.src_addr, &sink->selected_sfd->socket.local);
reti.ssrc = stream->ssrc_in ? htonl(stream->ssrc_in->parent->ssrc) : 0;
reti.ssrc = stream->ssrc_in ? htonl(stream->ssrc_in->parent->h.ssrc) : 0;
stream->handler->in->kernel(&reti.decrypt, stream);
stream->handler->out->kernel(&reti.encrypt, sink);
@ -1171,7 +1171,7 @@ static void __stream_ssrc(struct packet_stream *in_srtp, struct packet_stream *o
mutex_lock(&in_srtp->in_lock);
(*ssrc_in_p) = in_srtp->ssrc_in;
if (G_UNLIKELY(!(*ssrc_in_p) || (*ssrc_in_p)->parent->ssrc != ssrc)) {
if (G_UNLIKELY(!(*ssrc_in_p) || (*ssrc_in_p)->parent->h.ssrc != ssrc)) {
// SSRC mismatch - get the new entry
(*ssrc_in_p) = in_srtp->ssrc_in =
get_ssrc_ctx(ssrc, ssrc_hash, SSRC_DIR_INPUT);
@ -1183,7 +1183,7 @@ static void __stream_ssrc(struct packet_stream *in_srtp, struct packet_stream *o
mutex_lock(&out_srtp->out_lock);
(*ssrc_out_p) = out_srtp->ssrc_out;
if (G_UNLIKELY(!(*ssrc_out_p) || (*ssrc_out_p)->parent->ssrc != ssrc)) {
if (G_UNLIKELY(!(*ssrc_out_p) || (*ssrc_out_p)->parent->h.ssrc != ssrc)) {
// SSRC mismatch - get the new entry
(*ssrc_out_p) = out_srtp->ssrc_out =
get_ssrc_ctx(ssrc, ssrc_hash, SSRC_DIR_OUTPUT);

@ -1243,7 +1243,7 @@ static int json_medias(struct call *c, struct redis_list *medias, JsonReader *ro
med = uid_slice_alloc0(med, &c->medias);
med->call = c;
med->codecs = g_hash_table_new_full(g_int_hash, g_int_equal, NULL,
__payload_type_free);
(GDestroyNotify) payload_type_free);
if (redis_hash_get_unsigned(&med->index, rh, "index"))
return -1;
@ -1467,7 +1467,7 @@ static int json_build_ssrc(struct call *c, JsonReader *root_reader) {
return -1;
u_int32_t ssrc = json_reader_get_ll(root_reader, "ssrc");
struct ssrc_entry *se = get_ssrc(ssrc, c->ssrc_hash);
struct ssrc_entry_call *se = get_ssrc(ssrc, c->ssrc_hash);
se->input_ctx.srtp_index = json_reader_get_ll(root_reader, "in_srtp_index");
se->input_ctx.srtcp_index = json_reader_get_ll(root_reader, "in_srtcp_index");
se->output_ctx.srtp_index = json_reader_get_ll(root_reader, "out_srtp_index");
@ -2068,10 +2068,10 @@ char* redis_encode_json(struct call *c) {
json_builder_set_member_name(builder, "ssrc_table");
json_builder_begin_array (builder);
for (m = k; m; m = m->next) {
struct ssrc_entry *se = m->data;
struct ssrc_entry_call *se = m->data;
json_builder_begin_object (builder);
JSON_SET_SIMPLE("ssrc","%" PRIu32, se->ssrc);
JSON_SET_SIMPLE("ssrc","%" PRIu32, se->h.ssrc);
// XXX use function for in/out
JSON_SET_SIMPLE("in_srtp_index","%" PRIu64, se->input_ctx.srtp_index);
JSON_SET_SIMPLE("in_srtcp_index","%" PRIu64, se->input_ctx.srtcp_index);

@ -6,20 +6,23 @@
static void init_ssrc_ctx(struct ssrc_ctx *c, struct ssrc_entry *parent) {
static void init_ssrc_ctx(struct ssrc_ctx *c, struct ssrc_entry_call *parent) {
c->parent = parent;
}
static struct ssrc_entry *create_ssrc_entry(u_int32_t ssrc) {
struct ssrc_entry *ent;
ent = g_slice_alloc0(sizeof(struct ssrc_entry));
static void init_ssrc_entry(struct ssrc_entry *ent, u_int32_t ssrc) {
ent->ssrc = ssrc;
mutex_init(&ent->lock);
}
static struct ssrc_entry *create_ssrc_entry_call(void *uptr) {
struct ssrc_entry_call *ent;
ent = g_slice_alloc0(sizeof(*ent));
ent->payload_type = -1;
init_ssrc_ctx(&ent->input_ctx, ent);
init_ssrc_ctx(&ent->output_ctx, ent);
return ent;
return &ent->h;
}
static void add_ssrc_entry(struct ssrc_entry *ent, struct ssrc_hash *ht) {
static void add_ssrc_entry(u_int32_t ssrc, struct ssrc_entry *ent, struct ssrc_hash *ht) {
init_ssrc_entry(ent, ssrc);
g_hash_table_replace(ht->ht, &ent->ssrc, ent);
g_queue_push_tail(&ht->q, ent);
}
@ -32,7 +35,7 @@ static void free_rr_time(struct ssrc_rr_time_item *i) {
static void free_stats_block(struct ssrc_stats_block *ssb) {
g_slice_free1(sizeof(*ssb), ssb);
}
static void free_ssrc_entry(struct ssrc_entry *e) {
static void free_ssrc_entry_call(struct ssrc_entry_call *e) {
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);
@ -58,13 +61,18 @@ static void mos_calc(struct ssrc_stats_block *ssb) {
ssb->mos = intmos;
}
struct ssrc_entry *find_ssrc(u_int32_t ssrc, struct ssrc_hash *ht) {
static struct ssrc_entry *find_ssrc(u_int32_t ssrc, struct ssrc_hash *ht) {
rwlock_lock_r(&ht->lock);
struct ssrc_entry *ret = g_hash_table_lookup(ht->ht, &ssrc);
struct ssrc_entry *ret = g_atomic_pointer_get(&ht->cache);
if (!ret || ret->ssrc != ssrc) {
ret = g_hash_table_lookup(ht->ht, &ssrc);
if (ret)
g_atomic_pointer_set(&ht->cache, ret);
}
rwlock_unlock_r(&ht->lock);
return ret;
}
struct ssrc_entry *get_ssrc(u_int32_t ssrc, struct ssrc_hash *ht /* , int *created */) {
void *get_ssrc(u_int32_t ssrc, struct ssrc_hash *ht /* , int *created */) {
struct ssrc_entry *ent;
restart:
@ -75,7 +83,19 @@ restart:
return ent;
}
ent = create_ssrc_entry(ssrc);
// use precreated entry if possible
while (1) {
ent = g_atomic_pointer_get(&ht->precreat);
if (!ent)
break; // create one ourselves
if (g_atomic_pointer_compare_and_exchange(&ht->precreat, ent, NULL))
break;
// something got in the way - retry
}
if (G_UNLIKELY(!ent))
ent = ht->create_func(ht->uptr);
if (G_UNLIKELY(!ent))
return NULL;
rwlock_lock_w(&ht->lock);
@ -84,18 +104,30 @@ restart:
ilog(LOG_DEBUG, "SSRC hash table exceeded size limit (trying to add %u) - deleting SSRC %u",
ssrc, old_ent->ssrc);
g_hash_table_remove(ht->ht, &old_ent->ssrc);
g_atomic_pointer_set(&ht->cache, NULL);
}
if (g_hash_table_lookup(ht->ht, &ssrc)) {
// preempted
rwlock_unlock_w(&ht->lock);
free_ssrc_entry(ent);
// return created entry if slot is still empty
if (!g_atomic_pointer_compare_and_exchange(&ht->precreat, NULL, ent))
ht->destroy_func(ent);
goto restart;
}
add_ssrc_entry(ent, ht);
add_ssrc_entry(ssrc, ent, ht);
g_atomic_pointer_set(&ht->cache, ent);
rwlock_unlock_w(&ht->lock);
// if (created)
// *created = 1;
// keep entry filled for next SSRC
if (g_atomic_pointer_get(&ht->precreat) == NULL) {
struct ssrc_entry *nextent = ht->create_func(ht->uptr);
if (!g_atomic_pointer_compare_and_exchange(&ht->precreat, NULL, nextent))
ht->destroy_func(nextent);
}
return ent;
}
void free_ssrc_hash(struct ssrc_hash **ht) {
@ -103,18 +135,27 @@ void free_ssrc_hash(struct ssrc_hash **ht) {
return;
g_hash_table_destroy((*ht)->ht);
g_queue_clear(&(*ht)->q);
if ((*ht)->precreat)
(*ht)->destroy_func((void *) (*ht)->precreat);
g_slice_free1(sizeof(**ht), *ht);
*ht = NULL;
}
struct ssrc_hash *create_ssrc_hash(void) {
struct ssrc_hash *create_ssrc_hash_full(ssrc_create_func_t cfunc, ssrc_free_func_t ffunc, void *uptr) {
struct ssrc_hash *ret;
ret = g_slice_alloc0(sizeof(*ret));
ret->ht = g_hash_table_new_full(uint32_hash, uint32_eq, NULL, (GDestroyNotify) free_ssrc_entry);
ret->ht = g_hash_table_new_full(uint32_hash, uint32_eq, NULL, (GDestroyNotify) ffunc);
rwlock_init(&ret->lock);
ret->create_func = cfunc;
ret->destroy_func = ffunc;
ret->uptr = uptr;
ret->precreat = cfunc(uptr); // because object creation might be slow
return ret;
}
struct ssrc_hash *create_ssrc_hash_call(void) {
return create_ssrc_hash_full(create_ssrc_entry_call, (ssrc_free_func_t) free_ssrc_entry_call, NULL);
}
struct ssrc_ctx *get_ssrc_ctx(u_int32_t ssrc, struct ssrc_hash *ht, enum ssrc_dir dir) {
struct ssrc_entry *s = get_ssrc(ssrc, ht /* , NULL */);
@ -165,7 +206,7 @@ static long long __calc_rtt(struct call *c, u_int32_t ssrc, u_int32_t ntp_middle
if (!ntp_middle_bits || !delay)
return 0;
struct ssrc_entry *e = get_ssrc(ssrc, c->ssrc_hash);
struct ssrc_entry_call *e = get_ssrc(ssrc, c->ssrc_hash);
if (G_UNLIKELY(!e))
return 0;
@ -174,7 +215,7 @@ static long long __calc_rtt(struct call *c, u_int32_t ssrc, u_int32_t ntp_middle
struct ssrc_time_item *sti;
GQueue *q = (((void *) e) + reports_queue_offset);
mutex_lock(&e->lock);
mutex_lock(&e->h.lock);
// go through the list backwards until we find the SR referenced
for (GList *l = q->tail; l; l = l->prev) {
sti = l->data;
@ -184,14 +225,14 @@ static long long __calc_rtt(struct call *c, u_int32_t ssrc, u_int32_t ntp_middle
}
// not found
mutex_unlock(&e->lock);
mutex_unlock(&e->h.lock);
return 0;
found:;
// `e` remains locked for access to `sti`
long long rtt = timeval_diff(tv, &sti->received);
mutex_unlock(&e->lock);
mutex_unlock(&e->h.lock);
rtt -= (long long) delay * 1000000LL / 65536LL;
ilog(LOG_DEBUG, "Calculated round-trip time for %u is %lli us", ssrc, rtt);
@ -211,7 +252,7 @@ void ssrc_sender_report(struct call_media *m, const struct ssrc_sender_report *s
{
struct ssrc_entry *e;
struct ssrc_sender_report_item *seri = __do_time_report_item(m, sizeof(*seri),
G_STRUCT_OFFSET(struct ssrc_entry, sender_reports), tv, sr->ssrc,
G_STRUCT_OFFSET(struct ssrc_entry_call, sender_reports), tv, sr->ssrc,
sr->ntp_msw, sr->ntp_lsw, (GDestroyNotify) free_sender_report, &e);
if (!seri)
return;
@ -236,9 +277,9 @@ void ssrc_receiver_report(struct call_media *m, const struct ssrc_receiver_repor
int pt;
long long rtt = __calc_rtt(c, rr->ssrc, rr->lsr, rr->dlsr,
G_STRUCT_OFFSET(struct ssrc_entry, sender_reports), tv, &pt);
G_STRUCT_OFFSET(struct ssrc_entry_call, sender_reports), tv, &pt);
struct ssrc_entry *other_e = get_ssrc(rr->from, c->ssrc_hash);
struct ssrc_entry_call *other_e = get_ssrc(rr->from, c->ssrc_hash);
if (G_UNLIKELY(!other_e))
goto out_nl;
@ -273,7 +314,7 @@ void ssrc_receiver_report(struct call_media *m, const struct ssrc_receiver_repor
ilog(LOG_DEBUG, "Calculated MOS from RR for %u is %.1f", rr->from, (double) ssb->mos / 10.0);
// got a new stats block, add it to reporting ssrc
mutex_lock(&other_e->lock);
mutex_lock(&other_e->h.lock);
// discard stats block if last has been received less than a second ago
if (G_LIKELY(other_e->stats_blocks.length > 0)) {
@ -300,7 +341,7 @@ void ssrc_receiver_report(struct call_media *m, const struct ssrc_receiver_repor
goto out_ul_oe;
out_ul_oe:
mutex_unlock(&other_e->lock);
mutex_unlock(&other_e->h.lock);
goto out_nl;
out_nl:
;
@ -311,7 +352,7 @@ void ssrc_receiver_rr_time(struct call_media *m, const struct ssrc_xr_rr_time *r
{
struct ssrc_entry *e;
struct ssrc_rr_time_item *srti = __do_time_report_item(m, sizeof(*srti),
G_STRUCT_OFFSET(struct ssrc_entry, rr_time_reports), tv, rr->ssrc,
G_STRUCT_OFFSET(struct ssrc_entry_call, rr_time_reports), tv, rr->ssrc,
rr->ntp_msw, rr->ntp_lsw, (GDestroyNotify) free_rr_time, &e);
if (!srti)
return;
@ -331,7 +372,7 @@ void ssrc_receiver_dlrr(struct call_media *m, const struct ssrc_xr_dlrr *dlrr,
dlrr->lrr, dlrr->dlrr);
__calc_rtt(m->call, dlrr->ssrc, dlrr->lrr, dlrr->dlrr,
G_STRUCT_OFFSET(struct ssrc_entry, rr_time_reports), tv, NULL);
G_STRUCT_OFFSET(struct ssrc_entry_call, rr_time_reports), tv, NULL);
}
void ssrc_voip_metrics(struct call_media *m, const struct ssrc_xr_voip_metrics *vm,
@ -348,7 +389,7 @@ void ssrc_voip_metrics(struct call_media *m, const struct ssrc_xr_voip_metrics *
vm->jb_max, vm->jb_abs_max);
struct call *c = m->call;
struct ssrc_entry *e = get_ssrc(vm->ssrc, c->ssrc_hash);
struct ssrc_entry_call *e = get_ssrc(vm->ssrc, c->ssrc_hash);
if (!e)
return;
e->last_rtt = vm->rnd_trip_delay;

@ -15,17 +15,27 @@ struct call_media;
struct timeval;
struct rtp_payload_type;
struct ssrc_entry;
struct ssrc_entry_call;
enum ssrc_dir;
typedef struct ssrc_entry *(*ssrc_create_func_t)(void *uptr);
typedef void (*ssrc_free_func_t)(struct ssrc_entry *);
struct ssrc_hash {
GHashTable *ht;
GQueue q;
rwlock_t lock;
ssrc_create_func_t create_func;
void *uptr;
ssrc_free_func_t destroy_func;
volatile struct ssrc_entry *cache; // last used entry
volatile struct ssrc_entry *precreat; // next used entry
};
struct ssrc_ctx {
struct ssrc_entry *parent;
struct ssrc_entry_call *parent;
// XXX lock this?
u_int64_t srtp_index,
srtcp_index;
@ -43,6 +53,10 @@ struct ssrc_stats_block {
struct ssrc_entry {
mutex_t lock;
u_int32_t ssrc;
};
struct ssrc_entry_call {
struct ssrc_entry h; // must be first
struct ssrc_ctx input_ctx,
output_ctx;
GQueue sender_reports; // as received via RTCP
@ -55,8 +69,8 @@ struct ssrc_entry {
unsigned int last_rtt; // last calculated raw rtt without rtt from opposide side
};
enum ssrc_dir { // these values must not be used externally
SSRC_DIR_INPUT = G_STRUCT_OFFSET(struct ssrc_entry, input_ctx),
SSRC_DIR_OUTPUT = G_STRUCT_OFFSET(struct ssrc_entry, output_ctx),
SSRC_DIR_INPUT = G_STRUCT_OFFSET(struct ssrc_entry_call, input_ctx),
SSRC_DIR_OUTPUT = G_STRUCT_OFFSET(struct ssrc_entry_call, output_ctx),
};
struct ssrc_time_item {
@ -137,11 +151,12 @@ struct ssrc_xr_voip_metrics {
void free_ssrc_hash(struct ssrc_hash **);
struct ssrc_hash *create_ssrc_hash(void);
struct ssrc_hash *create_ssrc_hash_full(ssrc_create_func_t, ssrc_free_func_t, void *uptr);
struct ssrc_hash *create_ssrc_hash_call(void);
void *get_ssrc(u_int32_t, struct ssrc_hash * /* , int *created */); // creates new entry if not found
struct ssrc_entry *find_ssrc(u_int32_t, struct ssrc_hash *); // returns NULL if not found
struct ssrc_entry *get_ssrc(u_int32_t, struct ssrc_hash * /* , int *created */); // creates new entry if not found
//struct ssrc_entry *create_ssrc_entry(u_int32_t);
struct ssrc_ctx *get_ssrc_ctx(u_int32_t, struct ssrc_hash *, enum ssrc_dir); // creates new entry if not found

Loading…
Cancel
Save