|
|
|
@ -4473,6 +4473,94 @@ static struct ast_frame *red_t140_to_red(struct rtp_red *red)
|
|
|
|
|
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 @@ static int ast_rtp_write(struct ast_rtp_instance *instance, struct ast_frame *fr
|
|
|
|
|
|
|
|
|
|
/* 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;
|
|
|
|
|
}
|
|
|
|
|