TT#91151 tie codec handlers to output media/sink

Change-Id: Id577f9afabbe5645a6e220b6450c39a35ff839a9
pull/1295/head
Richard Fuchs 4 years ago
parent 751653a359
commit 1e0765bf6e

@ -2383,7 +2383,20 @@ const char *call_play_dtmf_ng(bencode_item_t *input, bencode_item_t *output) {
goto out;
found:;
err = dtmf_inject(media, code, volume, duration, pause);
struct call_monologue *dialogue = monologue->active_dialogue;
struct call_media *sink = NULL;
for (GList *l = dialogue->medias.head; l; l = l->next) {
sink = l->data;
if (media->type_id != MT_AUDIO)
continue;
goto found_sink;
}
err = "Sink monologue has no media capable of DTMF playback";
goto out;
found_sink:
err = dtmf_inject(media, code, volume, duration, pause, sink);
if (err)
break;
}

@ -193,6 +193,7 @@ static struct ssrc_entry *__ssrc_handler_transcode_new(void *p);
static struct ssrc_entry *__ssrc_handler_new(void *p);
static void __ssrc_handler_stop(void *p);
static void __free_ssrc_handler(void *);
INLINE struct codec_handler *codec_handler_lookup(GHashTable *ht, int pt, struct call_media *sink);
static void __transcode_packet_free(struct transcode_packet *);
@ -263,7 +264,9 @@ void codec_handler_free(struct codec_handler **handler) {
*handler = NULL;
}
static struct codec_handler *__handler_new(const struct rtp_payload_type *pt, struct call_media *media) {
static struct codec_handler *__handler_new(const struct rtp_payload_type *pt, struct call_media *media,
struct call_media *sink)
{
struct codec_handler *handler = g_slice_alloc0(sizeof(*handler));
handler->source_pt.payload_type = -1;
if (pt)
@ -275,6 +278,7 @@ static struct codec_handler *__handler_new(const struct rtp_payload_type *pt, st
handler->packet_encoded = packet_encoded_rtp;
handler->packet_decoded = packet_decoded_fifo;
handler->media = media;
handler->sink = sink;
return handler;
}
@ -407,7 +411,7 @@ check_output:;
struct codec_handler *codec_handler_make_playback(const struct rtp_payload_type *src_pt,
const struct rtp_payload_type *dst_pt, unsigned long last_ts, struct call_media *media)
{
struct codec_handler *handler = __handler_new(src_pt, media);
struct codec_handler *handler = __handler_new(src_pt, media, NULL);
rtp_payload_type_copy(&handler->dest_pt, dst_pt);
handler->func = handler_func_playback;
handler->ssrc_handler = (void *) __ssrc_handler_transcode_new(handler);
@ -591,7 +595,7 @@ static void __check_dtmf_injector(struct call_media *receiver, struct call_media
return;
}
parent->dtmf_injector = __handler_new(&src_pt, receiver);
parent->dtmf_injector = __handler_new(&src_pt, receiver, sink);
__make_transcoder(parent->dtmf_injector, &parent->dest_pt, output_transcoders, -1, 0, -1);
parent->dtmf_injector->func = handler_func_inject_dtmf;
}
@ -599,28 +603,28 @@ static void __check_dtmf_injector(struct call_media *receiver, struct call_media
static struct codec_handler *__get_pt_handler(struct call_media *receiver, struct rtp_payload_type *pt) {
static struct codec_handler *__get_pt_handler(struct call_media *receiver, struct rtp_payload_type *pt,
struct call_media *sink)
{
ensure_codec_def(pt, receiver);
struct codec_handler *handler;
handler = g_hash_table_lookup(receiver->codec_handlers, GINT_TO_POINTER(pt->payload_type));
handler = codec_handler_lookup(receiver->codec_handlers, pt->payload_type, sink);
if (handler) {
// make sure existing handler matches this PT
if (rtp_payload_type_cmp(pt, &handler->source_pt)) {
ilogs(codec, LOG_DEBUG, "Resetting codec handler for PT %i", pt->payload_type);
g_hash_table_remove(receiver->codec_handlers, handler);
__handler_shutdown(handler);
handler = NULL;
g_atomic_pointer_set(&receiver->codec_handler_cache, NULL);
g_hash_table_remove(receiver->codec_handlers, GINT_TO_POINTER(pt->payload_type));
}
}
if (!handler) {
ilogs(codec, LOG_DEBUG, "Creating codec handler for " STR_FORMAT " (%i)",
STR_FMT(&pt->encoding_with_params),
pt->payload_type);
handler = __handler_new(pt, receiver);
g_hash_table_insert(receiver->codec_handlers,
GINT_TO_POINTER(handler->source_pt.payload_type),
handler);
handler = __handler_new(pt, receiver, sink);
g_hash_table_insert(receiver->codec_handlers, handler, handler);
g_queue_push_tail(&receiver->codec_handlers_store, handler);
}
@ -640,7 +644,7 @@ static void __check_t38_decoder(struct call_media *t38_media) {
if (t38_media->t38_handler)
return;
ilogs(codec, LOG_DEBUG, "Creating T.38 packet handler");
t38_media->t38_handler = __handler_new(NULL, t38_media);
t38_media->t38_handler = __handler_new(NULL, t38_media, NULL);
t38_media->t38_handler->func = handler_func_t38;
}
@ -702,7 +706,7 @@ static void __check_t38_gateway(struct call_media *pcm_media, struct call_media
// links to the T.38 encoder
for (GList *l = pcm_media->codecs.codec_prefs.head; l; l = l->next) {
struct rtp_payload_type *pt = l->data;
struct codec_handler *handler = __get_pt_handler(pcm_media, pt);
struct codec_handler *handler = __get_pt_handler(pcm_media, pt, t38_media);
if (!pt->codec_def) {
// should not happen
ilogs(codec, LOG_WARN, "Unsupported codec " STR_FORMAT " for T.38 transcoding",
@ -831,6 +835,29 @@ static void __codec_rtcp_timer(struct call_media *receiver) {
// XXX unify with media player into a generic RTCP player
}
static unsigned int __codec_handler_hash(const void *p) {
const struct codec_handler *h = p;
return h->source_pt.payload_type ^ GPOINTER_TO_UINT(h->sink);
}
static int __codec_handler_eq(const void *a, const void *b) {
const struct codec_handler *h = a, *j = b;
return h->source_pt.payload_type == j->source_pt.payload_type
&& h->sink == j->sink;
}
INLINE struct codec_handler __codec_handler_lookup_struct(int pt, struct call_media *sink) {
struct codec_handler lookup = {
.source_pt = {
.payload_type = pt,
},
.sink = sink,
};
return lookup;
}
INLINE struct codec_handler *codec_handler_lookup(GHashTable *ht, int pt, struct call_media *sink) {
struct codec_handler lookup = __codec_handler_lookup_struct(pt, sink);
return g_hash_table_lookup(ht, &lookup);
}
// call must be locked in W
void codec_handlers_update(struct call_media *receiver, struct call_media *sink,
const struct sdp_ng_flags *flags, const struct stream_params *sp)
@ -855,7 +882,7 @@ void codec_handlers_update(struct call_media *receiver, struct call_media *sink,
}
if (!receiver->codec_handlers)
receiver->codec_handlers = g_hash_table_new(g_direct_hash, g_direct_equal);
receiver->codec_handlers = g_hash_table_new(__codec_handler_hash, __codec_handler_eq);
// should we transcode to a non-RTP protocol?
if (proto_is_not_rtp(sink->protocol)) {
@ -894,7 +921,7 @@ void codec_handlers_update(struct call_media *receiver, struct call_media *sink,
ilogs(codec, LOG_DEBUG, "Checking receiver codec " STR_FORMAT " (%i)",
STR_FMT(&pt->encoding_with_full_params), pt->payload_type);
struct codec_handler *handler = __get_pt_handler(receiver, pt);
struct codec_handler *handler = __get_pt_handler(receiver, pt, sink);
// check our own support for this codec
if (!pt->codec_def) {
@ -1136,19 +1163,22 @@ next:
}
static struct codec_handler *codec_handler_get_rtp(struct call_media *m, int payload_type) {
static struct codec_handler *codec_handler_get_rtp(struct call_media *m, int payload_type,
struct call_media *sink)
{
struct codec_handler *h;
if (payload_type < 0)
return NULL;
struct codec_handler lookup = __codec_handler_lookup_struct(payload_type, sink);
h = g_atomic_pointer_get(&m->codec_handler_cache);
if (G_LIKELY(G_LIKELY(h) && G_LIKELY(h->source_pt.payload_type == payload_type)))
if (G_LIKELY(G_LIKELY(h) && G_LIKELY(__codec_handler_eq(&lookup, h))))
return h;
if (G_UNLIKELY(!m->codec_handlers))
return NULL;
h = g_hash_table_lookup(m->codec_handlers, GINT_TO_POINTER(payload_type));
h = g_hash_table_lookup(m->codec_handlers, &lookup);
if (!h)
return NULL;
@ -1233,7 +1263,7 @@ 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 codec_handler *codec_handler_get(struct call_media *m, int payload_type, struct call_media *sink) {
#ifdef WITH_TRANSCODING
struct codec_handler *ret = NULL;
@ -1241,7 +1271,7 @@ struct codec_handler *codec_handler_get(struct call_media *m, int payload_type)
goto out;
if (m->protocol->rtp)
ret = codec_handler_get_rtp(m, payload_type);
ret = codec_handler_get_rtp(m, payload_type, sink);
else if (m->protocol->index == PROTO_UDPTL)
ret = codec_handler_get_udptl(m);
@ -1669,7 +1699,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);
struct codec_handler *sequencer_h = codec_handler_get(mp->media, prim_pt, mp->media_out);
if (sequencer_h == h)
continue;
if (sequencer_h->source_pt.codec_def && sequencer_h->source_pt.codec_def->supplemental)
@ -3570,7 +3600,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);
struct codec_handler *h = codec_handler_get(src_media, pt->payload_type, dst_media);
if (!h || h->dest_pt.payload_type == -1) {
// passthrough or missing
if (pt->for_transcoding)

@ -228,7 +228,8 @@ static char dtmf_code_to_char(int code) {
}
// takes over the csh reference
static const char *dtmf_inject_pcm(struct call_media *media, struct call_monologue *monologue,
static const char *dtmf_inject_pcm(struct call_media *media, struct call_media *sink,
struct call_monologue *monologue,
struct packet_stream *ps, struct ssrc_ctx *ssrc_in, struct codec_handler *ch,
struct codec_ssrc_handler *csh,
int code, int volume, int duration, int pause)
@ -265,7 +266,7 @@ static const char *dtmf_inject_pcm(struct call_media *media, struct call_monolog
.tv = rtpe_now,
.call = call,
.media = media,
.media_out = media,
.media_out = sink,
.rtp = &rtp,
.ssrc_in = ssrc_in,
.ssrc_out = ssrc_out,
@ -301,7 +302,9 @@ static const char *dtmf_inject_pcm(struct call_media *media, struct call_monolog
return 0;
}
const char *dtmf_inject(struct call_media *media, int code, int volume, int duration, int pause) {
const char *dtmf_inject(struct call_media *media, int code, int volume, int duration, int pause,
struct call_media *sink)
{
struct call_monologue *monologue = media->monologue;
if (!media->streams.head)
@ -321,7 +324,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);
ch = codec_handler_get(media, pt, sink);
if (!ch)
continue;
if (ch->output_handler && ch->output_handler->ssrc_hash) // context switch if we have multiple inputs going to one output
@ -353,7 +356,8 @@ const char *dtmf_inject(struct call_media *media, int code, int volume, int dura
// if we don't have a DTMF payload type, we have to generate PCM
if (ch->dtmf_payload_type == -1 && ch->dtmf_injector)
return dtmf_inject_pcm(media, monologue, ps, ssrc_in, ch, csh, code, volume, duration, pause);
return dtmf_inject_pcm(media, sink, monologue, ps, ssrc_in, ch, csh, code, volume, duration,
pause);
ilog(LOG_DEBUG, "Injecting RFC DTMF event #%i for %i ms (vol %i) from '" STR_FORMAT "' (media #%u) "
"into RTP PT %i, SSRC %" PRIx32,

@ -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);
struct codec_handler *transcoder = codec_handler_get(mp->media, payload_type, mp->media_out);
if(transcoder) {
if(transcoder->source_pt.payload_type == payload_type)
rtp_pt = &transcoder->source_pt;

@ -1233,7 +1233,7 @@ void kernelize(struct packet_stream *stream) {
}
rs = l->data;
// only add payload types that are passthrough
struct codec_handler *ch = codec_handler_get(media, rs->payload_type);
struct codec_handler *ch = codec_handler_get(media, rs->payload_type, sink->media);
if (!ch->kernelize)
continue;
reti.payload_types[reti.num_payload_types] = rs->payload_type;
@ -2105,7 +2105,8 @@ static int stream_packet(struct packet_handler_ctx *phc) {
goto drop;
}
else {
struct codec_handler *transcoder = codec_handler_get(phc->mp.media, phc->payload_type);
struct codec_handler *transcoder = codec_handler_get(phc->mp.media, phc->payload_type,
phc->mp.media_out);
// this transfers the packet from 's' to 'packets_out'
if (transcoder->func(transcoder, &phc->mp))
goto drop;

@ -44,6 +44,7 @@ struct codec_handler {
struct codec_handler *input_handler; // == main handler for supp codecs
struct codec_handler *output_handler; // == self, or other PT handler
struct call_media *media;
struct call_media *sink;
#ifdef WITH_TRANSCODING
int (*packet_encoded)(encoder_t *enc, void *u1, void *u2);
int (*packet_decoded)(decoder_t *, AVFrame *, void *, void *);
@ -78,7 +79,7 @@ void rtcp_timer_stop(struct rtcp_timer **);
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 codec_handler *codec_handler_get(struct call_media *, int payload_type, struct call_media *sink);
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 *);

@ -22,7 +22,8 @@ int dtmf_event(struct media_packet *, str *, int);
int dtmf_event_payload(str *, uint64_t *, uint64_t, struct dtmf_event *, GQueue *);
void dtmf_event_free(void *);
int dtmf_code_from_char(char);
const char *dtmf_inject(struct call_media *media, int code, int volume, int duration, int pause);
const char *dtmf_inject(struct call_media *media, int code, int volume, int duration, int pause,
struct call_media *sink);
int dtmf_do_logging(void);

@ -212,7 +212,14 @@ static void __packet_seq_ts(const char *file, int line, struct call_media *media
long long ts_exp, int seq_diff_exp, int fatal)
{
printf("running test %s:%i\n", file, line);
struct codec_handler *h = codec_handler_get(media, pt_in & 0x7f);
struct call_media *other_media;
if (media == media_A)
other_media = media_B;
else if (media == media_B)
other_media = media_A;
else
abort();
struct codec_handler *h = codec_handler_get(media, pt_in & 0x7f, other_media);
str pl = pload;
str pl_exp = pload_exp;
@ -220,6 +227,7 @@ static void __packet_seq_ts(const char *file, int line, struct call_media *media
struct media_packet mp = {
.call = &call,
.media = media,
.media_out = other_media,
.ssrc_in = get_ssrc_ctx(ssrc, media->monologue->ssrc_hash, SSRC_DIR_INPUT, NULL),
};
// from __stream_ssrc()

Loading…
Cancel
Save