mirror of
https://github.com/asterisk/asterisk.git
synced 2025-10-03 19:16:46 +00:00
Merge "format: Reintroduce smoother flags" into 13
This commit is contained in:
@@ -26,6 +26,9 @@
|
||||
#ifndef _AST_CODEC_H_
|
||||
#define _AST_CODEC_H_
|
||||
|
||||
#define AST_SMOOTHER_FLAGS_PACK(x) ((x) << 1)
|
||||
#define AST_SMOOTHER_FLAGS_UNPACK(x) ((x) >> 1)
|
||||
|
||||
/*! \brief Types of media */
|
||||
enum ast_media_type {
|
||||
AST_MEDIA_TYPE_UNKNOWN = 0,
|
||||
|
@@ -337,6 +337,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
|
||||
*
|
||||
|
@@ -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
|
||||
*/
|
||||
|
@@ -37,6 +37,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#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);
|
||||
@@ -264,7 +265,7 @@ static struct ast_codec slin8 = {
|
||||
.minimum_bytes = 160,
|
||||
.samples_count = slin_samples,
|
||||
.get_length = slin_length,
|
||||
.smooth = 1,
|
||||
.smooth = AST_SMOOTHER_FLAGS_PACK(AST_SMOOTHER_FLAG_BE | AST_SMOOTHER_FLAG_FORCED),
|
||||
};
|
||||
|
||||
static struct ast_codec slin12 = {
|
||||
@@ -278,7 +279,7 @@ static struct ast_codec slin12 = {
|
||||
.minimum_bytes = 240,
|
||||
.samples_count = slin_samples,
|
||||
.get_length = slin_length,
|
||||
.smooth = 1,
|
||||
.smooth = AST_SMOOTHER_FLAGS_PACK(AST_SMOOTHER_FLAG_BE | AST_SMOOTHER_FLAG_FORCED),
|
||||
};
|
||||
|
||||
static struct ast_codec slin16 = {
|
||||
@@ -292,7 +293,7 @@ static struct ast_codec slin16 = {
|
||||
.minimum_bytes = 320,
|
||||
.samples_count = slin_samples,
|
||||
.get_length = slin_length,
|
||||
.smooth = 1,
|
||||
.smooth = AST_SMOOTHER_FLAGS_PACK(AST_SMOOTHER_FLAG_BE | AST_SMOOTHER_FLAG_FORCED),
|
||||
};
|
||||
|
||||
static struct ast_codec slin24 = {
|
||||
@@ -306,7 +307,7 @@ static struct ast_codec slin24 = {
|
||||
.minimum_bytes = 480,
|
||||
.samples_count = slin_samples,
|
||||
.get_length = slin_length,
|
||||
.smooth = 1,
|
||||
.smooth = AST_SMOOTHER_FLAGS_PACK(AST_SMOOTHER_FLAG_BE | AST_SMOOTHER_FLAG_FORCED),
|
||||
};
|
||||
|
||||
static struct ast_codec slin32 = {
|
||||
@@ -320,7 +321,7 @@ static struct ast_codec slin32 = {
|
||||
.minimum_bytes = 640,
|
||||
.samples_count = slin_samples,
|
||||
.get_length = slin_length,
|
||||
.smooth = 1,
|
||||
.smooth = AST_SMOOTHER_FLAGS_PACK(AST_SMOOTHER_FLAG_BE | AST_SMOOTHER_FLAG_FORCED),
|
||||
};
|
||||
|
||||
static struct ast_codec slin44 = {
|
||||
@@ -334,7 +335,7 @@ static struct ast_codec slin44 = {
|
||||
.minimum_bytes = 882,
|
||||
.samples_count = slin_samples,
|
||||
.get_length = slin_length,
|
||||
.smooth = 1,
|
||||
.smooth = AST_SMOOTHER_FLAGS_PACK(AST_SMOOTHER_FLAG_BE | AST_SMOOTHER_FLAG_FORCED),
|
||||
};
|
||||
|
||||
static struct ast_codec slin48 = {
|
||||
@@ -348,7 +349,7 @@ static struct ast_codec slin48 = {
|
||||
.minimum_bytes = 960,
|
||||
.samples_count = slin_samples,
|
||||
.get_length = slin_length,
|
||||
.smooth = 1,
|
||||
.smooth = AST_SMOOTHER_FLAGS_PACK(AST_SMOOTHER_FLAG_BE | AST_SMOOTHER_FLAG_FORCED),
|
||||
};
|
||||
|
||||
static struct ast_codec slin96 = {
|
||||
@@ -362,7 +363,7 @@ static struct ast_codec slin96 = {
|
||||
.minimum_bytes = 1920,
|
||||
.samples_count = slin_samples,
|
||||
.get_length = slin_length,
|
||||
.smooth = 1,
|
||||
.smooth = AST_SMOOTHER_FLAGS_PACK(AST_SMOOTHER_FLAG_BE | AST_SMOOTHER_FLAG_FORCED),
|
||||
};
|
||||
|
||||
static struct ast_codec slin192 = {
|
||||
@@ -376,7 +377,7 @@ static struct ast_codec slin192 = {
|
||||
.minimum_bytes = 3840,
|
||||
.samples_count = slin_samples,
|
||||
.get_length = slin_length,
|
||||
.smooth = 1,
|
||||
.smooth = AST_SMOOTHER_FLAGS_PACK(AST_SMOOTHER_FLAG_BE | AST_SMOOTHER_FLAG_FORCED),
|
||||
};
|
||||
|
||||
static int lpc10_samples(struct ast_frame *frame)
|
||||
|
@@ -377,7 +377,13 @@ const char *ast_format_get_codec_name(const struct ast_format *format)
|
||||
|
||||
int ast_format_can_be_smoothed(const struct ast_format *format)
|
||||
{
|
||||
return format->codec->smooth;
|
||||
/* Coalesce to 1 if non-zero */
|
||||
return format->codec->smooth ? 1 : 0;
|
||||
}
|
||||
|
||||
int ast_format_get_smoother_flags(const struct ast_format *format)
|
||||
{
|
||||
return AST_SMOOTHER_FLAGS_UNPACK(format->codec->smooth);
|
||||
}
|
||||
|
||||
enum ast_media_type ast_format_get_type(const struct ast_format *format)
|
||||
|
@@ -3743,7 +3743,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;
|
||||
@@ -4014,10 +4014,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);
|
||||
}
|
||||
|
||||
@@ -4028,9 +4028,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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4045,7 +4043,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;
|
||||
@@ -4057,7 +4055,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);
|
||||
|
@@ -56,6 +56,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#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
|
||||
@@ -97,6 +98,7 @@ struct multicast_rtp {
|
||||
uint16_t seqno;
|
||||
unsigned int lastts;
|
||||
struct timeval txcore;
|
||||
struct ast_smoother *smoother;
|
||||
};
|
||||
|
||||
enum {
|
||||
@@ -397,6 +399,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);
|
||||
@@ -404,41 +410,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 */
|
||||
if ((codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(instance), 1, frame->subclass.format, 0)) < 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 +440,84 @@ 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 */
|
||||
if ((codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(instance), 1, frame->subclass.format, 0)) < 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 */
|
||||
|
Reference in New Issue
Block a user