1
0
Fork 0
mirror of https://gitlab.gnome.org/GNOME/calls.git synced 2025-01-06 03:25:31 +00:00

sip: media: rework codec negotiation

introduce `calls_sip_media_manager_get_capabilities ()` which takes
a GList of MediaCodecInfo's as input to generate a SDP message.
If using in an SDP answer we simply feed it a list of the common codecs
as gathered from the SDP offer.
This commit is contained in:
Evangelos Ribeiro Tzaras 2021-04-08 16:43:13 +02:00 committed by Guido Gunther
parent 4eb07148cc
commit c2bd6e9344
7 changed files with 144 additions and 11 deletions

View file

@ -46,6 +46,7 @@ struct _CallsSipCall
CallsSipMediaManager *manager;
CallsSipMediaPipeline *pipeline;
nua_handle_t *nh;
GList *codecs;
};
static void calls_sip_call_message_source_interface_init (CallsMessageSourceInterface *iface);
@ -108,9 +109,10 @@ calls_sip_call_answer (CallsCall *call)
/* TODO get free port by creating GSocket and passing that to the pipeline */
calls_sip_call_setup_local_media_connection (self, local_port, local_port + 1);
local_sdp = calls_sip_media_manager_static_capabilities (self->manager,
local_port,
FALSE);
local_sdp = calls_sip_media_manager_get_capabilities (self->manager,
local_port,
FALSE,
self->codecs);
g_assert (local_sdp);
g_debug ("Setting local SDP to string:\n%s", local_sdp);
@ -210,6 +212,8 @@ calls_sip_call_finalize (GObject *object)
calls_sip_media_pipeline_stop (self->pipeline);
g_clear_object (&self->pipeline);
}
g_clear_pointer (&self->codecs, g_list_free);
G_OBJECT_CLASS (calls_sip_call_parent_class)->finalize (object);
}
@ -354,3 +358,14 @@ calls_sip_call_set_state (CallsSipCall *self,
old_state);
}
void
calls_sip_call_set_codecs (CallsSipCall *self,
GList *codecs)
{
g_return_if_fail (CALLS_IS_SIP_CALL (self));
g_return_if_fail (codecs);
g_list_free (self->codecs);
self->codecs = codecs;
}

View file

@ -49,5 +49,7 @@ void calls_sip_call_activate_media (CallsSi
gboolean enabled);
void calls_sip_call_set_state (CallsSipCall *self,
CallsCallState state);
void calls_sip_call_set_codecs (CallsSipCall *self,
GList *codecs);
G_END_DECLS

View file

@ -85,18 +85,21 @@ calls_sip_media_manager_default ()
}
/* calls_sip_media_manager_static_capabilities:
/* calls_sip_media_manager_get_capabilities:
*
* @self: A #CallsSipMediaManager
* @port: Should eventually come from the ICE stack
* @use_srtp: Whether to use srtp (not really handled)
* @supported_codecs: A #GList of #MediaCodecInfo
*
* Returns: (full-control) string describing capabilities
* Returns: (transfer: full) string describing capabilities
* to be used in the session description (SDP)
*/
char *
calls_sip_media_manager_static_capabilities (CallsSipMediaManager *self,
guint port,
gboolean use_srtp)
calls_sip_media_manager_get_capabilities (CallsSipMediaManager *self,
guint port,
gboolean use_srtp,
GList *supported_codecs)
{
char *payload_type = use_srtp ? "SAVP" : "AVP";
g_autoptr (GString) media_line = NULL;
@ -108,7 +111,7 @@ calls_sip_media_manager_static_capabilities (CallsSipMediaManager *self,
media_line = g_string_new (NULL);
attribute_lines = g_string_new (NULL);
if (self->supported_codecs == NULL) {
if (supported_codecs == NULL) {
g_warning ("No supported codecs found. Can't build meaningful SDP message");
g_string_append_printf (media_line, "m=audio 0 RTP/AVP 0");
goto done;
@ -118,7 +121,7 @@ calls_sip_media_manager_static_capabilities (CallsSipMediaManager *self,
g_string_append_printf (media_line,
"m=audio %d RTP/%s", port, payload_type);
for (node = self->supported_codecs; node != NULL; node = node->next) {
for (node = supported_codecs; node != NULL; node = node->next) {
MediaCodecInfo *codec = node->data;
g_string_append_printf (media_line, " %u", codec->payload_id);
@ -141,8 +144,86 @@ calls_sip_media_manager_static_capabilities (CallsSipMediaManager *self,
}
/* calls_sip_media_manager_static_capabilities:
*
* @self: A #CallsSipMediaManager
* @port: Should eventually come from the ICE stack
* @use_srtp: Whether to use srtp (not really handled)
*
* Returns: (transfer: full) string describing capabilities
* to be used in the session description (SDP)
*/
char *
calls_sip_media_manager_static_capabilities (CallsSipMediaManager *self,
guint port,
gboolean use_srtp)
{
g_return_val_if_fail (CALLS_IS_SIP_MEDIA_MANAGER (self), NULL);
return calls_sip_media_manager_get_capabilities (self,
port,
use_srtp,
self->supported_codecs);
}
MediaCodecInfo*
get_best_codec (CallsSipMediaManager *self)
{
return media_codec_by_name ("PCMA");
}
/* calls_sip_media_manager_codec_candiates:
*
* @self: A #CallsSipMediaManager
*
* Returns: (transfer: none) A #GList of supported
* #MediaCodecInfo
*/
GList *
calls_sip_media_manager_codec_candidates (CallsSipMediaManager *self)
{
g_return_val_if_fail (CALLS_IS_SIP_MEDIA_MANAGER (self), NULL);
return self->supported_codecs;
}
/* calls_sip_media_manager_get_codecs_from_sdp
*
* @self: A #CallsSipMediaManager
* @sdp: A #sdp_media_t media description
*
* Returns: (transfer: full) A #GList of codecs found in the
* SDP message
*/
GList *
calls_sip_media_manager_get_codecs_from_sdp (CallsSipMediaManager *self,
sdp_media_t *sdp_media)
{
GList *codecs = NULL;
sdp_rtpmap_t *rtpmap = NULL;
g_return_val_if_fail (CALLS_IS_SIP_MEDIA_MANAGER (self), NULL);
g_return_val_if_fail (sdp_media, NULL);
if (sdp_media->m_type != sdp_media_audio) {
g_warning ("Only the 'audio' media type is supported");
return NULL;
}
for (rtpmap = sdp_media->m_rtpmaps; rtpmap != NULL; rtpmap = rtpmap->rm_next) {
MediaCodecInfo *codec = media_codec_by_payload_id (rtpmap->rm_pt);
if (codec)
codecs = g_list_append (codecs, codec);
}
if (sdp_media->m_next != NULL)
g_warning ("Currently only a single media session is supported");
if (codecs == NULL)
g_warning ("Did not find any common codecs");
return codecs;
}

View file

@ -27,6 +27,7 @@
#include "gst-rfc3551.h"
#include <sofia-sip/nua.h>
#include <sofia-sip/sdp.h>
#include <glib-object.h>
#define CALLS_TYPE_SIP_MEDIA_MANAGER (calls_sip_media_manager_get_type ())
@ -35,9 +36,16 @@ G_DECLARE_FINAL_TYPE (CallsSipMediaManager, calls_sip_media_manager, CALLS, SIP_
CallsSipMediaManager* calls_sip_media_manager_default (void);
gchar* calls_sip_media_manager_get_capabilities (CallsSipMediaManager *self,
guint port,
gboolean use_srtp,
GList *supported_codecs);
gchar* calls_sip_media_manager_static_capabilities (CallsSipMediaManager *self,
guint port,
gboolean use_srtp);
gboolean calls_sip_media_manager_supports_media (CallsSipMediaManager *self,
const char *media_type);
MediaCodecInfo* get_best_codec (CallsSipMediaManager *self);
GList * calls_sip_media_manager_codec_candidates (CallsSipMediaManager *self);
GList * calls_sip_media_manager_get_codecs_from_sdp (CallsSipMediaManager *self,
sdp_media_t *sdp_media);

View file

@ -218,9 +218,14 @@ sip_i_state (int status,
tagi_t tags[])
{
const sdp_session_t *r_sdp = NULL;
const sdp_session_t *l_sdp = NULL;
gint call_state = nua_callstate_init;
CallsCallState state;
CallsSipCall *call;
int offer_sent = 0;
int offer_recv = 0;
int answer_sent = 0;
int answer_recv = 0;
g_assert (CALLS_IS_SIP_ORIGIN (origin));
@ -234,8 +239,13 @@ sip_i_state (int status,
}
tl_gets (tags,
SOATAG_LOCAL_SDP_REF (l_sdp),
SOATAG_REMOTE_SDP_REF (r_sdp),
NUTAG_CALLSTATE_REF (call_state),
NUTAG_OFFER_SENT_REF (offer_sent),
NUTAG_OFFER_RECV_REF (offer_recv),
NUTAG_ANSWER_SENT_REF (answer_sent),
NUTAG_ANSWER_RECV_REF (answer_recv),
TAG_END ());
if (status == 503) {
@ -247,6 +257,11 @@ sip_i_state (int status,
* also: rtcp port = rtp port + 1
*/
if (r_sdp) {
GList *codecs =
calls_sip_media_manager_get_codecs_from_sdp (origin->media_manager,
r_sdp->sdp_media);
calls_sip_call_set_codecs (call, codecs);
calls_sip_call_setup_remote_media_connection (call,
r_sdp->sdp_connection->c_address,
r_sdp->sdp_media->m_port,
@ -1161,7 +1176,7 @@ calls_sip_origin_go_online (CallsSipOrigin *self,
nua_register (self->oper->register_handle,
SIPTAG_EXPIRES_STR ("180"),
NUTAG_SUPPORTED ("replaces, outbound, gruu"),
NUTAG_OUTBOUND ("outbound natify gruuize"), // <- janus uses "no-validate"
NUTAG_OUTBOUND ("outbound natify gruuize validate"), // <- janus uses "no-validate"
NUTAG_M_USERNAME (self->user),
NUTAG_M_DISPLAY ("SIP tester"),
NUTAG_M_PARAMS ("user=phone"),

View file

@ -55,6 +55,17 @@ media_codec_by_name (const char *name)
return NULL;
}
MediaCodecInfo *
media_codec_by_payload_id (guint payload_id)
{
for (guint i = 0; i < G_N_ELEMENTS (gst_codecs); i++) {
if (payload_id == gst_codecs[i].payload_id)
return &gst_codecs[i];
}
return NULL;
}
gchar *
media_codec_get_gst_capabilities (MediaCodecInfo *codec)
{

View file

@ -44,5 +44,6 @@ typedef struct {
MediaCodecInfo* media_codec_by_name (const char *name);
MediaCodecInfo* media_codec_by_payload_id (uint payload_id);
gchar* media_codec_get_gst_capabilities (MediaCodecInfo *codec);
GList* media_codecs_get_candidates ();