diff options
Diffstat (limited to 'res')
-rw-r--r-- | res/res_pjsip_outbound_publish.c | 2 | ||||
-rw-r--r-- | res/res_pjsip_session.c | 10 | ||||
-rw-r--r-- | res/res_rtp_asterisk.c | 119 | ||||
-rw-r--r-- | res/res_stasis.c | 19 |
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; |