Browse Source

TT#136957 obsolete TRANSCODE flag

Change-Id: I7307b63a8f5a10aa3b5c98fb48218bcc7a123441
pull/1487/head
Richard Fuchs 4 years ago
parent
commit
84fed5ca7e
12 changed files with 148 additions and 91 deletions
  1. +45
    -16
      daemon/call.c
  2. +20
    -14
      daemon/codec.c
  3. +3
    -2
      daemon/dtmf.c
  4. +1
    -1
      daemon/jitter_buffer.c
  5. +36
    -23
      daemon/media_socket.c
  6. +4
    -4
      daemon/redis.c
  7. +2
    -1
      include/call.h
  8. +9
    -4
      include/codec.h
  9. +1
    -0
      include/media_socket.h
  10. +2
    -1
      kernel-module/xt_RTPENGINE.h
  11. +24
    -24
      t/auto-daemon-tests-pubsub.pl
  12. +1
    -1
      t/test-transcode.c

+ 45
- 16
daemon/call.c View File

@ -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);
}


+ 20
- 14
daemon/codec.c View File

@ -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)


+ 3
- 2
daemon/dtmf.c View File

@ -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


+ 1
- 1
daemon/jitter_buffer.c View File

@ -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;


+ 36
- 23
daemon/media_socket.c View File

@ -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;


+ 4
- 4
daemon/redis.c View File

@ -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)


+ 2
- 1
include/call.h View File

@ -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);


+ 9
- 4
include/codec.h View File

@ -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) { }


+ 1
- 0
include/media_socket.h View File

@ -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;


+ 2
- 1
kernel-module/xt_RTPENGINE.h View File

@ -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 {


+ 24
- 24
t/auto-daemon-tests-pubsub.pl View File

@ -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'] } }, <<SDP);
@ -1781,10 +1781,10 @@ 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));
rcv($sock_a, $port_b, rtpm(0, 2001, 4160, 0x3456, "\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(8, 4001, 7160, $ssrc_b, "\x2a" x 160));
rcv($sock_b, $port_a, rtpm(0, 4001, 7160, 0x6543, "\x00" x 160));
rcv($sock_c, $port_c, rtpm(8, 4001, 7160, -1, "\x2a" x 160));
@ -1927,9 +1927,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('multi subs w diff codecs',
{ 'from-tag' => ft(), codec => {transcode => ['PCMA', 'G722', 'G723'] } }, <<SDP);
@ -1961,10 +1961,10 @@ 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));
rcv($sock_a, $port_b, rtpm(0, 2001, 4160, 0x3456, "\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));
rcv($sock_b, $port_a, rtpm(0, 4001, 7160, 0x6543, "\x00" x 160));
rcv($sock_c, $port_c, rtpm(0, 4001, 7160, 0x6543, "\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);
@ -1996,11 +1996,11 @@ 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));
rcv($sock_a, $port_b, rtpm(0, 2002, 4320, 0x3456, "\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));
rcv($sock_b, $port_a, rtpm(0, 4002, 7320, 0x6543, "\x00" x 160));
rcv($sock_c, $port_c, rtpm(0, 4002, 7320, 0x6543, "\x00" x 160));
rcv($sock_d, $port_d, rtpm(8, 4002, 7320, -1, "\x2a" x 160));
($ftr, $ttr, undef, undef, undef, $port_e) = subscribe_request('multi subs w diff codecs',
@ -2033,20 +2033,20 @@ 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));
rcv($sock_a, $port_b, rtpm(0, 2003, 4480, 0x3456, "\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($sock_b, $port_a, rtpm(0, 4003, 7480, 0x6543, "\x00" x 160));
rcv($sock_c, $port_c, rtpm(0, 4003, 7480, 0x6543, "\x00" x 160));
($ssrc_a) = rcv($sock_d, $port_d, rtpm(8, 4003, 7480, -1, "\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));
rcv($sock_a, $port_b, rtpm(0, 2004, 4640, 0x3456, "\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"));
rcv($sock_b, $port_a, rtpm(0, 4004, 7640, 0x6543, "\x00" x 160));
rcv($sock_c, $port_c, rtpm(0, 4004, 7640, 0x6543, "\x00" x 160));
rcv($sock_d, $port_d, rtpm(8, 4004, 7640, $ssrc_a, "\x2a" x 160));
rcv($sock_e, $port_e, rtpm(9, 4003, 7480, $ssrc_a, "\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"));
@ -2995,7 +2995,7 @@ SDP
snd($sock_a, $port_a, rtp(8, 2002, 4320, 0x3456, "\x00" x 160));
rcv($sock_b, $port_b, rtpm(8, 2002, 4320, 0x3456, "\x00" x 160));
rcv($sock_c, $port_c, rtpm(0, 2002, 4320, 0x3456, "\x29" x 160));
rcv($sock_c, $port_c, rtpm(0, 2002, 4320, -1, "\x29" x 160));


+ 1
- 1
t/test-transcode.c View File

@ -224,7 +224,7 @@ static void __packet_seq_ts(const char *file, int line, struct call_media *media
other_media = media_A;
else
abort();
struct codec_handler *h = codec_handler_get(media, pt_in & 0x7f, other_media);
struct codec_handler *h = codec_handler_get(media, pt_in & 0x7f, other_media, NULL);
str pl = pload;
str pl_exp = pload_exp;


Loading…
Cancel
Save