From 99990980240f2d7161cd4a4f147e1b1a51a503af Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Mon, 4 Dec 2023 14:21:34 -0500 Subject: [PATCH] MT#55283 use typed GQueue for codec_store Change-Id: I6942e5b8209aba99aaa1a81bfd449d0a31679595 --- daemon/codec.c | 74 +++++++++++++++++++++---------------------- daemon/janus.c | 2 +- daemon/media_player.c | 2 +- daemon/redis.c | 2 +- daemon/sdp.c | 4 +-- include/call.h | 4 +-- lib/rtplib.h | 9 +++++- t/test-transcode.c | 6 ++-- 8 files changed, 55 insertions(+), 48 deletions(-) diff --git a/daemon/codec.c b/daemon/codec.c index 40d12f813..c4f3640a6 100644 --- a/daemon/codec.c +++ b/daemon/codec.c @@ -77,7 +77,7 @@ static void __ht_queue_del(GHashTable *ht, const void *key, const void *val) { g_queue_remove_all(q, val); } -static GList *__codec_store_delete_link(GList *link, struct codec_store *cs) { +static rtp_pt_list *__codec_store_delete_link(rtp_pt_list *link, struct codec_store *cs) { struct rtp_payload_type *pt = link->data; g_hash_table_remove(cs->codecs, GINT_TO_POINTER(pt->payload_type)); @@ -85,10 +85,10 @@ static GList *__codec_store_delete_link(GList *link, struct codec_store *cs) { __ht_queue_del(cs->codec_names, &pt->encoding_with_params, GINT_TO_POINTER(pt->payload_type)); __ht_queue_del(cs->codec_names, &pt->encoding_with_full_params, GINT_TO_POINTER(pt->payload_type)); - GList *next = link->next; + __auto_type next = link->next; if (cs->supp_link == link) cs->supp_link = next; - g_queue_delete_link(&cs->codec_prefs, link); + t_queue_delete_link(&cs->codec_prefs, link); payload_type_free(pt); return next; } @@ -618,7 +618,7 @@ static void __track_supp_codec(GHashTable *supplemental_sinks, struct rtp_payloa } static void __check_codec_list(GHashTable **supplemental_sinks, struct rtp_payload_type **pref_dest_codec, - struct call_media *sink, GQueue *sink_list) + struct call_media *sink, rtp_pt_q *sink_list) { // first initialise and populate the list of supp sinks GHashTable *ss = *supplemental_sinks = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, @@ -632,7 +632,7 @@ static void __check_codec_list(GHashTable **supplemental_sinks, struct rtp_paylo struct rtp_payload_type *pdc = NULL; struct rtp_payload_type *first_tc_codec = NULL; - for (GList *l = sink->codecs.codec_prefs.head; l; l = l->next) { + for (__auto_type l = sink->codecs.codec_prefs.head; l; l = l->next) { struct rtp_payload_type *pt = l->data; ensure_codec_def(pt, sink); if (!pt->codec_def) // not supported, next @@ -860,7 +860,7 @@ static void __check_t38_gateway(struct call_media *pcm_media, struct call_media // for each codec type supported by the pcm_media, we create a codec handler that // links to the T.38 encoder - for (GList *l = pcm_media->codecs.codec_prefs.head; l; l = l->next) { + for (__auto_type l = pcm_media->codecs.codec_prefs.head; l; l = l->next) { struct rtp_payload_type *pt = l->data; struct codec_handler *handler = __get_pt_handler(pcm_media, pt, t38_media); if (!pt->codec_def) { @@ -1134,7 +1134,7 @@ void __codec_handlers_update(struct call_media *receiver, struct call_media *sin // do we have to force everything through the transcoding engine even if codecs match? bool force_transcoding = do_pcm_dtmf_blocking || do_dtmf_blocking || use_audio_player; - for (GList *l = receiver->codecs.codec_prefs.head; l; ) { + for (__auto_type l = receiver->codecs.codec_prefs.head; l; ) { struct rtp_payload_type *pt = l->data; struct rtp_payload_type *sink_pt = NULL; @@ -1433,7 +1433,7 @@ next: // we have to translate RTCP packets receiver->rtcp_handler = rtcp_transcode_handler; - for (GList *l = receiver->codecs.codec_prefs.head; l; ) { + for (__auto_type l = receiver->codecs.codec_prefs.head; l; ) { struct rtp_payload_type *pt = l->data; if (pt->codec_def) { @@ -4554,7 +4554,7 @@ static void __rtp_payload_type_add_name(GHashTable *ht, struct rtp_payload_type } #ifdef WITH_TRANSCODING static void __insert_codec_tracker(GHashTable *all_clockrates, GHashTable *all_supp_codecs, - struct codec_tracker *sct, GList *link) + struct codec_tracker *sct, rtp_pt_list *link) { struct rtp_payload_type *pt = link->data; @@ -4693,7 +4693,7 @@ void codec_tracker_update(struct codec_store *cs, struct codec_store *orig_cs) { GHashTable *all_clockrates = g_hash_table_new(g_direct_hash, g_direct_equal); GHashTable *all_supp_codecs = g_hash_table_new_full(str_case_hash, str_case_equal, free, (GDestroyNotify) g_hash_table_destroy); - for (GList *l = cs->codec_prefs.head; l; l = l->next) + for (__auto_type l = cs->codec_prefs.head; l; l = l->next) __insert_codec_tracker(all_clockrates, all_supp_codecs, sct, l); // get all supported audio clock rates @@ -4772,7 +4772,7 @@ void codec_tracker_update(struct codec_store *cs, struct codec_store *orig_cs) { GQueue *entries = g_hash_table_lookup(supp_clockrates, GUINT_TO_POINTER(clockrate)); for (GList *j = entries->head; j; j = j->next) { - GList *link = j->data; + rtp_pt_list *link = j->data; struct rtp_payload_type *pt = link->data; ilogs(codec, LOG_DEBUG, "Eliminating supplemental codec " STR_FORMAT "/" STR_FORMAT " (%i) with " @@ -4797,7 +4797,7 @@ void codec_store_cleanup(struct codec_store *cs) { g_hash_table_destroy(cs->codecs); if (cs->codec_names) g_hash_table_destroy(cs->codec_names); - g_queue_clear_full(&cs->codec_prefs, (GDestroyNotify) payload_type_free); + t_queue_clear_full(&cs->codec_prefs, payload_type_free); cs->supp_link = NULL; codec_tracker_destroy(&cs->tracker); ZERO(*cs); @@ -4824,7 +4824,7 @@ static void codec_store_move(struct codec_store *dst, struct codec_store *src) { // `out_compat` must be initialised already, or NULL // either `codec` or `pt_parsed` must be given (or both) -static void codec_store_find_matching_codecs(GQueue *out_compat, struct rtp_payload_type **out_exact, +static void codec_store_find_matching_codecs(rtp_pt_q *out_compat, struct rtp_payload_type **out_exact, struct codec_store *cs, const str *codec, struct rtp_payload_type *pt_parsed) { @@ -4863,15 +4863,15 @@ static void codec_store_find_matching_codecs(GQueue *out_compat, struct rtp_payl if (out_exact && !*out_exact) *out_exact = pt2; if (out_compat) - g_queue_push_head(out_compat, pt2); + t_queue_push_head(out_compat, pt2); } else if (out_compat && match == 1) - g_queue_push_tail(out_compat, pt2); + t_queue_push_tail(out_compat, pt2); } } __attribute__((nonnull(1, 2))) -static void codec_store_add_raw_link(struct codec_store *cs, struct rtp_payload_type *pt, GList *link) { +static void codec_store_add_raw_link(struct codec_store *cs, struct rtp_payload_type *pt, rtp_pt_list *link) { // cs->media may be NULL ensure_codec_def(pt, cs->media); if (cs->media && cs->media->ptime > 0) @@ -4885,11 +4885,11 @@ static void codec_store_add_raw_link(struct codec_store *cs, struct rtp_payload_ g_hash_table_insert(cs->codecs, GINT_TO_POINTER(pt->payload_type), pt); __rtp_payload_type_add_name(cs->codec_names, pt); if (!link) { - g_queue_push_tail(&cs->codec_prefs, pt); + t_queue_push_tail(&cs->codec_prefs, pt); pt->prefs_link = cs->codec_prefs.tail; } else { - g_queue_insert_before(&cs->codec_prefs, link, pt); + t_queue_insert_before(&cs->codec_prefs, link, pt); pt->prefs_link = link->prev; } if (!cs->supp_link && pt->codec_def && pt->codec_def->supplemental) @@ -4909,7 +4909,7 @@ void codec_store_add_raw(struct codec_store *cs, struct rtp_payload_type *pt) { __attribute__((nonnull(1, 2))) static struct rtp_payload_type *codec_store_add_link(struct codec_store *cs, - struct rtp_payload_type *pt, GList *link) + struct rtp_payload_type *pt, rtp_pt_list *link) { if (!cs->media) return NULL; @@ -4973,7 +4973,7 @@ void __codec_store_populate_reuse(struct codec_store *dst, struct codec_store *s struct call_media *media = dst->media; struct call *call = media ? media->call : NULL; - for (GList *l = src->codec_prefs.head; l; l = l->next) { + for (__auto_type l = src->codec_prefs.head; l; l = l->next) { struct rtp_payload_type *pt = l->data; struct rtp_payload_type *orig_pt = g_hash_table_lookup(dst->codecs, GINT_TO_POINTER(pt->payload_type)); @@ -5003,7 +5003,7 @@ void __codec_store_populate_reuse(struct codec_store *dst, struct codec_store *s pt->payload_type); } } - for (GList *l = dst->codec_prefs.head; l;) { + for (__auto_type l = dst->codec_prefs.head; l;) { struct rtp_payload_type *pt = l->data; struct rtp_payload_type *orig_pt = g_hash_table_lookup(src->codecs, GINT_TO_POINTER(pt->payload_type)); @@ -5030,7 +5030,7 @@ void codec_store_check_empty(struct codec_store *dst, struct codec_store *src) { static void codec_store_merge(struct codec_store *dst, struct codec_store *src) { while (src->codec_prefs.length) { - struct rtp_payload_type *pt = g_queue_pop_tail(&src->codec_prefs); + struct rtp_payload_type *pt = t_queue_pop_tail(&src->codec_prefs); // src codecs take preference over existing entries in dst: if there's // a collision in payload types, remove the existing entry in dst, @@ -5054,7 +5054,7 @@ void __codec_store_populate(struct codec_store *dst, struct codec_store *src, st struct call_media *media = dst->media; struct call *call = media ? media->call : NULL; - for (GList *l = src->codec_prefs.head; l; l = l->next) { + for (__auto_type l = src->codec_prefs.head; l; l = l->next) { struct rtp_payload_type *pt = l->data; struct rtp_payload_type *orig_pt = g_hash_table_lookup(orig_dst.codecs, GINT_TO_POINTER(pt->payload_type)); @@ -5110,9 +5110,9 @@ void codec_store_strip(struct codec_store *cs, str_q *strip, GHashTable *except) cs->strip_full = 1; // strip all except ... - GList *link = cs->codec_prefs.head; + __auto_type link = cs->codec_prefs.head; while (link) { - GList *next = link->next; + __auto_type next = link->next; struct rtp_payload_type *pt = link->data; if (except && g_hash_table_lookup(except, &pt->encoding)) ; @@ -5209,9 +5209,9 @@ void codec_store_accept(struct codec_store *cs, str_q *accept, struct codec_stor // mark codecs as `for transcoding` for (__auto_type l = accept->head; l; l = l->next) { str *codec = l->data; - g_auto(GQueue) pts_matched = G_QUEUE_INIT; + g_auto(rtp_pt_q) pts_matched = TYPED_GQUEUE_INIT; - GQueue *pts = &pts_matched; + rtp_pt_q *pts = &pts_matched; if (!str_cmp(codec, "all") || !str_cmp(codec, "full")) pts = &cs->codec_prefs; else @@ -5229,9 +5229,9 @@ void codec_store_accept(struct codec_store *cs, str_q *accept, struct codec_stor continue; } // re-add from orig, then mark as accepted below - GQueue pt_readded = G_QUEUE_INIT; + rtp_pt_q pt_readded = TYPED_GQUEUE_INIT; // XXX duplicate code - for (GList *k = pts->head; k; k = k->next) { + for (__auto_type k = pts->head; k; k = k->next) { struct rtp_payload_type *orig_pt = k->data; if (g_hash_table_lookup(cs->codecs, GINT_TO_POINTER(orig_pt->payload_type))) { ilogs(codec, LOG_DEBUG, "PT %i (" STR_FORMAT ") already preset", @@ -5247,14 +5247,14 @@ void codec_store_accept(struct codec_store *cs, str_q *accept, struct codec_stor codec_touched(cs, orig_pt); struct rtp_payload_type *added = codec_store_add_order(cs, orig_pt); if (added) - g_queue_push_tail(&pt_readded, added); + t_queue_push_tail(&pt_readded, added); } - g_queue_clear(&pts_matched); + t_queue_clear(&pts_matched); pts_matched = pt_readded; if (!pts_matched.length) continue; } - for (GList *k = pts->head; k; k = k->next) { + for (__auto_type k = pts->head; k; k = k->next) { struct rtp_payload_type *fpt = k->data; int pt_num = fpt->payload_type; struct rtp_payload_type *pt = g_hash_table_lookup(cs->codecs, @@ -5308,7 +5308,7 @@ int codec_store_accept_one(struct codec_store *cs, str_q *accept, bool accept_an if (!accept_pt) { // none found yet - pick the first one - for (GList *l = cs->codec_prefs.head; l; l = l->next) { + for (__auto_type l = cs->codec_prefs.head; l; l = l->next) { struct rtp_payload_type *pt = l->data; if (!accept_any) { ensure_codec_def(pt, cs->media); @@ -5326,7 +5326,7 @@ int codec_store_accept_one(struct codec_store *cs, str_q *accept, bool accept_an } // delete all codecs except the accepted one - GList *link = cs->codec_prefs.head; + __auto_type link = cs->codec_prefs.head; while (link) { struct rtp_payload_type *pt = link->data; if (pt == accept_pt) { @@ -5452,7 +5452,7 @@ void codec_store_answer(struct codec_store *dst, struct codec_store *src, sdp_ng GQueue supp_codecs = G_QUEUE_INIT; // postpone actually adding them until the end // populate dst via output PTs from src's codec handlers - for (GList *l = src->codec_prefs.head; l; l = l->next) { + for (__auto_type l = src->codec_prefs.head; l; l = l->next) { bool add_codec = true; if (flags->single_codec && num_codecs >= 1) add_codec = false; @@ -5594,7 +5594,7 @@ void codec_store_synthesise(struct codec_store *dst, struct codec_store *opposit } else { // we already have a list of codecs - make sure they're all supported by us - for (GList *l = dst->codec_prefs.head; l;) { + for (__auto_type l = dst->codec_prefs.head; l;) { struct rtp_payload_type *pt = l->data; if (pt->codec_def) { l = l->next; @@ -5613,7 +5613,7 @@ void codec_store_synthesise(struct codec_store *dst, struct codec_store *opposit // check all codecs listed in the source are also be present in the answer (dst) bool codec_store_is_full_answer(const struct codec_store *src, const struct codec_store *dst) { - for (GList *l = src->codec_prefs.head; l; l = l->next) { + for (__auto_type l = src->codec_prefs.head; l; l = l->next) { const struct rtp_payload_type *src_pt = l->data; const struct rtp_payload_type *dst_pt = g_hash_table_lookup(dst->codecs, GINT_TO_POINTER(src_pt->payload_type)); diff --git a/daemon/janus.c b/daemon/janus.c index 13bbe1755..0a874282b 100644 --- a/daemon/janus.c +++ b/daemon/janus.c @@ -340,7 +340,7 @@ static void janus_add_publisher_details(JsonBuilder *builder, struct call_monolo continue; const char *codec = NULL; - for (GList *k = media->codecs.codec_prefs.head; k; k = k->next) { + for (__auto_type k = media->codecs.codec_prefs.head; k; k = k->next) { struct rtp_payload_type *pt = k->data; codec = pt->encoding.s; // XXX check codec support? diff --git a/daemon/media_player.c b/daemon/media_player.c index 456af5c65..725f15367 100644 --- a/daemon/media_player.c +++ b/daemon/media_player.c @@ -673,7 +673,7 @@ static bool media_player_cache_entry_init(struct media_player *mp, const struct // find suitable output payload type static struct rtp_payload_type *media_player_get_dst_pt(struct media_player *mp) { struct rtp_payload_type *dst_pt = NULL; - for (GList *l = mp->media->codecs.codec_prefs.head; l; l = l->next) { + for (__auto_type l = mp->media->codecs.codec_prefs.head; l; l = l->next) { dst_pt = l->data; ensure_codec_def(dst_pt, mp->media); if (dst_pt->codec_def && !dst_pt->codec_def->supplemental) diff --git a/daemon/redis.c b/daemon/redis.c index a0f014d35..de88519ba 100644 --- a/daemon/redis.c +++ b/daemon/redis.c @@ -2625,7 +2625,7 @@ char* redis_encode_json(struct call *c) { snprintf(tmp, sizeof(tmp), "payload_types-%u", media->unique_id); json_builder_set_member_name(builder, tmp); json_builder_begin_array(builder); - for (GList *m = media->codecs.codec_prefs.head; m; m = m->next) { + for (__auto_type m = media->codecs.codec_prefs.head; m; m = m->next) { struct rtp_payload_type *pt = m->data; JSON_ADD_STRING("%u/" STR_FORMAT "/%u/" STR_FORMAT "/" STR_FORMAT "/%i/%i", pt->payload_type, STR_FMT(&pt->encoding), diff --git a/daemon/sdp.c b/daemon/sdp.c index 4392a8457..abd95f60b 100644 --- a/daemon/sdp.c +++ b/daemon/sdp.c @@ -2090,7 +2090,7 @@ static int print_codec_list(GString *s, struct call_media *media) { if (media->codecs.codec_prefs.length == 0) return 0; // legacy protocol or usage error - for (GList *l = media->codecs.codec_prefs.head; l; l = l->next) { + for (__auto_type l = media->codecs.codec_prefs.head; l; l = l->next) { struct rtp_payload_type *pt = l->data; if (l != media->codecs.codec_prefs.head) g_string_append_c(s, ' '); @@ -2113,7 +2113,7 @@ static int replace_codec_list(struct sdp_chopper *chop, static void insert_codec_parameters(GString *s, struct call_media *cm, sdp_ng_flags *flags) { - for (GList *l = cm->codecs.codec_prefs.head; l; l = l->next) + for (__auto_type l = cm->codecs.codec_prefs.head; l; l = l->next) { struct rtp_payload_type *pt = l->data; if (!pt->encoding_with_params.len) diff --git a/include/call.h b/include/call.h index 6a1b67863..9778bbd59 100644 --- a/include/call.h +++ b/include/call.h @@ -302,8 +302,8 @@ typedef bencode_buffer_t call_buffer_t; struct codec_store { GHashTable *codecs; // int payload type -> struct rtp_payload_type GHashTable *codec_names; // codec name -> GQueue of int payload types; storage container - GQueue codec_prefs; // preference by order in SDP; storage container - GList *supp_link; // tracks location for codec_store_add_end + rtp_pt_q codec_prefs; // preference by order in SDP; storage container + rtp_pt_list *supp_link; // tracks location for codec_store_add_end struct codec_tracker *tracker; struct call_media *media; unsigned int strip_all:1, // set by codec_store_strip diff --git a/lib/rtplib.h b/lib/rtplib.h index d3055282a..1b6138e91 100644 --- a/lib/rtplib.h +++ b/lib/rtplib.h @@ -4,6 +4,7 @@ #include #include #include "str.h" +#include "containers.h" @@ -90,6 +91,11 @@ struct rtp_codec_format { unsigned int fmtp_parsed:1; // set if fmtp string was successfully parsed }; + +struct rtp_payload_type; +TYPED_GQUEUE(rtp_pt, struct rtp_payload_type) +G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(rtp_pt_q, rtp_pt_q_clear) + struct rtp_payload_type { int payload_type; int reverse_payload_type; @@ -107,7 +113,7 @@ struct rtp_payload_type { int bitrate; codec_def_t *codec_def; - GList *prefs_link; // link in `codec_prefs` list + rtp_pt_list *prefs_link; // link in `codec_prefs` list struct rtp_codec_format format; // parsed out fmtp unsigned int for_transcoding:1; @@ -115,6 +121,7 @@ struct rtp_payload_type { }; + extern const struct rtp_payload_type rfc_rtp_payload_types[]; extern const int num_rfc_rtp_payload_types; diff --git a/t/test-transcode.c b/t/test-transcode.c index 9b9b0fd8f..18cd573dc 100644 --- a/t/test-transcode.c +++ b/t/test-transcode.c @@ -20,8 +20,8 @@ static str *sdup(char *s) { str r = STR_INIT(s); return str_dup(&r); } -static void queue_dump(GString *s, GQueue *q) { - for (GList *l = q->head; l; l = l->next) { +static void queue_dump(GString *s, rtp_pt_q *q) { + for (__auto_type l = q->head; l; l = l->next) { if (s->len) g_string_append(s, " "); struct rtp_payload_type *pt = l->data; @@ -185,7 +185,7 @@ static void answer(void) { #define expect(side, exp_str) \ __expect(__FILE__, __LINE__, &media_ ## side->codecs.codec_prefs, exp_str) -static void __expect(const char *file, int line, GQueue *dumper, const char *codecs) { +static void __expect(const char *file, int line, rtp_pt_q *dumper, const char *codecs) { printf("running test %s:%i\n", file, line); GString *s = g_string_new(""); queue_dump(s, dumper);