|
|
|
@ -1497,9 +1497,7 @@ INLINE void __re_address_translate_ep(struct re_address *o, const endpoint_t *ep |
|
|
|
ep->address.family->endpoint2kernel(o, ep); |
|
|
|
} |
|
|
|
|
|
|
|
static int __rtp_stats_pt_sort(const void *ap, const void *bp) { |
|
|
|
const struct rtp_stats *a = ap, *b = bp; |
|
|
|
|
|
|
|
static int __rtp_stats_pt_sort(const struct rtp_stats *a, const struct rtp_stats *b) { |
|
|
|
if (a->payload_type < b->payload_type) |
|
|
|
return -1; |
|
|
|
if (a->payload_type > b->payload_type) |
|
|
|
@ -1516,7 +1514,7 @@ static int __rtp_stats_pt_sort(const void *ap, const void *bp) { |
|
|
|
*/ |
|
|
|
static const char *kernelize_one(struct rtpengine_target_info *reti, GQueue *outputs, |
|
|
|
struct packet_stream *stream, struct sink_handler *sink_handler, sink_handler_q *sinks, |
|
|
|
GList **payload_types) |
|
|
|
rtp_stats_arr **payload_types) |
|
|
|
{ |
|
|
|
struct rtpengine_destination_info *redi = NULL; |
|
|
|
call_t *call = stream->call; |
|
|
|
@ -1608,19 +1606,24 @@ static const char *kernelize_one(struct rtpengine_target_info *reti, GQueue *out |
|
|
|
} |
|
|
|
|
|
|
|
if (reti->rtp && sinks && sinks->length && payload_types) { |
|
|
|
GList *l; |
|
|
|
struct rtp_stats *rs; |
|
|
|
|
|
|
|
// this code is execute only once: list therefore must be empty |
|
|
|
assert(*payload_types == NULL); |
|
|
|
*payload_types = g_hash_table_get_values(stream->rtp_stats); |
|
|
|
*payload_types = g_list_sort(*payload_types, __rtp_stats_pt_sort); |
|
|
|
for (l = *payload_types; l; ) { |
|
|
|
// create sorted list of payload types |
|
|
|
*payload_types = rtp_stats_arr_new_sized(t_hash_table_size(stream->rtp_stats)); |
|
|
|
rtp_stats_ht_iter iter; |
|
|
|
t_hash_table_iter_init(&iter, stream->rtp_stats); |
|
|
|
unsigned int i = 0; |
|
|
|
while (t_hash_table_iter_next(&iter, NULL, &rs)) |
|
|
|
(*payload_types)->pdata[i++] = rs; |
|
|
|
t_ptr_array_sort(*payload_types, __rtp_stats_pt_sort); |
|
|
|
for (i = 0; i < (*payload_types)->len; i++) { |
|
|
|
if (reti->num_payload_types >= G_N_ELEMENTS(reti->pt_stats)) { |
|
|
|
ilog(LOG_WARNING | LOG_FLAG_LIMIT, "Too many RTP payload types for kernel module"); |
|
|
|
break; |
|
|
|
} |
|
|
|
rs = l->data; |
|
|
|
rs = (*payload_types)->pdata[i]; |
|
|
|
// only add payload types that are passthrough for all sinks |
|
|
|
bool can_kernelize = true; |
|
|
|
for (__auto_type k = sinks->head; k; k = k->next) { |
|
|
|
@ -1637,16 +1640,12 @@ static const char *kernelize_one(struct rtpengine_target_info *reti, GQueue *out |
|
|
|
reti->pt_filter = 1; |
|
|
|
// ensure that the final list in *payload_types reflects the payload |
|
|
|
// types populated in reti->payload_types |
|
|
|
GList *next = l->next; |
|
|
|
*payload_types = g_list_delete_link(*payload_types, l); |
|
|
|
l = next; |
|
|
|
t_ptr_array_remove_index(*payload_types, i); |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
reti->pt_stats[reti->num_payload_types] = rs; |
|
|
|
reti->num_payload_types++; |
|
|
|
|
|
|
|
l = l->next; |
|
|
|
} |
|
|
|
} |
|
|
|
else { |
|
|
|
@ -1673,10 +1672,9 @@ output: |
|
|
|
|| sink_handler->attrs.silence_media; |
|
|
|
bool manipulate_pt = silenced || ML_ISSET(media->monologue, BLOCK_SHORT); |
|
|
|
if (manipulate_pt && payload_types) { |
|
|
|
int i = 0; |
|
|
|
for (GList *l = *payload_types; l; l = l->next) { |
|
|
|
struct rtp_stats *rs = l->data; |
|
|
|
struct rtpengine_pt_output *rpt = &redi->output.pt_output[i++]; |
|
|
|
for (unsigned int i = 0; i < (*payload_types)->len; i++) { |
|
|
|
__auto_type rs = (*payload_types)->pdata[i]; |
|
|
|
struct rtpengine_pt_output *rpt = &redi->output.pt_output[i]; |
|
|
|
struct codec_handler *ch = codec_handler_get(media, rs->payload_type, |
|
|
|
sink->media, sink_handler); |
|
|
|
|
|
|
|
@ -1746,7 +1744,7 @@ output: |
|
|
|
// helper function for kernelize() |
|
|
|
static void kernelize_one_sink_handler(struct rtpengine_target_info *reti, GQueue *outputs, |
|
|
|
struct packet_stream *stream, struct sink_handler *sink_handler, sink_handler_q *sinks, |
|
|
|
GList **payload_types) |
|
|
|
rtp_stats_arr **payload_types) |
|
|
|
{ |
|
|
|
struct packet_stream *sink = sink_handler->sink; |
|
|
|
if (PS_ISSET(sink, NAT_WAIT) && !PS_ISSET(sink, RECEIVED)) |
|
|
|
@ -1761,6 +1759,7 @@ void kernelize(struct packet_stream *stream) { |
|
|
|
call_t *call = stream->call; |
|
|
|
const char *nk_warn_msg; |
|
|
|
struct call_media *media = stream->media; |
|
|
|
g_autoptr(rtp_stats_arr) payload_types = NULL; |
|
|
|
|
|
|
|
if (PS_ISSET(stream, KERNELIZED)) |
|
|
|
return; |
|
|
|
@ -1784,7 +1783,6 @@ void kernelize(struct packet_stream *stream) { |
|
|
|
struct rtpengine_target_info reti; |
|
|
|
ZERO(reti); // reti.local.family determines if anything can be done |
|
|
|
GQueue outputs = G_QUEUE_INIT; |
|
|
|
GList *payload_types = NULL; |
|
|
|
|
|
|
|
unsigned int num_sinks = stream->rtp_sinks.length + stream->rtcp_sinks.length; |
|
|
|
|
|
|
|
@ -1816,8 +1814,6 @@ void kernelize(struct packet_stream *stream) { |
|
|
|
reti.num_rtcp_destinations = reti.num_destinations - num_rtp_dests; |
|
|
|
} |
|
|
|
|
|
|
|
g_list_free(payload_types); |
|
|
|
|
|
|
|
if (!reti.local.family) |
|
|
|
goto no_kernel; |
|
|
|
|
|
|
|
@ -2248,7 +2244,7 @@ static void media_packet_rtp_in(struct packet_handler_ctx *phc) |
|
|
|
// XXX yet another hash table per payload type -> combine |
|
|
|
struct rtp_stats *rtp_s = g_atomic_pointer_get(&phc->mp.stream->rtp_stats_cache); |
|
|
|
if (G_UNLIKELY(!rtp_s) || G_UNLIKELY(rtp_s->payload_type != phc->payload_type)) |
|
|
|
rtp_s = g_hash_table_lookup(phc->mp.stream->rtp_stats, |
|
|
|
rtp_s = t_hash_table_lookup(phc->mp.stream->rtp_stats, |
|
|
|
GUINT_TO_POINTER(phc->payload_type)); |
|
|
|
if (!rtp_s) { |
|
|
|
ilog(LOG_WARNING | LOG_FLAG_LIMIT, |
|
|
|
|