Browse Source

TT#100200 properly support multiple supplemental codecs

Change-Id: I643fa844b504bf1264d6d2cddebf6d6602c80b35
pull/1116/head
Richard Fuchs 5 years ago
parent
commit
bd53179cd1
1 changed files with 68 additions and 38 deletions
  1. +68
    -38
      daemon/codec.c

+ 68
- 38
daemon/codec.c View File

@ -140,6 +140,7 @@ static codec_handler_func handler_func_passthrough_ssrc;
static codec_handler_func handler_func_transcode; static codec_handler_func handler_func_transcode;
static codec_handler_func handler_func_playback; static codec_handler_func handler_func_playback;
static codec_handler_func handler_func_inject_dtmf; static codec_handler_func handler_func_inject_dtmf;
static codec_handler_func handler_func_supplemental;
static codec_handler_func handler_func_dtmf; static codec_handler_func handler_func_dtmf;
static codec_handler_func handler_func_t38; static codec_handler_func handler_func_t38;
@ -149,6 +150,7 @@ static void __free_ssrc_handler(void *);
static void __transcode_packet_free(struct transcode_packet *); static void __transcode_packet_free(struct transcode_packet *);
static int packet_decode(struct codec_ssrc_handler *, struct transcode_packet *, struct media_packet *);
static int packet_encoded_rtp(encoder_t *enc, void *u1, void *u2); static int packet_encoded_rtp(encoder_t *enc, void *u1, void *u2);
static int packet_decoded_fifo(decoder_t *decoder, AVFrame *frame, void *u1, void *u2); static int packet_decoded_fifo(decoder_t *decoder, AVFrame *frame, void *u1, void *u2);
static int packet_decoded_direct(decoder_t *decoder, AVFrame *frame, void *u1, void *u2); static int packet_decoded_direct(decoder_t *decoder, AVFrame *frame, void *u1, void *u2);
@ -213,6 +215,8 @@ static void __make_passthrough(struct codec_handler *handler) {
STR_FMT(&handler->source_pt.encoding_with_params)); STR_FMT(&handler->source_pt.encoding_with_params));
if (handler->source_pt.codec_def && handler->source_pt.codec_def->dtmf) if (handler->source_pt.codec_def && handler->source_pt.codec_def->dtmf)
handler->func = handler_func_dtmf; handler->func = handler_func_dtmf;
else if (handler->source_pt.codec_def && handler->source_pt.codec_def->supplemental)
handler->func = handler_func_supplemental;
else { else {
handler->func = handler_func_passthrough; handler->func = handler_func_passthrough;
handler->kernelize = 1; handler->kernelize = 1;
@ -226,6 +230,8 @@ static void __make_passthrough_ssrc(struct codec_handler *handler) {
STR_FMT(&handler->source_pt.encoding_with_params)); STR_FMT(&handler->source_pt.encoding_with_params));
if (handler->source_pt.codec_def && handler->source_pt.codec_def->dtmf) if (handler->source_pt.codec_def && handler->source_pt.codec_def->dtmf)
handler->func = handler_func_dtmf; handler->func = handler_func_dtmf;
else if (handler->source_pt.codec_def && handler->source_pt.codec_def->supplemental)
handler->func = handler_func_supplemental;
else { else {
handler->func = handler_func_passthrough_ssrc; handler->func = handler_func_passthrough_ssrc;
handler->kernelize = 1; handler->kernelize = 1;
@ -384,8 +390,19 @@ static void __dtmf_dsp_shutdown(struct call_media *sink, int payload_type) {
} }
static void __track_supp_codec(GHashTable *supplemental_sinks, struct rtp_payload_type *pt) {
if (!pt->codec_def || !pt->codec_def->supplemental)
return;
GHashTable *supp_sinks = g_hash_table_lookup(supplemental_sinks, pt->codec_def->rtpname);
if (!supp_sinks)
return;
if (!g_hash_table_lookup(supp_sinks, GUINT_TO_POINTER(pt->clock_rate)))
g_hash_table_insert(supp_sinks, GUINT_TO_POINTER(pt->clock_rate), pt);
}
static struct rtp_payload_type *__check_dest_codecs(struct call_media *receiver, struct call_media *sink, static struct rtp_payload_type *__check_dest_codecs(struct call_media *receiver, struct call_media *sink,
const struct sdp_ng_flags *flags, GHashTable *dtmf_sinks, int *sink_transcoding)
const struct sdp_ng_flags *flags, GHashTable *supplemental_sinks, int *sink_transcoding)
{ {
struct rtp_payload_type *pref_dest_codec = NULL; struct rtp_payload_type *pref_dest_codec = NULL;
@ -416,22 +433,14 @@ static struct rtp_payload_type *__check_dest_codecs(struct call_media *receiver,
&pt->payload_type); &pt->payload_type);
if (!recv_pt || rtp_payload_type_cmp(pt, recv_pt)) { if (!recv_pt || rtp_payload_type_cmp(pt, recv_pt)) {
*sink_transcoding = 1; *sink_transcoding = 1;
// can the sink receive RFC DTMF but the receiver can't send it?
if (pt->codec_def && pt->codec_def->dtmf) {
if (!g_hash_table_lookup(dtmf_sinks, GUINT_TO_POINTER(pt->clock_rate)))
g_hash_table_insert(dtmf_sinks, GUINT_TO_POINTER(pt->clock_rate),
pt);
}
// can the sink receive supplemental codec but the receiver can't send it?
__track_supp_codec(supplemental_sinks, pt);
} }
} }
else if (flags && (flags->always_transcode || flags->inject_dtmf)) { else if (flags && (flags->always_transcode || flags->inject_dtmf)) {
// with always-transcode, we must keep track of potential output DTMF payload
// with always-transcode, we must keep track of potential output supplemental payload
// types as well // types as well
if (pt->codec_def && pt->codec_def->dtmf) {
if (!g_hash_table_lookup(dtmf_sinks, GUINT_TO_POINTER(pt->clock_rate)))
g_hash_table_insert(dtmf_sinks, GUINT_TO_POINTER(pt->clock_rate),
pt);
}
__track_supp_codec(supplemental_sinks, pt);
} }
} }
@ -439,7 +448,7 @@ static struct rtp_payload_type *__check_dest_codecs(struct call_media *receiver,
} }
static void __check_send_codecs(struct call_media *receiver, struct call_media *sink, static void __check_send_codecs(struct call_media *receiver, struct call_media *sink,
const struct sdp_ng_flags *flags, GHashTable *dtmf_sinks, int *sink_transcoding)
const struct sdp_ng_flags *flags, GHashTable *supplemental_sinks, int *sink_transcoding)
{ {
if (!MEDIA_ISSET(sink, TRANSCODE)) if (!MEDIA_ISSET(sink, TRANSCODE))
return; return;
@ -450,12 +459,8 @@ static void __check_send_codecs(struct call_media *receiver, struct call_media *
&pt->payload_type); &pt->payload_type);
if (!recv_pt || rtp_payload_type_cmp(pt, recv_pt) || (flags && flags->inject_dtmf)) { if (!recv_pt || rtp_payload_type_cmp(pt, recv_pt) || (flags && flags->inject_dtmf)) {
*sink_transcoding = 1; *sink_transcoding = 1;
// can the sink receive RFC DTMF but the receiver can't send it?
if (pt->codec_def && pt->codec_def->dtmf) {
if (!g_hash_table_lookup(dtmf_sinks, GUINT_TO_POINTER(pt->clock_rate)))
g_hash_table_insert(dtmf_sinks, GUINT_TO_POINTER(pt->clock_rate),
pt);
}
// can the sink receive supplemental codec but the receiver can't send it?
__track_supp_codec(supplemental_sinks, pt);
continue; continue;
} }
@ -473,7 +478,10 @@ static void __check_send_codecs(struct call_media *receiver, struct call_media *
} }
} }
static int __dtmf_payload_type(GHashTable *dtmf_sinks, struct rtp_payload_type *pref_dest_codec) {
static int __dtmf_payload_type(GHashTable *supplemental_sinks, struct rtp_payload_type *pref_dest_codec) {
GHashTable *dtmf_sinks = g_hash_table_lookup(supplemental_sinks, "telephone-event");
if (!dtmf_sinks)
return -1;
if (!g_hash_table_size(dtmf_sinks) || !pref_dest_codec) if (!g_hash_table_size(dtmf_sinks) || !pref_dest_codec)
return -1; return -1;
@ -986,23 +994,29 @@ void codec_handlers_update(struct call_media *receiver, struct call_media *sink,
// that the sink specified. determine this first. // that the sink specified. determine this first.
struct rtp_payload_type *pref_dest_codec = NULL; struct rtp_payload_type *pref_dest_codec = NULL;
int sink_transcoding = 0; int sink_transcoding = 0;
// keep track of telephone-event payload types. we hash them by clock rate
// keep track of supplemental payload types. we hash them by clock rate
// in case there's several of them. the clock rates of the destination // in case there's several of them. the clock rates of the destination
// codec and the telephone-event codec must match.
GHashTable *dtmf_sinks = g_hash_table_new(g_direct_hash, g_direct_equal);
// codec and the supplemental codec must match.
GHashTable *supplemental_sinks = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
(GDestroyNotify) g_hash_table_destroy);
for (GList *l = codec_supplemental_codecs->head; l; l = l->next) {
codec_def_t *def = l->data;
g_hash_table_replace(supplemental_sinks, (void *) def->rtpname,
g_hash_table_new(g_direct_hash, g_direct_equal));
}
pref_dest_codec = __check_dest_codecs(receiver, sink, flags, dtmf_sinks, &sink_transcoding);
pref_dest_codec = __check_dest_codecs(receiver, sink, flags, supplemental_sinks, &sink_transcoding);
// similarly, if the sink can receive a codec that the receiver can't send, it's also transcoding // similarly, if the sink can receive a codec that the receiver can't send, it's also transcoding
__check_send_codecs(receiver, sink, flags, dtmf_sinks, &sink_transcoding);
__check_send_codecs(receiver, sink, flags, supplemental_sinks, &sink_transcoding);
if (flags && flags->opmode == OP_ANSWER && flags->symmetric_codecs) if (flags && flags->opmode == OP_ANSWER && flags->symmetric_codecs)
__symmetric_codecs(receiver, sink, &sink_transcoding); __symmetric_codecs(receiver, sink, &sink_transcoding);
ilog(LOG_DEBUG, "%i DTMF sink entries", g_hash_table_size(dtmf_sinks));
int dtmf_payload_type = __dtmf_payload_type(dtmf_sinks, pref_dest_codec);
int dtmf_payload_type = __dtmf_payload_type(supplemental_sinks, pref_dest_codec);
g_hash_table_destroy(dtmf_sinks);
g_hash_table_destroy(supplemental_sinks);
supplemental_sinks = NULL;
struct rtp_payload_type *dtmf_pt = NULL; struct rtp_payload_type *dtmf_pt = NULL;
struct rtp_payload_type *reverse_dtmf_pt = NULL; struct rtp_payload_type *reverse_dtmf_pt = NULL;
@ -1031,7 +1045,7 @@ void codec_handlers_update(struct call_media *receiver, struct call_media *sink,
// payload type to keep track of this. // payload type to keep track of this.
GHashTable *output_transcoders = g_hash_table_new(g_direct_hash, g_direct_equal); GHashTable *output_transcoders = g_hash_table_new(g_direct_hash, g_direct_equal);
int transcode_dtmf = 0; // is one of our destination codecs DTMF?
int transcode_supplemental = 0; // is one of our source codecs a supplemental one?
// do we need to detect PCM DTMF tones? // do we need to detect PCM DTMF tones?
int pcm_dtmf_detect = 0; int pcm_dtmf_detect = 0;
@ -1143,8 +1157,8 @@ unsupported:
// the sink does not support this codec -> transcode // the sink does not support this codec -> transcode
ilog(LOG_DEBUG, "Sink does not support codec " STR_FORMAT, STR_FMT(&pt->encoding_with_params)); ilog(LOG_DEBUG, "Sink does not support codec " STR_FORMAT, STR_FMT(&pt->encoding_with_params));
dest_pt = pref_dest_codec; dest_pt = pref_dest_codec;
if (pt->codec_def->dtmf)
transcode_dtmf = 1;
if (pt->codec_def->supplemental)
transcode_supplemental = 1;
transcode:; transcode:;
// look up the reverse side of this payload type, which is the decoder to our // look up the reverse side of this payload type, which is the decoder to our
// encoder. if any codec options such as bitrate were set during an offer, // encoder. if any codec options such as bitrate were set during an offer,
@ -1198,7 +1212,7 @@ next:
// if the sink does not support DTMF but we can receive it, we must transcode // if the sink does not support DTMF but we can receive it, we must transcode
// DTMF event packets to PCM. this requires all codecs to be transcoded to the // DTMF event packets to PCM. this requires all codecs to be transcoded to the
// sink's preferred destination codec. // sink's preferred destination codec.
if (!transcode_dtmf && dtmf_payload_type == -1)
if (!transcode_supplemental && dtmf_payload_type == -1)
__make_passthrough_ssrc(handler); __make_passthrough_ssrc(handler);
else if (dtmf_pt && reverse_dtmf_pt) else if (dtmf_pt && reverse_dtmf_pt)
__make_passthrough_ssrc(handler); __make_passthrough_ssrc(handler);
@ -1602,7 +1616,10 @@ static int packet_dtmf_dup(struct codec_ssrc_handler *ch, struct transcode_packe
return 0; return 0;
} }
static int handler_func_dtmf(struct codec_handler *h, struct media_packet *mp) {
static int __handler_func_supplemental(struct codec_handler *h, struct media_packet *mp,
int (*func)(struct codec_ssrc_handler *, struct transcode_packet *, struct media_packet *),
int (*dup_func)(struct codec_ssrc_handler *, struct transcode_packet *, struct media_packet *))
{
if (G_UNLIKELY(!mp->rtp)) if (G_UNLIKELY(!mp->rtp))
return handler_func_passthrough(h, mp); return handler_func_passthrough(h, mp);
@ -1610,7 +1627,8 @@ static int handler_func_dtmf(struct codec_handler *h, struct media_packet *mp) {
// create new packet and insert it into sequencer queue // create new packet and insert it into sequencer queue
ilog(LOG_DEBUG, "Received DTMF RTP packet: SSRC %" PRIx32 ", PT %u, seq %u, TS %u, len %i",
ilog(LOG_DEBUG, "Received %s RTP packet: SSRC %" PRIx32 ", PT %u, seq %u, TS %u, len %i",
h->source_pt.codec_def->rtpname,
ntohl(mp->rtp->ssrc), mp->rtp->m_pt, ntohs(mp->rtp->seq_num), ntohl(mp->rtp->ssrc), mp->rtp->m_pt, ntohs(mp->rtp->seq_num),
ntohl(mp->rtp->timestamp), mp->payload.len); ntohl(mp->rtp->timestamp), mp->payload.len);
@ -1627,14 +1645,20 @@ static int handler_func_dtmf(struct codec_handler *h, struct media_packet *mp) {
sequencer_h = codec_handler_get(mp->media, prim_pt); sequencer_h = codec_handler_get(mp->media, prim_pt);
if (sequencer_h == h) if (sequencer_h == h)
continue; continue;
ilog(LOG_DEBUG, "Primary RTP payload type for handling DTMF event is %i", prim_pt);
if (sequencer_h->source_pt.codec_def && sequencer_h->source_pt.codec_def->supplemental)
continue;
ilog(LOG_DEBUG, "Primary RTP payload type for handling %s is %i",
h->source_pt.codec_def->rtpname,
prim_pt);
break; break;
} }
} }
// XXX ? h->output_handler = sequencer_h->output_handler; // XXX locking?
struct transcode_packet *packet = g_slice_alloc0(sizeof(*packet)); struct transcode_packet *packet = g_slice_alloc0(sizeof(*packet));
packet->func = packet_dtmf;
packet->dup_func = packet_dtmf_dup;
packet->func = func;
packet->dup_func = dup_func;
packet->handler = h; packet->handler = h;
packet->rtp = *mp->rtp; packet->rtp = *mp->rtp;
@ -1647,6 +1671,12 @@ static int handler_func_dtmf(struct codec_handler *h, struct media_packet *mp) {
return __handler_func_sequencer(mp, packet); return __handler_func_sequencer(mp, packet);
} }
static int handler_func_supplemental(struct codec_handler *h, struct media_packet *mp) {
return __handler_func_supplemental(h, mp, packet_decode, NULL);
}
static int handler_func_dtmf(struct codec_handler *h, struct media_packet *mp) {
return __handler_func_supplemental(h, mp, packet_dtmf, packet_dtmf_dup);
}
static int handler_func_t38(struct codec_handler *h, struct media_packet *mp) { static int handler_func_t38(struct codec_handler *h, struct media_packet *mp) {
if (!mp->media) if (!mp->media)


Loading…
Cancel
Save