diff --git a/daemon/call.c b/daemon/call.c index 4313a7dd8..c6deeeb86 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -683,6 +683,7 @@ static struct call_media *__get_media(struct call_monologue *ml, GList **it, con med->call = ml->call; med->index = sp->index; call_str_cpy(ml->call, &med->type, &sp->type); + med->type_id = codec_get_type(&med->type); med->codecs_recv = g_hash_table_new_full(g_int_hash, g_int_equal, NULL, NULL); med->codecs_send = g_hash_table_new_full(g_int_hash, g_int_equal, NULL, NULL); med->codec_names_recv = g_hash_table_new_full(str_hash, str_equal, NULL, (void (*)(void*)) g_queue_free); diff --git a/daemon/call.h b/daemon/call.h index 029f3df7c..12a53292d 100644 --- a/daemon/call.h +++ b/daemon/call.h @@ -19,6 +19,7 @@ #include "media_socket.h" #include "recording.h" #include "statistics.h" +#include "codeclib.h" #define UNDEFINED ((unsigned int) -1) @@ -310,6 +311,7 @@ struct call_media { unsigned int index; /* RO */ unsigned int unique_id; /* RO */ str type; /* RO */ + enum media_type type_id; // RO const struct transport_protocol *protocol; sockfamily_t *desired_family; const struct logical_intf *logical_intf; diff --git a/daemon/codec.c b/daemon/codec.c index 8a8498dd1..37574cf9b 100644 --- a/daemon/codec.c +++ b/daemon/codec.c @@ -109,11 +109,11 @@ reset: STR_FMT(&dest->encoding), dest->clock_rate, dest->channels); } -static void __ensure_codec_def(struct rtp_payload_type *pt) { +static void __ensure_codec_def(struct rtp_payload_type *pt, struct call_media *media) { if (pt->codec_def) return; - pt->codec_def = codec_find(&pt->encoding); + pt->codec_def = codec_find(&pt->encoding, media->type_id); if (!pt->codec_def) return; if (!pt->codec_def->encoder || !pt->codec_def->decoder) @@ -148,7 +148,7 @@ void codec_handlers_update(struct call_media *receiver, struct call_media *sink) struct rtp_payload_type *pref_dest_codec = NULL; for (GList *l = sink->codecs_prefs_send.head; l; l = l->next) { struct rtp_payload_type *pt = l->data; - __ensure_codec_def(pt); + __ensure_codec_def(pt, sink); if (!pt->codec_def || pt->codec_def->avcodec_id == -1) // not supported, next continue; @@ -171,7 +171,7 @@ void codec_handlers_update(struct call_media *receiver, struct call_media *sink) GList *insert_pos = NULL; for (GList *l = receiver->codecs_prefs_send.head; l; l = l->next) { struct rtp_payload_type *pt = l->data; - __ensure_codec_def(pt); + __ensure_codec_def(pt, receiver); if (!pt->codec_def) continue; if (g_hash_table_lookup(receiver->codecs_recv, &pt->payload_type)) { @@ -242,7 +242,7 @@ void codec_handlers_update(struct call_media *receiver, struct call_media *sink) } // check our own support for this codec - __ensure_codec_def(pt); + __ensure_codec_def(pt, receiver); if (!pt->codec_def || pt->codec_def->avcodec_id == -1) { // not supported, or not a real audio codec @@ -624,8 +624,9 @@ static struct rtp_payload_type *codec_make_dynamic_payload_type(const codec_def_ // XXX allow specifying codec params (e.g. "transcode=opus/16000/1") -static struct rtp_payload_type *codec_make_payload_type(const str *codec, struct call *call) { - const codec_def_t *dec = codec_find(codec); +static struct rtp_payload_type *codec_make_payload_type(const str *codec, struct call_media *media) { + struct call *call = media->call; + const codec_def_t *dec = codec_find(codec, media->type_id); if (!dec) return NULL; // we must support both encoding and decoding @@ -648,7 +649,7 @@ static struct rtp_payload_type *codec_make_payload_type(const str *codec, struct static struct rtp_payload_type *codec_add_payload_type(const str *codec, struct call_media *media) { - struct rtp_payload_type *pt = codec_make_payload_type(codec, media->call); + struct rtp_payload_type *pt = codec_make_payload_type(codec, media); if (!pt) { ilog(LOG_WARN, "Codec '" STR_FORMAT "' requested for transcoding is not supported", STR_FMT(codec)); diff --git a/lib/codeclib.c b/lib/codeclib.c index cd8b439ad..90dff11a8 100644 --- a/lib/codeclib.c +++ b/lib/codeclib.c @@ -42,6 +42,7 @@ static codec_def_t __codec_defs[] = { .default_ptime = 20, .packetizer = packetizer_samplestream, .bits_per_sample = 8, + .type = MT_AUDIO, }, { .rtpname = "PCMU", @@ -52,6 +53,7 @@ static codec_def_t __codec_defs[] = { .default_ptime = 20, .packetizer = packetizer_samplestream, .bits_per_sample = 8, + .type = MT_AUDIO, }, { .rtpname = "G723", @@ -61,6 +63,7 @@ static codec_def_t __codec_defs[] = { .default_channels = 1, .default_ptime = 30, .packetizer = packetizer_passthrough, + .type = MT_AUDIO, }, { .rtpname = "G722", @@ -71,6 +74,7 @@ static codec_def_t __codec_defs[] = { .default_ptime = 20, .packetizer = packetizer_samplestream, .bits_per_sample = 8, + .type = MT_AUDIO, }, { .rtpname = "QCELP", @@ -79,6 +83,7 @@ static codec_def_t __codec_defs[] = { .default_ptime = 20, .packetizer = packetizer_passthrough, .decode_only_ok = 1, + .type = MT_AUDIO, }, { .rtpname = "G729", @@ -88,6 +93,7 @@ static codec_def_t __codec_defs[] = { .default_channels = 1, .default_ptime = 20, .packetizer = packetizer_passthrough, + .type = MT_AUDIO, }, { .rtpname = "speex", @@ -97,6 +103,7 @@ static codec_def_t __codec_defs[] = { .default_bitrate = 11000, .default_ptime = 20, .packetizer = packetizer_passthrough, + .type = MT_AUDIO, }, { .rtpname = "GSM", @@ -105,12 +112,14 @@ static codec_def_t __codec_defs[] = { .default_channels = 1, .default_ptime = 20, .packetizer = packetizer_passthrough, + .type = MT_AUDIO, }, { .rtpname = "iLBC", .avcodec_id = AV_CODEC_ID_ILBC, .default_ptime = 20, .packetizer = packetizer_passthrough, + .type = MT_AUDIO, }, { .rtpname = "opus", @@ -121,6 +130,7 @@ static codec_def_t __codec_defs[] = { .default_bitrate = 32000, .default_ptime = 20, .packetizer = packetizer_passthrough, + .type = MT_AUDIO, }, { .rtpname = "vorbis", @@ -128,18 +138,21 @@ static codec_def_t __codec_defs[] = { .avcodec_name = "libvorbis", .default_ptime = 20, .packetizer = packetizer_passthrough, + .type = MT_AUDIO, }, { .rtpname = "ac3", .avcodec_id = AV_CODEC_ID_AC3, .default_ptime = 20, .packetizer = packetizer_passthrough, + .type = MT_AUDIO, }, { .rtpname = "eac3", .avcodec_id = AV_CODEC_ID_EAC3, .default_ptime = 20, .packetizer = packetizer_passthrough, + .type = MT_AUDIO, }, { .rtpname = "ATRAC3", @@ -147,6 +160,7 @@ static codec_def_t __codec_defs[] = { .default_ptime = 20, .packetizer = packetizer_passthrough, .decode_only_ok = 1, + .type = MT_AUDIO, }, { .rtpname = "ATRAC-X", @@ -154,6 +168,7 @@ static codec_def_t __codec_defs[] = { .default_ptime = 20, .packetizer = packetizer_passthrough, .decode_only_ok = 1, + .type = MT_AUDIO, }, #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 0, 0) { @@ -163,6 +178,7 @@ static codec_def_t __codec_defs[] = { .default_ptime = 20, .packetizer = packetizer_passthrough, .decode_only_ok = 1, + .type = MT_AUDIO, }, { .rtpname = "EVRC0", @@ -172,6 +188,7 @@ static codec_def_t __codec_defs[] = { .default_ptime = 20, .packetizer = packetizer_passthrough, .decode_only_ok = 1, + .type = MT_AUDIO, }, { .rtpname = "EVRC1", @@ -181,6 +198,7 @@ static codec_def_t __codec_defs[] = { .default_ptime = 20, .packetizer = packetizer_passthrough, .decode_only_ok = 1, + .type = MT_AUDIO, }, #endif { @@ -192,6 +210,7 @@ static codec_def_t __codec_defs[] = { .default_bitrate = 6600, .default_ptime = 20, .packetizer = packetizer_passthrough, + .type = MT_AUDIO, }, { .rtpname = "AMR-WB", @@ -202,6 +221,7 @@ static codec_def_t __codec_defs[] = { .default_bitrate = 14250, .default_ptime = 20, .packetizer = packetizer_passthrough, + .type = MT_AUDIO, }, // pseudo-codecs { @@ -209,6 +229,7 @@ static codec_def_t __codec_defs[] = { .avcodec_id = -1, .avcodec_name = NULL, .packetizer = packetizer_passthrough, + .type = MT_AUDIO, }, // for file writing { @@ -216,12 +237,14 @@ static codec_def_t __codec_defs[] = { .avcodec_id = AV_CODEC_ID_PCM_S16LE, .avcodec_name = NULL, .packetizer = packetizer_passthrough, + .type = MT_AUDIO, }, { .rtpname = "MP3", .avcodec_id = AV_CODEC_ID_MP3, .avcodec_name = NULL, .packetizer = packetizer_passthrough, + .type = MT_AUDIO, }, }; @@ -231,11 +254,27 @@ static GHashTable *codecs_ht; -const codec_def_t *codec_find(const str *name) { +const codec_def_t *codec_find(const str *name, enum media_type type) { codec_def_t *ret = g_hash_table_lookup(codecs_ht, name); + if (!ret) + return NULL; + if (type && type != ret->type) + return NULL; return ret; } +enum media_type codec_get_type(const str *type) { + if (!type || !type->len) + return MT_UNKNOWN; + if (!str_cmp(type, "audio")) + return MT_AUDIO; + if (!str_cmp(type, "video")) + return MT_VIDEO; + if (!str_cmp(type, "image")) + return MT_IMAGE; + return MT_OTHER; +} + decoder_t *decoder_new_fmt(const codec_def_t *def, int clockrate, int channels, const format_t *resample_fmt) { diff --git a/lib/codeclib.h b/lib/codeclib.h index 5ed247922..9bbc78f8f 100644 --- a/lib/codeclib.h +++ b/lib/codeclib.h @@ -29,6 +29,14 @@ typedef int packetizer_f(AVPacket *, GString *, str *); +enum media_type { + MT_UNKNOWN = 0, + MT_AUDIO, + MT_VIDEO, + MT_IMAGE, + MT_OTHER, +}; + struct codec_def_s { const char * const rtpname; int clockrate_mult; @@ -41,6 +49,7 @@ struct codec_def_s { packetizer_f * const packetizer; const int bits_per_sample; const int decode_only_ok; + const enum media_type type; // filled in by codeclib_init() str rtpname_str; @@ -101,7 +110,8 @@ struct packet_sequencer_s { void codeclib_init(void); -const codec_def_t *codec_find(const str *name); +const codec_def_t *codec_find(const str *name, enum media_type); +enum media_type codec_get_type(const str *type); decoder_t *decoder_new_fmt(const codec_def_t *def, int clockrate, int channels, const format_t *resample_fmt); diff --git a/recording-daemon/decoder.c b/recording-daemon/decoder.c index 0f9046594..d8af63704 100644 --- a/recording-daemon/decoder.c +++ b/recording-daemon/decoder.c @@ -41,7 +41,7 @@ decoder_t *decoder_new(const char *payload_str) { channels = 1; } - const codec_def_t *def = codec_find(&name); + const codec_def_t *def = codec_find(&name, MT_AUDIO); if (!def) { ilog(LOG_WARN, "No decoder for payload %s", payload_str); return NULL; diff --git a/recording-daemon/output.c b/recording-daemon/output.c index f11d0ebb2..fbbcddf54 100644 --- a/recording-daemon/output.c +++ b/recording-daemon/output.c @@ -229,6 +229,6 @@ void output_init(const char *format) { else die("Unknown output format '%s'", format); - output_codec = codec_find(&codec); + output_codec = codec_find(&codec, MT_AUDIO); assert(output_codec != NULL); }