<p>Jenkins2 <strong>merged</strong> this change.</p><p><a href="https://gerrit.asterisk.org/8682">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  Matthew Fredrickson: Looks good to me, but someone else must approve
  George Joseph: Looks good to me, approved
  Jenkins2: Approved for Submit

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">pjsip / res_rtp_asterisk: Add support for sending REMB<br><br>This change allows chan_pjsip to be given an AST_FRAME_RTCP<br>containing REMB feedback and pass it to res_rtp_asterisk.<br>Once res_rtp_asterisk receives the frame a REMB RTCP feedback<br>packet is constructed with the appropriate contents and sent<br>to the remote endpoint.<br><br>ASTERISK-27776<br><br>Change-Id: Ic53f821c1560d8924907ad82c4d9c0bc322b38cd<br>---<br>M channels/chan_pjsip.c<br>M res/res_rtp_asterisk.c<br>2 files changed, 103 insertions(+), 36 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">diff --git a/channels/chan_pjsip.c b/channels/chan_pjsip.c<br>index 60bb9ed..69797d3 100644<br>--- a/channels/chan_pjsip.c<br>+++ b/channels/chan_pjsip.c<br>@@ -966,6 +966,16 @@<br>        case AST_FRAME_CNG:<br>           break;<br>        case AST_FRAME_RTCP:<br>+         /* We only support writing out feedback */<br>+           if (frame->subclass.integer != AST_RTP_RTCP_PSFB || !media) {<br>+                     return 0;<br>+            } else if (media->type != AST_MEDIA_TYPE_VIDEO) {<br>+                 ast_debug(3, "Channel %s stream %d is of type '%s', not video! Unable to write RTCP feedback.\n",<br>+                          ast_channel_name(ast), stream_num, ast_codec_media_type2str(media->type));<br>+                        return 0;<br>+            } else if (media->write_callback) {<br>+                       res = media->write_callback(session, media, frame);<br>+               }<br>             break;<br>        default:<br>              ast_log(LOG_WARNING, "Can't send %u type frames with PJSIP\n", frame->frametype);<br>diff --git a/res/res_rtp_asterisk.c b/res/res_rtp_asterisk.c<br>index b010f6c..2d854f2 100644<br>--- a/res/res_rtp_asterisk.c<br>+++ b/res/res_rtp_asterisk.c<br>@@ -4473,6 +4473,94 @@<br>   return &red->t140red;<br> }<br> <br>+static void rtp_write_rtcp_fir(struct ast_rtp_instance *instance, struct ast_rtp *rtp, struct ast_sockaddr *remote_address)<br>+{<br>+        unsigned int *rtcpheader;<br>+    char bdata[1024];<br>+    int len = 20;<br>+        int ice;<br>+     int res;<br>+<br>+  if (!rtp || !rtp->rtcp) {<br>+         return;<br>+      }<br>+<br>+ if (ast_sockaddr_isnull(&rtp->rtcp->them) || rtp->rtcp->schedid < 0) {<br>+            /*<br>+            * RTCP was stopped.<br>+          */<br>+          return;<br>+      }<br>+<br>+ if (!rtp->themssrc_valid) {<br>+               /* We don't know their SSRC value so we don't know who to update. */<br>+         return;<br>+      }<br>+<br>+ /* Prepare RTCP FIR (PT=206, FMT=4) */<br>+       rtp->rtcp->firseq++;<br>+   if(rtp->rtcp->firseq == 256) {<br>+         rtp->rtcp->firseq = 0;<br>+ }<br>+<br>+ rtcpheader = (unsigned int *)bdata;<br>+  rtcpheader[0] = htonl((2 << 30) | (4 << 24) | (RTCP_PT_PSFB << 16) | ((len/4)-1));<br>+ rtcpheader[1] = htonl(rtp->ssrc);<br>+ rtcpheader[2] = htonl(rtp->themssrc);<br>+     rtcpheader[3] = htonl(rtp->themssrc);        /* FCI: SSRC */<br>+      rtcpheader[4] = htonl(rtp->rtcp->firseq << 24);                     /* FCI: Sequence number */<br>+   res = rtcp_sendto(instance, (unsigned int *)rtcpheader, len, 0, rtp->bundled ? remote_address : &rtp->rtcp->them, &ice);<br>+    if (res < 0) {<br>+            ast_log(LOG_ERROR, "RTCP FIR transmission error: %s\n", strerror(errno));<br>+  }<br>+}<br>+<br>+static void rtp_write_rtcp_psfb(struct ast_rtp_instance *instance, struct ast_rtp *rtp, struct ast_frame *frame, struct ast_sockaddr *remote_address)<br>+{<br>+ struct ast_rtp_rtcp_feedback *feedback = frame->data.ptr;<br>+ unsigned int *rtcpheader;<br>+    char bdata[1024];<br>+    int len = 24;<br>+        int ice;<br>+     int res;<br>+<br>+  if (feedback->fmt != AST_RTP_RTCP_FMT_REMB) {<br>+             ast_debug(1, "Provided an RTCP feedback frame of format %d to write on RTP instance '%p' but only REMB is supported\n",<br>+                    feedback->fmt, instance);<br>+         return;<br>+      }<br>+<br>+ if (!rtp || !rtp->rtcp) {<br>+         return;<br>+      }<br>+<br>+ /* If REMB support is not enabled don't send this RTCP packet */<br>+ if (!ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_REMB)) {<br>+           ast_debug(1, "Provided an RTCP feedback REMB report to write on RTP instance '%p' but REMB support not enabled\n",<br>+                 instance);<br>+           return;<br>+      }<br>+<br>+ if (ast_sockaddr_isnull(&rtp->rtcp->them) || rtp->rtcp->schedid < 0) {<br>+            /*<br>+            * RTCP was stopped.<br>+          */<br>+          return;<br>+      }<br>+<br>+ rtcpheader = (unsigned int *)bdata;<br>+  rtcpheader[0] = htonl((2 << 30) | (AST_RTP_RTCP_FMT_REMB << 24) | (RTCP_PT_PSFB << 16) | ((len/4)-1));<br>+     rtcpheader[1] = htonl(rtp->ssrc);<br>+ rtcpheader[2] = htonl(0); /* Per the draft this should always be 0 */<br>+        rtcpheader[3] = htonl(('R' << 24) | ('E' << 16) | ('M' << 8) | ('B')); /* Unique identifier 'R' 'E' 'M' 'B' */<br>+     rtcpheader[4] = htonl((1 << 24) | (feedback->remb.br_exp << 18) | (feedback->remb.br_mantissa)); /* Number of SSRCs / BR Exp / BR Mantissa */<br>+      rtcpheader[5] = htonl(rtp->ssrc); /* The SSRC this feedback message applies to */<br>+ res = rtcp_sendto(instance, (unsigned int *)rtcpheader, len, 0, rtp->bundled ? remote_address : &rtp->rtcp->them, &ice);<br>+    if (res < 0) {<br>+            ast_log(LOG_ERROR, "RTCP PSFB transmission error: %s\n", strerror(errno));<br>+ }<br>+}<br>+<br> /*! \pre instance is locked */<br> static int ast_rtp_write(struct ast_rtp_instance *instance, struct ast_frame *frame)<br> {<br>@@ -4491,42 +4579,11 @@<br> <br>      /* VP8: is this a request to send a RTCP FIR? */<br>      if (frame->frametype == AST_FRAME_CONTROL && frame->subclass.integer == AST_CONTROL_VIDUPDATE) {<br>-               unsigned int *rtcpheader;<br>-            char bdata[1024];<br>-            int len = 20;<br>-                int ice;<br>-             int res;<br>-<br>-          if (!rtp || !rtp->rtcp) {<br>-                 return 0;<br>-            }<br>-<br>-         if (ast_sockaddr_isnull(&rtp->rtcp->them) || rtp->rtcp->schedid < 0) {<br>-                    /*<br>-                    * RTCP was stopped.<br>-                  */<br>-                  return 0;<br>-            }<br>-            if (!rtp->themssrc_valid) {<br>-                       /* We don't know their SSRC value so we don't know who to update. */<br>-                 return 0;<br>-            }<br>-<br>-         /* Prepare RTCP FIR (PT=206, FMT=4) */<br>-               rtp->rtcp->firseq++;<br>-           if(rtp->rtcp->firseq == 256) {<br>-                 rtp->rtcp->firseq = 0;<br>-         }<br>-<br>-         rtcpheader = (unsigned int *)bdata;<br>-          rtcpheader[0] = htonl((2 << 30) | (4 << 24) | (RTCP_PT_PSFB << 16) | ((len/4)-1));<br>-         rtcpheader[1] = htonl(rtp->ssrc);<br>-         rtcpheader[2] = htonl(rtp->themssrc);<br>-             rtcpheader[3] = htonl(rtp->themssrc);        /* FCI: SSRC */<br>-              rtcpheader[4] = htonl(rtp->rtcp->firseq << 24);                     /* FCI: Sequence number */<br>-           res = rtcp_sendto(instance, (unsigned int *)rtcpheader, len, 0, rtp->bundled ? &remote_address : &rtp->rtcp->them, &ice);<br>-               if (res < 0) {<br>-                    ast_log(LOG_ERROR, "RTCP FIR transmission error: %s\n", strerror(errno));<br>+          rtp_write_rtcp_fir(instance, rtp, &remote_address);<br>+              return 0;<br>+    } else if (frame->frametype == AST_FRAME_RTCP) {<br>+          if (frame->subclass.integer == AST_RTP_RTCP_PSFB) {<br>+                       rtp_write_rtcp_psfb(instance, rtp, frame, &remote_address);<br>               }<br>             return 0;<br>     }<br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/8682">change 8682</a>. To unsubscribe, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/8682"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: 15 </div>
<div style="display:none"> Gerrit-MessageType: merged </div>
<div style="display:none"> Gerrit-Change-Id: Ic53f821c1560d8924907ad82c4d9c0bc322b38cd </div>
<div style="display:none"> Gerrit-Change-Number: 8682 </div>
<div style="display:none"> Gerrit-PatchSet: 2 </div>
<div style="display:none"> Gerrit-Owner: Joshua Colp <jcolp@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: George Joseph <gjoseph@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins2 </div>
<div style="display:none"> Gerrit-Reviewer: Kevin Harwell <kharwell@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Matthew Fredrickson <creslin@digium.com> </div>