|
|
|
@ -1070,6 +1070,33 @@ static void __codec_rtcp_timer(struct call_media *receiver) { |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// returns: 0 = supp codec not present; 1 = sink has codec but receiver does not, 2 = both have codec |
|
|
|
int __supp_codec_match(struct call_media *receiver, struct call_media *sink, int pt, |
|
|
|
struct rtp_payload_type **sink_pt, struct rtp_payload_type **recv_pt) |
|
|
|
{ |
|
|
|
if (pt == -1) |
|
|
|
return 0; |
|
|
|
|
|
|
|
struct rtp_payload_type *sink_pt_stor = NULL; |
|
|
|
struct rtp_payload_type *recv_pt_stor = NULL; |
|
|
|
if (!sink_pt) |
|
|
|
sink_pt = &sink_pt_stor; |
|
|
|
if (!recv_pt) |
|
|
|
recv_pt = &recv_pt_stor; |
|
|
|
|
|
|
|
// find a matching output payload type |
|
|
|
*sink_pt = g_hash_table_lookup(sink->codecs_send, &pt); |
|
|
|
if (!*sink_pt) |
|
|
|
return 0; |
|
|
|
// XXX should go by codec name/params, not payload type number |
|
|
|
*recv_pt = g_hash_table_lookup(receiver->codecs_recv, &pt); |
|
|
|
if (!*recv_pt) |
|
|
|
return 1; |
|
|
|
if (rtp_payload_type_cmp(*sink_pt, *recv_pt)) |
|
|
|
return 1; |
|
|
|
return 2; |
|
|
|
} |
|
|
|
|
|
|
|
// 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) |
|
|
|
@ -1141,14 +1168,7 @@ void codec_handlers_update(struct call_media *receiver, struct call_media *sink, |
|
|
|
|
|
|
|
struct rtp_payload_type *dtmf_pt = NULL; |
|
|
|
struct rtp_payload_type *reverse_dtmf_pt = NULL; |
|
|
|
|
|
|
|
if (dtmf_payload_type != -1) { |
|
|
|
// find a matching output DTMF payload type |
|
|
|
dtmf_pt = g_hash_table_lookup(sink->codecs_send, &dtmf_payload_type); |
|
|
|
reverse_dtmf_pt = g_hash_table_lookup(receiver->codecs_recv, &dtmf_payload_type); |
|
|
|
if (reverse_dtmf_pt && dtmf_pt && rtp_payload_type_cmp(reverse_dtmf_pt, dtmf_pt)) |
|
|
|
reverse_dtmf_pt = NULL; |
|
|
|
} |
|
|
|
int dtmf_pt_match = __supp_codec_match(receiver, sink, dtmf_payload_type, &dtmf_pt, &reverse_dtmf_pt); |
|
|
|
|
|
|
|
// stop transcoding if we've determined that we don't need it |
|
|
|
if (MEDIA_ISSET(sink, TRANSCODE) && !sink_transcoding) { |
|
|
|
@ -1170,7 +1190,6 @@ void codec_handlers_update(struct call_media *receiver, struct call_media *sink, |
|
|
|
|
|
|
|
// do we need to detect PCM DTMF tones? |
|
|
|
int pcm_dtmf_detect = 0; |
|
|
|
if (reverse_dtmf_pt) |
|
|
|
if ((MEDIA_ISSET(sink, TRANSCODE) || (flags && flags->always_transcode)) |
|
|
|
&& dtmf_payload_type != -1 |
|
|
|
&& dtmf_pt && (!reverse_dtmf_pt || reverse_dtmf_pt->for_transcoding || |
|
|
|
@ -1222,7 +1241,7 @@ void codec_handlers_update(struct call_media *receiver, struct call_media *sink, |
|
|
|
GQueue *dest_codecs = NULL; |
|
|
|
if (!flags || !flags->always_transcode) { |
|
|
|
// we ignore output codec matches if we must transcode DTMF |
|
|
|
if (dtmf_pt && !reverse_dtmf_pt) |
|
|
|
if (dtmf_pt_match == 1 && MEDIA_ISSET(sink, TRANSCODE)) |
|
|
|
; |
|
|
|
else if (pcm_dtmf_detect) |
|
|
|
; |
|
|
|
@ -1343,7 +1362,7 @@ next: |
|
|
|
// sink's preferred destination codec. |
|
|
|
if (!transcode_supplemental && !pcm_dtmf_detect) |
|
|
|
__make_passthrough_ssrc(handler); |
|
|
|
else if (dtmf_pt && reverse_dtmf_pt) |
|
|
|
else if (dtmf_pt_match == 2) |
|
|
|
__make_passthrough_ssrc(handler); |
|
|
|
else if (!pref_dest_codec |
|
|
|
|| !handler->source_pt.codec_def || !pref_dest_codec->codec_def) |
|
|
|
@ -2317,13 +2336,21 @@ static int packet_encoded_rtp(encoder_t *enc, void *u1, void *u2) { |
|
|
|
|
|
|
|
ilog(LOG_DEBUG, "Received packet of %i bytes from packetizer", inout.len); |
|
|
|
|
|
|
|
// check special payloads |
|
|
|
|
|
|
|
unsigned int repeats = 0; |
|
|
|
int payload_type = -1; |
|
|
|
int is_dtmf = dtmf_event_payload(&inout, (uint64_t *) &enc->avpkt.pts, enc->avpkt.duration, |
|
|
|
&ch->dtmf_event, &ch->dtmf_events); |
|
|
|
if (is_dtmf == 1) |
|
|
|
ch->rtp_mark = 1; // DTMF start event |
|
|
|
else if (is_dtmf == 3) |
|
|
|
repeats = 2; // DTMF end event |
|
|
|
if (is_dtmf) { |
|
|
|
payload_type = ch->handler->dtmf_payload_type; |
|
|
|
if (is_dtmf == 1) |
|
|
|
ch->rtp_mark = 1; // DTMF start event |
|
|
|
else if (is_dtmf == 3) |
|
|
|
repeats = 2; // DTMF end event |
|
|
|
} |
|
|
|
|
|
|
|
// ready to send |
|
|
|
|
|
|
|
do { |
|
|
|
char *send_buf = buf; |
|
|
|
@ -2335,7 +2362,7 @@ static int packet_encoded_rtp(encoder_t *enc, void *u1, void *u2) { |
|
|
|
__output_rtp(mp, ch, ch->handler, send_buf, inout.len, ch->first_ts |
|
|
|
+ enc->avpkt.pts / enc->def->clockrate_mult, |
|
|
|
ch->rtp_mark ? 1 : 0, -1, 0, |
|
|
|
is_dtmf ? ch->handler->dtmf_payload_type : -1); |
|
|
|
payload_type); |
|
|
|
mp->ssrc_out->parent->seq_diff++; |
|
|
|
//mp->iter_out++; |
|
|
|
ch->rtp_mark = 0; |
|
|
|
@ -2702,9 +2729,7 @@ static void __insert_codec_tracker(struct call_media *media, GList *link) { |
|
|
|
} |
|
|
|
} |
|
|
|
#endif |
|
|
|
static void __queue_insert_supp(GQueue *q, struct rtp_payload_type *pt, int supp_check, |
|
|
|
struct codec_tracker *sct) |
|
|
|
{ |
|
|
|
static void __queue_insert_supp(GQueue *q, struct rtp_payload_type *pt, int supp_check) { |
|
|
|
// do we care at all? |
|
|
|
if (!supp_check) { |
|
|
|
g_queue_push_tail(q, pt); |
|
|
|
@ -2748,7 +2773,7 @@ void __rtp_payload_type_add_recv(struct call_media *media, struct rtp_payload_ty |
|
|
|
pt->ptime = media->ptime; |
|
|
|
g_hash_table_insert(media->codecs_recv, &pt->payload_type, pt); |
|
|
|
__rtp_payload_type_add_name(media->codec_names_recv, pt); |
|
|
|
__queue_insert_supp(&media->codecs_prefs_recv, pt, supp_check, media->codec_tracker); |
|
|
|
__queue_insert_supp(&media->codecs_prefs_recv, pt, supp_check); |
|
|
|
} |
|
|
|
// consumes 'pt' |
|
|
|
void __rtp_payload_type_add_send(struct call_media *other_media, |
|
|
|
|