|
|
|
|
@ -33,6 +33,7 @@ struct transcode_packet {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static codec_handler_func handler_func_passthrough;
|
|
|
|
|
static codec_handler_func handler_func_passthrough_ssrc;
|
|
|
|
|
static codec_handler_func handler_func_transcode;
|
|
|
|
|
|
|
|
|
|
static struct ssrc_entry *__ssrc_handler_new(void *p);
|
|
|
|
|
@ -49,6 +50,10 @@ static struct codec_handler codec_handler_stub = {
|
|
|
|
|
.source_pt.payload_type = -1,
|
|
|
|
|
.func = handler_func_passthrough,
|
|
|
|
|
};
|
|
|
|
|
static struct codec_handler codec_handler_stub_ssrc = {
|
|
|
|
|
.source_pt.payload_type = -1,
|
|
|
|
|
.func = handler_func_passthrough_ssrc,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -73,6 +78,11 @@ static void __make_passthrough(struct codec_handler *handler) {
|
|
|
|
|
handler->func = handler_func_passthrough;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void __make_passthrough_ssrc(struct codec_handler *handler) {
|
|
|
|
|
__handler_shutdown(handler);
|
|
|
|
|
handler->func = handler_func_passthrough_ssrc;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void __make_transcoder(struct codec_handler *handler, struct rtp_payload_type *source,
|
|
|
|
|
struct rtp_payload_type *dest)
|
|
|
|
|
{
|
|
|
|
|
@ -140,6 +150,7 @@ void codec_handlers_update(struct call_media *receiver, struct call_media *sink)
|
|
|
|
|
|
|
|
|
|
MEDIA_CLEAR(receiver, TRANSCODE);
|
|
|
|
|
receiver->rtcp_handler = NULL;
|
|
|
|
|
GSList *passthrough_handlers = NULL;
|
|
|
|
|
|
|
|
|
|
// we go through the list of codecs that the receiver supports and compare it
|
|
|
|
|
// with the list of codecs supported by the sink. if the receiver supports
|
|
|
|
|
@ -250,6 +261,7 @@ void codec_handlers_update(struct call_media *receiver, struct call_media *sink)
|
|
|
|
|
if (!pt->codec_def || pt->codec_def->avcodec_id == -1) {
|
|
|
|
|
// not supported, or not a real audio codec
|
|
|
|
|
__make_passthrough(handler);
|
|
|
|
|
passthrough_handlers = g_slist_prepend(passthrough_handlers, handler);
|
|
|
|
|
goto next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -267,6 +279,7 @@ void codec_handlers_update(struct call_media *receiver, struct call_media *sink)
|
|
|
|
|
ilog(LOG_DEBUG, "No known/supported sink codec for " STR_FORMAT,
|
|
|
|
|
STR_FMT(&pt->encoding_with_params));
|
|
|
|
|
__make_passthrough(handler);
|
|
|
|
|
passthrough_handlers = g_slist_prepend(passthrough_handlers, handler);
|
|
|
|
|
goto next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -303,6 +316,7 @@ void codec_handlers_update(struct call_media *receiver, struct call_media *sink)
|
|
|
|
|
// XXX check format parameters as well
|
|
|
|
|
ilog(LOG_DEBUG, "Sink supports codec " STR_FORMAT, STR_FMT(&pt->encoding_with_params));
|
|
|
|
|
__make_passthrough(handler);
|
|
|
|
|
passthrough_handlers = g_slist_prepend(passthrough_handlers, handler);
|
|
|
|
|
goto next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -322,8 +336,6 @@ next:
|
|
|
|
|
// the list, as we must expect to potentially receive media in that codec, which we
|
|
|
|
|
// then could not transcode.
|
|
|
|
|
if (MEDIA_ISSET(receiver, TRANSCODE)) {
|
|
|
|
|
// XXX we also must switch all "passthrough" handlers to a special passthrough
|
|
|
|
|
// that substitutes out the SSRC
|
|
|
|
|
for (GList *l = receiver->codecs_prefs_recv.head; l; ) {
|
|
|
|
|
struct rtp_payload_type *pt = l->data;
|
|
|
|
|
|
|
|
|
|
@ -338,7 +350,18 @@ next:
|
|
|
|
|
l = __delete_receiver_codec(receiver, l);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// we have to translate RTCP packets
|
|
|
|
|
receiver->rtcp_handler = rtcp_transcode_handler;
|
|
|
|
|
|
|
|
|
|
// at least some payload types will be transcoded, which will result in SSRC
|
|
|
|
|
// change. for payload types which we don't actually transcode, we still
|
|
|
|
|
// must substitute the SSRC
|
|
|
|
|
while (passthrough_handlers) {
|
|
|
|
|
struct codec_handler *handler = passthrough_handlers->data;
|
|
|
|
|
__make_passthrough_ssrc(handler);
|
|
|
|
|
passthrough_handlers = g_slist_delete_link(passthrough_handlers, passthrough_handlers);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -362,6 +385,8 @@ struct codec_handler *codec_handler_get(struct call_media *m, int payload_type)
|
|
|
|
|
return h;
|
|
|
|
|
|
|
|
|
|
out:
|
|
|
|
|
if (MEDIA_ISSET(m, TRANSCODE))
|
|
|
|
|
return &codec_handler_stub_ssrc;
|
|
|
|
|
return &codec_handler_stub;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -384,6 +409,20 @@ static int handler_func_passthrough(struct codec_handler *h, struct call_media *
|
|
|
|
|
codec_add_raw_packet(mp);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
static int handler_func_passthrough_ssrc(struct codec_handler *h, struct call_media *media,
|
|
|
|
|
struct media_packet *mp)
|
|
|
|
|
{
|
|
|
|
|
if (G_UNLIKELY(!mp->rtp))
|
|
|
|
|
return handler_func_passthrough(h, media, mp);
|
|
|
|
|
|
|
|
|
|
// substitute out SSRC
|
|
|
|
|
mp->rtp->ssrc = htonl(mp->ssrc_in->ssrc_map_out);
|
|
|
|
|
|
|
|
|
|
// keep track of other stats here?
|
|
|
|
|
|
|
|
|
|
codec_add_raw_packet(mp);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void __transcode_packet_free(struct transcode_packet *p) {
|
|
|
|
|
@ -545,7 +584,7 @@ static int __packet_decoded(decoder_t *decoder, AVFrame *frame, void *u1, void *
|
|
|
|
|
static int handler_func_transcode(struct codec_handler *h, struct call_media *media,
|
|
|
|
|
struct media_packet *mp)
|
|
|
|
|
{
|
|
|
|
|
if (G_UNLIKELY(!mp->rtp || mp->rtcp))
|
|
|
|
|
if (G_UNLIKELY(!mp->rtp))
|
|
|
|
|
return handler_func_passthrough(h, media, mp);
|
|
|
|
|
|
|
|
|
|
assert((mp->rtp->m_pt & 0x7f) == h->source_pt.payload_type);
|
|
|
|
|
|