From 9147d5e438a83ba7d581e1e096a1aee691cbf380 Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Wed, 14 Feb 2018 09:17:44 -0500 Subject: [PATCH] TT#32983 support transcoding options in redis (re)store Change-Id: I8552743a5ec48b6d4464e8a2c4acd1c9bf11f02a --- daemon/call.c | 18 +++++++---- daemon/call.h | 1 + daemon/codec.c | 33 +++++++++++++------ daemon/codec.h | 8 +++++ daemon/redis.c | 88 ++++++++++++++++++++++++++++---------------------- 5 files changed, 94 insertions(+), 54 deletions(-) diff --git a/daemon/call.c b/daemon/call.c index c6deeeb86..940868b44 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -656,6 +656,17 @@ void payload_type_free(struct rtp_payload_type *p) { g_slice_free1(sizeof(*p), p); } +struct call_media *call_media_new(struct call *call) { + struct call_media *med; + med = uid_slice_alloc0(med, &call->medias); + med->call = call; + 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); + med->codec_names_send = g_hash_table_new_full(str_hash, str_equal, NULL, (void (*)(void*)) g_queue_free); + return med; +} + static struct call_media *__get_media(struct call_monologue *ml, GList **it, const struct stream_params *sp) { struct call_media *med; struct call *call; @@ -678,16 +689,11 @@ static struct call_media *__get_media(struct call_monologue *ml, GList **it, con __C_DBG("allocating new call_media for stream #%u", sp->index); call = ml->call; - med = uid_slice_alloc0(med, &call->medias); + med = call_media_new(call); med->monologue = ml; - 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); - med->codec_names_send = g_hash_table_new_full(str_hash, str_equal, NULL, (void (*)(void*)) g_queue_free); g_queue_push_tail(&ml->medias, med); diff --git a/daemon/call.h b/daemon/call.h index a049a59f8..b0af6d21c 100644 --- a/daemon/call.h +++ b/daemon/call.h @@ -429,6 +429,7 @@ int monologue_offer_answer(struct call_monologue *monologue, GQueue *streams, co int call_delete_branch(const str *callid, const str *branch, const str *fromtag, const str *totag, bencode_item_t *output, int delete_delay); void call_destroy(struct call *); +struct call_media *call_media_new(struct call *call); enum call_stream_state call_stream_state_machine(struct packet_stream *); void call_media_state_machine(struct call_media *m); void call_media_unkernelize(struct call_media *media); diff --git a/daemon/codec.c b/daemon/codec.c index 350f9ef58..f21d175c4 100644 --- a/daemon/codec.c +++ b/daemon/codec.c @@ -693,7 +693,7 @@ 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 clockrate, int channels, int bitrate, int ptime) { if (dec->default_channels <= 0 || dec->default_clockrate < 0) return NULL; @@ -704,7 +704,7 @@ static struct rtp_payload_type *codec_make_dynamic_payload_type(const codec_def_ ret->clock_rate = clockrate ? : dec->default_clockrate; ret->channels = channels ? : dec->default_channels; ret->bitrate = bitrate; - ret->ptime = media->ptime ? : dec->default_ptime; + ret->ptime = ptime ? : (media->ptime ? : dec->default_ptime); if (dec->init) dec->init(ret); @@ -732,18 +732,20 @@ static struct rtp_payload_type *codec_make_dynamic_payload_type(const codec_def_ // special return value `(void *) 0x1` to signal type mismatch -static struct rtp_payload_type *codec_make_payload_type(const str *codec_str, struct call_media *media) { +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; + 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; @@ -768,10 +770,11 @@ static struct rtp_payload_type *codec_make_payload_type(const str *codec_str, st { 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); + return codec_make_dynamic_payload_type(dec, media, clockrate, channels, bitrate, ptime); } @@ -835,28 +838,38 @@ static void __rtp_payload_type_add_name(GHashTable *ht, struct rtp_payload_type g_queue_push_tail(q, GUINT_TO_POINTER(pt->payload_type)); } // consumes 'pt' -static void __rtp_payload_type_add_recv(struct call_media *media, +void __rtp_payload_type_add_recv(struct call_media *media, struct rtp_payload_type *pt) { + if (!pt) + return; g_hash_table_insert(media->codecs_recv, &pt->payload_type, pt); __rtp_payload_type_add_name(media->codec_names_recv, pt); g_queue_push_tail(&media->codecs_prefs_recv, pt); } -// duplicates 'pt' -static void __rtp_payload_type_add_send(struct call_media *other_media, +// consumes 'pt' +void __rtp_payload_type_add_send(struct call_media *other_media, struct rtp_payload_type *pt) { - pt = __rtp_payload_type_copy(pt); + if (!pt) + return; g_hash_table_insert(other_media->codecs_send, &pt->payload_type, pt); __rtp_payload_type_add_name(other_media->codec_names_send, pt); g_queue_push_tail(&other_media->codecs_prefs_send, pt); } +// duplicates 'pt' +void __rtp_payload_type_add_send_dup(struct call_media *other_media, + struct rtp_payload_type *pt) +{ + pt = __rtp_payload_type_copy(pt); + __rtp_payload_type_add_send(other_media, pt); +} // consumes 'pt' static void __rtp_payload_type_add(struct call_media *media, struct call_media *other_media, struct rtp_payload_type *pt) { __rtp_payload_type_add_recv(media, pt); - __rtp_payload_type_add_send(other_media, pt); + __rtp_payload_type_add_send_dup(other_media, pt); } static void __payload_queue_free(void *qq) { diff --git a/daemon/codec.h b/daemon/codec.h index 0ec9aba6c..897e1f754 100644 --- a/daemon/codec.h +++ b/daemon/codec.h @@ -43,6 +43,14 @@ void codec_rtp_payload_types(struct call_media *media, struct call_media *other_ GQueue *types, GHashTable *strip, const GQueue *offer, const GQueue *transcode); +// 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); + + +// used by redis +void __rtp_payload_type_add_recv(struct call_media *media, struct rtp_payload_type *pt); +void __rtp_payload_type_add_send(struct call_media *other_media, struct rtp_payload_type *pt); + #ifdef WITH_TRANSCODING diff --git a/daemon/redis.c b/daemon/redis.c index 413fe0fc2..d1fcccf2c 100644 --- a/daemon/redis.c +++ b/daemon/redis.c @@ -31,6 +31,7 @@ #include "str.h" #include "ssrc.h" #include "main.h" +#include "codec.h" struct redis *rtpe_redis; struct redis *rtpe_redis_write; @@ -1200,34 +1201,29 @@ static int redis_tags(struct call *c, struct redis_list *tags) { return 0; } -static int rbl_cb_plts(str *s, GQueue *q, struct redis_list *list, void *ptr) { - struct rtp_payload_type *pt; - str ptype, enc, clock, enc_parms, fmt_parms; +static struct rtp_payload_type *rbl_cb_plts_g(str *s, GQueue *q, struct redis_list *list, void *ptr) { + str ptype; struct call_media *med = ptr; - struct call *call = med->call; if (str_token(&ptype, s, '/')) - return -1; - if (str_token(&enc, s, '/')) - return -1; - if (str_token(&clock, s, '/')) - return -1; - if (str_token(&enc_parms, s, '/')) { - enc_parms = *s; - fmt_parms = STR_EMPTY; - } - else - fmt_parms = *s; - - // from call.c - // XXX remove all the duplicate code - pt = g_slice_alloc0(sizeof(*pt)); - pt->payload_type = str_to_ui(&ptype, 0); - call_str_cpy(call, &pt->encoding, &enc); - pt->clock_rate = str_to_ui(&clock, 0); - call_str_cpy(call, &pt->encoding_parameters, &enc_parms); - call_str_cpy(call, &pt->format_parameters, &fmt_parms); - g_hash_table_replace(med->codecs_recv, &pt->payload_type, pt); + return NULL; + + struct rtp_payload_type *pt = codec_make_payload_type(s, med); + if (!pt || pt == (void *) 0x1) + return NULL; + + pt->payload_type = str_to_i(&ptype, 0); + + return pt; +} +static int rbl_cb_plts_r(str *s, GQueue *q, struct redis_list *list, void *ptr) { + struct call_media *med = ptr; + __rtp_payload_type_add_recv(med, rbl_cb_plts_g(s, q, list, ptr)); + return 0; +} +static int rbl_cb_plts_s(str *s, GQueue *q, struct redis_list *list, void *ptr) { + struct call_media *med = ptr; + __rtp_payload_type_add_send(med, rbl_cb_plts_g(s, q, list, ptr)); return 0; } static int json_medias(struct call *c, struct redis_list *medias, JsonReader *root_reader) { @@ -1240,10 +1236,7 @@ static int json_medias(struct call *c, struct redis_list *medias, JsonReader *ro rh = &medias->rh[i]; /* from call.c:__get_media() */ - med = uid_slice_alloc0(med, &c->medias); - med->call = c; - med->codecs_recv = g_hash_table_new_full(g_int_hash, g_int_equal, NULL, - (GDestroyNotify) payload_type_free); + med = call_media_new(c); if (redis_hash_get_unsigned(&med->index, rh, "index")) return -1; @@ -1278,7 +1271,8 @@ static int json_medias(struct call *c, struct redis_list *medias, JsonReader *ro if (redis_hash_get_crypto_params(&med->sdes_out.params, rh, "sdes_out") < 0) return -1; - json_build_list_cb(NULL, c, "payload_types", i, NULL, rbl_cb_plts, med, root_reader); + json_build_list_cb(NULL, c, "payload_types", i, NULL, rbl_cb_plts_r, med, root_reader); + json_build_list_cb(NULL, c, "payload_types_send", i, NULL, rbl_cb_plts_s, med, root_reader); /* XXX dtls */ medias->ptrs[i] = med; @@ -1409,6 +1403,17 @@ static int json_link_medias(struct call *c, struct redis_list *medias, return -1; if (json_build_list(&med->endpoint_maps, c, "maps", &c->callid, i, maps, root_reader)) return -1; + + // find the pair media + struct call_monologue *ml = med->monologue; + struct call_monologue *other_ml = ml->active_dialogue; + for (GList *l = other_ml->medias.head; l; l = l->next) { + struct call_media *other_m = l->data; + if (other_m->index == med->index) { + codec_handlers_update(med, other_m); + break; + } + } } return 0; } @@ -1971,6 +1976,7 @@ char* redis_encode_json(struct call *c) { JSON_SET_SIMPLE("sdes_in_tag","%u",media->sdes_in.tag); JSON_SET_SIMPLE("sdes_out_tag","%u",media->sdes_out.tag); JSON_SET_SIMPLE_STR("logical_intf",&media->logical_intf->name); + JSON_SET_SIMPLE("ptime","%i",media->ptime); JSON_SET_SIMPLE("media_flags","%u",media->media_flags); json_update_crypto_params(builder, "media", media->unique_id, "sdes_in", @@ -1978,9 +1984,6 @@ char* redis_encode_json(struct call *c) { json_update_crypto_params(builder, "media", media->unique_id, "sdes_out", &media->sdes_out.params); json_update_dtls_fingerprint(builder, "media", media->unique_id, &media->fingerprint); - - // streams and maps- and payload_types- was here before - } json_builder_end_object (builder); @@ -2009,20 +2012,29 @@ char* redis_encode_json(struct call *c) { } json_builder_end_array (builder); - k = g_hash_table_get_values(media->codecs_recv); snprintf(tmp, sizeof(tmp), "payload_types-%u", media->unique_id); json_builder_set_member_name(builder, tmp); json_builder_begin_array (builder); - for (m = k; m; m = m->next) { + for (m = media->codecs_prefs_recv.head; m; m = m->next) { pt = m->data; - JSON_ADD_STRING("%u/" STR_FORMAT "/%u/" STR_FORMAT "/" STR_FORMAT, + JSON_ADD_STRING("%u/" STR_FORMAT "/%u/" STR_FORMAT "/" STR_FORMAT "/%i/%i", pt->payload_type, STR_FMT(&pt->encoding), pt->clock_rate, STR_FMT(&pt->encoding_parameters), - STR_FMT(&pt->format_parameters)); + STR_FMT(&pt->format_parameters), pt->bitrate, pt->ptime); } json_builder_end_array (builder); - g_list_free(k); + snprintf(tmp, sizeof(tmp), "payload_types_send-%u", media->unique_id); + json_builder_set_member_name(builder, tmp); + json_builder_begin_array (builder); + for (m = media->codecs_prefs_send.head; m; m = m->next) { + pt = m->data; + JSON_ADD_STRING("%u/" STR_FORMAT "/%u/" STR_FORMAT "/" STR_FORMAT "/%i/%i", + pt->payload_type, STR_FMT(&pt->encoding), + pt->clock_rate, STR_FMT(&pt->encoding_parameters), + STR_FMT(&pt->format_parameters), pt->bitrate, pt->ptime); + } + json_builder_end_array (builder); } for (l = c->endpoint_maps.head; l; l = l->next) {