Merge "format: Reintroduce smoother flags"

This commit is contained in:
Jenkins2
2017-06-06 08:59:37 -05:00
committed by Gerrit Code Review
7 changed files with 130 additions and 49 deletions
+2
View File
@@ -76,6 +76,8 @@ struct ast_codec {
int (*get_length)(unsigned int samples);
/*! \brief Whether the media can be smoothed or not */
unsigned int smooth;
/*! \brief Flags to be passed to the smoother */
unsigned int smoother_flags;
/*! \brief The module that registered this codec */
struct ast_module *mod;
};
+11
View File
@@ -355,6 +355,17 @@ const char *ast_format_get_codec_name(const struct ast_format *format);
*/
int ast_format_can_be_smoothed(const struct ast_format *format);
/*!
* \since 13.17.0
*
* \brief Get smoother flags for this format
*
* \param format The media format
*
* \return smoother flags for the provided format
*/
int ast_format_get_smoother_flags(const struct ast_format *format);
/*!
* \brief Get the media type of a format
*
+1
View File
@@ -33,6 +33,7 @@ extern "C" {
#define AST_SMOOTHER_FLAG_G729 (1 << 0)
#define AST_SMOOTHER_FLAG_BE (1 << 1)
#define AST_SMOOTHER_FLAG_FORCED (1 << 2)
/*! \name AST_Smoother
*/
+10
View File
@@ -36,6 +36,7 @@
#include "asterisk/format.h"
#include "asterisk/format_cache.h"
#include "asterisk/frame.h"
#include "asterisk/smoother.h"
int __ast_codec_register_with_format(struct ast_codec *codec, const char *format_name,
struct ast_module *mod);
@@ -288,6 +289,7 @@ static struct ast_codec slin8 = {
.samples_count = slin_samples,
.get_length = slin_length,
.smooth = 1,
.smoother_flags = AST_SMOOTHER_FLAG_BE | AST_SMOOTHER_FLAG_FORCED,
};
static struct ast_codec slin12 = {
@@ -302,6 +304,7 @@ static struct ast_codec slin12 = {
.samples_count = slin_samples,
.get_length = slin_length,
.smooth = 1,
.smoother_flags = AST_SMOOTHER_FLAG_BE | AST_SMOOTHER_FLAG_FORCED,
};
static struct ast_codec slin16 = {
@@ -316,6 +319,7 @@ static struct ast_codec slin16 = {
.samples_count = slin_samples,
.get_length = slin_length,
.smooth = 1,
.smoother_flags = AST_SMOOTHER_FLAG_BE | AST_SMOOTHER_FLAG_FORCED,
};
static struct ast_codec slin24 = {
@@ -330,6 +334,7 @@ static struct ast_codec slin24 = {
.samples_count = slin_samples,
.get_length = slin_length,
.smooth = 1,
.smoother_flags = AST_SMOOTHER_FLAG_BE | AST_SMOOTHER_FLAG_FORCED,
};
static struct ast_codec slin32 = {
@@ -344,6 +349,7 @@ static struct ast_codec slin32 = {
.samples_count = slin_samples,
.get_length = slin_length,
.smooth = 1,
.smoother_flags = AST_SMOOTHER_FLAG_BE | AST_SMOOTHER_FLAG_FORCED,
};
static struct ast_codec slin44 = {
@@ -358,6 +364,7 @@ static struct ast_codec slin44 = {
.samples_count = slin_samples,
.get_length = slin_length,
.smooth = 1,
.smoother_flags = AST_SMOOTHER_FLAG_BE | AST_SMOOTHER_FLAG_FORCED,
};
static struct ast_codec slin48 = {
@@ -372,6 +379,7 @@ static struct ast_codec slin48 = {
.samples_count = slin_samples,
.get_length = slin_length,
.smooth = 1,
.smoother_flags = AST_SMOOTHER_FLAG_BE | AST_SMOOTHER_FLAG_FORCED,
};
static struct ast_codec slin96 = {
@@ -386,6 +394,7 @@ static struct ast_codec slin96 = {
.samples_count = slin_samples,
.get_length = slin_length,
.smooth = 1,
.smoother_flags = AST_SMOOTHER_FLAG_BE | AST_SMOOTHER_FLAG_FORCED,
};
static struct ast_codec slin192 = {
@@ -400,6 +409,7 @@ static struct ast_codec slin192 = {
.samples_count = slin_samples,
.get_length = slin_length,
.smooth = 1,
.smoother_flags = AST_SMOOTHER_FLAG_BE | AST_SMOOTHER_FLAG_FORCED,
};
static int lpc10_samples(struct ast_frame *frame)
+5
View File
@@ -391,6 +391,11 @@ int ast_format_can_be_smoothed(const struct ast_format *format)
return format->codec->smooth;
}
int ast_format_get_smoother_flags(const struct ast_format *format)
{
return format->codec->smoother_flags;
}
enum ast_media_type ast_format_get_type(const struct ast_format *format)
{
return format->codec->type;
+6 -8
View File
@@ -3747,7 +3747,7 @@ static int ast_rtcp_write(const void *data)
}
/*! \pre instance is locked */
static int ast_rtp_raw_write(struct ast_rtp_instance *instance, struct ast_frame *frame, int codec)
static int rtp_raw_write(struct ast_rtp_instance *instance, struct ast_frame *frame, int codec)
{
struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
int pred, mark = 0;
@@ -4016,10 +4016,10 @@ static int ast_rtp_write(struct ast_rtp_instance *instance, struct ast_frame *fr
/* If no smoother is present see if we have to set one up */
if (!rtp->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));
int is_slinear = ast_format_cache_is_slinear(format);
if (!framing_ms && is_slinear) {
if (!framing_ms && (smoother_flags & AST_SMOOTHER_FLAG_FORCED)) {
framing_ms = ast_format_get_default_ms(format);
}
@@ -4030,9 +4030,7 @@ static int ast_rtp_write(struct ast_rtp_instance *instance, struct ast_frame *fr
ast_format_get_name(format), framing_ms, ast_format_get_minimum_bytes(format));
return -1;
}
if (is_slinear) {
ast_smoother_set_flags(rtp->smoother, AST_SMOOTHER_FLAG_BE);
}
ast_smoother_set_flags(rtp->smoother, smoother_flags);
}
}
@@ -4047,7 +4045,7 @@ static int ast_rtp_write(struct ast_rtp_instance *instance, struct ast_frame *fr
}
while ((f = ast_smoother_read(rtp->smoother)) && (f->data.ptr)) {
ast_rtp_raw_write(instance, f, codec);
rtp_raw_write(instance, f, codec);
}
} else {
int hdrlen = 12;
@@ -4059,7 +4057,7 @@ static int ast_rtp_write(struct ast_rtp_instance *instance, struct ast_frame *fr
f = frame;
}
if (f->data.ptr) {
ast_rtp_raw_write(instance, f, codec);
rtp_raw_write(instance, f, codec);
}
if (f != frame) {
ast_frfree(f);
+95 -41
View File
@@ -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,16 +408,53 @@ static int multicast_rtp_destroy(struct ast_rtp_instance *instance)
return 0;
}
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);
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;
/* Calculate last TS */
multicast->lastts = multicast->lastts + ms * rate;
/* Construct an RTP header for our packet */
rtpheader = (unsigned char *)(frame->data.ptr - hdrlen);
put_unaligned_uint32(rtpheader, htonl((2 << 30) | (codec << 16) | (multicast->seqno)));
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));
}
put_unaligned_uint32(rtpheader + 8, htonl(multicast->ssrc));
/* Increment sequence number and wrap to 0 if it overflows 16 bits. */
multicast->seqno = 0xFFFF & (multicast->seqno + 1);
/* 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, 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));
return -1;
}
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_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);
int rate = rtp_get_rate(frame->subclass.format) / 1000;
struct ast_format *format;
struct ast_frame *f;
int codec;
/* We only accept audio, nothing else */
if (frame->frametype != AST_FRAME_VOICE) {
@@ -425,45 +468,56 @@ static int multicast_rtp_write(struct ast_rtp_instance *instance, struct ast_fra
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);
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);
}
}
/* Calucate last TS */
multicast->lastts = multicast->lastts + ms * rate;
/* Construct an RTP header for our packet */
rtpheader = (unsigned char *)(f->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 (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 {
put_unaligned_uint32(rtpheader + 4, htonl(multicast->lastts));
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);
}
}
put_unaligned_uint32(rtpheader + 8, htonl(multicast->ssrc));
/* Increment sequence number and wrap to 0 if it overflows 16 bits. */
multicast->seqno = 0xFFFF & (multicast->seqno + 1);
/* 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) {
ast_log(LOG_ERROR, "Multicast RTP Transmission error to %s: %s\n",
ast_sockaddr_stringify(&remote_address),
strerror(errno));
res = -1;
}
/* If we were forced to duplicate the frame free the new one */
if (frame != f) {
ast_frfree(f);
}
return res;
return 0;
}
/*! \brief Function called to read from a multicast instance */