mirror of
https://gitlab.gnome.org/GNOME/calls.git
synced 2025-01-07 12: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;
|
CallsSipMediaManager *manager;
|
||||||
CallsSipMediaPipeline *pipeline;
|
CallsSipMediaPipeline *pipeline;
|
||||||
nua_handle_t *nh;
|
nua_handle_t *nh;
|
||||||
|
GList *codecs;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void calls_sip_call_message_source_interface_init (CallsMessageSourceInterface *iface);
|
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 */
|
/* 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);
|
calls_sip_call_setup_local_media_connection (self, local_port, local_port + 1);
|
||||||
|
|
||||||
local_sdp = calls_sip_media_manager_static_capabilities (self->manager,
|
local_sdp = calls_sip_media_manager_get_capabilities (self->manager,
|
||||||
local_port,
|
local_port,
|
||||||
FALSE);
|
FALSE,
|
||||||
|
self->codecs);
|
||||||
|
|
||||||
g_assert (local_sdp);
|
g_assert (local_sdp);
|
||||||
g_debug ("Setting local SDP to string:\n%s", 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);
|
calls_sip_media_pipeline_stop (self->pipeline);
|
||||||
g_clear_object (&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);
|
G_OBJECT_CLASS (calls_sip_call_parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -354,3 +358,14 @@ calls_sip_call_set_state (CallsSipCall *self,
|
||||||
old_state);
|
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);
|
gboolean enabled);
|
||||||
void calls_sip_call_set_state (CallsSipCall *self,
|
void calls_sip_call_set_state (CallsSipCall *self,
|
||||||
CallsCallState state);
|
CallsCallState state);
|
||||||
|
void calls_sip_call_set_codecs (CallsSipCall *self,
|
||||||
|
GList *codecs);
|
||||||
|
|
||||||
G_END_DECLS
|
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
|
* @port: Should eventually come from the ICE stack
|
||||||
* @use_srtp: Whether to use srtp (not really handled)
|
* @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)
|
* to be used in the session description (SDP)
|
||||||
*/
|
*/
|
||||||
char *
|
char *
|
||||||
calls_sip_media_manager_static_capabilities (CallsSipMediaManager *self,
|
calls_sip_media_manager_get_capabilities (CallsSipMediaManager *self,
|
||||||
guint port,
|
guint port,
|
||||||
gboolean use_srtp)
|
gboolean use_srtp,
|
||||||
|
GList *supported_codecs)
|
||||||
{
|
{
|
||||||
char *payload_type = use_srtp ? "SAVP" : "AVP";
|
char *payload_type = use_srtp ? "SAVP" : "AVP";
|
||||||
g_autoptr (GString) media_line = NULL;
|
g_autoptr (GString) media_line = NULL;
|
||||||
|
@ -108,7 +111,7 @@ calls_sip_media_manager_static_capabilities (CallsSipMediaManager *self,
|
||||||
media_line = g_string_new (NULL);
|
media_line = g_string_new (NULL);
|
||||||
attribute_lines = 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_warning ("No supported codecs found. Can't build meaningful SDP message");
|
||||||
g_string_append_printf (media_line, "m=audio 0 RTP/AVP 0");
|
g_string_append_printf (media_line, "m=audio 0 RTP/AVP 0");
|
||||||
goto done;
|
goto done;
|
||||||
|
@ -118,7 +121,7 @@ calls_sip_media_manager_static_capabilities (CallsSipMediaManager *self,
|
||||||
g_string_append_printf (media_line,
|
g_string_append_printf (media_line,
|
||||||
"m=audio %d RTP/%s", port, payload_type);
|
"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;
|
MediaCodecInfo *codec = node->data;
|
||||||
|
|
||||||
g_string_append_printf (media_line, " %u", codec->payload_id);
|
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*
|
MediaCodecInfo*
|
||||||
get_best_codec (CallsSipMediaManager *self)
|
get_best_codec (CallsSipMediaManager *self)
|
||||||
{
|
{
|
||||||
return media_codec_by_name ("PCMA");
|
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 "gst-rfc3551.h"
|
||||||
|
|
||||||
#include <sofia-sip/nua.h>
|
#include <sofia-sip/nua.h>
|
||||||
|
#include <sofia-sip/sdp.h>
|
||||||
#include <glib-object.h>
|
#include <glib-object.h>
|
||||||
|
|
||||||
#define CALLS_TYPE_SIP_MEDIA_MANAGER (calls_sip_media_manager_get_type ())
|
#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);
|
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,
|
gchar* calls_sip_media_manager_static_capabilities (CallsSipMediaManager *self,
|
||||||
guint port,
|
guint port,
|
||||||
gboolean use_srtp);
|
gboolean use_srtp);
|
||||||
gboolean calls_sip_media_manager_supports_media (CallsSipMediaManager *self,
|
gboolean calls_sip_media_manager_supports_media (CallsSipMediaManager *self,
|
||||||
const char *media_type);
|
const char *media_type);
|
||||||
MediaCodecInfo* get_best_codec (CallsSipMediaManager *self);
|
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[])
|
tagi_t tags[])
|
||||||
{
|
{
|
||||||
const sdp_session_t *r_sdp = NULL;
|
const sdp_session_t *r_sdp = NULL;
|
||||||
|
const sdp_session_t *l_sdp = NULL;
|
||||||
gint call_state = nua_callstate_init;
|
gint call_state = nua_callstate_init;
|
||||||
CallsCallState state;
|
CallsCallState state;
|
||||||
CallsSipCall *call;
|
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));
|
g_assert (CALLS_IS_SIP_ORIGIN (origin));
|
||||||
|
|
||||||
|
@ -234,8 +239,13 @@ sip_i_state (int status,
|
||||||
}
|
}
|
||||||
|
|
||||||
tl_gets (tags,
|
tl_gets (tags,
|
||||||
|
SOATAG_LOCAL_SDP_REF (l_sdp),
|
||||||
SOATAG_REMOTE_SDP_REF (r_sdp),
|
SOATAG_REMOTE_SDP_REF (r_sdp),
|
||||||
NUTAG_CALLSTATE_REF (call_state),
|
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 ());
|
TAG_END ());
|
||||||
|
|
||||||
if (status == 503) {
|
if (status == 503) {
|
||||||
|
@ -247,6 +257,11 @@ sip_i_state (int status,
|
||||||
* also: rtcp port = rtp port + 1
|
* also: rtcp port = rtp port + 1
|
||||||
*/
|
*/
|
||||||
if (r_sdp) {
|
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,
|
calls_sip_call_setup_remote_media_connection (call,
|
||||||
r_sdp->sdp_connection->c_address,
|
r_sdp->sdp_connection->c_address,
|
||||||
r_sdp->sdp_media->m_port,
|
r_sdp->sdp_media->m_port,
|
||||||
|
@ -1161,7 +1176,7 @@ calls_sip_origin_go_online (CallsSipOrigin *self,
|
||||||
nua_register (self->oper->register_handle,
|
nua_register (self->oper->register_handle,
|
||||||
SIPTAG_EXPIRES_STR ("180"),
|
SIPTAG_EXPIRES_STR ("180"),
|
||||||
NUTAG_SUPPORTED ("replaces, outbound, gruu"),
|
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_USERNAME (self->user),
|
||||||
NUTAG_M_DISPLAY ("SIP tester"),
|
NUTAG_M_DISPLAY ("SIP tester"),
|
||||||
NUTAG_M_PARAMS ("user=phone"),
|
NUTAG_M_PARAMS ("user=phone"),
|
||||||
|
|
|
@ -55,6 +55,17 @@ media_codec_by_name (const char *name)
|
||||||
return NULL;
|
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 *
|
gchar *
|
||||||
media_codec_get_gst_capabilities (MediaCodecInfo *codec)
|
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_name (const char *name);
|
||||||
|
MediaCodecInfo* media_codec_by_payload_id (uint payload_id);
|
||||||
gchar* media_codec_get_gst_capabilities (MediaCodecInfo *codec);
|
gchar* media_codec_get_gst_capabilities (MediaCodecInfo *codec);
|
||||||
GList* media_codecs_get_candidates ();
|
GList* media_codecs_get_candidates ();
|
||||||
|
|
Loading…
Reference in a new issue