Add pass through support for Opus and VP8; Opus format attribute negotiation

This patch adds pass through support for Opus and VP8. That includes:

* Format attribute negotiation for Opus. Note that unlike some other codecs,
  the draft RFC specifies having spaces delimiting the attributes in addition
  to ';', so you have "attra=X; attrb=Y". This broke the attribute parsing in
  chan_sip, so a small tweak was also included in this patch for that.

* A format attribute negotiation module for Opus, res_format_attr_opus

* Fast picture update for VP8. Since VP8 uses a different RTCP packet number
  than FIR, this really is specific to VP8 at this time.

Note that the format attribute negotiation in res_pjsip_sdp_rtp was written
by mjordan. The rest of this patch was written completely by Lorenzo Miniero.

Review: https://reviewboard.asterisk.org/r/2723/

(closes issue ASTERISK-21981)
Reported by: Tzafrir Cohen
patches:
  asterisk_opus+vp8_passthrough_20130718.patch uploaded by lminiero (License 6518)



git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@397526 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Matthew Jordan
2013-08-23 15:42:27 +00:00
parent e31bd332b8
commit 4d348e853c
11 changed files with 543 additions and 25 deletions

View File

@@ -90,6 +90,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#define RTCP_PT_SDES 202
#define RTCP_PT_BYE 203
#define RTCP_PT_APP 204
/* VP8: RTCP Feedback */
#define RTCP_PT_PSFB 206
#define RTP_MTU 1200
@@ -350,6 +352,9 @@ struct ast_rtcp {
double normdevrtt;
double stdevrtt;
unsigned int rtt_count;
/* VP8: sequence number for the RTCP FIR FCI */
int firseq;
};
struct rtp_red {
@@ -2414,7 +2419,7 @@ static int ast_rtcp_write(const void *data)
}
if (!res) {
/*
/*
* Not being rescheduled.
*/
ao2_ref(instance, -1);
@@ -2609,6 +2614,45 @@ static int ast_rtp_write(struct ast_rtp_instance *instance, struct ast_frame *fr
return 0;
}
/* VP8: is this a request to send a RTCP FIR? */
if (frame->frametype == AST_FRAME_CONTROL && frame->subclass.integer == AST_CONTROL_VIDUPDATE) {
struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
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)) {
/*
* RTCP was stopped.
*/
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->rtcp->them, &ice);
if (res < 0) {
ast_log(LOG_ERROR, "RTCP FIR transmission error: %s\n", strerror(errno));
}
return 0;
}
/* If there is no data length we can't very well send the packet */
if (!frame->datalen) {
ast_debug(1, "Received frame with no data for RTP instance '%p' so dropping frame\n", instance);
@@ -2660,6 +2704,8 @@ static int ast_rtp_write(struct ast_rtp_instance *instance, struct ast_frame *fr
case AST_FORMAT_SIREN7:
case AST_FORMAT_SIREN14:
case AST_FORMAT_G719:
/* Opus */
case AST_FORMAT_OPUS:
/* these are all frame-based codecs and cannot be safely run through
a smoother */
break;
@@ -3353,6 +3399,8 @@ static struct ast_frame *ast_rtcp_read(struct ast_rtp_instance *instance)
message_blob);
break;
case RTCP_PT_FUR:
/* Handle RTCP FIR as FUR */
case RTCP_PT_PSFB:
if (rtcp_debug_test_addr(&addr)) {
ast_verbose("Received an RTCP Fast Update Request\n");
}
@@ -4174,14 +4222,14 @@ static int ast_rtp_sendcng(struct ast_rtp_instance *instance, int level)
payload = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(instance), 0, NULL, AST_RTP_CN);
level = 127 - (level & 0x7f);
rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
/* Get a pointer to the header */
rtpheader = (unsigned int *)data;
rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno));
rtpheader[1] = htonl(rtp->lastts);
rtpheader[2] = htonl(rtp->ssrc);
rtpheader[2] = htonl(rtp->ssrc);
data[12] = level;
res = rtp_sendto(instance, (void *) rtpheader, hdrlen + 1, 0, &remote_address, &ice);