Asterisk - The Open Source Telephony Project GIT-master-a358458
res_rtp_multicast.c
Go to the documentation of this file.
1/*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 2009, Digium, Inc.
5 *
6 * Joshua Colp <jcolp@digium.com>
7 * Andreas 'MacBrody' Brodmann <andreas.brodmann@gmail.com>
8 *
9 * See http://www.asterisk.org for more information about
10 * the Asterisk project. Please do not directly contact
11 * any of the maintainers of this project for assistance;
12 * the project provides a web site, mailing lists and IRC
13 * channels for your use.
14 *
15 * This program is free software, distributed under the terms of
16 * the GNU General Public License Version 2. See the LICENSE file
17 * at the top of the source tree.
18 */
19
20/*!
21 * \file
22 *
23 * \brief Multicast RTP Engine
24 *
25 * \author Joshua Colp <jcolp@digium.com>
26 * \author Andreas 'MacBrody' Brodmann <andreas.brodmann@gmail.com>
27 *
28 * \ingroup rtp_engines
29 */
30
31/*** MODULEINFO
32 <support_level>core</support_level>
33 ***/
34
35#include "asterisk.h"
36
37#include <sys/time.h>
38#include <signal.h>
39#include <fcntl.h>
40#include <math.h>
41
42#include "asterisk/pbx.h"
43#include "asterisk/frame.h"
44#include "asterisk/channel.h"
45#include "asterisk/acl.h"
46#include "asterisk/config.h"
47#include "asterisk/lock.h"
48#include "asterisk/utils.h"
49#include "asterisk/cli.h"
50#include "asterisk/manager.h"
51#include "asterisk/unaligned.h"
52#include "asterisk/module.h"
53#include "asterisk/rtp_engine.h"
56#include "asterisk/app.h"
57#include "asterisk/smoother.h"
58
59/*! Command value used for Linksys paging to indicate we are starting */
60#define LINKSYS_MCAST_STARTCMD 6
61
62/*! Command value used for Linksys paging to indicate we are stopping */
63#define LINKSYS_MCAST_STOPCMD 7
64
65/*! \brief Type of paging to do */
67 /*! Type has not been set yet */
69 /*! Simple multicast enabled client/receiver paging like Snom and Barix uses */
71 /*! More advanced Linksys type paging which requires a start and stop packet */
73};
74
75/*! \brief Structure for a Linksys control packet */
77 /*! Unique identifier for the control packet */
78 uint32_t unique_id;
79 /*! Actual command in the control packet */
80 uint32_t command;
81 /*! IP address for the RTP */
82 uint32_t ip;
83 /*! Port for the RTP */
84 uint32_t port;
85};
86
87/*! \brief Structure for a multicast paging instance */
89 /*! TYpe of multicast paging this instance is doing */
91 /*! Socket used for sending the audio on */
92 int socket;
93 /*! Synchronization source value, used when creating/sending the RTP packet */
94 unsigned int ssrc;
95 /*! Sequence number, used when creating/sending the RTP packet */
96 uint16_t seqno;
97 unsigned int lastts;
98 struct timeval txcore;
100};
101
102#define MAX_TIMESTAMP_SKEW 640
103
104enum {
105 OPT_CODEC = (1 << 0),
106 OPT_LOOP = (1 << 1),
107 OPT_TTL = (1 << 2),
108 OPT_IF = (1 << 3),
109};
110
111enum {
117};
118
120 /*! Set the codec to be used for multicast RTP */
122 /*! Set whether multicast RTP is looped back to the sender */
124 /*! Set the hop count for multicast RTP */
126 /*! Set the interface from which multicast RTP is sent */
129
131 char *type;
132 char *options;
136 /*! The type and options are stored in this buffer */
137 char buf[0];
138};
139
141 const char *options)
142{
143 struct ast_multicast_rtp_options *mcast_options;
144 char *pos;
145
146 mcast_options = ast_calloc(1, sizeof(*mcast_options)
147 + strlen(type)
148 + strlen(S_OR(options, "")) + 2);
149 if (!mcast_options) {
150 return NULL;
151 }
152
153 pos = mcast_options->buf;
154
155 /* Safe */
156 strcpy(pos, type);
157 mcast_options->type = pos;
158 pos += strlen(type) + 1;
159
160 if (!ast_strlen_zero(options)) {
161 strcpy(pos, options); /* Safe */
162 }
163 mcast_options->options = pos;
164
166 mcast_options->opt_args, mcast_options->options)) {
167 ast_log(LOG_WARNING, "Error parsing multicast RTP options\n");
168 ast_multicast_rtp_free_options(mcast_options);
169 return NULL;
170 }
171
172 return mcast_options;
173}
174
176{
177 ast_free(mcast_options);
178}
179
181{
182 if (ast_test_flag(&mcast_options->opts, OPT_CODEC)
183 && !ast_strlen_zero(mcast_options->opt_args[OPT_ARG_CODEC])) {
184 return ast_format_cache_get(mcast_options->opt_args[OPT_ARG_CODEC]);
185 }
186
187 return NULL;
188}
189
190/* Forward Declarations */
191static int multicast_rtp_new(struct ast_rtp_instance *instance, struct ast_sched_context *sched, struct ast_sockaddr *addr, void *data);
192static int multicast_rtp_activate(struct ast_rtp_instance *instance);
193static int multicast_rtp_destroy(struct ast_rtp_instance *instance);
194static int multicast_rtp_write(struct ast_rtp_instance *instance, struct ast_frame *frame);
195static struct ast_frame *multicast_rtp_read(struct ast_rtp_instance *instance, int rtcp);
196
197/* RTP Engine Declaration */
199 .name = "multicast",
200 .new = multicast_rtp_new,
201 .activate = multicast_rtp_activate,
202 .destroy = multicast_rtp_destroy,
203 .write = multicast_rtp_write,
204 .read = multicast_rtp_read,
205};
206
207static int set_type(struct multicast_rtp *multicast, const char *type)
208{
209 if (!strcasecmp(type, "basic")) {
210 multicast->type = MULTICAST_TYPE_BASIC;
211 } else if (!strcasecmp(type, "linksys")) {
212 multicast->type = MULTICAST_TYPE_LINKSYS;
213 } else {
214 ast_log(LOG_WARNING, "Unrecognized multicast type '%s' specified.\n", type);
215 return -1;
216 }
217
218 return 0;
219}
220
221static void set_ttl(int sock, const char *ttl_str)
222{
223 int ttl;
224
225 if (ast_strlen_zero(ttl_str)) {
226 return;
227 }
228
229 ast_debug(3, "Setting multicast TTL to %s\n", ttl_str);
230
231 if (sscanf(ttl_str, "%30d", &ttl) < 1) {
232 ast_log(LOG_WARNING, "Invalid multicast ttl option '%s'\n", ttl_str);
233 return;
234 }
235
236 if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0) {
237 ast_log(LOG_WARNING, "Could not set multicast ttl to '%s': %s\n",
238 ttl_str, strerror(errno));
239 }
240}
241
242static void set_loop(int sock, const char *loop_str)
243{
244 unsigned char loop;
245
246 if (ast_strlen_zero(loop_str)) {
247 return;
248 }
249
250 ast_debug(3, "Setting multicast loop to %s\n", loop_str);
251
252 if (sscanf(loop_str, "%30hhu", &loop) < 1) {
253 ast_log(LOG_WARNING, "Invalid multicast loop option '%s'\n", loop_str);
254 return;
255 }
256
257 if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop)) < 0) {
258 ast_log(LOG_WARNING, "Could not set multicast loop to '%s': %s\n",
259 loop_str, strerror(errno));
260 }
261}
262
263static void set_if(int sock, const char *if_str)
264{
265 struct in_addr iface;
266
267 if (ast_strlen_zero(if_str)) {
268 return;
269 }
270
271 ast_debug(3, "Setting multicast if to %s\n", if_str);
272
273 if (!inet_aton(if_str, &iface)) {
274 ast_log(LOG_WARNING, "Cannot parse if option '%s'\n", if_str);
275 }
276
277 if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF, &iface, sizeof(iface)) < 0) {
278 ast_log(LOG_WARNING, "Could not set multicast if to '%s': %s\n",
279 if_str, strerror(errno));
280 }
281}
282
283/*! \brief Function called to create a new multicast instance */
284static int multicast_rtp_new(struct ast_rtp_instance *instance, struct ast_sched_context *sched, struct ast_sockaddr *addr, void *data)
285{
286 struct multicast_rtp *multicast;
287 struct ast_multicast_rtp_options *mcast_options = data;
288
289 if (!(multicast = ast_calloc(1, sizeof(*multicast)))) {
290 return -1;
291 }
292
293 if (set_type(multicast, mcast_options->type)) {
294 ast_free(multicast);
295 return -1;
296 }
297
298 if ((multicast->socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
299 ast_free(multicast);
300 return -1;
301 }
302
303 if (ast_test_flag(&mcast_options->opts, OPT_LOOP)) {
304 set_loop(multicast->socket, mcast_options->opt_args[OPT_ARG_LOOP]);
305 }
306
307 if (ast_test_flag(&mcast_options->opts, OPT_TTL)) {
308 set_ttl(multicast->socket, mcast_options->opt_args[OPT_ARG_TTL]);
309 }
310
311 if (ast_test_flag(&mcast_options->opts, OPT_IF)) {
312 set_if(multicast->socket, mcast_options->opt_args[OPT_ARG_IF]);
313 }
314
315 multicast->ssrc = ast_random();
316
317 ast_rtp_instance_set_data(instance, multicast);
318
319 return 0;
320}
321
322static int rtp_get_rate(struct ast_format *format)
323{
325 8000 : ast_format_get_sample_rate(format);
326}
327
328static unsigned int calc_txstamp(struct multicast_rtp *rtp, struct timeval *delivery)
329{
330 struct timeval t;
331 long ms;
332
333 if (ast_tvzero(rtp->txcore)) {
334 rtp->txcore = ast_tvnow();
335 rtp->txcore.tv_usec -= rtp->txcore.tv_usec % 20000;
336 }
337
338 t = (delivery && !ast_tvzero(*delivery)) ? *delivery : ast_tvnow();
339 if ((ms = ast_tvdiff_ms(t, rtp->txcore)) < 0) {
340 ms = 0;
341 }
342 rtp->txcore = t;
343
344 return (unsigned int) ms;
345}
346
347/*! \brief Helper function which populates a control packet with useful information and sends it */
348static int multicast_send_control_packet(struct ast_rtp_instance *instance, struct multicast_rtp *multicast, int command)
349{
350 struct multicast_control_packet control_packet = { .unique_id = htonl((u_long)time(NULL)),
351 .command = htonl(command),
352 };
353 struct ast_sockaddr control_address, remote_address;
354
355 ast_rtp_instance_get_local_address(instance, &control_address);
356 ast_rtp_instance_get_remote_address(instance, &remote_address);
357
358 /* Ensure the user of us have given us both the control address and destination address */
359 if (ast_sockaddr_isnull(&control_address) ||
360 ast_sockaddr_isnull(&remote_address)) {
361 return -1;
362 }
363
364 /* The protocol only supports IPv4. */
365 if (ast_sockaddr_is_ipv6(&remote_address)) {
366 ast_log(LOG_WARNING, "Cannot send control packet for IPv6 "
367 "remote address.\n");
368 return -1;
369 }
370
371 control_packet.ip = htonl(ast_sockaddr_ipv4(&remote_address));
372 control_packet.port = htonl(ast_sockaddr_port(&remote_address));
373
374 /* Based on a recommendation by Brian West who did the FreeSWITCH implementation we send control packets twice */
375 ast_sendto(multicast->socket, &control_packet, sizeof(control_packet), 0, &control_address);
376 ast_sendto(multicast->socket, &control_packet, sizeof(control_packet), 0, &control_address);
377
378 return 0;
379}
380
381/*! \brief Function called to indicate that audio is now going to flow */
382static int multicast_rtp_activate(struct ast_rtp_instance *instance)
383{
384 struct multicast_rtp *multicast = ast_rtp_instance_get_data(instance);
385
386 if (multicast->type != MULTICAST_TYPE_LINKSYS) {
387 return 0;
388 }
389
390 return multicast_send_control_packet(instance, multicast, LINKSYS_MCAST_STARTCMD);
391}
392
393/*! \brief Function called to destroy a multicast instance */
394static int multicast_rtp_destroy(struct ast_rtp_instance *instance)
395{
396 struct multicast_rtp *multicast = ast_rtp_instance_get_data(instance);
397
398 if (multicast->type == MULTICAST_TYPE_LINKSYS) {
400 }
401
402 if (multicast->smoother) {
403 ast_smoother_free(multicast->smoother);
404 }
405
406 close(multicast->socket);
407
408 ast_free(multicast);
409
410 return 0;
411}
412
413static int rtp_raw_write(struct ast_rtp_instance *instance, struct ast_frame *frame, int codec)
414{
415 struct multicast_rtp *multicast = ast_rtp_instance_get_data(instance);
416 unsigned int ms = calc_txstamp(multicast, &frame->delivery);
417 unsigned char *rtpheader;
418 struct ast_sockaddr remote_address = { {0,} };
419 int rate = rtp_get_rate(frame->subclass.format) / 1000;
420 int hdrlen = 12, mark = 0;
421
423 frame->samples /= 2;
424 }
425
427 multicast->lastts = frame->ts * rate;
428 } else {
429 /* Try to predict what our timestamp should be */
430 int pred = multicast->lastts + frame->samples;
431
432 /* Calculate last TS */
433 multicast->lastts = multicast->lastts + ms * rate;
434 if (ast_tvzero(frame->delivery)) {
435 int delta = abs((int) multicast->lastts - pred);
436 if (delta < MAX_TIMESTAMP_SKEW) {
437 multicast->lastts = pred;
438 } else {
439 ast_debug(3, "Difference is %d, ms is %u\n", delta, ms);
440 mark = 1;
441 }
442 }
443 }
444
445 /* Construct an RTP header for our packet */
446 rtpheader = (unsigned char *)(frame->data.ptr - hdrlen);
447
448 put_unaligned_uint32(rtpheader, htonl((2 << 30) | (codec << 16) | (multicast->seqno) | (mark << 23)));
449 put_unaligned_uint32(rtpheader + 4, htonl(multicast->lastts));
450 put_unaligned_uint32(rtpheader + 8, htonl(multicast->ssrc));
451
452 /* Increment sequence number and wrap to 0 if it overflows 16 bits. */
453 multicast->seqno = 0xFFFF & (multicast->seqno + 1);
454
455 /* Finally send it out to the eager phones listening for us */
456 ast_rtp_instance_get_remote_address(instance, &remote_address);
457
458 if (ast_sendto(multicast->socket, (void *) rtpheader, frame->datalen + hdrlen, 0, &remote_address) < 0) {
459 ast_log(LOG_ERROR, "Multicast RTP Transmission error to %s: %s\n",
460 ast_sockaddr_stringify(&remote_address),
461 strerror(errno));
462 return -1;
463 }
464
465 return 0;
466}
467
468/*! \brief Function called to broadcast some audio on a multicast instance */
469static int multicast_rtp_write(struct ast_rtp_instance *instance, struct ast_frame *frame)
470{
471 struct multicast_rtp *multicast = ast_rtp_instance_get_data(instance);
472 struct ast_format *format;
473 struct ast_frame *f;
474 int codec;
475
476 /* We only accept audio, nothing else */
477 if (frame->frametype != AST_FRAME_VOICE) {
478 return 0;
479 }
480
481 /* Grab the actual payload number for when we create the RTP packet */
483 1, frame->subclass.format, 0);
484 if (codec < 0) {
485 return -1;
486 }
487
488 format = frame->subclass.format;
489 if (!multicast->smoother && ast_format_can_be_smoothed(format)) {
490 unsigned int smoother_flags = ast_format_get_smoother_flags(format);
491 unsigned int framing_ms = ast_rtp_codecs_get_framing(ast_rtp_instance_get_codecs(instance));
492
493 if (!framing_ms && (smoother_flags & AST_SMOOTHER_FLAG_FORCED)) {
494 framing_ms = ast_format_get_default_ms(format);
495 }
496
497 if (framing_ms) {
498 multicast->smoother = ast_smoother_new((framing_ms * ast_format_get_minimum_bytes(format)) / ast_format_get_minimum_ms(format));
499 if (!multicast->smoother) {
500 ast_log(LOG_WARNING, "Unable to create smoother: format %s ms: %u len %u\n",
501 ast_format_get_name(format), framing_ms, ast_format_get_minimum_bytes(format));
502 return -1;
503 }
504 ast_smoother_set_flags(multicast->smoother, smoother_flags);
505 }
506 }
507
508 if (multicast->smoother) {
510 ast_smoother_feed_be(multicast->smoother, frame);
511 } else {
512 ast_smoother_feed(multicast->smoother, frame);
513 }
514
515 while ((f = ast_smoother_read(multicast->smoother)) && f->data.ptr) {
516 rtp_raw_write(instance, f, codec);
517 }
518 } else {
519 int hdrlen = 12;
520
521 /* If we do not have space to construct an RTP header duplicate the frame so we get some */
522 if (frame->offset < hdrlen) {
523 f = ast_frdup(frame);
524 } else {
525 f = frame;
526 }
527
528 if (f->data.ptr) {
529 rtp_raw_write(instance, f, codec);
530 }
531
532 if (f != frame) {
533 ast_frfree(f);
534 }
535 }
536
537 return 0;
538}
539
540/*! \brief Function called to read from a multicast instance */
541static struct ast_frame *multicast_rtp_read(struct ast_rtp_instance *instance, int rtcp)
542{
543 return &ast_null_frame;
544}
545
546static int load_module(void)
547{
550 }
551
553}
554
555static int unload_module(void)
556{
558
559 return 0;
560}
561
563 .support_level = AST_MODULE_SUPPORT_CORE,
564 .load = load_module,
565 .unload = unload_module,
566 .load_pri = AST_MODPRI_CHANNEL_DEPEND,
Access Control of various sorts.
Asterisk main include file. File version handling, generic pbx functions.
#define ast_free(a)
Definition: astmm.h:180
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define ast_log
Definition: astobj2.c:42
static const char type[]
Definition: chan_ooh323.c:109
General Asterisk PBX channel definitions.
Standard Command Line Interface.
#define abs(x)
Definition: f2c.h:195
int ast_format_get_smoother_flags(const struct ast_format *format)
Get smoother flags for this format.
Definition: format.c:349
int ast_format_can_be_smoothed(const struct ast_format *format)
Get whether or not the format can be smoothed.
Definition: format.c:344
unsigned int ast_format_get_minimum_bytes(const struct ast_format *format)
Get the minimum number of bytes expected in a frame for this format.
Definition: format.c:374
unsigned int ast_format_get_sample_rate(const struct ast_format *format)
Get the sample rate of a media format.
Definition: format.c:379
unsigned int ast_format_get_minimum_ms(const struct ast_format *format)
Get the minimum amount of media carried in this format.
Definition: format.c:364
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
@ AST_FORMAT_CMP_EQUAL
Definition: format.h:36
const char * ast_format_get_name(const struct ast_format *format)
Get the name associated with a format.
Definition: format.c:334
unsigned int ast_format_get_default_ms(const struct ast_format *format)
Get the default framing size (in milliseconds) for a format.
Definition: format.c:359
Media Format Cache API.
#define ast_format_cache_get(name)
Retrieve a named format from the cache.
Definition: format_cache.h:278
struct ast_format * ast_format_g722
Built-in cached g722 format.
Definition: format_cache.c:106
Application convenience functions, designed to give consistent look and feel to Asterisk apps.
#define END_OPTIONS
#define AST_APP_OPTIONS(holder, options...)
Declares an array of options for an application.
#define AST_APP_OPTION_ARG(option, flagno, argno)
Declares an application option that accepts an argument.
#define BEGIN_OPTIONS
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
Parses a string containing application options and sets flags/arguments.
Definition: main/app.c:3056
Configuration File Parser.
Asterisk internal frame definitions.
@ AST_FRFLAG_HAS_TIMING_INFO
#define ast_frdup(fr)
Copies a frame.
#define ast_frfree(fr)
@ AST_FRAME_VOICE
struct ast_frame ast_null_frame
Definition: main/frame.c:79
#define ast_debug(level,...)
Log a DEBUG message.
#define LOG_ERROR
#define LOG_WARNING
Asterisk locking-related definitions:
int errno
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
Asterisk module definitions.
@ AST_MODFLAG_LOAD_ORDER
Definition: module.h:317
@ AST_MODFLAG_GLOBAL_SYMBOLS
Definition: module.h:316
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
Definition: module.h:543
@ AST_MODPRI_CHANNEL_DEPEND
Definition: module.h:326
@ AST_MODULE_SUPPORT_CORE
Definition: module.h:121
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Definition: netsock2.h:256
#define ast_sockaddr_port(addr)
Get the port number of a socket address.
Definition: netsock2.h:517
int ast_sockaddr_is_ipv6(const struct ast_sockaddr *addr)
Determine if this is an IPv6 address.
Definition: netsock2.c:524
uint32_t ast_sockaddr_ipv4(const struct ast_sockaddr *addr)
Get an IPv4 address of an ast_sockaddr.
Definition: netsock2.c:491
ssize_t ast_sendto(int sockfd, const void *buf, size_t len, int flags, const struct ast_sockaddr *dest_addr)
Wrapper around sendto(2) that uses ast_sockaddr.
Definition: netsock2.c:614
static int ast_sockaddr_isnull(const struct ast_sockaddr *addr)
Checks if the ast_sockaddr is null. "null" in this sense essentially means uninitialized,...
Definition: netsock2.h:127
int inet_aton(const char *cp, struct in_addr *pin)
Core PBX routines and definitions.
static struct ast_rtp_engine multicast_rtp_engine
static int multicast_rtp_destroy(struct ast_rtp_instance *instance)
Function called to destroy a multicast instance.
#define MAX_TIMESTAMP_SKEW
static void set_ttl(int sock, const char *ttl_str)
struct ast_multicast_rtp_options * ast_multicast_rtp_create_options(const char *type, const char *options)
Create multicast RTP options.
static int rtp_raw_write(struct ast_rtp_instance *instance, struct ast_frame *frame, int codec)
static int multicast_rtp_write(struct ast_rtp_instance *instance, struct ast_frame *frame)
Function called to broadcast some audio on a multicast instance.
@ OPT_ARG_TTL
@ OPT_ARG_CODEC
@ OPT_ARG_IF
@ OPT_ARG_ARRAY_SIZE
@ OPT_ARG_LOOP
static unsigned int calc_txstamp(struct multicast_rtp *rtp, struct timeval *delivery)
#define LINKSYS_MCAST_STOPCMD
static int set_type(struct multicast_rtp *multicast, const char *type)
static int multicast_send_control_packet(struct ast_rtp_instance *instance, struct multicast_rtp *multicast, int command)
Helper function which populates a control packet with useful information and sends it.
#define LINKSYS_MCAST_STARTCMD
@ OPT_TTL
@ OPT_IF
@ OPT_CODEC
@ OPT_LOOP
static int rtp_get_rate(struct ast_format *format)
static void set_if(int sock, const char *if_str)
static struct ast_frame * multicast_rtp_read(struct ast_rtp_instance *instance, int rtcp)
Function called to read from a multicast instance.
static int multicast_rtp_new(struct ast_rtp_instance *instance, struct ast_sched_context *sched, struct ast_sockaddr *addr, void *data)
Function called to create a new multicast instance.
static int load_module(void)
static int multicast_rtp_activate(struct ast_rtp_instance *instance)
Function called to indicate that audio is now going to flow.
static int unload_module(void)
static void set_loop(int sock, const char *loop_str)
struct ast_format * ast_multicast_rtp_options_get_format(struct ast_multicast_rtp_options *mcast_options)
Get format specified in multicast options.
static const struct ast_app_option multicast_rtp_options[128]
multicast_type
Type of paging to do.
@ MULTICAST_TYPE_BASIC
@ MULTICAST_TYPE_LINKSYS
@ MULTICAST_TYPE_UNSPECIFIED
void ast_multicast_rtp_free_options(struct ast_multicast_rtp_options *mcast_options)
Free multicast RTP options.
#define NULL
Definition: resample.c:96
Pluggable RTP Architecture.
void * ast_rtp_instance_get_data(struct ast_rtp_instance *instance)
Get the data portion of an RTP instance.
Definition: rtp_engine.c:584
#define ast_rtp_instance_get_remote_address(instance, address)
Get the address of the remote endpoint that we are sending RTP to.
Definition: rtp_engine.h:1238
void ast_rtp_instance_set_data(struct ast_rtp_instance *instance, void *data)
Set the data portion of an RTP instance.
Definition: rtp_engine.c:579
void ast_rtp_instance_get_local_address(struct ast_rtp_instance *instance, struct ast_sockaddr *address)
Get the local address that we are expecting RTP on.
Definition: rtp_engine.c:664
int ast_rtp_codecs_payload_code_tx(struct ast_rtp_codecs *codecs, int asterisk_format, const struct ast_format *format, int code)
Retrieve a tx mapped payload type based on whether it is an Asterisk format and the code.
Definition: rtp_engine.c:1941
int ast_rtp_engine_unregister(struct ast_rtp_engine *engine)
Unregister an RTP engine.
Definition: rtp_engine.c:363
struct ast_rtp_codecs * ast_rtp_instance_get_codecs(struct ast_rtp_instance *instance)
Get the codecs structure of an RTP instance.
Definition: rtp_engine.c:748
unsigned int ast_rtp_codecs_get_framing(struct ast_rtp_codecs *codecs)
Get the framing used for a set of codecs.
Definition: rtp_engine.c:1582
#define ast_rtp_engine_register(engine)
Definition: rtp_engine.h:840
Asterisk internal frame definitions.
void ast_smoother_set_flags(struct ast_smoother *smoother, int flags)
Definition: smoother.c:123
#define ast_smoother_feed_be(s, f)
Definition: smoother.h:80
int ast_smoother_test_flag(struct ast_smoother *s, int flag)
Definition: smoother.c:128
void ast_smoother_free(struct ast_smoother *s)
Definition: smoother.c:220
#define AST_SMOOTHER_FLAG_FORCED
Definition: smoother.h:36
struct ast_frame * ast_smoother_read(struct ast_smoother *s)
Definition: smoother.c:169
#define ast_smoother_feed(s, f)
Definition: smoother.h:75
struct ast_smoother * ast_smoother_new(int bytes)
Definition: smoother.c:108
#define AST_SMOOTHER_FLAG_BE
Definition: smoother.h:35
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition: strings.h:80
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
Structure used to handle boolean flags.
Definition: utils.h:199
Definition of a media format.
Definition: format.c:43
struct ast_format * format
Data structure associated with a single frame of data.
struct ast_frame_subclass subclass
union ast_frame::@226 data
struct timeval delivery
enum ast_frame_type frametype
char * opt_args[OPT_ARG_ARRAY_SIZE]
const char * name
Definition: rtp_engine.h:662
Socket address structure.
Definition: netsock2.h:97
Structure for a Linksys control packet.
Structure for a multicast paging instance.
unsigned int lastts
struct ast_smoother * smoother
struct timeval txcore
unsigned int ssrc
enum multicast_type type
Definition: sched.c:76
static struct test_options options
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
Definition: time.h:117
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:107
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159
Handle unaligned data access.
static void put_unaligned_uint32(void *p, unsigned int datum)
Definition: unaligned.h:58
Utility functions.
#define ast_test_flag(p, flag)
Definition: utils.h:63
long int ast_random(void)
Definition: utils.c:2312