Asterisk - The Open Source Telephony Project GIT-master-7e7a603
pjsip_session_caps.c
Go to the documentation of this file.
1/*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 2020, Sangoma Technologies Corporation
5 *
6 * Kevin Harwell <kharwell@digium.com>
7 *
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
13 *
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
17 */
18
19#include "asterisk.h"
20
21#include "asterisk/astobj2.h"
22#include "asterisk/channel.h"
23#include "asterisk/format.h"
24#include "asterisk/format_cap.h"
25#include "asterisk/logger.h"
26#include "asterisk/sorcery.h"
27#include "asterisk/stream.h"
28#include "asterisk/res_pjsip.h"
31
32static void log_caps(int level, const char *file, int line, const char *function,
33 const struct ast_sip_session *session, enum ast_media_type media_type,
34 const struct ast_format_cap *local, const struct ast_format_cap *remote,
35 const struct ast_format_cap *joint)
36{
37 struct ast_str *s1;
38 struct ast_str *s2;
39 struct ast_str *s3;
40 int outgoing = session->call_direction == AST_SIP_SESSION_OUTGOING_CALL;
41 struct ast_flags pref =
43 ? session->endpoint->media.outgoing_call_offer_pref
44 : session->endpoint->media.incoming_call_offer_pref;
45
46 if (level == __LOG_DEBUG && !DEBUG_ATLEAST(3)) {
47 return;
48 }
49
53
54 ast_log(level, file, line, function, "'%s' Caps for %s %s call with pref '%s' - remote: %s local: %s joint: %s\n",
55 session->channel ? ast_channel_name(session->channel) :
57 outgoing? "outgoing" : "incoming",
58 ast_codec_media_type2str(media_type),
60 s2 ? ast_format_cap_get_names(remote, &s2) : "(NONE)",
61 s1 ? ast_format_cap_get_names(local, &s1) : "(NONE)",
62 s3 ? ast_format_cap_get_names(joint, &s3) : "(NONE)");
63}
64
66 struct ast_format_cap *local, enum ast_media_type media_type,
67 struct ast_flags codec_pref)
68{
72
73 if (!joint || !local_filtered || !remote_filtered) {
74 ast_log(LOG_ERROR, "Failed to allocate %s call offer capabilities\n",
75 ast_codec_media_type2str(media_type));
76 ao2_cleanup(joint);
77 ao2_cleanup(local_filtered);
78 ao2_cleanup(remote_filtered);
79 return NULL;
80 }
81
82 ast_format_cap_append_from_cap(local_filtered, local, media_type);
83
84 /* Remote should always be a subset of local, as local is what defines the underlying
85 * permitted formats.
86 */
87 ast_format_cap_get_compatible(remote, local_filtered, remote_filtered);
88
89 if (ast_sip_call_codec_pref_test(codec_pref, LOCAL)) {
90 if (ast_sip_call_codec_pref_test(codec_pref, INTERSECT)) {
91 ast_format_cap_get_compatible(local_filtered, remote_filtered, joint); /* Get common, prefer local */
92 } else {
93 ast_format_cap_append_from_cap(joint, local_filtered, media_type); /* Add local */
94 ast_format_cap_append_from_cap(joint, remote_filtered, media_type); /* Then remote */
95 }
96 } else {
97 if (ast_sip_call_codec_pref_test(codec_pref, INTERSECT)) {
98 joint = remote_filtered; /* Get common, prefer remote - as was done when filtering initially */
99 remote_filtered = NULL;
100 } else {
101 ast_format_cap_append_from_cap(joint, remote_filtered, media_type); /* Add remote */
102 ast_format_cap_append_from_cap(joint, local_filtered, media_type); /* Then local */
103 }
104 }
105
106 ao2_ref(local_filtered, -1);
107 ao2_cleanup(remote_filtered);
108
109 if (ast_format_cap_empty(joint)) {
110 return joint;
111 }
112
113 if (ast_sip_call_codec_pref_test(codec_pref, FIRST)) {
114 /*
115 * Save the most preferred one. Session capabilities are per stream and
116 * a stream only carries a single media type, so no reason to worry with
117 * the type here (i.e different or multiple types)
118 */
119 struct ast_format *single = ast_format_cap_get_format(joint, 0);
120 /* Remove all formats */
122 /* Put the most preferred one back */
123 ast_format_cap_append(joint, single, 0);
124 ao2_ref(single, -1);
125 }
126
127 return joint;
128}
129
131 struct ast_stream *remote_stream)
132{
133 struct ast_stream *joint_stream = ast_stream_clone(remote_stream, NULL);
134 const struct ast_format_cap *remote = ast_stream_get_formats(remote_stream);
135 enum ast_media_type media_type = ast_stream_get_type(remote_stream);
136
137 struct ast_format_cap *joint = ast_sip_create_joint_call_cap(remote,
138 session->endpoint->media.codecs, media_type,
139 session->call_direction == AST_SIP_SESSION_OUTGOING_CALL
140 ? session->endpoint->media.outgoing_call_offer_pref
141 : session->endpoint->media.incoming_call_offer_pref);
142
143 ast_stream_set_formats(joint_stream, joint);
144 ao2_cleanup(joint);
145
146 log_caps(LOG_DEBUG, session, media_type, session->endpoint->media.codecs, remote, joint);
147
148 return joint_stream;
149}
150
152 const struct ast_sip_session *session, enum ast_media_type media_type,
153 const struct ast_format_cap *remote)
154{
155 struct ast_format_cap *joint = ast_sip_create_joint_call_cap(remote,
156 session->endpoint->media.codecs, media_type,
157 session->call_direction == AST_SIP_SESSION_OUTGOING_CALL
158 ? session->endpoint->media.outgoing_call_offer_pref
159 : session->endpoint->media.incoming_call_offer_pref);
160
161 log_caps(LOG_DEBUG, session, media_type, session->endpoint->media.codecs, remote, joint);
162
163 return joint;
164}
Asterisk main include file. File version handling, generic pbx functions.
static struct ast_mansession session
#define ast_log
Definition: astobj2.c:42
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
General Asterisk PBX channel definitions.
const char * ast_channel_name(const struct ast_channel *chan)
ast_media_type
Types of media.
Definition: codec.h:30
@ AST_MEDIA_TYPE_UNKNOWN
Definition: codec.h:31
const char * ast_codec_media_type2str(enum ast_media_type type)
Conversion function to take a media type and turn it into a string.
Definition: codec.c:348
Media Format API.
Format Capabilities API.
#define AST_FORMAT_CAP_NAMES_LEN
Definition: format_cap.h:324
int ast_format_cap_empty(const struct ast_format_cap *cap)
Determine if a format cap has no formats in it.
Definition: format_cap.c:744
struct ast_format * ast_format_cap_get_format(const struct ast_format_cap *cap, int position)
Get the format at a specific index.
Definition: format_cap.c:400
int ast_format_cap_get_compatible(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2, struct ast_format_cap *result)
Find the compatible formats between two capabilities structures.
Definition: format_cap.c:628
void ast_format_cap_remove_by_type(struct ast_format_cap *cap, enum ast_media_type type)
Remove all formats matching a specific format type.
Definition: format_cap.c:523
@ AST_FORMAT_CAP_FLAG_DEFAULT
Definition: format_cap.h:38
int ast_format_cap_append_from_cap(struct ast_format_cap *dst, const struct ast_format_cap *src, enum ast_media_type type)
Append the formats of provided type in src to dst.
Definition: format_cap.c:269
const char * ast_format_cap_get_names(const struct ast_format_cap *cap, struct ast_str **buf)
Get the names of codecs of a set of formats.
Definition: format_cap.c:734
#define ast_format_cap_append(cap, format, framing)
Add format capability to capabilities structure.
Definition: format_cap.h:99
#define ast_format_cap_alloc(flags)
Allocate a new ast_format_cap structure.
Definition: format_cap.h:49
Support for logging to various files, console and syslog Configuration in file logger....
#define DEBUG_ATLEAST(level)
#define LOG_DEBUG
#define __LOG_DEBUG
#define LOG_ERROR
struct ast_format_cap * ast_sip_create_joint_call_cap(const struct ast_format_cap *remote, struct ast_format_cap *local, enum ast_media_type media_type, struct ast_flags codec_pref)
Create joint capabilities.
static void log_caps(int level, const char *file, int line, const char *function, const struct ast_sip_session *session, enum ast_media_type media_type, const struct ast_format_cap *local, const struct ast_format_cap *remote, const struct ast_format_cap *joint)
struct ast_format_cap * ast_sip_session_create_joint_call_cap(const struct ast_sip_session *session, enum ast_media_type media_type, const struct ast_format_cap *remote)
Create joint capabilities.
struct ast_stream * ast_sip_session_create_joint_call_stream(const struct ast_sip_session *session, struct ast_stream *remote_stream)
Create a new stream of joint capabilities.
#define ast_sip_call_codec_pref_test(__param, __codec_pref)
Returns true if the preference is set in the parameter.
Definition: res_pjsip.h:699
const char * ast_sip_call_codec_pref_to_str(struct ast_flags pref)
Convert the call codec preference flags to a string.
Definition: res_pjsip.c:2554
@ AST_SIP_SESSION_OUTGOING_CALL
#define NULL
Definition: resample.c:96
Sorcery Data Access Layer API.
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2317
Media Stream API.
struct ast_stream * ast_stream_clone(const struct ast_stream *stream, const char *name)
Create a deep clone of an existing stream.
Definition: stream.c:257
enum ast_media_type ast_stream_get_type(const struct ast_stream *stream)
Get the media type of a stream.
Definition: stream.c:316
void ast_stream_set_formats(struct ast_stream *stream, struct ast_format_cap *caps)
Set the current negotiated formats of a stream.
Definition: stream.c:365
const struct ast_format_cap * ast_stream_get_formats(const struct ast_stream *stream)
Get the current negotiated formats of a stream.
Definition: stream.c:330
#define ast_str_alloca(init_len)
Definition: strings.h:848
Structure used to handle boolean flags.
Definition: utils.h:199
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
Definition of a media format.
Definition: format.c:43
A structure describing a SIP session.
Support for dynamic strings.
Definition: strings.h:623