libosmocc: Flag codec as not accepted instead of removing it

This is required if multiple SDP responses are returned. We don't want
to remove a codec with with the first SDP response, which might get
accepted by the second SDP response. Instead we flag the codec as
negotiated or not negotiated.

When early media is received, different codecs may be accepted as when
we receive the actual answer.
This commit is contained in:
Andreas Eversberg 2023-11-12 17:36:05 +01:00
parent 39266802ef
commit 865f280bb1
4 changed files with 43 additions and 45 deletions

View File

@ -158,10 +158,6 @@ int osmo_cc_helper_audio_negotiate(osmo_cc_msg_t *msg, osmo_cc_session_t **sessi
abort();
}
/* once done, just ignore further messages that reply to setup */
if (*codec_p)
return 0;
/* SDP IE */
rc = osmo_cc_get_ie_sdp(msg, 0, sdp, sizeof(sdp));
if (rc < 0)
@ -172,12 +168,22 @@ int osmo_cc_helper_audio_negotiate(osmo_cc_msg_t *msg, osmo_cc_session_t **sessi
return rc;
osmo_cc_session_for_each_media((*session_p)->media_list, media) {
/* skip not accepted medias */
if (!media->accepted)
continue;
/* only audio */
if (media->description.type != osmo_cc_session_media_type_audio)
continue;
/* select first codec, if one was accpeted */
if (media->codec_list)
*codec_p = media->codec_list;
osmo_cc_session_for_each_codec(media->codec_list, codec) {
/* skip not accepted codecs */
if (!codec->accepted)
continue;
/* select first codec, if one was accpeted */
if (!(*codec_p)) {
LOGP(DCC, LOGL_DEBUG, "Select codec '%s'.\n", codec->payload_name);
*codec_p = codec;
}
}
if (*codec_p) {
osmo_cc_rtp_connect(media);
/* no more media streams */

View File

@ -36,7 +36,7 @@
}
/* generate SDP from session structure */
char *osmo_cc_session_gensdp(osmo_cc_session_t *session)
char *osmo_cc_session_gensdp(osmo_cc_session_t *session, int accepted_only)
{
/* calc max size of SDP: quick an dirty (close to max UDP payload size) */
static char sdp[65000];
@ -68,6 +68,8 @@ char *osmo_cc_session_gensdp(osmo_cc_session_t *session)
/* Connection Data (if all media have the same data) */
if (session->media_list) {
osmo_cc_session_for_each_media(session->media_list->next, media) {
if (accepted_only && !media->accepted)
continue;
if (session->media_list->connection_data_local.nettype != media->connection_data_local.nettype)
break;
if (session->media_list->connection_data_local.addrtype != media->connection_data_local.addrtype)
@ -87,6 +89,8 @@ char *osmo_cc_session_gensdp(osmo_cc_session_t *session)
/* sendonly /recvonly (if all media have the same data) */
if (session->media_list) {
osmo_cc_session_for_each_media(session->media_list->next, media) {
if (accepted_only && !media->accepted)
continue;
if (session->media_list->send != media->send)
break;
if (session->media_list->receive != media->receive)
@ -106,12 +110,17 @@ char *osmo_cc_session_gensdp(osmo_cc_session_t *session)
/* media */
osmo_cc_session_for_each_media(session->media_list, media) {
if (accepted_only && !media->accepted)
continue;
strncat_printf(sdp, "m=%s %u %s",
osmo_cc_session_media_type2string(media->description.type) ? : media->description.type_name,
media->description.port_local,
osmo_cc_session_media_proto2string(media->description.proto) ? : media->description.proto_name);
osmo_cc_session_for_each_codec(media->codec_list, codec)
osmo_cc_session_for_each_codec(media->codec_list, codec) {
if (accepted_only && !codec->accepted)
continue;
strncat_printf(sdp, " %u", codec->payload_type_local);
}
strncat_printf(sdp, "\r\n");
/* don't list rtpmap when session was canceled by setting port to 0 */
if (media->description.port_local == 0)
@ -119,6 +128,8 @@ char *osmo_cc_session_gensdp(osmo_cc_session_t *session)
if (individual_connection_data)
strncat_printf(sdp, "c=%s %s %s\r\n", osmo_cc_session_nettype2string(media->connection_data_local.nettype), osmo_cc_session_addrtype2string(media->connection_data_local.addrtype), media->connection_data_local.address);
osmo_cc_session_for_each_codec(media->codec_list, codec) {
if (accepted_only && !codec->accepted)
continue;
strncat_printf(sdp, "a=rtpmap:%u %s/%d", codec->payload_type_local, codec->payload_name, codec->payload_rate);
if (codec->payload_channels >= 2)
strncat_printf(sdp, "/%d", codec->payload_channels);

View File

@ -1,5 +1,5 @@
char *osmo_cc_session_gensdp(struct osmo_cc_session *session);
char *osmo_cc_session_gensdp(struct osmo_cc_session *session, int accepted_only);
struct osmo_cc_session *osmo_cc_session_parsesdp(osmo_cc_session_config_t *conf, void *priv, const char *_sdp);
int osmo_cc_payload_type_by_attrs(uint8_t *fmt, const char *name, uint32_t *rate, int *channels);
void osmo_cc_debug_sdp(const char *sdp);

View File

@ -348,7 +348,7 @@ const char *osmo_cc_session_send_offer(osmo_cc_session_t *session)
abort();
}
sdp = osmo_cc_session_gensdp(session);
sdp = osmo_cc_session_gensdp(session, 0);
osmo_cc_debug_sdp(sdp);
return sdp;
@ -419,42 +419,20 @@ void osmo_cc_session_accept_codec(osmo_cc_session_codec_t *codec, void (*encoder
LOGP(DCC, LOGL_DEBUG, " -> payload channels = %d\n", codec->payload_channels);
}
/* remove codecs/media that have not been accepted and generate SDP */
const char *osmo_cc_session_send_answer(osmo_cc_session_t *session)
{
osmo_cc_session_media_t *media;
osmo_cc_session_codec_t *codec, **codec_p;
const char *sdp;
int rc;
LOGP(DCC, LOGL_DEBUG, "Generating session answer.\n");
/* loop all media */
osmo_cc_session_for_each_media(session->media_list, media) {
/* remove unaccepted codecs */
codec_p = &media->codec_list;
codec = *codec_p;
while (codec) {
if (!codec->accepted) {
osmo_cc_free_codec(codec);
codec = *codec_p;
continue;
}
codec_p = &codec->next;
codec = *codec_p;
}
/* mark media as unused, if no codec or not accepted */
if (!media->accepted || !media->codec_list)
media->description.port_local = 0;
}
rc = osmo_cc_session_check(session, 0);
if (rc < 0) {
LOGP(DCC, LOGL_ERROR, "Please fix!\n");
abort();
}
sdp = osmo_cc_session_gensdp(session);
sdp = osmo_cc_session_gensdp(session, 1);
osmo_cc_debug_sdp(sdp);
return sdp;
@ -505,13 +483,14 @@ static int osmo_cc_session_negotiate(osmo_cc_session_t *session_local, struct os
&& codec_local->payload_channels == codec_remote->payload_channels)
break;
}
if (!codec_remote) {
osmo_cc_free_codec(codec_local);
codec_local = *codec_local_p;
continue;
if (codec_remote) {
/* mark as accepted, copy remote codec information */
codec_local->accepted = 1;
codec_local->payload_type_remote = codec_remote->payload_type_remote;
} else {
/* mark as not accepted, in case it was accepted in earlier response */
codec_local->accepted = 0;
}
/* copy remote codec information */
codec_local->payload_type_remote = codec_remote->payload_type_remote;
codec_local_p = &codec_local->next;
codec_local = *codec_local_p;
}
@ -525,14 +504,16 @@ static int osmo_cc_session_negotiate(osmo_cc_session_t *session_local, struct os
return -EINVAL;
}
/* remove media with port == 0 or no codec at all */
/* mark media as accepted, if there is a remote port and there is at least one codec */
media_local_p = &session_local->media_list;
media_local = *media_local_p;
while (media_local) {
if (media_local->description.port_remote == 0 || !media_local->codec_list) {
osmo_cc_free_media(media_local);
media_local = *media_local_p;
continue;
if (media_local->description.port_remote && media_local->codec_list) {
/* mark as accepted */
media_local->accepted = 1;
} else {
/* mark as not accepted, in case it was accepted in earlier response */
media_local->accepted = 0;
}
media_local_p = &media_local->next;
media_local = *media_local_p;