From 58f1c9a91226f4954a4799fab082f186923aa806 Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Sat, 3 Oct 2020 16:25:48 +0200 Subject: Add libraries from Osmocom-Analog --- src/libosmocc/helper.c | 171 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 171 insertions(+) create mode 100644 src/libosmocc/helper.c (limited to 'src/libosmocc/helper.c') diff --git a/src/libosmocc/helper.c b/src/libosmocc/helper.c new file mode 100644 index 0000000..cde8b27 --- /dev/null +++ b/src/libosmocc/helper.c @@ -0,0 +1,171 @@ +/* Osmo-CC: helpers to simplify Osmo-CC usage + * + * (C) 2016 by Andreas Eversberg + * All Rights Reserved + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include "../libtimer/timer.h" +#include "../libdebug/debug.h" +#include "endpoint.h" +#include "helper.h" + +osmo_cc_session_t *osmo_cc_helper_audio_offer(void *priv, struct osmo_cc_helper_audio_codecs *codecs, void (*receiver)(struct osmo_cc_session_codec *codec, uint16_t sequence_number, uint32_t timestamp, uint8_t *data, int len), osmo_cc_msg_t *msg, int debug) +{ + osmo_cc_session_t *session; + osmo_cc_session_media_t *media; + const char *sdp; + int i; + + session = osmo_cc_new_session(priv, NULL, NULL, NULL, 0, 0, NULL, NULL, debug); + if (!session) + return NULL; + + media = osmo_cc_add_media(session, 0, 0, NULL, osmo_cc_session_media_type_audio, 0, osmo_cc_session_media_proto_rtp, 1, 1, receiver, debug); + osmo_cc_rtp_open(media); + + for (i = 0; codecs[i].payload_name; i++) + osmo_cc_add_codec(media, codecs[i].payload_name, codecs[i].payload_rate, codecs[i].payload_channels, codecs[i].encoder, codecs[i].decoder, debug); + + sdp = osmo_cc_session_send_offer(session); + osmo_cc_add_ie_sdp(msg, sdp); + + return session; +} + +const char *osmo_cc_helper_audio_accept(void *priv, struct osmo_cc_helper_audio_codecs *codecs, void (*receiver)(struct osmo_cc_session_codec *codec, uint16_t sequence_number, uint32_t timestamp, uint8_t *data, int len), osmo_cc_msg_t *msg, osmo_cc_session_t **session_p, osmo_cc_session_codec_t **codec_p, int force_our_codec) +{ + char offer_sdp[65536]; + const char *accept_sdp; + osmo_cc_session_media_t *media, *selected_media = NULL; + osmo_cc_session_codec_t *codec, *selected_codec = NULL; + int rc; + int i, selected_i; + + if (*session_p) { + PDEBUG(DCC, DEBUG_ERROR, "Session already set, please fix!\n"); + abort(); + } + if (*codec_p) { + PDEBUG(DCC, DEBUG_ERROR, "Codec already set, please fix!\n"); + abort(); + } + + /* SDP IE */ + rc = osmo_cc_get_ie_sdp(msg, 0, offer_sdp, sizeof(offer_sdp)); + if (rc < 0) { + PDEBUG(DCC, DEBUG_ERROR, "There is no SDP included in setup request.\n"); + return NULL; + } + + *session_p = osmo_cc_session_receive_offer(priv, offer_sdp); + if (!*session_p) { + PDEBUG(DCC, DEBUG_ERROR, "Failed to parse SDP.\n"); + return NULL; + } + + selected_i = -1; + osmo_cc_session_for_each_media((*session_p)->media_list, media) { + /* only audio */ + if (media->description.type != osmo_cc_session_media_type_audio) + continue; + osmo_cc_session_for_each_codec(media->codec_list, codec) { + for (i = 0; codecs[i].payload_name; i++) { + if (osmo_cc_session_if_codec(codec, codecs[i].payload_name, codecs[i].payload_rate, codecs[i].payload_channels)) { + /* select the first matchting codec or the one we prefer */ + if (selected_i < 0 || i < selected_i) { + selected_codec = codec; + selected_media = media; + selected_i = i; + } + /* if we don't force our preferred codec, use the preferred one from the remote */ + if (!force_our_codec) + break; + } + } + } + } + if (!selected_codec) { + PDEBUG(DCC, DEBUG_ERROR, "No codec found in setup message that we support.\n"); + osmo_cc_free_session(*session_p); + return NULL; + } + osmo_cc_session_accept_codec(selected_codec, codecs[selected_i].encoder, codecs[selected_i].decoder); + osmo_cc_session_accept_media(selected_media, 0, 0, NULL, 1, 1, receiver); + osmo_cc_rtp_open(selected_media); + osmo_cc_rtp_connect(selected_media); + *codec_p = selected_codec; + + accept_sdp = osmo_cc_session_send_answer(*session_p); + if (!accept_sdp) { + osmo_cc_free_session(*session_p); + return NULL; + } + + return accept_sdp; +} + +int osmo_cc_helper_audio_negotiate(osmo_cc_msg_t *msg, osmo_cc_session_t **session_p, osmo_cc_session_codec_t **codec_p) +{ + char sdp[65536]; + osmo_cc_session_media_t *media; + int rc; + + if (!(*session_p)) { + PDEBUG(DCC, DEBUG_ERROR, "Session not set, please fix!\n"); + 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) + return 0; // no reply in this message + + rc = osmo_cc_session_receive_answer(*session_p, sdp); + if (rc < 0) + return rc; + + osmo_cc_session_for_each_media((*session_p)->media_list, media) { + /* 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; + if (*codec_p) { + osmo_cc_rtp_connect(media); + /* no more media streams */ + break; + } + } + if (!(*codec_p)) { + PDEBUG(DCC, DEBUG_ERROR, "No codec found in setup reply message that we support.\n"); + return -EIO; + } + + return 0; +} + -- cgit v1.2.3