[Asterisk-code-review] pjsip / res rtp asterisk: Add support for sending REMB (asterisk[master])

Jenkins2 asteriskteam at digium.com
Mon Apr 9 11:14:17 CDT 2018


Jenkins2 has submitted this change and it was merged. ( https://gerrit.asterisk.org/8683 )

Change subject: pjsip / res_rtp_asterisk: Add support for sending REMB
......................................................................

pjsip / res_rtp_asterisk: Add support for sending REMB

This change allows chan_pjsip to be given an AST_FRAME_RTCP
containing REMB feedback and pass it to res_rtp_asterisk.
Once res_rtp_asterisk receives the frame a REMB RTCP feedback
packet is constructed with the appropriate contents and sent
to the remote endpoint.

ASTERISK-27776

Change-Id: Ic53f821c1560d8924907ad82c4d9c0bc322b38cd
---
M channels/chan_pjsip.c
M res/res_rtp_asterisk.c
2 files changed, 103 insertions(+), 36 deletions(-)

Approvals:
  Matthew Fredrickson: Looks good to me, but someone else must approve
  George Joseph: Looks good to me, approved
  Jenkins2: Approved for Submit



diff --git a/channels/chan_pjsip.c b/channels/chan_pjsip.c
index 5cb52a5..6b26648 100644
--- a/channels/chan_pjsip.c
+++ b/channels/chan_pjsip.c
@@ -966,6 +966,16 @@
 	case AST_FRAME_CNG:
 		break;
 	case AST_FRAME_RTCP:
+		/* We only support writing out feedback */
+		if (frame->subclass.integer != AST_RTP_RTCP_PSFB || !media) {
+			return 0;
+		} else if (media->type != AST_MEDIA_TYPE_VIDEO) {
+			ast_debug(3, "Channel %s stream %d is of type '%s', not video! Unable to write RTCP feedback.\n",
+				ast_channel_name(ast), stream_num, ast_codec_media_type2str(media->type));
+			return 0;
+		} else if (media->write_callback) {
+			res = media->write_callback(session, media, frame);
+		}
 		break;
 	default:
 		ast_log(LOG_WARNING, "Can't send %u type frames with PJSIP\n", frame->frametype);
diff --git a/res/res_rtp_asterisk.c b/res/res_rtp_asterisk.c
index b010f6c..2d854f2 100644
--- a/res/res_rtp_asterisk.c
+++ b/res/res_rtp_asterisk.c
@@ -4473,6 +4473,94 @@
 	return &red->t140red;
 }
 
+static void rtp_write_rtcp_fir(struct ast_rtp_instance *instance, struct ast_rtp *rtp, struct ast_sockaddr *remote_address)
+{
+	unsigned int *rtcpheader;
+	char bdata[1024];
+	int len = 20;
+	int ice;
+	int res;
+
+	if (!rtp || !rtp->rtcp) {
+		return;
+	}
+
+	if (ast_sockaddr_isnull(&rtp->rtcp->them) || rtp->rtcp->schedid < 0) {
+		/*
+		 * RTCP was stopped.
+		 */
+		return;
+	}
+
+	if (!rtp->themssrc_valid) {
+		/* We don't know their SSRC value so we don't know who to update. */
+		return;
+	}
+
+	/* Prepare RTCP FIR (PT=206, FMT=4) */
+	rtp->rtcp->firseq++;
+	if(rtp->rtcp->firseq == 256) {
+		rtp->rtcp->firseq = 0;
+	}
+
+	rtcpheader = (unsigned int *)bdata;
+	rtcpheader[0] = htonl((2 << 30) | (4 << 24) | (RTCP_PT_PSFB << 16) | ((len/4)-1));
+	rtcpheader[1] = htonl(rtp->ssrc);
+	rtcpheader[2] = htonl(rtp->themssrc);
+	rtcpheader[3] = htonl(rtp->themssrc);	/* FCI: SSRC */
+	rtcpheader[4] = htonl(rtp->rtcp->firseq << 24);			/* FCI: Sequence number */
+	res = rtcp_sendto(instance, (unsigned int *)rtcpheader, len, 0, rtp->bundled ? remote_address : &rtp->rtcp->them, &ice);
+	if (res < 0) {
+		ast_log(LOG_ERROR, "RTCP FIR transmission error: %s\n", strerror(errno));
+	}
+}
+
+static void rtp_write_rtcp_psfb(struct ast_rtp_instance *instance, struct ast_rtp *rtp, struct ast_frame *frame, struct ast_sockaddr *remote_address)
+{
+	struct ast_rtp_rtcp_feedback *feedback = frame->data.ptr;
+	unsigned int *rtcpheader;
+	char bdata[1024];
+	int len = 24;
+	int ice;
+	int res;
+
+	if (feedback->fmt != AST_RTP_RTCP_FMT_REMB) {
+		ast_debug(1, "Provided an RTCP feedback frame of format %d to write on RTP instance '%p' but only REMB is supported\n",
+			feedback->fmt, instance);
+		return;
+	}
+
+	if (!rtp || !rtp->rtcp) {
+		return;
+	}
+
+	/* If REMB support is not enabled don't send this RTCP packet */
+	if (!ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_REMB)) {
+		ast_debug(1, "Provided an RTCP feedback REMB report to write on RTP instance '%p' but REMB support not enabled\n",
+			instance);
+		return;
+	}
+
+	if (ast_sockaddr_isnull(&rtp->rtcp->them) || rtp->rtcp->schedid < 0) {
+		/*
+		 * RTCP was stopped.
+		 */
+		return;
+	}
+
+	rtcpheader = (unsigned int *)bdata;
+	rtcpheader[0] = htonl((2 << 30) | (AST_RTP_RTCP_FMT_REMB << 24) | (RTCP_PT_PSFB << 16) | ((len/4)-1));
+	rtcpheader[1] = htonl(rtp->ssrc);
+	rtcpheader[2] = htonl(0); /* Per the draft this should always be 0 */
+	rtcpheader[3] = htonl(('R' << 24) | ('E' << 16) | ('M' << 8) | ('B')); /* Unique identifier 'R' 'E' 'M' 'B' */
+	rtcpheader[4] = htonl((1 << 24) | (feedback->remb.br_exp << 18) | (feedback->remb.br_mantissa)); /* Number of SSRCs / BR Exp / BR Mantissa */
+	rtcpheader[5] = htonl(rtp->ssrc); /* The SSRC this feedback message applies to */
+	res = rtcp_sendto(instance, (unsigned int *)rtcpheader, len, 0, rtp->bundled ? remote_address : &rtp->rtcp->them, &ice);
+	if (res < 0) {
+		ast_log(LOG_ERROR, "RTCP PSFB transmission error: %s\n", strerror(errno));
+	}
+}
+
 /*! \pre instance is locked */
 static int ast_rtp_write(struct ast_rtp_instance *instance, struct ast_frame *frame)
 {
@@ -4491,42 +4579,11 @@
 
 	/* VP8: is this a request to send a RTCP FIR? */
 	if (frame->frametype == AST_FRAME_CONTROL && frame->subclass.integer == AST_CONTROL_VIDUPDATE) {
-		unsigned int *rtcpheader;
-		char bdata[1024];
-		int len = 20;
-		int ice;
-		int res;
-
-		if (!rtp || !rtp->rtcp) {
-			return 0;
-		}
-
-		if (ast_sockaddr_isnull(&rtp->rtcp->them) || rtp->rtcp->schedid < 0) {
-			/*
-			 * RTCP was stopped.
-			 */
-			return 0;
-		}
-		if (!rtp->themssrc_valid) {
-			/* We don't know their SSRC value so we don't know who to update. */
-			return 0;
-		}
-
-		/* Prepare RTCP FIR (PT=206, FMT=4) */
-		rtp->rtcp->firseq++;
-		if(rtp->rtcp->firseq == 256) {
-			rtp->rtcp->firseq = 0;
-		}
-
-		rtcpheader = (unsigned int *)bdata;
-		rtcpheader[0] = htonl((2 << 30) | (4 << 24) | (RTCP_PT_PSFB << 16) | ((len/4)-1));
-		rtcpheader[1] = htonl(rtp->ssrc);
-		rtcpheader[2] = htonl(rtp->themssrc);
-		rtcpheader[3] = htonl(rtp->themssrc);	/* FCI: SSRC */
-		rtcpheader[4] = htonl(rtp->rtcp->firseq << 24);			/* FCI: Sequence number */
-		res = rtcp_sendto(instance, (unsigned int *)rtcpheader, len, 0, rtp->bundled ? &remote_address : &rtp->rtcp->them, &ice);
-		if (res < 0) {
-			ast_log(LOG_ERROR, "RTCP FIR transmission error: %s\n", strerror(errno));
+		rtp_write_rtcp_fir(instance, rtp, &remote_address);
+		return 0;
+	} else if (frame->frametype == AST_FRAME_RTCP) {
+		if (frame->subclass.integer == AST_RTP_RTCP_PSFB) {
+			rtp_write_rtcp_psfb(instance, rtp, frame, &remote_address);
 		}
 		return 0;
 	}

-- 
To view, visit https://gerrit.asterisk.org/8683
To unsubscribe, visit https://gerrit.asterisk.org/settings

Gerrit-Project: asterisk
Gerrit-Branch: master
Gerrit-MessageType: merged
Gerrit-Change-Id: Ic53f821c1560d8924907ad82c4d9c0bc322b38cd
Gerrit-Change-Number: 8683
Gerrit-PatchSet: 2
Gerrit-Owner: Joshua Colp <jcolp at digium.com>
Gerrit-Reviewer: George Joseph <gjoseph at digium.com>
Gerrit-Reviewer: Jenkins2
Gerrit-Reviewer: Kevin Harwell <kharwell at digium.com>
Gerrit-Reviewer: Matthew Fredrickson <creslin at digium.com>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.digium.com/pipermail/asterisk-code-review/attachments/20180409/796ba1cb/attachment.html>


More information about the asterisk-code-review mailing list