Asterisk - The Open Source Telephony Project GIT-master-f36a736
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 = AST_BUILDOPT_SUM, .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.nosp@m.ell@.nosp@m.digiu.nosp@m.m.co.nosp@m.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.

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:640

References app, ast_register_application_xml, and stream_echo_exec().

◆ 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.

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);
295 );
296
297 parse = ast_strdupa(data);
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
317
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 int stream_echo_perform(struct ast_channel *chan, struct ast_stream_topology *topology, enum ast_media_type type)
static struct ast_stream_topology * stream_echo_topology_alloc(struct ast_stream_topology *original, unsigned int num, enum ast_media_type type)
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
#define ast_log
Definition: astobj2.c:42
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.
ast_media_type
Types of media.
Definition: codec.h:30
@ AST_MEDIA_TYPE_UNKNOWN
Definition: codec.h:31
@ AST_MEDIA_TYPE_VIDEO
Definition: codec.h:33
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:364
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:348
int ast_str_to_uint(const char *str, unsigned int *res)
Convert the given string to an unsigned integer.
Definition: conversions.c:56
#define AST_APP_ARG(name)
Define an application argument.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
#define LOG_ERROR
#define NULL
Definition: resample.c:96
void ast_stream_topology_free(struct ast_stream_topology *topology)
Unreference and destroy a stream topology.
Definition: stream.c:746
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
const char * args

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, stream_echo_perform(), stream_echo_topology_alloc(), and type.

Referenced by load_module().

◆ 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.

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 */
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 &&
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 int stream_echo_write(struct ast_channel *chan, struct ast_frame *frame, enum ast_media_type type, int one_to_one)
const char * ast_channel_name(const struct ast_channel *chan)
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:10988
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3181
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:4281
#define AST_FRAME_DTMF
#define ast_frfree(fr)
@ AST_FRAME_VIDEO
@ AST_FRAME_NULL
@ AST_FRAME_MODEM
@ AST_FRAME_CONTROL
@ AST_CONTROL_VIDUPDATE
@ AST_CONTROL_STREAM_TOPOLOGY_CHANGED
@ AST_CONTROL_SRCCHANGE
#define LOG_WARNING
Data structure associated with a single frame of data.
struct ast_frame_subclass subclass
struct timeval delivery
enum ast_frame_type frametype

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(), ast_frame::subclass, and type.

Referenced by stream_echo_exec().

◆ 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.

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}
struct ast_stream_topology * ast_stream_topology_alloc(void)
Create a stream topology.
Definition: stream.c:652
@ AST_STREAM_STATE_REMOVED
Set when the stream has been removed/declined.
Definition: stream.h:78
@ AST_STREAM_STATE_SENDRECV
Set when the stream is sending and receiving media.
Definition: stream.h:82
@ AST_STREAM_STATE_SENDONLY
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_append_stream(struct ast_stream_topology *topology, struct ast_stream *stream)
Append a stream to the topology.
Definition: stream.c:751
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
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:791
int ast_stream_topology_get_count(const struct ast_stream_topology *topology)
Get the number of streams in a topology.
Definition: stream.c:768
enum ast_stream_state ast_stream_get_state(const struct ast_stream *stream)
Get the current state of a stream.
Definition: stream.c:373
enum ast_media_type ast_stream_get_type(const struct ast_stream *stream)
Get the media type of a stream.
Definition: stream.c:316
void ast_stream_free(struct ast_stream *stream)
Destroy a media stream representation.
Definition: stream.c:292

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(), NULL, and type.

Referenced by stream_echo_exec().

◆ 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.

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 int stream_echo_write_error(struct ast_channel *chan, struct ast_frame *frame, int pos)
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:5168
int ast_channel_is_multistream(struct ast_channel *chan)
Determine if a channel is multi-stream capable.
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_format * format

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, ast_frame::subclass, and type.

Referenced by stream_echo_perform().

◆ 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.

79{
80 char frame_type[32];
81 const char *media_type;
82 struct ast_stream *stream;
83
85
86 stream = pos < 0 ?
89
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,
95
96 return -1;
97}
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.
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
int ast_stream_get_position(const struct ast_stream *stream)
Get the position of the stream in the topology.
Definition: stream.c:500

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().

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 335 of file app_stream_echo.c.

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

References app, and ast_unregister_application().

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 = AST_BUILDOPT_SUM, .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.