summaryrefslogtreecommitdiff
path: root/res/res_rtp_multicast.c
diff options
context:
space:
mode:
authorSean Bright <sean.bright@gmail.com>2017-05-28 16:43:12 -0400
committerSean Bright <sean.bright@gmail.com>2017-05-30 15:10:20 -0500
commit5c27fe218776b499cff772660f2b4b7ee42b3802 (patch)
treeae91d3e182e3e2ba9d86b5063fad9367e1064631 /res/res_rtp_multicast.c
parentcf60a0c5bd9f01cee8f70003329dccc32752691e (diff)
format: Reintroduce smoother flags
In review 4843 (ASTERISK-24858), we added a hack that forced a smoother creation when sending signed linear so that the byte order was adjusted during transmission. This was needed because smoother flags were lost during the new format work that was done in Asterisk 13. Rather than rolling that same hack into res_rtp_multicast, re-introduce smoother flags so that formats can dictate their own options. Change-Id: I77b835fba0e539c6ce50014a984766f63cab2c16
Diffstat (limited to 'res/res_rtp_multicast.c')
-rw-r--r--res/res_rtp_multicast.c124
1 files changed, 89 insertions, 35 deletions
diff --git a/res/res_rtp_multicast.c b/res/res_rtp_multicast.c
index 42de11f65..14176da41 100644
--- a/res/res_rtp_multicast.c
+++ b/res/res_rtp_multicast.c
@@ -54,6 +54,7 @@
#include "asterisk/format_cache.h"
#include "asterisk/multicast_rtp.h"
#include "asterisk/app.h"
+#include "asterisk/smoother.h"
/*! Command value used for Linksys paging to indicate we are starting */
#define LINKSYS_MCAST_STARTCMD 6
@@ -95,6 +96,7 @@ struct multicast_rtp {
uint16_t seqno;
unsigned int lastts;
struct timeval txcore;
+ struct ast_smoother *smoother;
};
enum {
@@ -395,6 +397,10 @@ static int multicast_rtp_destroy(struct ast_rtp_instance *instance)
multicast_send_control_packet(instance, multicast, LINKSYS_MCAST_STOPCMD);
}
+ if (multicast->smoother) {
+ ast_smoother_free(multicast->smoother);
+ }
+
close(multicast->socket);
ast_free(multicast);
@@ -402,43 +408,24 @@ static int multicast_rtp_destroy(struct ast_rtp_instance *instance)
return 0;
}
-/*! \brief Function called to broadcast some audio on a multicast instance */
-static int multicast_rtp_write(struct ast_rtp_instance *instance, struct ast_frame *frame)
+static int rtp_raw_write(struct ast_rtp_instance *instance, struct ast_frame *frame, int codec)
{
struct multicast_rtp *multicast = ast_rtp_instance_get_data(instance);
- struct ast_frame *f = frame;
- struct ast_sockaddr remote_address;
- int hdrlen = 12, res = 0, codec;
- unsigned char *rtpheader;
unsigned int ms = calc_txstamp(multicast, &frame->delivery);
+ unsigned char *rtpheader;
+ struct ast_sockaddr remote_address = { {0,} };
int rate = rtp_get_rate(frame->subclass.format) / 1000;
+ int hdrlen = 12;
- /* We only accept audio, nothing else */
- if (frame->frametype != AST_FRAME_VOICE) {
- return 0;
- }
-
- /* Grab the actual payload number for when we create the RTP packet */
- codec = ast_rtp_codecs_payload_code_tx(ast_rtp_instance_get_codecs(instance),
- 1, frame->subclass.format, 0);
- if (codec < 0) {
- return -1;
- }
-
- /* If we do not have space to construct an RTP header duplicate the frame so we get some */
- if (frame->offset < hdrlen) {
- f = ast_frdup(frame);
- }
-
- /* Calucate last TS */
+ /* Calculate last TS */
multicast->lastts = multicast->lastts + ms * rate;
-
+
/* Construct an RTP header for our packet */
- rtpheader = (unsigned char *)(f->data.ptr - hdrlen);
+ rtpheader = (unsigned char *)(frame->data.ptr - hdrlen);
put_unaligned_uint32(rtpheader, htonl((2 << 30) | (codec << 16) | (multicast->seqno)));
-
- if (ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO)) {
- put_unaligned_uint32(rtpheader + 4, htonl(f->ts * 8));
+
+ if (ast_test_flag(frame, AST_FRFLAG_HAS_TIMING_INFO)) {
+ put_unaligned_uint32(rtpheader + 4, htonl(frame->ts * 8));
} else {
put_unaligned_uint32(rtpheader + 4, htonl(multicast->lastts));
}
@@ -451,19 +438,86 @@ static int multicast_rtp_write(struct ast_rtp_instance *instance, struct ast_fra
/* Finally send it out to the eager phones listening for us */
ast_rtp_instance_get_remote_address(instance, &remote_address);
- if (ast_sendto(multicast->socket, (void *) rtpheader, f->datalen + hdrlen, 0, &remote_address) < 0) {
+ if (ast_sendto(multicast->socket, (void *) rtpheader, frame->datalen + hdrlen, 0, &remote_address) < 0) {
ast_log(LOG_ERROR, "Multicast RTP Transmission error to %s: %s\n",
ast_sockaddr_stringify(&remote_address),
strerror(errno));
- res = -1;
+ return -1;
}
- /* If we were forced to duplicate the frame free the new one */
- if (frame != f) {
- ast_frfree(f);
+ return 0;
+}
+
+/*! \brief Function called to broadcast some audio on a multicast instance */
+static int multicast_rtp_write(struct ast_rtp_instance *instance, struct ast_frame *frame)
+{
+ struct multicast_rtp *multicast = ast_rtp_instance_get_data(instance);
+ struct ast_format *format;
+ struct ast_frame *f;
+ int codec;
+
+ /* We only accept audio, nothing else */
+ if (frame->frametype != AST_FRAME_VOICE) {
+ return 0;
}
- return res;
+ /* Grab the actual payload number for when we create the RTP packet */
+ codec = ast_rtp_codecs_payload_code_tx(ast_rtp_instance_get_codecs(instance),
+ 1, frame->subclass.format, 0);
+ if (codec < 0) {
+ return -1;
+ }
+
+ format = frame->subclass.format;
+ if (!multicast->smoother && ast_format_can_be_smoothed(format)) {
+ unsigned int smoother_flags = ast_format_get_smoother_flags(format);
+ unsigned int framing_ms = ast_rtp_codecs_get_framing(ast_rtp_instance_get_codecs(instance));
+
+ if (!framing_ms && (smoother_flags & AST_SMOOTHER_FLAG_FORCED)) {
+ framing_ms = ast_format_get_default_ms(format);
+ }
+
+ if (framing_ms) {
+ multicast->smoother = ast_smoother_new((framing_ms * ast_format_get_minimum_bytes(format)) / ast_format_get_minimum_ms(format));
+ if (!multicast->smoother) {
+ ast_log(LOG_WARNING, "Unable to create smoother: format %s ms: %u len %u\n",
+ ast_format_get_name(format), framing_ms, ast_format_get_minimum_bytes(format));
+ return -1;
+ }
+ ast_smoother_set_flags(multicast->smoother, smoother_flags);
+ }
+ }
+
+ if (multicast->smoother) {
+ if (ast_smoother_test_flag(multicast->smoother, AST_SMOOTHER_FLAG_BE)) {
+ ast_smoother_feed_be(multicast->smoother, frame);
+ } else {
+ ast_smoother_feed(multicast->smoother, frame);
+ }
+
+ while ((f = ast_smoother_read(multicast->smoother)) && f->data.ptr) {
+ rtp_raw_write(instance, f, codec);
+ }
+ } else {
+ int hdrlen = 12;
+
+ /* If we do not have space to construct an RTP header duplicate the frame so we get some */
+ if (frame->offset < hdrlen) {
+ f = ast_frdup(frame);
+ } else {
+ f = frame;
+ }
+
+ if (f->data.ptr) {
+ rtp_raw_write(instance, f, codec);
+ }
+
+ if (f != frame) {
+ ast_frfree(f);
+ }
+ }
+
+ return 0;
}
/*! \brief Function called to read from a multicast instance */