diff --git a/daemon/codec.c b/daemon/codec.c index 71b59df26..f45863c3b 100644 --- a/daemon/codec.c +++ b/daemon/codec.c @@ -448,6 +448,85 @@ void codec_packet_free(void *pp) { +struct rtp_payload_type *codec_make_payload_type(const str *codec_str, struct call_media *media) { + str codec_fmt = *codec_str; + str codec, parms, chans, opts, extra_opts; + if (str_token_sep(&codec, &codec_fmt, '/')) + return NULL; + str_token_sep(&parms, &codec_fmt, '/'); + str_token_sep(&chans, &codec_fmt, '/'); + str_token_sep(&opts, &codec_fmt, '/'); + str_token_sep(&extra_opts, &codec_fmt, '/'); + + int clockrate = str_to_i(&parms, 0); + int channels = str_to_i(&chans, 0); + int bitrate = str_to_i(&opts, 0); + int ptime = str_to_i(&extra_opts, 0); + + if (clockrate && !channels) + channels = 1; + + struct rtp_payload_type *ret = g_slice_alloc0(sizeof(*ret)); + ret->payload_type = -1; + ret->encoding = codec; + ret->clock_rate = clockrate; + ret->channels = channels; + ret->bitrate = bitrate; + ret->ptime = ptime; + + const codec_def_t *def = codec_find(&ret->encoding, 0); + ret->codec_def = def; + +#ifdef WITH_TRANSCODING + if (!ret->clock_rate) + ret->clock_rate = def->default_clockrate; + if (!ret->channels) + ret->channels = def->default_channels; + if (!ret->ptime) + ret->ptime = def->default_ptime; + + if (def->init) + def->init(ret); + + if (def->rfc_payload_type >= 0) { + const struct rtp_payload_type *rfc_pt = rtp_get_rfc_payload_type(def->rfc_payload_type); + // only use the RFC payload type if all parameters match + if (rfc_pt + && (ret->clock_rate == 0 || ret->clock_rate == rfc_pt->clock_rate) + && (ret->channels == 0 || ret->channels == rfc_pt->channels)) + { + ret->payload_type = rfc_pt->payload_type; + if (!ret->clock_rate) + ret->clock_rate = rfc_pt->clock_rate; + if (!ret->channels) + ret->channels = rfc_pt->channels; + } + } +#endif + + // init params strings + char full_encoding[64]; + char params[32] = ""; + + if (ret->channels > 1) { + snprintf(full_encoding, sizeof(full_encoding), STR_FORMAT "/%u/%i", STR_FMT(&codec), + ret->clock_rate, + ret->channels); + snprintf(params, sizeof(params), "%i", ret->channels); + } + else + snprintf(full_encoding, sizeof(full_encoding), STR_FORMAT "/%u", STR_FMT(&codec), + ret->clock_rate); + + str_init(&ret->encoding_with_params, full_encoding); + str_init(&ret->encoding_parameters, params); + ret->format_parameters = STR_EMPTY; + + __rtp_payload_type_dup(media->call, ret); + + return ret; +} + #ifdef WITH_TRANSCODING @@ -692,95 +771,36 @@ static int handler_func_transcode(struct codec_handler *h, struct call_media *me -static struct rtp_payload_type *codec_make_dynamic_payload_type(const codec_def_t *dec, struct call_media *media, - int clockrate, int channels, int bitrate, int ptime) -{ - if (dec->default_channels <= 0 || dec->default_clockrate < 0) +// special return value `(void *) 0x1` to signal type mismatch +static struct rtp_payload_type *codec_make_payload_type_sup(const str *codec_str, struct call_media *media) { + struct rtp_payload_type *ret = codec_make_payload_type(codec_str, media); + if (!ret) return NULL; - struct rtp_payload_type *ret = g_slice_alloc0(sizeof(*ret)); - ret->payload_type = -1; - str_init(&ret->encoding, (char *) dec->rtpname); - ret->clock_rate = clockrate ? : dec->default_clockrate; - ret->channels = channels ? : dec->default_channels; - ret->bitrate = bitrate; - ret->ptime = ptime ? : (media->ptime ? : dec->default_ptime); - - if (dec->init) - dec->init(ret); - - char full_encoding[64]; - char params[32] = ""; - - if (ret->channels > 1) { - snprintf(full_encoding, sizeof(full_encoding), "%s/%u/%i", dec->rtpname, ret->clock_rate, - ret->channels); - snprintf(params, sizeof(params), "%i", ret->channels); + if (media->type_id && ret->codec_def->media_type != media->type_id) { + payload_type_free(ret); + return (void *) 0x1; } - else - snprintf(full_encoding, sizeof(full_encoding), "%s/%u", dec->rtpname, ret->clock_rate); - - str_init(&ret->encoding_with_params, full_encoding); - str_init(&ret->encoding_parameters, params); - ret->format_parameters = STR_EMPTY; - ret->codec_def = dec; - - __rtp_payload_type_dup(media->call, ret); + // we must support both encoding and decoding + if (!ret->codec_def->support_decoding) + goto err; + if (!ret->codec_def->support_encoding) + goto err; + if (ret->codec_def->default_channels <= 0 || ret->codec_def->default_clockrate < 0) + goto err; return ret; -} -// special return value `(void *) 0x1` to signal type mismatch -struct rtp_payload_type *codec_make_payload_type(const str *codec_str, struct call_media *media) { - str codec_fmt = *codec_str; - str codec, parms, chans, opts, extra_opts; - if (str_token_sep(&codec, &codec_fmt, '/')) - return NULL; - str_token_sep(&parms, &codec_fmt, '/'); - str_token_sep(&chans, &codec_fmt, '/'); - str_token_sep(&opts, &codec_fmt, '/'); - str_token_sep(&extra_opts, &codec_fmt, '/'); - - int clockrate = str_to_i(&parms, 0); - int channels = str_to_i(&chans, 0); - int bitrate = str_to_i(&opts, 0); - int ptime = str_to_i(&extra_opts, 0); - - if (clockrate && !channels) - channels = 1; - - const codec_def_t *dec = codec_find(&codec, 0); - if (!dec) - return NULL; - if (media->type_id && dec->media_type != media->type_id) - return (void *) 0x1; - // we must support both encoding and decoding - if (!dec->support_decoding) - return NULL; - if (!dec->support_encoding) - return NULL; - - if (dec->rfc_payload_type >= 0) { - const struct rtp_payload_type *rfc_pt = rtp_get_rfc_payload_type(dec->rfc_payload_type); - // only use the RFC payload type if all parameters match - if (rfc_pt - && (clockrate == 0 || clockrate == rfc_pt->clock_rate) - && (channels == 0 || channels == rfc_pt->channels)) - { - struct rtp_payload_type *ret = __rtp_payload_type_copy(rfc_pt); - ret->codec_def = dec; - ret->ptime = ptime; - return ret; - } - } - return codec_make_dynamic_payload_type(dec, media, clockrate, channels, bitrate, ptime); +err: + payload_type_free(ret); + return NULL; } 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); + struct rtp_payload_type *pt = codec_make_payload_type_sup(codec, media); if (!pt) { ilog(LOG_WARN, "Codec '" STR_FORMAT "' requested for transcoding is not supported", STR_FMT(codec)); diff --git a/daemon/redis.c b/daemon/redis.c index d1fcccf2c..d92bbc683 100644 --- a/daemon/redis.c +++ b/daemon/redis.c @@ -1209,7 +1209,7 @@ static struct rtp_payload_type *rbl_cb_plts_g(str *s, GQueue *q, struct redis_li return NULL; struct rtp_payload_type *pt = codec_make_payload_type(s, med); - if (!pt || pt == (void *) 0x1) + if (!pt) return NULL; pt->payload_type = str_to_i(&ptype, 0);