diff --git a/daemon/call.c b/daemon/call.c index 744b950de..8b6097ad2 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -1353,11 +1353,12 @@ void free_sink_handler(void *p) { struct sink_handler *sh = p; g_slice_free1(sizeof(*sh), sh); } -void __add_sink_handler(GQueue *q, struct packet_stream *sink, bool rtcp_only) { +void __add_sink_handler(GQueue *q, struct packet_stream *sink, bool rtcp_only, bool transcoding) { struct sink_handler *sh = g_slice_alloc0(sizeof(*sh)); sh->sink = sink; sh->kernel_output_idx = -1; sh->rtcp_only = rtcp_only ? 1 : 0; + sh->transcoding = transcoding ? 1 : 0; g_queue_push_tail(q, sh); } @@ -1373,7 +1374,7 @@ static void __reset_streams(struct call_media *media) { // B can be NULL // XXX this function seems to do two things - stream init (with B NULL) and sink init - split up? static int __init_streams(struct call_media *A, struct call_media *B, const struct stream_params *sp, - const struct sdp_ng_flags *flags, bool rtcp_only) { + const struct sdp_ng_flags *flags, bool rtcp_only, bool transcoding) { GList *la, *lb; struct packet_stream *a, *ax, *b; unsigned int port_off = 0; @@ -1395,9 +1396,9 @@ static int __init_streams(struct call_media *A, struct call_media *B, const stru // we get SSRC flip-flops on the opposite side // XXX still necessary for blackhole? if (MEDIA_ISSET(A, ECHO) || MEDIA_ISSET(A, BLACKHOLE)) - __add_sink_handler(&a->rtp_sinks, a, rtcp_only); + __add_sink_handler(&a->rtp_sinks, a, rtcp_only, transcoding); else if (b) - __add_sink_handler(&a->rtp_sinks, b, rtcp_only); + __add_sink_handler(&a->rtp_sinks, b, rtcp_only, transcoding); PS_SET(a, RTP); /* XXX technically not correct, could be udptl too */ __rtp_stats_update(a->rtp_stats, &A->codecs); @@ -1434,7 +1435,7 @@ static int __init_streams(struct call_media *A, struct call_media *B, const stru if (MEDIA_ISSET(A, ECHO) || MEDIA_ISSET(A, BLACKHOLE)) { /* RTCP sink handler added below */ } else if (b) - __add_sink_handler(&a->rtcp_sinks, b, rtcp_only); + __add_sink_handler(&a->rtcp_sinks, b, rtcp_only, transcoding); PS_SET(a, RTCP); PS_CLEAR(a, IMPLICIT_RTCP); } @@ -1448,12 +1449,12 @@ static int __init_streams(struct call_media *A, struct call_media *B, const stru a = la->data; if (MEDIA_ISSET(A, ECHO) || MEDIA_ISSET(A, BLACKHOLE)) { - __add_sink_handler(&a->rtcp_sinks, a, rtcp_only); + __add_sink_handler(&a->rtcp_sinks, a, rtcp_only, transcoding); if (MEDIA_ISSET(A, RTCP_MUX)) - __add_sink_handler(&ax->rtcp_sinks, a, rtcp_only); + __add_sink_handler(&ax->rtcp_sinks, a, rtcp_only, transcoding); } else if (b) - __add_sink_handler(&a->rtcp_sinks, b, rtcp_only); + __add_sink_handler(&a->rtcp_sinks, b, rtcp_only, transcoding); PS_CLEAR(a, RTP); PS_SET(a, RTCP); a->rtcp_sibling = NULL; @@ -2373,6 +2374,22 @@ static void __update_media_protocol(struct call_media *media, struct call_media } } +static struct call_subscription *find_subscription(struct call_monologue *ml, struct call_monologue *sub) { + for (GList *l = ml->subscribers.head; l; l = l->next) { + struct call_subscription *cs = l->data; + if (cs->monologue == sub) + return cs; + } + return NULL; +} + +static void set_transcoding_flag(struct call_monologue *ml, struct call_monologue *sub, bool flag) { + struct call_subscription *cs = find_subscription(ml, sub); + if (!cs) + return; + cs->transcoding = flag ? 1 : 0; +} + void codecs_offer_answer(struct call_media *media, struct call_media *other_media, struct stream_params *sp, struct sdp_ng_flags *flags) { @@ -2437,7 +2454,8 @@ void codecs_offer_answer(struct call_media *media, struct call_media *other_medi codec_tracker_update(&media->codecs); // finally set up handlers again based on final results - codec_handlers_update(media, other_media, flags, sp); + if (codec_handlers_update(media, other_media, flags, sp)) + set_transcoding_flag(media->monologue, other_media->monologue, true); } else { // answer @@ -2471,8 +2489,10 @@ void codecs_offer_answer(struct call_media *media, struct call_media *other_medi codec_tracker_update(&other_media->codecs); // finally set up handlers again based on final results - codec_handlers_update(media, other_media, flags, sp); - codec_handlers_update(other_media, media, NULL, NULL); + if (codec_handlers_update(media, other_media, flags, sp)) + set_transcoding_flag(media->monologue, other_media->monologue, true); + if (codec_handlers_update(other_media, media, NULL, NULL)) + set_transcoding_flag(other_media->monologue, media->monologue, true); } } @@ -2486,6 +2506,7 @@ static void __update_init_subscribers(struct call_monologue *ml, GQueue *streams // create media iterators for all subscribers GList *sub_medias[ml->subscribers.length]; bool subs_rtcp_only[ml->subscribers.length]; + bool subs_tc[ml->subscribers.length]; unsigned int num_subs = 0; for (GList *l = ml->subscribers.head; l; l = l->next) { struct call_subscription *cs = l->data; @@ -2495,6 +2516,7 @@ static void __update_init_subscribers(struct call_monologue *ml, GQueue *streams for (unsigned int offset = cs->media_offset; offset && sub_medias[num_subs]; offset--) sub_medias[num_subs] = sub_medias[num_subs]->next; subs_rtcp_only[num_subs] = cs->rtcp_only ? true : false; + subs_tc[num_subs] = cs->transcoding ? true : false; num_subs++; } // keep num_subs as shortcut to ml->subscribers.length @@ -2521,8 +2543,9 @@ static void __update_init_subscribers(struct call_monologue *ml, GQueue *streams struct call_media *sub_media = sub_medias[i]->data; sub_medias[i] = sub_medias[i]->next; bool rtcp_only = subs_rtcp_only[i]; + bool tc = subs_tc[i]; - if (__init_streams(media, sub_media, sp, flags, rtcp_only)) + if (__init_streams(media, sub_media, sp, flags, rtcp_only, tc)) ilog(LOG_WARN, "Error initialising streams"); } @@ -2763,6 +2786,8 @@ int monologue_offer_answer(struct call_monologue *dialogue[2], GQueue *streams, ml_media = other_ml_media = NULL; + set_transcoding_flag(monologue, other_ml, false); + for (media_iter = streams->head; media_iter; media_iter = media_iter->next) { sp = media_iter->data; __C_DBG("processing media stream #%u", sp->index); @@ -3043,7 +3068,7 @@ int monologue_publish(struct call_monologue *ml, GQueue *streams, struct sdp_ng_ __assign_stream_fds(media, &em->intf_sfds); // XXX this should be covered by __update_init_subscribers ? - if (__init_streams(media, NULL, sp, flags, false)) + if (__init_streams(media, NULL, sp, flags, false, false)) return -1; __ice_start(media); ice_update(media->ice_agent, sp, false); @@ -3108,7 +3133,7 @@ static int monologue_subscribe_request1(struct call_monologue *src_ml, struct ca __num_media_streams(dst_media, num_ports); __assign_stream_fds(dst_media, &em->intf_sfds); - if (__init_streams(dst_media, NULL, NULL, flags, false)) + if (__init_streams(dst_media, NULL, NULL, flags, false, false)) return -1; } @@ -3152,6 +3177,8 @@ int monologue_subscribe_answer(struct call_monologue *dst_ml, struct sdp_ng_flag GList *src_ml_it = dst_ml->subscriptions.head; unsigned int index = 1; // running counter for input/src medias + bool transcoding = false; + for (GList *l = streams->head; l; l = l->next) { struct stream_params *sp = l->data; @@ -3186,11 +3213,12 @@ int monologue_subscribe_answer(struct call_monologue *dst_ml, struct sdp_ng_flag } codec_handlers_update(src_media, dst_media, NULL, NULL); - codec_handlers_update(dst_media, src_media, flags, sp); + if (codec_handlers_update(dst_media, src_media, flags, sp)) + transcoding = true; __dtls_logic(flags, dst_media, sp); - if (__init_streams(dst_media, NULL, sp, flags, false)) + if (__init_streams(dst_media, NULL, sp, flags, false, false)) return -1; MEDIA_CLEAR(dst_media, RECV); @@ -3206,6 +3234,7 @@ int monologue_subscribe_answer(struct call_monologue *dst_ml, struct sdp_ng_flag for (GList *l = dst_ml->subscriptions.head; l; l = l->next) { struct call_subscription *cs = l->data; struct call_monologue *src_ml = cs->monologue; + set_transcoding_flag(src_ml, dst_ml, transcoding); __update_init_subscribers(src_ml, NULL, NULL, flags->opmode); dialogue_unkernelize(src_ml); } diff --git a/daemon/codec.c b/daemon/codec.c index 75f69477e..de4f73164 100644 --- a/daemon/codec.c +++ b/daemon/codec.c @@ -779,9 +779,7 @@ static void __check_t38_gateway(struct call_media *pcm_media, struct call_media } __t38_options_from_flags(&t_opts, flags); - MEDIA_SET(pcm_media, TRANSCODE); MEDIA_SET(pcm_media, GENERATOR); - MEDIA_SET(t38_media, TRANSCODE); MEDIA_SET(t38_media, GENERATOR); if (t38_gateway_pair(t38_media, pcm_media, &t_opts)) @@ -959,27 +957,28 @@ INLINE struct codec_handler *codec_handler_lookup(GHashTable *ht, int pt, struct } // call must be locked in W -void codec_handlers_update(struct call_media *receiver, struct call_media *sink, +bool codec_handlers_update(struct call_media *receiver, struct call_media *sink, const struct sdp_ng_flags *flags, const struct stream_params *sp) { ilogs(codec, LOG_DEBUG, "Setting up codec handlers for " STR_FORMAT_M " #%u -> " STR_FORMAT_M " #%u", STR_FMT_M(&receiver->monologue->tag), receiver->index, STR_FMT_M(&sink->monologue->tag), sink->index); + MEDIA_CLEAR(receiver, TRANSCODE); MEDIA_CLEAR(receiver, GENERATOR); MEDIA_CLEAR(sink, GENERATOR); // non-RTP protocol? if (proto_is(receiver->protocol, PROTO_UDPTL)) { if (codec_handler_udptl_update(receiver, sink, flags)) - return; + return true; } // everything else is unsupported: pass through if (proto_is_not_rtp(receiver->protocol)) { __generator_stop(receiver); __generator_stop(sink); codec_handlers_stop(&receiver->codec_handlers_store); - return; + return false; } if (!receiver->codec_handlers) @@ -988,7 +987,7 @@ void codec_handlers_update(struct call_media *receiver, struct call_media *sink, // should we transcode to a non-RTP protocol? if (proto_is_not_rtp(sink->protocol)) { if (codec_handler_non_rtp_update(receiver, sink, flags, sp)) - return; + return true; } // we're doing some kind of media passthrough - shut down local generators @@ -996,7 +995,7 @@ void codec_handlers_update(struct call_media *receiver, struct call_media *sink, __generator_stop(sink); codec_handlers_stop(&receiver->codec_handlers_store); - MEDIA_CLEAR(receiver, TRANSCODE); + bool is_transcoding = false; receiver->rtcp_handler = NULL; GSList *passthrough_handlers = NULL; @@ -1262,7 +1261,7 @@ transcode:; str_init_dup_str(&sink_pt->codec_opts, &reverse_pt->codec_opts); } } - MEDIA_SET(receiver, TRANSCODE); + is_transcoding = true; __make_transcoder(handler, sink_pt, output_transcoders, sink_dtmf_pt ? sink_dtmf_pt->payload_type : -1, pcm_dtmf_detect, sink_cn_pt ? sink_cn_pt->payload_type : -1); @@ -1277,7 +1276,7 @@ next: l = l->next; } - if (MEDIA_ISSET(receiver, TRANSCODE)) { + if (is_transcoding) { // we have to translate RTCP packets receiver->rtcp_handler = rtcp_transcode_handler; @@ -1319,6 +1318,11 @@ next: sink->rtcp_handler = rtcp_sink_handler; __codec_rtcp_timer(sink); } + + if (is_transcoding) + MEDIA_SET(receiver, TRANSCODE); + + return is_transcoding; } @@ -1425,7 +1429,9 @@ void mqtt_timer_stop(struct mqtt_timer **mqtp) { // call must be locked in R -struct codec_handler *codec_handler_get(struct call_media *m, int payload_type, struct call_media *sink) { +struct codec_handler *codec_handler_get(struct call_media *m, int payload_type, struct call_media *sink, + struct sink_handler *sh) +{ #ifdef WITH_TRANSCODING struct codec_handler *ret = NULL; @@ -1440,7 +1446,7 @@ struct codec_handler *codec_handler_get(struct call_media *m, int payload_type, out: if (ret) return ret; - if (MEDIA_ISSET(m, TRANSCODE)) + if (sh && sh->transcoding) return &codec_handler_stub_ssrc; #endif return &codec_handler_stub; @@ -1945,7 +1951,7 @@ static struct codec_handler *__input_handler(struct codec_handler *h, struct med if (prim_pt == 255) continue; - struct codec_handler *sequencer_h = codec_handler_get(mp->media, prim_pt, mp->media_out); + struct codec_handler *sequencer_h = codec_handler_get(mp->media, prim_pt, mp->media_out, NULL); if (sequencer_h == h) continue; if (sequencer_h->source_pt.codec_def && sequencer_h->source_pt.codec_def->supplemental) @@ -2206,7 +2212,7 @@ static int handler_func_passthrough_ssrc(struct codec_handler *h, struct media_p } // substitute out SSRC etc - mp->rtp->ssrc = htonl(mp->ssrc_in->ssrc_map_out); + mp->rtp->ssrc = htonl(mp->ssrc_out->parent->h.ssrc); mp->rtp->seq_num = htons(ntohs(mp->rtp->seq_num) + mp->ssrc_out->parent->seq_diff); // keep track of other stats here? @@ -4657,7 +4663,7 @@ void codec_store_answer(struct codec_store *dst, struct codec_store *src, struct add_codec = 0; struct rtp_payload_type *pt = l->data; - struct codec_handler *h = codec_handler_get(src_media, pt->payload_type, dst_media); + struct codec_handler *h = codec_handler_get(src_media, pt->payload_type, dst_media, NULL); if (!h || h->dest_pt.payload_type == -1) { // passthrough or missing if (pt->for_transcoding) diff --git a/daemon/dtmf.c b/daemon/dtmf.c index a2af90706..d541bd65c 100644 --- a/daemon/dtmf.c +++ b/daemon/dtmf.c @@ -494,7 +494,8 @@ static const char *dtmf_inject_pcm(struct call_media *media, struct call_media * if (!seq) continue; - struct ssrc_ctx *ssrc_out = get_ssrc_ctx(ssrc_in->ssrc_map_out, + struct ssrc_ctx *ssrc_out = get_ssrc_ctx(sh->transcoding ? + ssrc_in->ssrc_map_out : ssrc_in->parent->h.ssrc, sink_ml->ssrc_hash, SSRC_DIR_OUTPUT, monologue); if (!ssrc_out) @@ -581,7 +582,7 @@ const char *dtmf_inject(struct call_media *media, int code, int volume, int dura if (pt == 255) continue; - ch = codec_handler_get(media, pt, sink); + ch = codec_handler_get(media, pt, sink, NULL); if (!ch) continue; if (ch->output_handler && ch->output_handler->ssrc_hash) // context switch if we have multiple inputs going to one output diff --git a/daemon/jitter_buffer.c b/daemon/jitter_buffer.c index c3cb0cb42..a4d3f101f 100644 --- a/daemon/jitter_buffer.c +++ b/daemon/jitter_buffer.c @@ -66,7 +66,7 @@ static void reset_jitter_buffer(struct jitter_buffer *jb) { static struct rtp_payload_type *get_rtp_payload_type(struct media_packet *mp, int payload_type) { struct rtp_payload_type *rtp_pt = NULL; - struct codec_handler *transcoder = codec_handler_get(mp->media, payload_type, mp->media_out); + struct codec_handler *transcoder = codec_handler_get(mp->media, payload_type, mp->media_out, NULL); if(transcoder) { if(transcoder->source_pt.payload_type == payload_type) rtp_pt = &transcoder->source_pt; diff --git a/daemon/media_socket.c b/daemon/media_socket.c index 51cfd7108..77e8c5aee 100644 --- a/daemon/media_socket.c +++ b/daemon/media_socket.c @@ -1211,8 +1211,6 @@ static const char *kernelize_one(struct rtpengine_target_info *reti, GQueue *out if (stream->ssrc_in[u]) reti->ssrc[u] = htonl(stream->ssrc_in[u]->parent->h.ssrc); } - if (MEDIA_ISSET(media, TRANSCODE) || MEDIA_ISSET(media, ECHO)) - reti->transcoding = 1; ZERO(stream->kernel_stats); @@ -1238,7 +1236,7 @@ static const char *kernelize_one(struct rtpengine_target_info *reti, GQueue *out struct sink_handler *ksh = k->data; struct packet_stream *ksink = ksh->sink; struct codec_handler *ch = codec_handler_get(media, rs->payload_type, - ksink->media); + ksink->media, ksh); clockrate = ch->source_pt.clock_rate; if (silenced && ch->source_pt.codec_def) replace_pattern = ch->source_pt.codec_def->silence_pattern; @@ -1264,7 +1262,7 @@ static const char *kernelize_one(struct rtpengine_target_info *reti, GQueue *out g_list_free(values); } else { - if (MEDIA_ISSET(media, TRANSCODE)) + if (sink_handler && sink_handler->transcoding) return NULL; } @@ -1281,11 +1279,19 @@ output: redi->local = reti->local; redi->output.tos = call->tos; + if (MEDIA_ISSET(media, ECHO)) + redi->output.ssrc_subst = 1; + + if (sink_handler && sink_handler->transcoding) { + redi->output.ssrc_subst = 1; + reti->pt_filter = 1; + } + mutex_lock(&sink->out_lock); __re_address_translate_ep(&redi->output.dst_addr, &sink->endpoint); __re_address_translate_ep(&redi->output.src_addr, &sink->selected_sfd->socket.local); - if (reti->transcoding) { + if (redi->output.ssrc_subst) { for (unsigned int u = 0; u < G_N_ELEMENTS(stream->ssrc_in); u++) { if (stream->ssrc_in[u]) redi->output.ssrc_out[u] = htonl(stream->ssrc_in[u]->ssrc_map_out); @@ -1616,7 +1622,7 @@ static const struct streamhandler *__determine_handler(struct packet_stream *in, must_recrypt = true; else if (MEDIA_ISSET(in->media, DTLS) || (out && MEDIA_ISSET(out->media, DTLS))) must_recrypt = true; - else if (MEDIA_ISSET(in->media, TRANSCODE) || (out && MEDIA_ISSET(out->media, TRANSCODE))) + else if (sh->transcoding) must_recrypt = true; else if (in->call->recording) must_recrypt = true; @@ -1677,20 +1683,18 @@ static bool __stream_ssrc_inout(struct packet_stream *ps, uint32_t ssrc, mutex_t ctx_idx = 0; } - // extract and hold entry (ctx_idx == 0) + // extract and hold entry if (*output) ssrc_ctx_put(output); - *output = list[0]; + *output = list[ctx_idx]; ssrc_ctx_hold(*output); // reverse SSRC mapping - if (!output_ssrc) { - // make sure we reset the output SSRC if we're not transcoding - if (!MEDIA_ISSET(ps->media, TRANSCODE) && !MEDIA_ISSET(ps->media, ECHO)) + if (dir == SSRC_DIR_OUTPUT) { + if (!output_ssrc) (*output)->ssrc_map_out = ssrc; - } - else { - (*output)->ssrc_map_out = output_ssrc; + else + (*output)->ssrc_map_out = output_ssrc; } mutex_unlock(lock); @@ -1705,12 +1709,19 @@ static bool __stream_ssrc_in(struct packet_stream *in_srtp, uint32_t ssrc_bs, } // check and update output SSRC pointers static bool __stream_ssrc_out(struct packet_stream *out_srtp, uint32_t ssrc_bs, - struct ssrc_ctx *ssrc_in, struct ssrc_ctx **ssrc_out_p, struct ssrc_hash *ssrc_hash) + struct ssrc_ctx *ssrc_in, struct ssrc_ctx **ssrc_out_p, struct ssrc_hash *ssrc_hash, + bool ssrc_change) { - return __stream_ssrc_inout(out_srtp, ssrc_in->ssrc_map_out, &out_srtp->out_lock, + if (ssrc_change) + return __stream_ssrc_inout(out_srtp, ssrc_in->ssrc_map_out, &out_srtp->out_lock, + out_srtp->ssrc_out, + &out_srtp->ssrc_out_idx, ntohl(ssrc_bs), ssrc_out_p, ssrc_hash, SSRC_DIR_OUTPUT, + "egress (mapped)"); + + return __stream_ssrc_inout(out_srtp, ntohl(ssrc_bs), &out_srtp->out_lock, out_srtp->ssrc_out, - &out_srtp->ssrc_out_idx, ntohl(ssrc_bs), ssrc_out_p, ssrc_hash, SSRC_DIR_OUTPUT, - "egress"); + &out_srtp->ssrc_out_idx, 0, ssrc_out_p, ssrc_hash, SSRC_DIR_OUTPUT, + "egress (direct)"); } @@ -1869,7 +1880,7 @@ static void media_packet_rtp_in(struct packet_handler_ctx *phc) if (unkern) phc->unkernelize = true; } -static void media_packet_rtp_out(struct packet_handler_ctx *phc) +static void media_packet_rtp_out(struct packet_handler_ctx *phc, struct sink_handler *sh) { if (G_UNLIKELY(!proto_is_rtp(phc->mp.media->protocol))) return; @@ -1878,11 +1889,13 @@ static void media_packet_rtp_out(struct packet_handler_ctx *phc) if (G_LIKELY(!phc->rtcp && phc->mp.rtp)) { unkern = __stream_ssrc_out(phc->out_srtp, phc->mp.rtp->ssrc, phc->mp.ssrc_in, - &phc->mp.ssrc_out, phc->mp.media_out->monologue->ssrc_hash); + &phc->mp.ssrc_out, phc->mp.media_out->monologue->ssrc_hash, + sh->transcoding ? true : false); } else if (phc->rtcp && phc->mp.rtcp) { unkern = __stream_ssrc_out(phc->out_srtp, phc->mp.rtcp->ssrc, phc->mp.ssrc_in, - &phc->mp.ssrc_out, phc->mp.media_out->monologue->ssrc_hash); + &phc->mp.ssrc_out, phc->mp.media_out->monologue->ssrc_hash, + sh->transcoding ? true : false); } if (unkern) @@ -2407,7 +2420,7 @@ static int stream_packet(struct packet_handler_ctx *phc) { media_packet_rtcp_mux(phc, sh); // this set ssrc_out - media_packet_rtp_out(phc); + media_packet_rtp_out(phc, sh); rtcp_list_free(&phc->rtcp_list); @@ -2459,7 +2472,7 @@ static int stream_packet(struct packet_handler_ctx *phc) { } else { struct codec_handler *transcoder = codec_handler_get(phc->mp.media, phc->payload_type, - phc->mp.media_out); + phc->mp.media_out, sh); // this transfers the packet from 's' to 'packets_out' if (transcoder->handler_func(transcoder, &phc->mp)) goto err_next; diff --git a/daemon/redis.c b/daemon/redis.c index 6c80c2ff9..e655b0c5e 100644 --- a/daemon/redis.c +++ b/daemon/redis.c @@ -1717,7 +1717,7 @@ static int json_link_streams(struct call *c, struct redis_list *streams, if (!sink) return -1; struct call_subscription *cs = __find_subscriber(ps_ml, sink); - __add_sink_handler(&ps->rtp_sinks, sink, cs ? cs->rtcp_only : false); + __add_sink_handler(&ps->rtp_sinks, sink, cs ? cs->rtcp_only : false, false); } g_queue_clear(&q); @@ -1725,7 +1725,7 @@ static int json_link_streams(struct call *c, struct redis_list *streams, if (!ps->rtp_sinks.length) { struct packet_stream *sink = redis_list_get_ptr(streams, &streams->rh[i], "rtp_sink"); if (sink) - __add_sink_handler(&ps->rtp_sinks, sink, false); + __add_sink_handler(&ps->rtp_sinks, sink, false, false); } if (json_build_list(&q, c, "rtcp_sinks", i, streams, root_reader)) @@ -1734,7 +1734,7 @@ static int json_link_streams(struct call *c, struct redis_list *streams, struct packet_stream *sink = l->data; if (!sink) return -1; - __add_sink_handler(&ps->rtcp_sinks, sink, false); + __add_sink_handler(&ps->rtcp_sinks, sink, false, false); } g_queue_clear(&q); @@ -1742,7 +1742,7 @@ static int json_link_streams(struct call *c, struct redis_list *streams, if (!ps->rtcp_sinks.length) { struct packet_stream *sink = redis_list_get_ptr(streams, &streams->rh[i], "rtcp_sink"); if (sink) - __add_sink_handler(&ps->rtcp_sinks, sink, false); + __add_sink_handler(&ps->rtcp_sinks, sink, false, false); } if (ps->media) diff --git a/include/call.h b/include/call.h index 2d6b715a8..3fe60a8b8 100644 --- a/include/call.h +++ b/include/call.h @@ -430,6 +430,7 @@ struct call_subscription { unsigned int media_offset; // 0 if media indexes match up unsigned int offer_answer:1; // bidirectional, exclusive unsigned int rtcp_only:1; + unsigned int transcoding:1; }; /* half a dialogue */ @@ -644,7 +645,7 @@ struct packet_stream *__packet_stream_new(struct call *call); void __add_subscription(struct call_monologue *ml, struct call_monologue *other, bool offer_answer, unsigned int media_offset, bool rtcp_only); void free_sink_handler(void *); -void __add_sink_handler(GQueue *, struct packet_stream *, bool rtcp_only); +void __add_sink_handler(GQueue *, struct packet_stream *, bool rtcp_only, bool transcoding); void call_subscription_free(void *); void call_subscriptions_clear(GQueue *q); diff --git a/include/codec.h b/include/codec.h index a18ecad1a..6a8d379a9 100644 --- a/include/codec.h +++ b/include/codec.h @@ -27,6 +27,7 @@ struct call; struct codec_store; struct call_monologue; struct delay_buffer; +struct sink_handler; typedef int codec_handler_func(struct codec_handler *, struct media_packet *); @@ -85,7 +86,8 @@ void codec_timer_callback(struct call *, void (*)(struct call *, void *), void * void mqtt_timer_stop(struct mqtt_timer **); void mqtt_timer_start(struct mqtt_timer **mqtp, struct call *call, struct call_media *media); -struct codec_handler *codec_handler_get(struct call_media *, int payload_type, struct call_media *sink); +struct codec_handler *codec_handler_get(struct call_media *, int payload_type, struct call_media *sink, + struct sink_handler *); void codec_handlers_free(struct call_media *); struct codec_handler *codec_handler_make_playback(const struct rtp_payload_type *src_pt, const struct rtp_payload_type *dst_pt, unsigned long ts, struct call_media *); @@ -127,7 +129,7 @@ void payload_type_clear(struct rtp_payload_type *p); void ensure_codec_def(struct rtp_payload_type *pt, struct call_media *media); void codec_handler_free(struct codec_handler **handler); -void codec_handlers_update(struct call_media *receiver, struct call_media *sink, const struct sdp_ng_flags *, +bool codec_handlers_update(struct call_media *receiver, struct call_media *sink, const struct sdp_ng_flags *, const struct stream_params *); void codec_add_dtmf_event(struct codec_ssrc_handler *ch, int code, int level, uint64_t ts); uint64_t codec_last_dtmf_event(struct codec_ssrc_handler *ch); @@ -139,8 +141,11 @@ void codec_handlers_stop(GQueue *); #else -INLINE void codec_handlers_update(struct call_media *receiver, struct call_media *sink, - const struct sdp_ng_flags *flags, const struct stream_params *sp) { } +INLINE bool codec_handlers_update(struct call_media *receiver, struct call_media *sink, + const struct sdp_ng_flags *flags, const struct stream_params *sp) +{ + return false; +} INLINE void codec_handler_free(struct codec_handler **handler) { } INLINE void codec_tracker_update(struct codec_store *cs) { } INLINE void codec_handlers_stop(GQueue *q) { } diff --git a/include/media_socket.h b/include/media_socket.h index 7d811685e..ad1bcfdb0 100644 --- a/include/media_socket.h +++ b/include/media_socket.h @@ -132,6 +132,7 @@ struct sink_handler { const struct streamhandler *handler; int kernel_output_idx; unsigned int rtcp_only:1; + unsigned int transcoding:1; }; struct media_packet { str raw; diff --git a/kernel-module/xt_RTPENGINE.h b/kernel-module/xt_RTPENGINE.h index 30b46aed4..ac65b7670 100644 --- a/kernel-module/xt_RTPENGINE.h +++ b/kernel-module/xt_RTPENGINE.h @@ -119,7 +119,7 @@ struct rtpengine_target_info { rtp:1, rtp_only:1, do_intercept:1, - transcoding:1, // SSRC subst and RTP PT filtering + pt_filter:1, non_forwarding:1, // empty src/dst addr blackhole:1, rtp_stats:1; // requires SSRC and clock_rates to be set @@ -134,6 +134,7 @@ struct rtpengine_output_info { unsigned char tos; unsigned int rtcp_only:1; + unsigned int ssrc_subst:1; }; struct rtpengine_destination_info { diff --git a/t/auto-daemon-tests-pubsub.pl b/t/auto-daemon-tests-pubsub.pl index 7751bfdea..6d100ec64 100755 --- a/t/auto-daemon-tests-pubsub.pl +++ b/t/auto-daemon-tests-pubsub.pl @@ -1749,9 +1749,9 @@ 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)); +rcv($sock_a, $port_b, rtpm(0, 2000, 4000, 0x3456, "\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)); +rcv($sock_b, $port_a, rtpm(0, 4000, 7000, 0x6543, "\x00" x 160)); ($ftr, $ttr, undef, undef, undef, $port_c) = subscribe_request('sub w tc - acc', { 'from-tag' => ft(), codec => { transcode => ['PCMA'] } }, < ft(), codec => {transcode => ['PCMA', 'G722', 'G723'] } }, < ft(), codec => {transcode => ['PCMA', 'G722', 'G723'] } }, <