|
|
@ -98,6 +98,7 @@ static struct codec_handler codec_handler_stub_ssrc = {
|
|
|
|
static void __handler_shutdown(struct codec_handler *handler) {
|
|
|
|
static void __handler_shutdown(struct codec_handler *handler) {
|
|
|
|
free_ssrc_hash(&handler->ssrc_hash);
|
|
|
|
free_ssrc_hash(&handler->ssrc_hash);
|
|
|
|
handler->kernelize = 0;
|
|
|
|
handler->kernelize = 0;
|
|
|
|
|
|
|
|
handler->transcoder = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void __codec_handler_free(void *pp) {
|
|
|
|
static void __codec_handler_free(void *pp) {
|
|
|
@ -142,6 +143,8 @@ static void __make_transcoder(struct codec_handler *handler, struct rtp_payload_
|
|
|
|
assert(source->payload_type == handler->source_pt.payload_type);
|
|
|
|
assert(source->payload_type == handler->source_pt.payload_type);
|
|
|
|
|
|
|
|
|
|
|
|
// don't reset handler if it already matches what we want
|
|
|
|
// don't reset handler if it already matches what we want
|
|
|
|
|
|
|
|
if (!handler->transcoder)
|
|
|
|
|
|
|
|
goto reset;
|
|
|
|
if (rtp_payload_type_cmp(source, &handler->source_pt))
|
|
|
|
if (rtp_payload_type_cmp(source, &handler->source_pt))
|
|
|
|
goto reset;
|
|
|
|
goto reset;
|
|
|
|
if (rtp_payload_type_cmp(dest, &handler->dest_pt))
|
|
|
|
if (rtp_payload_type_cmp(dest, &handler->dest_pt))
|
|
|
@ -161,6 +164,7 @@ reset:
|
|
|
|
handler->source_pt = *source;
|
|
|
|
handler->source_pt = *source;
|
|
|
|
handler->dest_pt = *dest;
|
|
|
|
handler->dest_pt = *dest;
|
|
|
|
handler->func = handler_func_transcode;
|
|
|
|
handler->func = handler_func_transcode;
|
|
|
|
|
|
|
|
handler->transcoder = 1;
|
|
|
|
|
|
|
|
|
|
|
|
handler->ssrc_hash = create_ssrc_hash_full(__ssrc_handler_transcode_new, handler);
|
|
|
|
handler->ssrc_hash = create_ssrc_hash_full(__ssrc_handler_transcode_new, handler);
|
|
|
|
|
|
|
|
|
|
|
@ -233,13 +237,34 @@ void codec_handlers_update(struct call_media *receiver, struct call_media *sink,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// similarly, if the sink 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
|
|
|
|
if (MEDIA_ISSET(sink, TRANSCODE)) {
|
|
|
|
// XXX these blocks should go into their own functions
|
|
|
|
|
|
|
|
if (MEDIA_ISSET(sink, TRANSCODE) && !sink_transcoding) {
|
|
|
|
for (GList *l = sink->codecs_prefs_recv.head; l; l = l->next) {
|
|
|
|
for (GList *l = sink->codecs_prefs_recv.head; l; l = l->next) {
|
|
|
|
struct rtp_payload_type *pt = l->data;
|
|
|
|
struct rtp_payload_type *pt = l->data;
|
|
|
|
if (!g_hash_table_lookup(receiver->codec_names_recv, &pt->encoding))
|
|
|
|
GQueue *recv_pts = g_hash_table_lookup(receiver->codec_names_recv, &pt->encoding);
|
|
|
|
|
|
|
|
if (!recv_pts) {
|
|
|
|
sink_transcoding = 1;
|
|
|
|
sink_transcoding = 1;
|
|
|
|
|
|
|
|
goto done;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// even if the receiver can receive the same codec that the sink can
|
|
|
|
|
|
|
|
// send, we might still have it configured as a transcoder due to
|
|
|
|
|
|
|
|
// always-transcode in the offer
|
|
|
|
|
|
|
|
for (GList *k = recv_pts->head; k; k = k->next) {
|
|
|
|
|
|
|
|
// XXX codec_handlers can be converted to g_direct_hash table
|
|
|
|
|
|
|
|
int pt = GPOINTER_TO_INT(k->data);
|
|
|
|
|
|
|
|
struct codec_handler *ch_recv =
|
|
|
|
|
|
|
|
g_hash_table_lookup(sink->codec_handlers, &pt);
|
|
|
|
|
|
|
|
if (!ch_recv)
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (ch_recv->transcoder) {
|
|
|
|
|
|
|
|
sink_transcoding = 1;
|
|
|
|
|
|
|
|
goto done;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
done:;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// stop transcoding if we've determined that we don't need it
|
|
|
|
// stop transcoding if we've determined that we don't need it
|
|
|
|