add codec_mapping_next() and codec_mapping_foreach()

So far, querying the codec mapping returns one match.
For example:

 const struct codec_mapping *m;
 m = codec_mapping_by_speech_ver(GSM48_BCAP_SV_FR);
 if (!m)
         return -ENOENT;

But when supporting various AMR rates, we need to find multiple matches
in some code paths.

Also to support AMR OA vs BE modes, we need to combine multiple criteria
in some places.

With this patch, and as soon as an upcoming patch implements
codec_mapping_matches_speech_ver(), above code example becomes:

 const struct codec_mapping *m;
 codec_mapping_foreach (m) {
         if (codec_mapping_matches_speech_ver(m, GSM48_BCAP_SV_FR))
	         break;
 }
 if (!m)
         return -ENOENT;

This pattern supports collecting multiple matches in a list:

 const struct codec_mapping *m;
 codec_mapping_foreach (m) {
         if (codec_mapping_matches_speech_ver(m, GSM48_BCAP_SV_FR))
	         sdp_audio_codecs_add_copy(my_list, m);
 }

And this pattern also supports combining criteria:

 const struct codec_mapping *m;
 codec_mapping_foreach (m) {
	 // only allow AMR in OA mode
 	 if (!osmo_sdp_fmtp_amr_is_octet_aligned(m->sdp.fmtp))
	         continue;
         if (codec_mapping_matches_speech_ver(m, GSM48_BCAP_SV_AMR_F)
	     || codec_mapping_matches_speech_ver(m, GSM48_BCAP_SV_AMR_H))
	         sdp_audio_codecs_add_copy(my_list, m);
 }

Change-Id: Iaaa59d4bf5a6126a1bfe4ae282b82f6cb3ec6f99
This commit is contained in:
Neels Hofmeyr 2024-01-19 05:51:53 +01:00
parent e3059a74f7
commit 21f1bfb4a8
2 changed files with 46 additions and 12 deletions

View File

@ -39,6 +39,25 @@ struct codec_mapping {
enum codec_frhr frhr;
};
const struct codec_mapping *codec_mapping_next(const struct codec_mapping *c);
/* Iterate all known codec mappings.
* CODEC_MAPPING: const struct codec_mapping*.
* Example:
*
* const struct codec_mapping *m;
* codec_mapping_foreach (m) {
* if (codec_mapping_matches_speech_ver(m, GSM48_BCAP_SV_FR))
* break;
* }
* if (!m)
* printf("not found\n");
* else
* printf("%s\n", sdp_audio_codec_to_str(&m->sdp);
*/
#define codec_mapping_foreach(CODEC_MAPPING) \
for ((CODEC_MAPPING) = codec_mapping_next(NULL); (CODEC_MAPPING); (CODEC_MAPPING) = codec_mapping_next(CODEC_MAPPING))
const struct codec_mapping *codec_mapping_by_speech_ver(enum gsm48_bcap_speech_ver speech_ver);
const struct codec_mapping *codec_mapping_by_gsm0808_speech_codec_type(enum gsm0808_speech_codec_type sct);
const struct codec_mapping *codec_mapping_by_gsm0808_speech_codec(const struct gsm0808_speech_codec *sc);

View File

@ -202,8 +202,23 @@ const struct codec_mapping codec_map[] = {
},
};
#define foreach_codec_mapping(CODEC_MAPPING) \
for ((CODEC_MAPPING) = codec_map; (CODEC_MAPPING) < codec_map + ARRAY_SIZE(codec_map); (CODEC_MAPPING)++)
/* Iterate the entire codec_map, one struct codec_mapping per call.
* Initiate iteration by passing c = NULL, and call repeatedly until NULL is returned:
*
* for (const struct codec_mapping *c = codec_mapping_next(NULL); c; c = codec_mapping_next(c))
* handle(c);
*/
const struct codec_mapping *codec_mapping_next(const struct codec_mapping *c)
{
if (!c)
return codec_map;
if (c < codec_map)
return NULL;
c++;
if (c >= codec_map + ARRAY_SIZE(codec_map))
return NULL;
return c;
}
const struct gsm_mncc_bearer_cap bearer_cap_empty = {
.speech_ver = { -1 },
@ -212,7 +227,7 @@ const struct gsm_mncc_bearer_cap bearer_cap_empty = {
const struct codec_mapping *codec_mapping_by_speech_ver(enum gsm48_bcap_speech_ver speech_ver)
{
const struct codec_mapping *m;
foreach_codec_mapping(m) {
codec_mapping_foreach(m) {
int i;
for (i = 0; i < m->speech_ver_count; i++)
if (m->speech_ver[i] == speech_ver)
@ -224,7 +239,7 @@ const struct codec_mapping *codec_mapping_by_speech_ver(enum gsm48_bcap_speech_v
const struct codec_mapping *codec_mapping_by_gsm0808_speech_codec_type(enum gsm0808_speech_codec_type sct)
{
const struct codec_mapping *m;
foreach_codec_mapping(m) {
codec_mapping_foreach(m) {
if (!m->has_gsm0808_speech_codec)
continue;
if (m->gsm0808_speech_codec.type == sct)
@ -236,7 +251,7 @@ const struct codec_mapping *codec_mapping_by_gsm0808_speech_codec_type(enum gsm0
const struct codec_mapping *codec_mapping_by_gsm0808_speech_codec(const struct gsm0808_speech_codec *sc)
{
const struct codec_mapping *m;
foreach_codec_mapping(m) {
codec_mapping_foreach(m) {
if (!m->has_gsm0808_speech_codec)
continue;
if (m->gsm0808_speech_codec.type != sc->type)
@ -252,7 +267,7 @@ const struct codec_mapping *codec_mapping_by_gsm0808_speech_codec(const struct g
const struct codec_mapping *codec_mapping_by_perm_speech(enum gsm0808_permitted_speech perm_speech)
{
const struct codec_mapping *m;
foreach_codec_mapping(m) {
codec_mapping_foreach(m) {
if (m->perm_speech == perm_speech)
return m;
}
@ -262,7 +277,7 @@ const struct codec_mapping *codec_mapping_by_perm_speech(enum gsm0808_permitted_
const struct codec_mapping *codec_mapping_by_subtype_name(const char *subtype_name)
{
const struct codec_mapping *m;
foreach_codec_mapping(m) {
codec_mapping_foreach(m) {
if (!strcmp(m->sdp.subtype_name, subtype_name))
return m;
}
@ -272,7 +287,7 @@ const struct codec_mapping *codec_mapping_by_subtype_name(const char *subtype_na
const struct codec_mapping *codec_mapping_by_mgcp_codec(enum mgcp_codecs mgcp)
{
const struct codec_mapping *m;
foreach_codec_mapping(m) {
codec_mapping_foreach(m) {
if (m->mgcp == mgcp)
return m;
}
@ -332,7 +347,7 @@ int sdp_audio_codec_add_to_bearer_cap(struct gsm_mncc_bearer_cap *bearer_cap, co
{
const struct codec_mapping *m;
int added = 0;
foreach_codec_mapping(m) {
codec_mapping_foreach(m) {
int i;
if (strcmp(m->sdp.subtype_name, codec->subtype_name))
continue;
@ -366,7 +381,7 @@ struct sdp_audio_codec *sdp_audio_codecs_add_speech_ver(struct sdp_audio_codecs
{
const struct codec_mapping *m;
struct sdp_audio_codec *ret = NULL;
foreach_codec_mapping(m) {
codec_mapping_foreach(m) {
int i;
for (i = 0; i < m->speech_ver_count; i++) {
if (m->speech_ver[i] == speech_ver) {
@ -486,7 +501,7 @@ int sdp_audio_codecs_to_gsm0808_channel_type(struct gsm0808_channel_type *ct, co
int i;
bool dup;
idx++;
foreach_codec_mapping(m) {
codec_mapping_foreach(m) {
if (strcmp(m->sdp.subtype_name, codec->subtype_name))
continue;
@ -548,7 +563,7 @@ int sdp_audio_codecs_to_gsm0808_channel_type(struct gsm0808_channel_type *ct, co
enum mgcp_codecs sdp_audio_codec_to_mgcp_codec(const struct sdp_audio_codec *codec)
{
const struct codec_mapping *m;
foreach_codec_mapping(m) {
codec_mapping_foreach(m) {
if (!sdp_audio_codec_cmp(&m->sdp, codec, false, false))
return m->mgcp;
}