summaryrefslogtreecommitdiff
path: root/res/res_pjsip_sdp_rtp.c
diff options
context:
space:
mode:
Diffstat (limited to 'res/res_pjsip_sdp_rtp.c')
-rw-r--r--res/res_pjsip_sdp_rtp.c245
1 files changed, 104 insertions, 141 deletions
diff --git a/res/res_pjsip_sdp_rtp.c b/res/res_pjsip_sdp_rtp.c
index b7e1eef3d..90a2cec46 100644
--- a/res/res_pjsip_sdp_rtp.c
+++ b/res/res_pjsip_sdp_rtp.c
@@ -41,6 +41,8 @@
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/module.h"
+#include "asterisk/format.h"
+#include "asterisk/format_cap.h"
#include "asterisk/rtp_engine.h"
#include "asterisk/netsock2.h"
#include "asterisk/channel.h"
@@ -68,38 +70,39 @@ static const char STR_VIDEO[] = "video";
static const int FD_VIDEO = 2;
/*! \brief Retrieves an ast_format_type based on the given stream_type */
-static enum ast_format_type stream_to_media_type(const char *stream_type)
+static enum ast_media_type stream_to_media_type(const char *stream_type)
{
if (!strcasecmp(stream_type, STR_AUDIO)) {
- return AST_FORMAT_TYPE_AUDIO;
+ return AST_MEDIA_TYPE_AUDIO;
} else if (!strcasecmp(stream_type, STR_VIDEO)) {
- return AST_FORMAT_TYPE_VIDEO;
+ return AST_MEDIA_TYPE_VIDEO;
}
return 0;
}
/*! \brief Get the starting descriptor for a media type */
-static int media_type_to_fdno(enum ast_format_type media_type)
+static int media_type_to_fdno(enum ast_media_type media_type)
{
switch (media_type) {
- case AST_FORMAT_TYPE_AUDIO: return FD_AUDIO;
- case AST_FORMAT_TYPE_VIDEO: return FD_VIDEO;
- case AST_FORMAT_TYPE_TEXT:
- case AST_FORMAT_TYPE_IMAGE: break;
+ case AST_MEDIA_TYPE_AUDIO: return FD_AUDIO;
+ case AST_MEDIA_TYPE_VIDEO: return FD_VIDEO;
+ case AST_MEDIA_TYPE_TEXT:
+ case AST_MEDIA_TYPE_UNKNOWN:
+ case AST_MEDIA_TYPE_IMAGE: break;
}
return -1;
}
/*! \brief Remove all other cap types but the one given */
-static void format_cap_only_type(struct ast_format_cap *caps, enum ast_format_type media_type)
+static void format_cap_only_type(struct ast_format_cap *caps, enum ast_media_type media_type)
{
- int i = AST_FORMAT_INC;
- while (i <= AST_FORMAT_TYPE_TEXT) {
- if (i != media_type) {
- ast_format_cap_remove_bytype(caps, i);
+ int i = 0;
+ while (i <= AST_MEDIA_TYPE_TEXT) {
+ if (i != media_type && i != AST_MEDIA_TYPE_UNKNOWN) {
+ ast_format_cap_remove_by_type(caps, i);
}
- i += AST_FORMAT_INC;
+ i += 1;
}
}
@@ -116,9 +119,6 @@ static int create_rtp(struct ast_sip_session *session, struct ast_sip_session_me
ast_rtp_instance_set_prop(session_media->rtp, AST_RTP_PROPERTY_RTCP, 1);
ast_rtp_instance_set_prop(session_media->rtp, AST_RTP_PROPERTY_NAT, session->endpoint->media.rtp.symmetric);
- ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(session_media->rtp),
- session_media->rtp, &session->endpoint->media.prefs);
-
if (session->endpoint->dtmf == AST_SIP_DTMF_INBAND) {
ast_rtp_instance_dtmf_mode_set(session_media->rtp, AST_RTP_DTMF_MODE_INBAND);
}
@@ -185,74 +185,97 @@ static void get_codecs(struct ast_sip_session *session, const struct pjmedia_sdp
if ((pjmedia_sdp_attr_get_fmtp(attr, &fmtp)) == PJ_SUCCESS) {
sscanf(pj_strbuf(&fmtp.fmt), "%d", &num);
if ((format = ast_rtp_codecs_get_payload_format(codecs, num))) {
+ struct ast_format *format_parsed;
+
ast_copy_pj_str(fmt_param, &fmtp.fmt_param, sizeof(fmt_param));
- ast_format_sdp_parse(format, fmt_param);
+
+ format_parsed = ast_format_parse_sdp_fmtp(format, fmt_param);
+ if (format_parsed) {
+ ast_rtp_codecs_payload_replace_format(codecs, num, format_parsed);
+ ao2_ref(format_parsed, -1);
+ }
+
+ ao2_ref(format, -1);
}
}
}
+
+ /* Get the packetization, if it exists */
+ if ((attr = pjmedia_sdp_media_find_attr2(stream, "ptime", NULL))) {
+ unsigned long framing = pj_strtoul(pj_strltrim(&attr->value));
+ if (framing && session->endpoint->media.rtp.use_ptime) {
+ ast_rtp_codecs_set_framing(codecs, framing);
+ }
+ }
}
static int set_caps(struct ast_sip_session *session, struct ast_sip_session_media *session_media,
const struct pjmedia_sdp_media *stream)
{
- RAII_VAR(struct ast_format_cap *, caps, NULL, ast_format_cap_destroy);
- RAII_VAR(struct ast_format_cap *, peer, NULL, ast_format_cap_destroy);
- RAII_VAR(struct ast_format_cap *, joint, NULL, ast_format_cap_destroy);
- enum ast_format_type media_type = stream_to_media_type(session_media->stream_type);
- struct ast_rtp_codecs codecs;
- struct ast_format fmt;
+ RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format_cap *, peer, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_format_cap *, joint, NULL, ao2_cleanup);
+ enum ast_media_type media_type = stream_to_media_type(session_media->stream_type);
+ struct ast_rtp_codecs codecs = AST_RTP_CODECS_NULL_INIT;
int fmts = 0;
int direct_media_enabled = !ast_sockaddr_isnull(&session_media->direct_media_addr) &&
- !ast_format_cap_is_empty(session->direct_media_cap);
+ ast_format_cap_count(session->direct_media_cap);
- if (!(caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK)) ||
- !(peer = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK))) {
+ if (!(caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT)) ||
+ !(peer = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT)) ||
+ !(joint = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
ast_log(LOG_ERROR, "Failed to allocate %s capabilities\n", session_media->stream_type);
return -1;
}
/* get the endpoint capabilities */
if (direct_media_enabled) {
- ast_format_cap_joint_copy(session->endpoint->media.codecs, session->direct_media_cap, caps);
+ ast_format_cap_get_compatible(session->endpoint->media.codecs, session->direct_media_cap, caps);
+ format_cap_only_type(caps, media_type);
} else {
- ast_format_cap_copy(caps, session->endpoint->media.codecs);
+ ast_format_cap_append_from_cap(caps, session->endpoint->media.codecs, media_type);
}
- format_cap_only_type(caps, media_type);
/* get the capabilities on the peer */
get_codecs(session, stream, &codecs);
ast_rtp_codecs_payload_formats(&codecs, peer, &fmts);
/* get the joint capabilities between peer and endpoint */
- if (!(joint = ast_format_cap_joint(caps, peer))) {
- char usbuf[64], thembuf[64];
+ ast_format_cap_get_compatible(caps, peer, joint);
+ if (!ast_format_cap_count(joint)) {
+ struct ast_str *usbuf = ast_str_alloca(64);
+ struct ast_str *thembuf = ast_str_alloca(64);
ast_rtp_codecs_payloads_destroy(&codecs);
-
- ast_getformatname_multiple(usbuf, sizeof(usbuf), caps);
- ast_getformatname_multiple(thembuf, sizeof(thembuf), peer);
- ast_log(LOG_WARNING, "No joint capabilities between our configuration(%s) and incoming SDP(%s)\n", usbuf, thembuf);
+ ast_log(LOG_WARNING, "No joint capabilities between our configuration(%s) and incoming SDP(%s)\n",
+ ast_format_cap_get_names(peer, &usbuf),
+ ast_format_cap_get_names(caps, &thembuf));
return -1;
}
ast_rtp_codecs_payloads_copy(&codecs, ast_rtp_instance_get_codecs(session_media->rtp),
session_media->rtp);
- ast_format_cap_copy(caps, session->req_caps);
- ast_format_cap_remove_bytype(caps, media_type);
- ast_format_cap_append(caps, joint);
- ast_format_cap_append(session->req_caps, caps);
+ ast_format_cap_remove_by_type(caps, AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_append_from_cap(caps, session->req_caps, AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_remove_by_type(caps, media_type);
+ ast_format_cap_append_from_cap(caps, joint, AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_append_from_cap(session->req_caps, caps, AST_MEDIA_TYPE_UNKNOWN);
if (session->channel) {
- ast_format_cap_copy(caps, ast_channel_nativeformats(session->channel));
- ast_format_cap_remove_bytype(caps, media_type);
- ast_codec_choose(&session->endpoint->media.prefs, joint, 1, &fmt);
- ast_format_cap_add(caps, &fmt);
+ struct ast_format *fmt;
+
+ ast_format_cap_append_from_cap(caps, ast_channel_nativeformats(session->channel), AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_remove_by_type(caps, media_type);
+ fmt = ast_format_cap_get_format(joint, 0);
+ ast_format_cap_append(caps, fmt, 0);
/* Apply the new formats to the channel, potentially changing read/write formats while doing so */
- ast_format_cap_copy(ast_channel_nativeformats(session->channel), caps);
- ast_set_read_format(session->channel, ast_channel_readformat(session->channel));
- ast_set_write_format(session->channel, ast_channel_writeformat(session->channel));
+ ast_channel_nativeformats_set(session->channel, caps);
+ ast_channel_set_rawwriteformat(session->channel, fmt);
+ ast_channel_set_rawreadformat(session->channel, fmt);
+
+ ao2_ref(fmt, -1);
}
ast_rtp_codecs_payloads_destroy(&codecs);
@@ -286,7 +309,7 @@ static pjmedia_sdp_attr* generate_fmtp_attr(pj_pool_t *pool, struct ast_format *
pjmedia_sdp_attr *attr = NULL;
char *tmp;
- ast_format_sdp_generate(format, rtp_code, &fmtp0);
+ ast_format_generate_sdp_fmtp(format, rtp_code, &fmtp0);
if (ast_str_strlen(fmtp0)) {
tmp = ast_str_buffer(fmtp0) + ast_str_strlen(fmtp0) - 1;
/* remove any carriage return line feeds */
@@ -304,18 +327,6 @@ static pjmedia_sdp_attr* generate_fmtp_attr(pj_pool_t *pool, struct ast_format *
return attr;
}
-static int codec_pref_has_type(struct ast_codec_pref *prefs, enum ast_format_type media_type)
-{
- int i;
- struct ast_format fmt;
- for (i = 0; ast_codec_pref_index(prefs, i, &fmt); ++i) {
- if (AST_FORMAT_GET_TYPE(fmt.id) == media_type) {
- return 1;
- }
- }
- return 0;
-}
-
/*! \brief Function which adds ICE attributes to a media stream */
static void add_ice_to_stream(struct ast_sip_session *session, struct ast_sip_session_media *session_media, pj_pool_t *pool, pjmedia_sdp_media *media)
{
@@ -469,38 +480,6 @@ static void process_ice_attributes(struct ast_sip_session *session, struct ast_s
ice->start(session_media->rtp);
}
-static void apply_packetization(struct ast_sip_session *session, struct ast_sip_session_media *session_media,
- const struct pjmedia_sdp_media *remote_stream)
-{
- pjmedia_sdp_attr *attr;
- pj_str_t value;
- unsigned long framing;
- int codec;
- struct ast_codec_pref *pref = &ast_rtp_instance_get_codecs(session_media->rtp)->pref;
-
- /* Apply packetization if available and configured to do so */
- if (!session->endpoint->media.rtp.use_ptime || !(attr = pjmedia_sdp_media_find_attr2(remote_stream, "ptime", NULL))) {
- return;
- }
-
- value = attr->value;
- framing = pj_strtoul(pj_strltrim(&value));
-
- for (codec = 0; codec < AST_RTP_MAX_PT; codec++) {
- struct ast_rtp_payload_type format = ast_rtp_codecs_payload_lookup(ast_rtp_instance_get_codecs(
- session_media->rtp), codec);
-
- if (!format.asterisk_format) {
- continue;
- }
-
- ast_codec_pref_setsize(pref, &format.format, framing);
- }
-
- ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(session_media->rtp),
- session_media->rtp, pref);
-}
-
/*! \brief figure out media transport encryption type from the media transport string */
static enum ast_sip_session_media_encryption get_media_encryption_type(pj_str_t transport)
{
@@ -722,7 +701,7 @@ static int negotiate_incoming_sdp_stream(struct ast_sip_session *session, struct
{
char host[NI_MAXHOST];
RAII_VAR(struct ast_sockaddr *, addrs, NULL, ast_free_ptr);
- enum ast_format_type media_type = stream_to_media_type(session_media->stream_type);
+ enum ast_media_type media_type = stream_to_media_type(session_media->stream_type);
/* If no type formats have been configured reject this stream */
if (!ast_format_cap_has_type(session->endpoint->media.codecs, media_type)) {
@@ -759,11 +738,6 @@ static int negotiate_incoming_sdp_stream(struct ast_sip_session *session, struct
if (set_caps(session, session_media, stream)) {
return -1;
}
-
- if (media_type == AST_FORMAT_TYPE_AUDIO) {
- apply_packetization(session, session_media, stream);
- }
-
return 1;
}
@@ -892,18 +866,14 @@ static int create_outgoing_sdp_stream(struct ast_sip_session *session, struct as
int noncodec = (session->endpoint->dtmf == AST_SIP_DTMF_RFC_4733) ? AST_RTP_DTMF : 0;
int min_packet_size = 0, max_packet_size = 0;
int rtp_code;
- struct ast_format format;
- RAII_VAR(struct ast_format_cap *, caps, NULL, ast_format_cap_destroy);
- enum ast_format_type media_type = stream_to_media_type(session_media->stream_type);
+ RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
+ enum ast_media_type media_type = stream_to_media_type(session_media->stream_type);
+ int use_override_prefs = ast_format_cap_count(session->req_caps);
int direct_media_enabled = !ast_sockaddr_isnull(&session_media->direct_media_addr) &&
- !ast_format_cap_is_empty(session->direct_media_cap);
+ ast_format_cap_count(session->direct_media_cap);
- int use_override_prefs = session->override_prefs.formats[0].id;
- struct ast_codec_pref *prefs = use_override_prefs ?
- &session->override_prefs : &session->endpoint->media.prefs;
-
- if ((use_override_prefs && !codec_pref_has_type(&session->override_prefs, media_type)) ||
+ if ((use_override_prefs && !ast_format_cap_has_type(session->req_caps, media_type)) ||
(!use_override_prefs && !ast_format_cap_has_type(session->endpoint->media.codecs, media_type))) {
/* If no type formats are configured don't add a stream */
return 0;
@@ -954,59 +924,53 @@ static int create_outgoing_sdp_stream(struct ast_sip_session *session, struct as
/* Add ICE attributes and candidates */
add_ice_to_stream(session, session_media, pool, media);
- if (!(caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK))) {
+ if (!(caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
ast_log(LOG_ERROR, "Failed to allocate %s capabilities\n", session_media->stream_type);
return -1;
}
if (direct_media_enabled) {
- ast_format_cap_joint_copy(session->endpoint->media.codecs, session->direct_media_cap, caps);
- } else if (ast_format_cap_is_empty(session->req_caps) || !ast_format_cap_has_joint(session->req_caps, session->endpoint->media.codecs)) {
- ast_format_cap_copy(caps, session->endpoint->media.codecs);
+ ast_format_cap_get_compatible(session->endpoint->media.codecs, session->direct_media_cap, caps);
+ } else if (!ast_format_cap_count(session->req_caps) ||
+ !ast_format_cap_iscompatible(session->req_caps, session->endpoint->media.codecs)) {
+ ast_format_cap_append_from_cap(caps, session->endpoint->media.codecs, media_type);
} else {
- ast_format_cap_copy(caps, session->req_caps);
+ ast_format_cap_append_from_cap(caps, session->req_caps, media_type);
}
- for (index = 0; ast_codec_pref_index(prefs, index, &format); ++index) {
- struct ast_codec_pref *pref = &ast_rtp_instance_get_codecs(session_media->rtp)->pref;
-
- if (AST_FORMAT_GET_TYPE(format.id) != media_type) {
- continue;
- }
+ for (index = 0; index < ast_format_cap_count(caps); ++index) {
+ struct ast_format *format = ast_format_cap_get_format(caps, index);
- if (!use_override_prefs && !ast_format_cap_get_compatible_format(caps, &format, &format)) {
+ if (ast_format_get_type(format) != media_type) {
+ ao2_ref(format, -1);
continue;
}
- if ((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(session_media->rtp), 1, &format, 0)) == -1) {
- ast_log(LOG_WARNING,"Unable to get rtp codec payload code for %s\n",ast_getformatname(&format));
+ if ((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(session_media->rtp), 1, format, 0)) == -1) {
+ ast_log(LOG_WARNING,"Unable to get rtp codec payload code for %s\n", ast_format_get_name(format));
+ ao2_ref(format, -1);
continue;
}
- if (!(attr = generate_rtpmap_attr(media, pool, rtp_code, 1, &format, 0))) {
+ if (!(attr = generate_rtpmap_attr(media, pool, rtp_code, 1, format, 0))) {
+ ao2_ref(format, -1);
continue;
}
-
media->attr[media->attr_count++] = attr;
- if ((attr = generate_fmtp_attr(pool, &format, rtp_code))) {
+ if ((attr = generate_fmtp_attr(pool, format, rtp_code))) {
media->attr[media->attr_count++] = attr;
}
- if (pref && media_type != AST_FORMAT_TYPE_VIDEO) {
- struct ast_format_list fmt = ast_codec_pref_getsize(pref, &format);
- if (fmt.cur_ms && ((fmt.cur_ms < min_packet_size) || !min_packet_size)) {
- min_packet_size = fmt.cur_ms;
- }
-
- if (fmt.max_ms && ((fmt.max_ms < max_packet_size) || !max_packet_size)) {
- max_packet_size = fmt.max_ms;
- }
+ if (ast_format_get_maximum_ms(format) &&
+ ((ast_format_get_maximum_ms(format) < max_packet_size) || !max_packet_size)) {
+ max_packet_size = ast_format_get_maximum_ms(format);
}
+ ao2_ref(format, -1);
}
/* Add non-codec formats */
- if (media_type != AST_FORMAT_TYPE_VIDEO) {
+ if (media_type != AST_MEDIA_TYPE_VIDEO) {
for (index = 1LL; index <= AST_RTP_MAX; index <<= 1) {
if (!(noncodec & index) || (rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(session_media->rtp),
0, NULL, index)) == -1) {
@@ -1033,6 +997,10 @@ static int create_outgoing_sdp_stream(struct ast_sip_session *session, struct as
}
/* If ptime is set add it as an attribute */
+ min_packet_size = ast_rtp_codecs_get_framing(ast_rtp_instance_get_codecs(session_media->rtp));
+ if (!min_packet_size) {
+ min_packet_size = ast_format_cap_get_framing(caps);
+ }
if (min_packet_size) {
snprintf(tmp, sizeof(tmp), "%d", min_packet_size);
attr = pjmedia_sdp_attr_create(pool, "ptime", pj_cstr(&stmp, tmp));
@@ -1061,7 +1029,7 @@ static int apply_negotiated_sdp_stream(struct ast_sip_session *session, struct a
const struct pjmedia_sdp_session *remote, const struct pjmedia_sdp_media *remote_stream)
{
RAII_VAR(struct ast_sockaddr *, addrs, NULL, ast_free_ptr);
- enum ast_format_type media_type = stream_to_media_type(session_media->stream_type);
+ enum ast_media_type media_type = stream_to_media_type(session_media->stream_type);
char host[NI_MAXHOST];
int fdno;
@@ -1095,15 +1063,10 @@ static int apply_negotiated_sdp_stream(struct ast_sip_session *session, struct a
/* Apply connection information to the RTP instance */
ast_sockaddr_set_port(addrs, remote_stream->desc.port);
ast_rtp_instance_set_remote_address(session_media->rtp, addrs);
-
if (set_caps(session, session_media, local_stream)) {
return -1;
}
- if (media_type == AST_FORMAT_TYPE_AUDIO) {
- apply_packetization(session, session_media, remote_stream);
- }
-
if ((fdno = media_type_to_fdno(media_type)) < 0) {
return -1;
}
@@ -1117,7 +1080,7 @@ static int apply_negotiated_sdp_stream(struct ast_sip_session *session, struct a
ast_rtp_instance_activate(session_media->rtp);
/* audio stream handles music on hold */
- if (media_type != AST_FORMAT_TYPE_AUDIO) {
+ if (media_type != AST_MEDIA_TYPE_AUDIO) {
return 1;
}