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:
parent
4eb07148cc
commit
c2bd6e9344
7 changed files with 144 additions and 11 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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"),
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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 ();
|
||||
|
|
Loading…
Reference in a new issue