diff --git a/daemon/media_socket.c b/daemon/media_socket.c index bf5d5d6f5..e1283cfe4 100644 --- a/daemon/media_socket.c +++ b/daemon/media_socket.c @@ -1538,11 +1538,17 @@ INLINE void __re_address_translate_ep(struct re_address *o, const endpoint_t *ep ep->address.family->endpoint2kernel(o, ep); } + +struct kernel_pt { + struct rtp_stats *stats; + struct packet_stream *stream; +}; + static int __rtp_stats_pt_sort(const void *A, const void *B) { - const struct rtp_stats *const *a = A, *const *b = B; - if ((*a)->payload_type < (*b)->payload_type) + const struct kernel_pt *a = A, *b = B; + if (a->stats->payload_type < b->stats->payload_type) return -1; - if ((*a)->payload_type > (*b)->payload_type) + if (a->stats->payload_type > b->stats->payload_type) return 1; return 0; } @@ -1557,8 +1563,7 @@ struct kernelize_state { sink_handler_q *rtp_sinks[RTPE_NUM_OUTPUT_MEDIA]; sink_handler_q *rtp_mirrors[RTPE_NUM_OUTPUT_MEDIA]; sink_handler_q *rtcp_sinks[RTPE_NUM_OUTPUT_MEDIA]; - struct rtp_stats *payload_types[RTPE_NUM_PAYLOAD_TYPES]; - struct packet_stream *pt_streams[RTPE_NUM_PAYLOAD_TYPES]; + struct kernel_pt pts[RTPE_NUM_PAYLOAD_TYPES]; unsigned int num_payload_types; bool blackhole; bool non_forwarding; @@ -1574,13 +1579,36 @@ static void kernelize_state_clear(kernelize_state *s) { G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(kernelize_state, kernelize_state_clear) -static void fill_pt_stats(kernelize_state *s, struct packet_stream *stream) { +__attribute__((nonnull(1, 2))) +static void fill_bundle_pt_stats(kernelize_state *s, struct call_media *bundle, unsigned int component) { + pt_media_ht_iter iter; + t_hash_table_iter_init(&iter, bundle->pt_media); + void *pt; + struct call_media *pt_media; + while (t_hash_table_iter_next(&iter, &pt, &pt_media)) { + struct packet_stream *pt_ps = get_media_component(pt_media, component); + if (!pt_ps) + continue; // log as error? + __auto_type rs = t_hash_table_lookup(pt_ps->rtp_stats, pt); + if (!rs) + continue; // log as error? + s->pts[s->num_payload_types].stream = pt_ps; + s->pts[s->num_payload_types++].stats = rs; + } +} + +static void fill_pt_stats(kernelize_state *s, struct packet_stream *stream, unsigned int component) { + if (stream->media->bundle) { + fill_bundle_pt_stats(s, stream->media->bundle, component); + return; + } + rtp_stats_ht_iter iter; t_hash_table_iter_init(&iter, stream->rtp_stats); struct rtp_stats *rs; while (t_hash_table_iter_next(&iter, NULL, &rs) && s->num_payload_types < RTPE_NUM_PAYLOAD_TYPES) { - s->pt_streams[s->num_payload_types] = stream; - s->payload_types[s->num_payload_types++] = rs; + s->pts[s->num_payload_types].stream = stream; + s->pts[s->num_payload_types++].stats = rs; } } @@ -1591,28 +1619,6 @@ static void fill_media_sinks(kernelize_state *s, unsigned int media_idx, struct s->rtcp_sinks[media_idx] = &ps->rtcp_sinks; } -__attribute__((nonnull(1, 2))) -static void fill_pt_bundle_media(kernelize_state *s, struct call_media *media, unsigned int component) { - if (!t_hash_table_is_set(media->pt_media)) - return; - - // reset output stream and stats for any PTs known to belong to other media - for (unsigned int i = 0; i < s->num_payload_types; i++) { - struct rtp_stats *rs = s->payload_types[i]; - __auto_type pt_media = t_hash_table_lookup(media->pt_media, GUINT_TO_POINTER(rs->payload_type)); - if (!pt_media) - continue; - if (pt_media == media) - continue; - - struct packet_stream *pt_ps = get_media_component(pt_media, component); - if (!pt_ps) - continue; // log as error? - s->pt_streams[s->num_payload_types] = pt_ps; - } - -} - __attribute__((nonnull(1, 2))) static const char *kernelize_target(kernelize_state *s, struct packet_stream *stream) { struct call_media *media = stream->media; @@ -1729,8 +1735,7 @@ static const char *kernelize_target(kernelize_state *s, struct packet_stream *st s->num_payload_types = 0; - fill_pt_stats(s, stream); - fill_pt_bundle_media(s, media, stream->component); + fill_pt_stats(s, stream, stream->component); if (!s->num_payload_types) { // set single output @@ -1738,17 +1743,17 @@ static const char *kernelize_target(kernelize_state *s, struct packet_stream *st return NULL; } - qsort(s->payload_types, s->num_payload_types, sizeof(*s->payload_types), + qsort(s->pts, s->num_payload_types, sizeof(s->pts[0]), __rtp_stats_pt_sort); unsigned int i = 0; while (i < s->num_payload_types) { - struct rtp_stats *rs = s->payload_types[i]; + struct rtp_stats *rs = s->pts[i].stats; // only add payload types that are passthrough for all sinks bool can_kernelize = true; // set sinks for this media - struct packet_stream *pt_stream = s->pt_streams[i]; + struct packet_stream *pt_stream = s->pts[i].stream; struct call_media *stream_media = pt_stream->media; unsigned int media_idx = stream_media->index - 1; @@ -1779,8 +1784,8 @@ static const char *kernelize_target(kernelize_state *s, struct packet_stream *st reti->pt_filter = 1; // ensure that the final list in *payload_types reflects the payload // types populated in reti->payload_types - memmove(s->payload_types + i, s->payload_types + i + 1, - sizeof(*s->payload_types) * (s->num_payload_types - i - 1)); + memmove(s->pts + i, s->pts + i + 1, + sizeof(s->pts[0]) * (s->num_payload_types - i - 1)); s->num_payload_types--; continue; } @@ -1851,7 +1856,7 @@ static const char *kernelize_one(kernelize_state *s, bool silenced = s->silenced || sink_handler->attrs.silence_media; if (s->manipulate_pt) { for (unsigned int i = 0; i < s->num_payload_types; i++) { - __auto_type rs = s->payload_types[i]; + __auto_type rs = s->pts[i].stats; 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);