]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
format: Reintroduce smoother flags
authorSean Bright <sean.bright@gmail.com>
Sun, 28 May 2017 20:43:12 +0000 (16:43 -0400)
committerSean Bright <sean.bright@gmail.com>
Tue, 30 May 2017 20:09:33 +0000 (15:09 -0500)
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

include/asterisk/codec.h
include/asterisk/format.h
include/asterisk/smoother.h
main/codec_builtin.c
main/format.c
res/res_rtp_asterisk.c
res/res_rtp_multicast.c

index 3873324b14399b453ae9bd5ab57e9695358acff2..e3b71062b3e4b6676d5ff8d343a32e13c3570e64 100644 (file)
@@ -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,
index a5ca038183a2d4442430bcd4191b56e545a96145..fb130e83b9e9ee3ee7afadde7b189021830a77ce 100644 (file)
@@ -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
  *
index e63aa77bd684ca8c6324373a337d25f7a672ec83..65ac88921fa86998db662d0443c580f318b53c18 100644 (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
 */
index 4f175059859c6fc80c64e2655cad71ba47fd2f11..96868e674a7f7f0a4cf2260eaf04907ee9115cfe 100644 (file)
@@ -38,6 +38,7 @@ ASTERISK_REGISTER_FILE()
 #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);
@@ -265,7 +266,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 = {
@@ -279,7 +280,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 = {
@@ -293,7 +294,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 = {
@@ -307,7 +308,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 = {
@@ -321,7 +322,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 = {
@@ -335,7 +336,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 = {
@@ -349,7 +350,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 = {
@@ -363,7 +364,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 = {
@@ -377,7 +378,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)
index cc9ac45d73a5d22ed3dd0f42dc6fbd924fe855ff..e5120d79fca9221479e5b1604ca072a75a5c601e 100644 (file)
@@ -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)
index 8d4e50d378b5880fab5751c3fb9e9c71a6881eba..1006c22b2ad1309604e2d0fbe6fb1072a6c1f524 100644 (file)
@@ -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;
@@ -4012,10 +4012,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);
                }
 
@@ -4026,9 +4026,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);
                }
        }
 
@@ -4043,7 +4041,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;
@@ -4055,7 +4053,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);
index fce4926594649f9ed3965de9274bafb18860e862..06111aa24c571144c0371625af3ca6cd31e050ca 100644 (file)
@@ -56,6 +56,7 @@ ASTERISK_REGISTER_FILE()
 #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,43 +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 */
-       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));
        }
@@ -453,19 +440,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 */