Asterisk - The Open Source Telephony Project  18.5.0
Data Structures | Macros | Functions
smoother.c File Reference

Frame smoother manipulation routines. More...

#include "asterisk.h"
#include "asterisk/_private.h"
#include "asterisk/frame.h"
#include "asterisk/astobj2.h"
#include "asterisk/time.h"
#include "asterisk/utils.h"
#include "asterisk/format.h"
#include "asterisk/codec.h"
#include "asterisk/smoother.h"
Include dependency graph for smoother.c:

Go to the source code of this file.

Data Structures

struct  ast_smoother
 

Macros

#define SMOOTHER_SIZE   8000
 

Functions

int __ast_smoother_feed (struct ast_smoother *s, struct ast_frame *f, int swap)
 
void ast_smoother_free (struct ast_smoother *s)
 
int ast_smoother_get_flags (struct ast_smoother *s)
 
struct ast_smootherast_smoother_new (int size)
 
struct ast_frameast_smoother_read (struct ast_smoother *s)
 
void ast_smoother_reconfigure (struct ast_smoother *s, int bytes)
 Reconfigure an existing smoother to output a different number of bytes per frame. More...
 
void ast_smoother_reset (struct ast_smoother *s, int bytes)
 
void ast_smoother_set_flags (struct ast_smoother *s, int flags)
 
int ast_smoother_test_flag (struct ast_smoother *s, int flag)
 
static int smoother_frame_feed (struct ast_smoother *s, struct ast_frame *f, int swap)
 

Detailed Description

Frame smoother manipulation routines.

Author
Mark Spencer marks.nosp@m.ter@.nosp@m.digiu.nosp@m.m.co.nosp@m.m

Definition in file smoother.c.

Macro Definition Documentation

◆ SMOOTHER_SIZE

#define SMOOTHER_SIZE   8000

Definition at line 41 of file smoother.c.

Referenced by __ast_smoother_feed().

Function Documentation

◆ __ast_smoother_feed()

int __ast_smoother_feed ( struct ast_smoother s,
struct ast_frame f,
int  swap 
)

Definition at line 133 of file smoother.c.

References ao2_bump, ast_format_cmp(), AST_FORMAT_CMP_NOT_EQUAL, ast_format_get_name(), AST_FRAME_VOICE, ast_log, AST_MIN_OFFSET, AST_SMOOTHER_FLAG_G729, ast_swapcopy_samples(), ast_frame::data, ast_frame::datalen, ast_smoother::f, ast_smoother::flags, ast_smoother::format, ast_frame_subclass::format, ast_frame::frametype, ast_smoother::len, LOG_WARNING, ast_frame::offset, ast_smoother::opt, ast_smoother::opt_needs_swap, ast_frame::ptr, ast_frame::samples, ast_smoother::samplesperbyte, ast_smoother::size, smoother_frame_feed(), SMOOTHER_SIZE, and ast_frame::subclass.

134 {
135  if (f->frametype != AST_FRAME_VOICE) {
136  ast_log(LOG_WARNING, "Huh? Can't smooth a non-voice frame!\n");
137  return -1;
138  }
139  if (!s->format) {
140  s->format = ao2_bump(f->subclass.format);
141  s->samplesperbyte = (float)f->samples / (float)f->datalen;
143  ast_log(LOG_WARNING, "Smoother was working on %s format frames, now trying to feed %s?\n",
145  return -1;
146  }
147  if (s->len + f->datalen > SMOOTHER_SIZE) {
148  ast_log(LOG_WARNING, "Out of smoother space\n");
149  return -1;
150  }
151  if (((f->datalen == s->size) ||
152  ((f->datalen < 10) && (s->flags & AST_SMOOTHER_FLAG_G729))) &&
153  !s->opt &&
154  !s->len &&
155  (f->offset >= AST_MIN_OFFSET)) {
156  /* Optimize by sending the frame we just got
157  on the next read, thus eliminating the douple
158  copy */
159  if (swap)
161  s->opt = f;
162  s->opt_needs_swap = swap ? 1 : 0;
163  return 0;
164  }
165 
166  return smoother_frame_feed(s, f, swap);
167 }
#define AST_SMOOTHER_FLAG_G729
Definition: smoother.h:34
#define LOG_WARNING
Definition: logger.h:274
void ast_swapcopy_samples(void *dst, const void *src, int samples)
Definition: main/frame.c:396
const char * ast_format_get_name(const struct ast_format *format)
Get the name associated with a format.
Definition: format.c:334
#define SMOOTHER_SIZE
Definition: smoother.c:41
struct ast_frame_subclass subclass
#define AST_MIN_OFFSET
#define ao2_bump(obj)
Definition: astobj2.h:491
#define ast_log
Definition: astobj2.c:42
enum ast_format_cmp_res ast_format_cmp(const struct ast_format *format1, const struct ast_format *format2)
Compare two formats.
Definition: format.c:201
static int smoother_frame_feed(struct ast_smoother *s, struct ast_frame *f, int swap)
Definition: smoother.c:57
float samplesperbyte
Definition: smoother.c:47
struct ast_frame * opt
Definition: smoother.c:53
unsigned int opt_needs_swap
Definition: smoother.c:48
struct ast_format * format
Definition: smoother.c:45
union ast_frame::@263 data
enum ast_frame_type frametype
struct ast_format * format

◆ ast_smoother_free()

void ast_smoother_free ( struct ast_smoother s)

Definition at line 220 of file smoother.c.

References ao2_cleanup, ast_free, and ast_smoother::format.

Referenced by ast_rtp_destroy(), ast_rtp_dtmf_end_with_duration(), ast_rtp_local_bridge(), ast_rtp_write(), destroy_session(), generic_fax_exec(), mbl_load_device(), multicast_rtp_destroy(), and unload_module().

221 {
222  ao2_cleanup(s->format);
223  ast_free(s);
224 }
#define ast_free(a)
Definition: astmm.h:182
struct ast_format * format
Definition: smoother.c:45
#define ao2_cleanup(obj)
Definition: astobj2.h:1958

◆ ast_smoother_get_flags()

int ast_smoother_get_flags ( struct ast_smoother s)

Definition at line 118 of file smoother.c.

References ast_smoother::flags.

119 {
120  return s->flags;
121 }

◆ ast_smoother_new()

struct ast_smoother* ast_smoother_new ( int  size)

Definition at line 108 of file smoother.c.

References ast_calloc, ast_smoother_reset(), and NULL.

Referenced by ast_rtp_write(), generic_fax_exec(), mbl_load_device(), and multicast_rtp_write().

109 {
110  struct ast_smoother *s;
111  if (size < 1)
112  return NULL;
113  if ((s = ast_calloc(1, sizeof(*s))))
115  return s;
116 }
void ast_smoother_reset(struct ast_smoother *s, int bytes)
Definition: smoother.c:79
#define NULL
Definition: resample.c:96
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204

◆ ast_smoother_read()

struct ast_frame* ast_smoother_read ( struct ast_smoother s)

Definition at line 169 of file smoother.c.

References ast_format_get_sample_rate(), AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_log, ast_samp2tv(), AST_SMOOTHER_FLAG_G729, ast_tvadd(), ast_tvzero(), ast_smoother::data, ast_frame::data, ast_frame::datalen, ast_smoother::delivery, ast_frame::delivery, ast_smoother::f, ast_smoother::flags, ast_smoother::format, ast_frame_subclass::format, ast_smoother::framedata, ast_frame::frametype, ast_smoother::len, LOG_WARNING, NULL, ast_frame::offset, ast_smoother::opt, ast_frame::ptr, ast_frame::samples, ast_smoother::samplesperbyte, ast_smoother::size, and ast_frame::subclass.

Referenced by ast_rtp_write(), generic_fax_exec(), mbl_read(), mbl_write(), and multicast_rtp_write().

170 {
171  struct ast_frame *opt;
172  int len;
173 
174  /* IF we have an optimization frame, send it */
175  if (s->opt) {
176  if (s->opt->offset < AST_FRIENDLY_OFFSET)
177  ast_log(LOG_WARNING, "Returning a frame of inappropriate offset (%d).\n",
178  s->opt->offset);
179  opt = s->opt;
180  s->opt = NULL;
181  return opt;
182  }
183 
184  /* Make sure we have enough data */
185  if (s->len < s->size) {
186  /* Or, if this is a G.729 frame with VAD on it, send it immediately anyway */
187  if (!((s->flags & AST_SMOOTHER_FLAG_G729) && (s->len % 10)))
188  return NULL;
189  }
190  len = s->size;
191  if (len > s->len)
192  len = s->len;
193  /* Make frame */
195  s->f.subclass.format = s->format;
198  s->f.datalen = len;
199  /* Samples will be improper given VAD, but with VAD the concept really doesn't even exist */
200  s->f.samples = len * s->samplesperbyte; /* XXX rounding */
201  s->f.delivery = s->delivery;
202  /* Fill Data */
203  memcpy(s->f.data.ptr, s->data, len);
204  s->len -= len;
205  /* Move remaining data to the front if applicable */
206  if (s->len) {
207  /* In principle this should all be fine because if we are sending
208  G.729 VAD, the next timestamp will take over anyawy */
209  memmove(s->data, s->data + len, s->len);
210  if (!ast_tvzero(s->delivery)) {
211  /* If we have delivery time, increment it, otherwise, leave it at 0 */
214  }
215  }
216  /* Return frame */
217  return &s->f;
218 }
#define AST_SMOOTHER_FLAG_G729
Definition: smoother.h:34
#define LOG_WARNING
Definition: logger.h:274
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
Definition: time.h:108
struct ast_frame f
Definition: smoother.c:49
#define NULL
Definition: resample.c:96
struct ast_frame_subclass subclass
#define ast_log
Definition: astobj2.c:42
#define AST_FRIENDLY_OFFSET
Offset into a frame&#39;s data buffer.
struct timeval ast_samp2tv(unsigned int _nsamp, unsigned int _rate)
Returns a timeval corresponding to the duration of n samples at rate r. Useful to convert samples to ...
Definition: time.h:238
char data[SMOOTHER_SIZE]
Definition: smoother.c:51
float samplesperbyte
Definition: smoother.c:47
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
struct timeval delivery
Definition: smoother.c:50
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
Definition: extconf.c:2283
struct ast_frame * opt
Definition: smoother.c:53
struct timeval delivery
struct ast_format * format
Definition: smoother.c:45
unsigned int ast_format_get_sample_rate(const struct ast_format *format)
Get the sample rate of a media format.
Definition: format.c:379
Data structure associated with a single frame of data.
char framedata[SMOOTHER_SIZE+AST_FRIENDLY_OFFSET]
Definition: smoother.c:52
union ast_frame::@263 data
enum ast_frame_type frametype
struct ast_format * format

◆ ast_smoother_reconfigure()

void ast_smoother_reconfigure ( struct ast_smoother s,
int  bytes 
)

Reconfigure an existing smoother to output a different number of bytes per frame.

Parameters
sthe smoother to reconfigure
bytesthe desired number of bytes per output frame
Returns
nothing

Definition at line 86 of file smoother.c.

References NULL, ast_smoother::opt, ast_smoother::opt_needs_swap, ast_smoother::size, and smoother_frame_feed().

87 {
88  /* if there is no change, then nothing to do */
89  if (s->size == bytes) {
90  return;
91  }
92  /* set the new desired output size */
93  s->size = bytes;
94  /* if there is no 'optimized' frame in the smoother,
95  * then there is nothing left to do
96  */
97  if (!s->opt) {
98  return;
99  }
100  /* there is an 'optimized' frame here at the old size,
101  * but it must now be put into the buffer so the data
102  * can be extracted at the new size
103  */
105  s->opt = NULL;
106 }
#define NULL
Definition: resample.c:96
static int smoother_frame_feed(struct ast_smoother *s, struct ast_frame *f, int swap)
Definition: smoother.c:57
struct ast_frame * opt
Definition: smoother.c:53
unsigned int opt_needs_swap
Definition: smoother.c:48

◆ ast_smoother_reset()

void ast_smoother_reset ( struct ast_smoother s,
int  bytes 
)

Definition at line 79 of file smoother.c.

References ao2_cleanup, ast_smoother::format, and ast_smoother::size.

Referenced by ast_smoother_new(), and mbl_new().

80 {
81  ao2_cleanup(s->format);
82  memset(s, 0, sizeof(*s));
83  s->size = bytes;
84 }
struct ast_format * format
Definition: smoother.c:45
#define ao2_cleanup(obj)
Definition: astobj2.h:1958

◆ ast_smoother_set_flags()

void ast_smoother_set_flags ( struct ast_smoother s,
int  flags 
)

Definition at line 123 of file smoother.c.

References ast_smoother::flags.

Referenced by ast_rtp_write(), and multicast_rtp_write().

124 {
125  s->flags = flags;
126 }
unsigned int flags

◆ ast_smoother_test_flag()

int ast_smoother_test_flag ( struct ast_smoother s,
int  flag 
)

Definition at line 128 of file smoother.c.

References ast_smoother::flags.

Referenced by ast_rtp_write(), and multicast_rtp_write().

129 {
130  return (s->flags & flag);
131 }
long int flag
Definition: f2c.h:83

◆ smoother_frame_feed()

static int smoother_frame_feed ( struct ast_smoother s,
struct ast_frame f,
int  swap 
)
static

Definition at line 57 of file smoother.c.

References ast_log, AST_SMOOTHER_FLAG_G729, ast_swapcopy_samples(), ast_tvzero(), ast_smoother::data, ast_frame::data, ast_frame::datalen, ast_smoother::delivery, ast_frame::delivery, ast_smoother::flags, ast_smoother::len, LOG_NOTICE, ast_frame::ptr, and ast_frame::samples.

Referenced by __ast_smoother_feed(), and ast_smoother_reconfigure().

58 {
59  if (s->flags & AST_SMOOTHER_FLAG_G729) {
60  if (s->len % 10) {
61  ast_log(LOG_NOTICE, "Dropping extra frame of G.729 since we already have a VAD frame at the end\n");
62  return 0;
63  }
64  }
65  if (swap) {
66  ast_swapcopy_samples(s->data + s->len, f->data.ptr, f->samples);
67  } else {
68  memcpy(s->data + s->len, f->data.ptr, f->datalen);
69  }
70  /* If either side is empty, reset the delivery time */
71  if (!s->len || ast_tvzero(f->delivery) || ast_tvzero(s->delivery)) { /* XXX really ? */
72  s->delivery = f->delivery;
73  }
74  s->len += f->datalen;
75 
76  return 0;
77 }
#define AST_SMOOTHER_FLAG_G729
Definition: smoother.h:34
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
Definition: time.h:108
void ast_swapcopy_samples(void *dst, const void *src, int samples)
Definition: main/frame.c:396
#define ast_log
Definition: astobj2.c:42
char data[SMOOTHER_SIZE]
Definition: smoother.c:51
struct timeval delivery
Definition: smoother.c:50
#define LOG_NOTICE
Definition: logger.h:263
struct timeval delivery
union ast_frame::@263 data