summaryrefslogtreecommitdiff
path: root/res
diff options
context:
space:
mode:
Diffstat (limited to 'res')
-rw-r--r--res/res_pjsip_outbound_publish.c2
-rw-r--r--res/res_pjsip_session.c10
-rw-r--r--res/res_rtp_asterisk.c119
-rw-r--r--res/res_stasis.c19
4 files changed, 108 insertions, 42 deletions
diff --git a/res/res_pjsip_outbound_publish.c b/res/res_pjsip_outbound_publish.c
index 18525bf6c..0fac8adf6 100644
--- a/res/res_pjsip_outbound_publish.c
+++ b/res/res_pjsip_outbound_publish.c
@@ -986,7 +986,7 @@ static int sip_outbound_publisher_init(void *data)
pj_cstr(&event, publish->event);
if (pjsip_publishc_init(publisher->client, &event, &server_uri, &from_uri, &to_uri,
- publish->expiration != PJ_SUCCESS)) {
+ publish->expiration) != PJ_SUCCESS) {
ast_log(LOG_ERROR, "Failed to initialize publishing client on outbound publish '%s'\n",
ast_sorcery_object_get_id(publish));
pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
diff --git a/res/res_pjsip_session.c b/res/res_pjsip_session.c
index 9636583d2..70c88a504 100644
--- a/res/res_pjsip_session.c
+++ b/res/res_pjsip_session.c
@@ -2486,6 +2486,16 @@ struct ast_sip_session *ast_sip_session_create_outgoing(struct ast_sip_endpoint
continue;
}
+ if (ast_stream_get_type(req_stream) == AST_MEDIA_TYPE_AUDIO) {
+ /*
+ * By appending codecs from the endpoint after compatible ones this
+ * guarantees that priority is given to those while also allowing
+ * translation to occur for non-compatible.
+ */
+ ast_format_cap_append_from_cap(joint_cap,
+ endpoint->media.codecs, AST_MEDIA_TYPE_AUDIO);
+ }
+
ast_stream_set_formats(clone_stream, joint_cap);
ao2_ref(joint_cap, -1);
diff --git a/res/res_rtp_asterisk.c b/res/res_rtp_asterisk.c
index c8cc04f96..7bf5b0064 100644
--- a/res/res_rtp_asterisk.c
+++ b/res/res_rtp_asterisk.c
@@ -3771,6 +3771,7 @@ static int ast_rtcp_write_report(struct ast_rtp_instance *instance, int sr)
RAII_VAR(struct ast_json *, message_blob, NULL, ast_json_unref);
int res;
int len = 0;
+ uint16_t sdes_packet_len_bytes, sdes_packet_len_rounded;
struct timeval now;
unsigned int now_lsw;
unsigned int now_msw;
@@ -3778,7 +3779,7 @@ static int ast_rtcp_write_report(struct ast_rtp_instance *instance, int sr)
unsigned int lost_packets;
int fraction_lost;
struct timeval dlsr = { 0, };
- unsigned char bdata[512] = "";
+ unsigned char bdata[AST_UUID_STR_LEN + 128] = ""; /* More than enough */
int rate = rtp_get_rate(rtp->f.subclass.format);
int ice;
struct ast_sockaddr remote_address = { { 0, } };
@@ -3858,12 +3859,35 @@ static int ast_rtcp_write_report(struct ast_rtp_instance *instance, int sr)
put_unaligned_uint32(rtcpheader, htonl((2 << 30) | (rtcp_report->reception_report_count << 24)
| ((sr ? RTCP_PT_SR : RTCP_PT_RR) << 16) | ((len/4)-1)));
- put_unaligned_uint32(rtcpheader + len, htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | (2 + (AST_UUID_STR_LEN / 4))));
+ sdes_packet_len_bytes =
+ 4 + /* RTCP Header */
+ 4 + /* SSRC */
+ 1 + /* Type (CNAME) */
+ 1 + /* Text Length */
+ AST_UUID_STR_LEN /* Text and NULL terminator */
+ ;
+
+ /* Round to 32 bit boundary */
+ sdes_packet_len_rounded = (sdes_packet_len_bytes + 3) & ~0x3;
+
+ put_unaligned_uint32(rtcpheader + len, htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | ((sdes_packet_len_rounded / 4) - 1)));
put_unaligned_uint32(rtcpheader + len + 4, htonl(rtcp_report->ssrc));
- put_unaligned_uint16(rtcpheader + len + 8, htonl(0x01 << 24));
- put_unaligned_uint16(rtcpheader + len + 9, htonl(AST_UUID_STR_LEN << 24));
+ rtcpheader[len + 8] = 0x01; /* CNAME */
+ rtcpheader[len + 9] = AST_UUID_STR_LEN - 1; /* Number of bytes of text */
memcpy(rtcpheader + len + 10, rtp->cname, AST_UUID_STR_LEN);
- len += 12 + AST_UUID_STR_LEN;
+ len += 10 + AST_UUID_STR_LEN;
+
+ /* Padding - Note that we don't set the padded bit on the packet. From
+ * RFC 3550 Section 6.5:
+ *
+ * No length octet follows the null item type octet, but additional null
+ * octets MUST be included if needed to pad until the next 32-bit
+ * boundary. Note that this padding is separate from that indicated by
+ * the P bit in the RTCP header.
+ *
+ * These bytes will already be zeroed out during array initialization.
+ */
+ len += (sdes_packet_len_rounded - sdes_packet_len_bytes);
if (rtp->bundled) {
ast_rtp_instance_get_remote_address(instance, &remote_address);
@@ -5316,7 +5340,7 @@ static int bridge_p2p_rtp_write(struct ast_rtp_instance *instance,
struct ast_rtp_instance *instance1, unsigned int *rtpheader, int len, int hdrlen)
{
struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
- struct ast_rtp *bridged = ast_rtp_instance_get_data(instance1);
+ struct ast_rtp *bridged;
int res = 0, payload = 0, bridged_payload = 0, mark;
RAII_VAR(struct ast_rtp_payload_type *, payload_type, NULL, ao2_cleanup);
int reconstruct = ntohl(rtpheader[0]);
@@ -5326,7 +5350,7 @@ static int bridge_p2p_rtp_write(struct ast_rtp_instance *instance,
/* Get fields from packet */
payload = (reconstruct & 0x7f0000) >> 16;
- mark = (((reconstruct & 0x800000) >> 23) != 0);
+ mark = (reconstruct & 0x800000) >> 23;
/* Check what the payload value should be */
payload_type = ast_rtp_codecs_get_payload(ast_rtp_instance_get_codecs(instance), payload);
@@ -5349,12 +5373,6 @@ static int bridge_p2p_rtp_write(struct ast_rtp_instance *instance,
return -1;
}
- /* If bridged peer is in dtmf, feed all packets to core until it finishes to avoid infinite dtmf */
- if (bridged->sending_digit) {
- ast_debug(1, "Feeding packets to core until DTMF finishes\n");
- return -1;
- }
-
/*
* Even if we are no longer in dtmf, we could still be receiving
* re-transmissions of the last dtmf end still. Feed those to the
@@ -5365,35 +5383,10 @@ static int bridge_p2p_rtp_write(struct ast_rtp_instance *instance,
return -1;
}
-
- ao2_replace(rtp->lastrxformat, payload_type->format);
- ao2_replace(bridged->lasttxformat, payload_type->format);
-
- /*
- * If bridged peer has already received rtp, perform the asymmetric codec check
- * if that feature has been activated
- */
- if (!bridged->asymmetric_codec && bridged->lastrxformat != ast_format_none) {
- if (ast_format_cmp(bridged->lasttxformat, bridged->lastrxformat) == AST_FORMAT_CMP_NOT_EQUAL) {
- ast_debug(1, "Asymmetric RTP codecs detected (TX: %s, RX: %s) sending frame to core\n",
- ast_format_get_name(bridged->lasttxformat),
- ast_format_get_name(bridged->lastrxformat));
- return -1;
- }
- }
-
- /* If the marker bit has been explicitly set turn it on */
- if (ast_test_flag(rtp, FLAG_NEED_MARKER_BIT)) {
- mark = 1;
- ast_clear_flag(rtp, FLAG_NEED_MARKER_BIT);
+ if (payload_type->asterisk_format) {
+ ao2_replace(rtp->lastrxformat, payload_type->format);
}
- /* Reconstruct part of the packet */
- reconstruct &= 0xFF80FFFF;
- reconstruct |= (bridged_payload << 16);
- reconstruct |= (mark << 23);
- rtpheader[0] = htonl(reconstruct);
-
/*
* We have now determined that we need to send the RTP packet
* out the bridged instance to do local bridging so we must unlock
@@ -5409,6 +5402,40 @@ static int bridge_p2p_rtp_write(struct ast_rtp_instance *instance,
ao2_unlock(instance);
ao2_lock(instance1);
+ /*
+ * Get the peer rtp pointer now to emphasize that using it
+ * must happen while instance1 is locked.
+ */
+ bridged = ast_rtp_instance_get_data(instance1);
+
+
+ /* If bridged peer is in dtmf, feed all packets to core until it finishes to avoid infinite dtmf */
+ if (bridged->sending_digit) {
+ ast_debug(1, "Feeding packet to core until DTMF finishes\n");
+ ao2_unlock(instance1);
+ ao2_lock(instance);
+ return -1;
+ }
+
+ if (payload_type->asterisk_format) {
+ /*
+ * If bridged peer has already received rtp, perform the asymmetric codec check
+ * if that feature has been activated
+ */
+ if (!bridged->asymmetric_codec
+ && bridged->lastrxformat != ast_format_none
+ && ast_format_cmp(payload_type->format, bridged->lastrxformat) == AST_FORMAT_CMP_NOT_EQUAL) {
+ ast_debug(1, "Asymmetric RTP codecs detected (TX: %s, RX: %s) sending frame to core\n",
+ ast_format_get_name(payload_type->format),
+ ast_format_get_name(bridged->lastrxformat));
+ ao2_unlock(instance1);
+ ao2_lock(instance);
+ return -1;
+ }
+
+ ao2_replace(bridged->lasttxformat, payload_type->format);
+ }
+
ast_rtp_instance_get_remote_address(instance1, &remote_address);
if (ast_sockaddr_isnull(&remote_address)) {
@@ -5418,6 +5445,18 @@ static int bridge_p2p_rtp_write(struct ast_rtp_instance *instance,
return 0;
}
+ /* If the marker bit has been explicitly set turn it on */
+ if (ast_test_flag(bridged, FLAG_NEED_MARKER_BIT)) {
+ mark = 1;
+ ast_clear_flag(bridged, FLAG_NEED_MARKER_BIT);
+ }
+
+ /* Reconstruct part of the packet */
+ reconstruct &= 0xFF80FFFF;
+ reconstruct |= (bridged_payload << 16);
+ reconstruct |= (mark << 23);
+ rtpheader[0] = htonl(reconstruct);
+
/* Send the packet back out */
res = rtp_sendto(instance1, (void *)rtpheader, len, 0, &remote_address, &ice);
if (res < 0) {
diff --git a/res/res_stasis.c b/res/res_stasis.c
index 899c8f720..f99dcee37 100644
--- a/res/res_stasis.c
+++ b/res/res_stasis.c
@@ -766,6 +766,7 @@ static struct ast_bridge *bridge_create_common(const char *type, const char *nam
int flags = AST_BRIDGE_FLAG_MERGE_INHIBIT_FROM | AST_BRIDGE_FLAG_MERGE_INHIBIT_TO
| AST_BRIDGE_FLAG_SWAP_INHIBIT_FROM | AST_BRIDGE_FLAG_SWAP_INHIBIT_TO
| AST_BRIDGE_FLAG_TRANSFER_BRIDGE_ONLY;
+ enum ast_bridge_video_mode_type video_mode = AST_BRIDGE_VIDEO_MODE_TALKER_SRC;
if (invisible) {
flags |= AST_BRIDGE_FLAG_INVISIBLE;
@@ -782,9 +783,17 @@ static struct ast_bridge *bridge_create_common(const char *type, const char *nam
} else if (!strcmp(requested_type, "dtmf_events") ||
!strcmp(requested_type, "proxy_media")) {
capabilities &= ~AST_BRIDGE_CAPABILITY_NATIVE;
+ } else if (!strcmp(requested_type, "video_sfu")) {
+ video_mode = AST_BRIDGE_VIDEO_MODE_SFU;
}
}
+ /* For an SFU video bridge we ensure it always remains in multimix for the best experience. */
+ if (video_mode == AST_BRIDGE_VIDEO_MODE_SFU) {
+ capabilities = AST_BRIDGE_CAPABILITY_MULTIMIX;
+ flags &= ~AST_BRIDGE_FLAG_SMART;
+ }
+
if (!capabilities
/* Holding and mixing capabilities don't mix. */
|| ((capabilities & AST_BRIDGE_CAPABILITY_HOLDING)
@@ -794,7 +803,15 @@ static struct ast_bridge *bridge_create_common(const char *type, const char *nam
bridge = bridge_stasis_new(capabilities, flags, name, id);
if (bridge) {
- ast_bridge_set_talker_src_video_mode(bridge);
+ if (video_mode == AST_BRIDGE_VIDEO_MODE_SFU) {
+ ast_bridge_set_sfu_video_mode(bridge);
+ /* We require a minimum 5 seconds between video updates to stop floods from clients,
+ * this should rarely be changed but should become configurable in the future.
+ */
+ ast_bridge_set_video_update_discard(bridge, 5);
+ } else {
+ ast_bridge_set_talker_src_video_mode(bridge);
+ }
if (!ao2_link(app_bridges, bridge)) {
ast_bridge_destroy(bridge, 0);
bridge = NULL;