Asterisk - The Open Source Telephony Project  18.5.0
Functions | Variables
app_stream_echo.c File Reference

Stream echo application. More...

#include "asterisk.h"
#include "asterisk/app.h"
#include "asterisk/conversions.h"
#include "asterisk/file.h"
#include "asterisk/module.h"
#include "asterisk/channel.h"
#include "asterisk/stream.h"
Include dependency graph for app_stream_echo.c:

Go to the source code of this file.

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static int load_module (void)
 
static int stream_echo_exec (struct ast_channel *chan, const char *data)
 
static int stream_echo_perform (struct ast_channel *chan, struct ast_stream_topology *topology, enum ast_media_type type)
 
static struct ast_stream_topologystream_echo_topology_alloc (struct ast_stream_topology *original, unsigned int num, enum ast_media_type type)
 
static int stream_echo_write (struct ast_channel *chan, struct ast_frame *frame, enum ast_media_type type, int one_to_one)
 
static int stream_echo_write_error (struct ast_channel *chan, struct ast_frame *frame, int pos)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Stream Echo Application" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "30ef0c93b36035ec78c9cfd712d36d9b" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, }
 
static const char app [] = "StreamEcho"
 
static const struct ast_module_infoast_module_info = &__mod_info
 

Detailed Description

Stream echo application.

Author
Kevin Harwell kharw[email protected][email protected][email protected]digiu[email protected]m.co[email protected]m

Definition in file app_stream_echo.c.

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 345 of file app_stream_echo.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 345 of file app_stream_echo.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 345 of file app_stream_echo.c.

◆ load_module()

static int load_module ( void  )
static

Definition at line 340 of file app_stream_echo.c.

References app, ast_register_application_xml, and stream_echo_exec().

341 {
343 }
static const char app[]
static int stream_echo_exec(struct ast_channel *chan, const char *data)
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:626

◆ stream_echo_exec()

static int stream_echo_exec ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 284 of file app_stream_echo.c.

References args, AST_APP_ARG, ast_channel_get_stream_topology(), ast_codec_media_type2str(), AST_DECLARE_APP_ARGS, ast_log, ast_media_type_from_str(), AST_MEDIA_TYPE_UNKNOWN, AST_MEDIA_TYPE_VIDEO, AST_STANDARD_APP_ARGS, ast_str_to_uint(), ast_strdupa, ast_stream_topology_free(), ast_strlen_zero, LOG_ERROR, NULL, parse(), stream_echo_perform(), stream_echo_topology_alloc(), and type.

Referenced by load_module().

285 {
286  int res;
287  unsigned int num = 0;
288  enum ast_media_type type;
289  char *parse;
290  struct ast_stream_topology *topology;
291 
293  AST_APP_ARG(num);
294  AST_APP_ARG(type);
295  );
296 
297  parse = ast_strdupa(data);
298  AST_STANDARD_APP_ARGS(args, parse);
299 
300  if (ast_strlen_zero(args.num)) {
301  /*
302  * If a number is not given then no topology is to be created
303  * and renegotiated. The app will just echo back each stream
304  * received to itself.
305  */
307  }
308 
309  if (ast_str_to_uint(args.num, &num)) {
310  ast_log(LOG_ERROR, "Failed to parse the first parameter '%s' into a"
311  " greater than or equal to zero\n", args.num);
312  return -1;
313  }
314 
315  type = ast_strlen_zero(args.type) ? AST_MEDIA_TYPE_VIDEO :
317 
318  topology = stream_echo_topology_alloc(
319  ast_channel_get_stream_topology(chan), num, type);
320  if (!topology) {
321  ast_log(LOG_ERROR, "Unable to create '%u' streams of type '%s' to"
322  " the topology\n", num, ast_codec_media_type2str(type));
323  return -1;
324  }
325 
326  res = stream_echo_perform(chan, topology, type);
327 
328  if (ast_channel_get_stream_topology(chan) != topology) {
329  ast_stream_topology_free(topology);
330  }
331 
332  return res;
333 }
static const char type[]
Definition: chan_ooh323.c:109
struct ast_stream_topology * ast_channel_get_stream_topology(const struct ast_channel *chan)
Retrieve the topology of streams on a channel.
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
const char * ast_codec_media_type2str(enum ast_media_type type)
Conversion function to take a media type and turn it into a string.
Definition: codec.c:347
enum ast_media_type ast_media_type_from_str(const char *media_type_str)
Conversion function to take a media string and convert it to a media type.
Definition: codec.c:363
const char * args
#define NULL
Definition: resample.c:96
static struct ast_stream_topology * stream_echo_topology_alloc(struct ast_stream_topology *original, unsigned int num, enum ast_media_type type)
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_log
Definition: astobj2.c:42
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
#define LOG_ERROR
Definition: logger.h:285
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1872
int ast_str_to_uint(const char *str, unsigned int *res)
Convert the given string to an unsigned integer.
Definition: conversions.c:56
static int stream_echo_perform(struct ast_channel *chan, struct ast_stream_topology *topology, enum ast_media_type type)
ast_media_type
Types of media.
Definition: codec.h:30
void ast_stream_topology_free(struct ast_stream_topology *topology)
Unreference and destroy a stream topology.
Definition: stream.c:743
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define AST_APP_ARG(name)
Define an application argument.

◆ stream_echo_perform()

static int stream_echo_perform ( struct ast_channel chan,
struct ast_stream_topology topology,
enum ast_media_type  type 
)
static

Definition at line 154 of file app_stream_echo.c.

References ast_channel_name(), ast_channel_request_stream_topology_change(), AST_CONTROL_SRCCHANGE, AST_CONTROL_STREAM_TOPOLOGY_CHANGED, AST_CONTROL_VIDUPDATE, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_MODEM, AST_FRAME_NULL, AST_FRAME_VIDEO, ast_frfree, ast_log, ast_read_stream(), ast_waitfor(), ast_frame::delivery, ast_frame::frametype, ast_frame_subclass::integer, LOG_WARNING, NULL, stream_echo_write(), and ast_frame::subclass.

Referenced by stream_echo_exec().

156 {
157  int update_sent = 0;
158  int request_change = topology != NULL;
159  int one_to_one = 1;
160 
161  while (ast_waitfor(chan, -1) > -1) {
162  struct ast_frame *f;
163 
164  if (request_change) {
165  /* Request a change to the new topology */
166  if (ast_channel_request_stream_topology_change(chan, topology, NULL)) {
167  ast_log(LOG_WARNING, "Request stream topology change not supported "
168  "by channel '%s'\n", ast_channel_name(chan));
169  }
170  request_change = 0;
171  }
172 
173  f = ast_read_stream(chan);
174  if (!f) {
175  return -1;
176  }
177 
178  if ((f->frametype == AST_FRAME_DTMF) && (f->subclass.integer == '#')) {
179  ast_frfree(f);
180  break;
181  }
182 
183  f->delivery.tv_sec = 0;
184  f->delivery.tv_usec = 0;
185 
186  if (f->frametype == AST_FRAME_CONTROL) {
187  if (f->subclass.integer == AST_CONTROL_VIDUPDATE && !update_sent) {
188  if (stream_echo_write(chan, f, type, one_to_one)) {
189  ast_frfree(f);
190  return -1;
191  }
192  update_sent = 1;
193  } else if (f->subclass.integer == AST_CONTROL_SRCCHANGE) {
194  update_sent = 0;
196  update_sent = 0;
197  one_to_one = 0; /* Switch writing to one to many */
198  }
199  } else if (f->frametype == AST_FRAME_VIDEO && !update_sent){
200  struct ast_frame frame = {
202  .subclass.integer = AST_CONTROL_VIDUPDATE,
203  };
204  stream_echo_write(chan, &frame, type, one_to_one);
205  update_sent = 1;
206  }
207 
208  if (f->frametype != AST_FRAME_CONTROL &&
209  f->frametype != AST_FRAME_MODEM &&
210  f->frametype != AST_FRAME_NULL &&
211  stream_echo_write(chan, f, type, one_to_one)) {
212  ast_frfree(f);
213  return -1;
214  }
215 
216  ast_frfree(f);
217  }
218 
219  return 0;
220 }
static const char type[]
Definition: chan_ooh323.c:109
static int stream_echo_write(struct ast_channel *chan, struct ast_frame *frame, enum ast_media_type type, int one_to_one)
#define LOG_WARNING
Definition: logger.h:274
struct ast_frame * ast_read_stream(struct ast_channel *chan)
Reads a frame, but does not filter to just the default streams.
Definition: channel.c:4307
int ast_channel_request_stream_topology_change(struct ast_channel *chan, struct ast_stream_topology *topology, void *change_source)
Request that the stream topology of a channel change.
Definition: channel.c:11167
#define NULL
Definition: resample.c:96
#define AST_FRAME_DTMF
struct ast_frame_subclass subclass
#define ast_log
Definition: astobj2.c:42
struct timeval delivery
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3171
const char * ast_channel_name(const struct ast_channel *chan)
#define ast_frfree(fr)
Data structure associated with a single frame of data.
enum ast_frame_type frametype

◆ stream_echo_topology_alloc()

static struct ast_stream_topology* stream_echo_topology_alloc ( struct ast_stream_topology original,
unsigned int  num,
enum ast_media_type  type 
)
static

Definition at line 222 of file app_stream_echo.c.

References ast_stream_clone(), ast_stream_free(), ast_stream_get_state(), ast_stream_get_type(), ast_stream_set_state(), AST_STREAM_STATE_REMOVED, AST_STREAM_STATE_SENDONLY, AST_STREAM_STATE_SENDRECV, ast_stream_topology_alloc(), ast_stream_topology_append_stream(), ast_stream_topology_free(), ast_stream_topology_get_count(), ast_stream_topology_get_stream(), and NULL.

Referenced by stream_echo_exec().

224 {
225  int i, n = num;
227 
228  if (!res) {
229  return NULL;
230  }
231 
232  /*
233  * Clone every stream of a type not matching the given one. If the type
234  * matches clone only the first stream found for the given type. Then for
235  * that stream clone it again up to num - 1 times. Ignore any other streams
236  * of the same matched type in the original topology.
237  *
238  * So for instance if the original stream contains 1 audio stream and 2 video
239  * streams (video stream 'A' and video stream 'B'), num is '3', and the given
240  * type is 'video' then the resulting topology will contain a clone of the
241  * audio stream along with 3 clones of video stream 'A'. Video stream 'B' is
242  * not copied over.
243  */
244  for (i = 0; i < ast_stream_topology_get_count(original); ++i) {
245  struct ast_stream *stream = ast_stream_topology_get_stream(original, i);
246 
247  if (!n && ast_stream_get_type(stream) == type) {
248  /* Don't copy any[more] of the given type */
249  continue;
250  }
251 
253  /* Don't copy removed/declined streams */
254  continue;
255  }
256 
257  do {
258  stream = ast_stream_clone(stream, NULL);
259 
260  if (!stream || ast_stream_topology_append_stream(res, stream) < 0) {
261  ast_stream_free(stream);
263  return NULL;
264  }
265 
266  if (ast_stream_get_type(stream) != type) {
267  /* Do not multiply non matching streams */
268  break;
269  }
270 
271  /*
272  * Since num is not zero yet (i.e. this is first stream found to
273  * match on the type) and the types match then loop num - 1 times
274  * cloning the same stream.
275  */
276  ast_stream_set_state(stream, n == num ?
278  } while (--n);
279  }
280 
281  return res;
282 }
static const char type[]
Definition: chan_ooh323.c:109
enum ast_media_type ast_stream_get_type(const struct ast_stream *stream)
Get the media type of a stream.
Definition: stream.c:316
Set when the stream has been removed/declined.
Definition: stream.h:78
struct ast_stream * ast_stream_topology_get_stream(const struct ast_stream_topology *topology, unsigned int position)
Get a specific stream from the topology.
Definition: stream.c:788
#define NULL
Definition: resample.c:96
int ast_stream_topology_append_stream(struct ast_stream_topology *topology, struct ast_stream *stream)
Append a stream to the topology.
Definition: stream.c:748
Set when the stream is sending and receiving media.
Definition: stream.h:82
struct ast_stream_topology * ast_stream_topology_alloc(void)
Create a stream topology.
Definition: stream.c:650
Set when the stream is sending media only.
Definition: stream.h:86
void ast_stream_set_state(struct ast_stream *stream, enum ast_stream_state state)
Set the state of a stream.
Definition: stream.c:380
int ast_stream_topology_get_count(const struct ast_stream_topology *topology)
Get the number of streams in a topology.
Definition: stream.c:765
void ast_stream_free(struct ast_stream *stream)
Destroy a media stream representation.
Definition: stream.c:292
struct ast_stream * ast_stream_clone(const struct ast_stream *stream, const char *name)
Create a deep clone of an existing stream.
Definition: stream.c:257
void ast_stream_topology_free(struct ast_stream_topology *topology)
Unreference and destroy a stream topology.
Definition: stream.c:743
enum ast_stream_state ast_stream_get_state(const struct ast_stream *stream)
Get the current state of a stream.
Definition: stream.c:373

◆ stream_echo_write()

static int stream_echo_write ( struct ast_channel chan,
struct ast_frame frame,
enum ast_media_type  type,
int  one_to_one 
)
static

Definition at line 99 of file app_stream_echo.c.

References ast_channel_get_stream_topology(), ast_channel_is_multistream(), ast_format_get_type(), ast_stream_get_type(), ast_stream_topology_get_count(), ast_stream_topology_get_stream(), ast_write_stream(), ast_frame_subclass::format, stream_echo_write_error(), ast_frame::stream_num, and ast_frame::subclass.

Referenced by stream_echo_perform().

101 {
102  int i;
103  int num;
104  struct ast_stream_topology *topology;
105 
106  /*
107  * Since this is an echo application if we get a frame in on a stream
108  * we simply want to echo it back out onto the same stream number.
109  */
110  num = ast_channel_is_multistream(chan) ? frame->stream_num : -1;
111  if (ast_write_stream(chan, num, frame)) {
112  return stream_echo_write_error(chan, frame, num);
113  }
114 
115  /*
116  * If the frame's type and given type don't match, or we are operating in
117  * a one to one stream echo mode then there is nothing left to do.
118  *
119  * Note, if the channel is not multi-stream capable then one_to_one will
120  * always be true, so it is safe to also not check for that here too.
121  */
122  if (one_to_one || !frame->subclass.format ||
124  return 0;
125  }
126 
127  /*
128  * However, if we are operating in a single stream echoed to many stream
129  * mode, and the frame's type matches the given type then we also need to
130  * find the other streams of the same type and write out to those streams
131  * as well.
132  *
133  * If we are here, then it's accepted that whatever stream number the frame
134  * was read from for the given type is the only one set to send/receive,
135  * while the others of the same type are set to receive only. Since we
136  * shouldn't assume any order to the streams, we'll loop back through all
137  * streams in the channel's topology writing only to those of the same type.
138  * And, of course also not the stream which has already been written to.
139  */
140  topology = ast_channel_get_stream_topology(chan);
141 
142  for (i = 0; i < ast_stream_topology_get_count(topology); ++i) {
143  struct ast_stream *stream = ast_stream_topology_get_stream(topology, i);
144  if (num != i && ast_stream_get_type(stream) == type) {
145  if (ast_write_stream(chan, i, frame)) {
146  return stream_echo_write_error(chan, frame, i);
147  }
148  }
149  }
150 
151  return 0;
152 }
static const char type[]
Definition: chan_ooh323.c:109
enum ast_media_type ast_format_get_type(const struct ast_format *format)
Get the media type of a format.
Definition: format.c:354
int ast_channel_is_multistream(struct ast_channel *chan)
Determine if a channel is multi-stream capable.
struct ast_stream_topology * ast_channel_get_stream_topology(const struct ast_channel *chan)
Retrieve the topology of streams on a channel.
enum ast_media_type ast_stream_get_type(const struct ast_stream *stream)
Get the media type of a stream.
Definition: stream.c:316
struct ast_stream * ast_stream_topology_get_stream(const struct ast_stream_topology *topology, unsigned int position)
Get a specific stream from the topology.
Definition: stream.c:788
int ast_write_stream(struct ast_channel *chan, int stream_num, struct ast_frame *frame)
Write a frame to a stream This function writes the given frame to the indicated stream on the channel...
Definition: channel.c:5194
struct ast_frame_subclass subclass
static int stream_echo_write_error(struct ast_channel *chan, struct ast_frame *frame, int pos)
int ast_stream_topology_get_count(const struct ast_stream_topology *topology)
Get the number of streams in a topology.
Definition: stream.c:765
struct ast_format * format

◆ stream_echo_write_error()

static int stream_echo_write_error ( struct ast_channel chan,
struct ast_frame frame,
int  pos 
)
static

Definition at line 78 of file app_stream_echo.c.

References ast_channel_get_default_stream(), ast_channel_get_stream_topology(), ast_channel_name(), ast_codec_media_type2str(), ast_format_get_type(), ast_frame_type2str(), ast_log, ast_stream_get_position(), ast_stream_get_type(), ast_stream_topology_get_stream(), ast_frame_subclass::format, ast_frame::frametype, LOG_ERROR, and ast_frame::subclass.

Referenced by stream_echo_write().

79 {
80  char frame_type[32];
81  const char *media_type;
82  struct ast_stream *stream;
83 
84  ast_frame_type2str(frame->frametype, frame_type, sizeof(frame_type));
85 
86  stream = pos < 0 ?
89 
90  media_type = ast_codec_media_type2str(ast_stream_get_type(stream));
91 
92  ast_log(LOG_ERROR, "%s - unable to write frame type '%s' to stream type '%s' at "
93  "position '%d'\n", ast_channel_name(chan), frame_type, media_type,
94  ast_stream_get_position(stream));
95 
96  return -1;
97 }
enum ast_media_type ast_format_get_type(const struct ast_format *format)
Get the media type of a format.
Definition: format.c:354
struct ast_stream_topology * ast_channel_get_stream_topology(const struct ast_channel *chan)
Retrieve the topology of streams on a channel.
media_type
Media types generate different "dummy answers" for not accepting the offer of a media stream...
Definition: sip.h:489
enum ast_media_type ast_stream_get_type(const struct ast_stream *stream)
Get the media type of a stream.
Definition: stream.c:316
const char * ast_codec_media_type2str(enum ast_media_type type)
Conversion function to take a media type and turn it into a string.
Definition: codec.c:347
struct ast_stream * ast_stream_topology_get_stream(const struct ast_stream_topology *topology, unsigned int position)
Get a specific stream from the topology.
Definition: stream.c:788
struct ast_frame_subclass subclass
#define ast_log
Definition: astobj2.c:42
struct ast_stream * ast_channel_get_default_stream(struct ast_channel *chan, enum ast_media_type type)
Retrieve the default stream of a specific media type on a channel.
#define LOG_ERROR
Definition: logger.h:285
frame_type
Definition: codec_builtin.c:44
char * ast_frame_type2str(enum ast_frame_type frame_type, char *ftype, size_t len)
Copy the discription of a frame type into the provided string.
Definition: main/frame.c:671
const char * ast_channel_name(const struct ast_channel *chan)
enum ast_frame_type frametype
struct ast_format * format
int ast_stream_get_position(const struct ast_stream *stream)
Get the position of the stream in the topology.
Definition: stream.c:500

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 335 of file app_stream_echo.c.

References app, and ast_unregister_application().

336 {
338 }
static const char app[]
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx_app.c:392

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Stream Echo Application" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "30ef0c93b36035ec78c9cfd712d36d9b" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, }
static

Definition at line 345 of file app_stream_echo.c.

◆ app

const char app[] = "StreamEcho"
static

Definition at line 76 of file app_stream_echo.c.

Referenced by load_module(), and unload_module().

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 345 of file app_stream_echo.c.