Asterisk - The Open Source Telephony Project GIT-master-8f1982c
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Modules Pages
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 348 of file app_stream_echo.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 348 of file app_stream_echo.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 348 of file app_stream_echo.c.

◆ load_module()

static int load_module ( void  )
static

Definition at line 343 of file app_stream_echo.c.

344{
346}
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 287 of file app_stream_echo.c.

288{
289 int res;
290 unsigned int num = 0;
291 enum ast_media_type type;
292 char *parse;
293 struct ast_stream_topology *topology;
294
296 AST_APP_ARG(num);
298 );
299
300 parse = ast_strdupa(data);
302
303 if (ast_strlen_zero(args.num)) {
304 /*
305 * If a number is not given then no topology is to be created
306 * and renegotiated. The app will just echo back each stream
307 * received to itself.
308 */
310 }
311
312 if (ast_str_to_uint(args.num, &num)) {
313 ast_log(LOG_ERROR, "Failed to parse the first parameter '%s' into a"
314 " greater than or equal to zero\n", args.num);
315 return -1;
316 }
317
320
323 if (!topology) {
324 ast_log(LOG_ERROR, "Unable to create '%u' streams of type '%s' to"
325 " the topology\n", num, ast_codec_media_type2str(type));
326 return -1;
327 }
328
329 res = stream_echo_perform(chan, topology, type);
330
331 if (ast_channel_get_stream_topology(chan) != topology) {
332 ast_stream_topology_free(topology);
333 }
334
335 return res;
336}
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 157 of file app_stream_echo.c.

159{
160 int update_sent = 0;
161 int request_change = topology != NULL;
162 int one_to_one = 1;
163
164 while (ast_waitfor(chan, -1) > -1) {
165 struct ast_frame *f;
166
167 if (request_change) {
168 /* Request a change to the new topology */
170 ast_log(LOG_WARNING, "Request stream topology change not supported "
171 "by channel '%s'\n", ast_channel_name(chan));
172 }
173 request_change = 0;
174 }
175
176 f = ast_read_stream(chan);
177 if (!f) {
178 return -1;
179 }
180
181 if ((f->frametype == AST_FRAME_DTMF) && (f->subclass.integer == '#')) {
182 ast_frfree(f);
183 break;
184 }
185
186 f->delivery.tv_sec = 0;
187 f->delivery.tv_usec = 0;
188
189 if (f->frametype == AST_FRAME_CONTROL) {
190 if (f->subclass.integer == AST_CONTROL_VIDUPDATE && !update_sent) {
191 if (stream_echo_write(chan, f, type, one_to_one)) {
192 ast_frfree(f);
193 return -1;
194 }
195 update_sent = 1;
196 } else if (f->subclass.integer == AST_CONTROL_SRCCHANGE) {
197 update_sent = 0;
199 update_sent = 0;
200 one_to_one = 0; /* Switch writing to one to many */
201 }
202 } else if (f->frametype == AST_FRAME_VIDEO && !update_sent){
203 struct ast_frame frame = {
205 .subclass.integer = AST_CONTROL_VIDUPDATE,
206 };
207 stream_echo_write(chan, &frame, type, one_to_one);
208 update_sent = 1;
209 }
210
211 if (f->frametype != AST_FRAME_CONTROL &&
214 stream_echo_write(chan, f, type, one_to_one)) {
215 ast_frfree(f);
216 return -1;
217 }
218
219 ast_frfree(f);
220 }
221
222 return 0;
223}
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:10971
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3130
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:4219
#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 225 of file app_stream_echo.c.

227{
228 int i, n = num;
230
231 if (!res) {
232 return NULL;
233 }
234
235 /*
236 * Clone every stream of a type not matching the given one. If the type
237 * matches clone only the first stream found for the given type. Then for
238 * that stream clone it again up to num - 1 times. Ignore any other streams
239 * of the same matched type in the original topology.
240 *
241 * So for instance if the original stream contains 1 audio stream and 2 video
242 * streams (video stream 'A' and video stream 'B'), num is '3', and the given
243 * type is 'video' then the resulting topology will contain a clone of the
244 * audio stream along with 3 clones of video stream 'A'. Video stream 'B' is
245 * not copied over.
246 */
247 for (i = 0; i < ast_stream_topology_get_count(original); ++i) {
248 struct ast_stream *stream = ast_stream_topology_get_stream(original, i);
249
250 if (!n && ast_stream_get_type(stream) == type) {
251 /* Don't copy any[more] of the given type */
252 continue;
253 }
254
256 /* Don't copy removed/declined streams */
257 continue;
258 }
259
260 do {
261 stream = ast_stream_clone(stream, NULL);
262
263 if (!stream || ast_stream_topology_append_stream(res, stream) < 0) {
264 ast_stream_free(stream);
266 return NULL;
267 }
268
269 if (ast_stream_get_type(stream) != type) {
270 /* Do not multiply non matching streams */
271 break;
272 }
273
274 /*
275 * Since num is not zero yet (i.e. this is first stream found to
276 * match on the type) and the types match then loop num - 1 times
277 * cloning the same stream.
278 */
279 ast_stream_set_state(stream, n == num ?
281 } while (--n);
282 }
283
284 return res;
285}
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 102 of file app_stream_echo.c.

104{
105 int i;
106 int num;
107 struct ast_stream_topology *topology;
108
109 /*
110 * Since this is an echo application if we get a frame in on a stream
111 * we simply want to echo it back out onto the same stream number.
112 */
113 num = ast_channel_is_multistream(chan) ? frame->stream_num : -1;
114 if (ast_write_stream(chan, num, frame)) {
115 return stream_echo_write_error(chan, frame, num);
116 }
117
118 /*
119 * If the frame's type and given type don't match, or we are operating in
120 * a one to one stream echo mode then there is nothing left to do.
121 *
122 * Note, if the channel is not multi-stream capable then one_to_one will
123 * always be true, so it is safe to also not check for that here too.
124 */
125 if (one_to_one || !frame->subclass.format ||
127 return 0;
128 }
129
130 /*
131 * However, if we are operating in a single stream echoed to many stream
132 * mode, and the frame's type matches the given type then we also need to
133 * find the other streams of the same type and write out to those streams
134 * as well.
135 *
136 * If we are here, then it's accepted that whatever stream number the frame
137 * was read from for the given type is the only one set to send/receive,
138 * while the others of the same type are set to receive only. Since we
139 * shouldn't assume any order to the streams, we'll loop back through all
140 * streams in the channel's topology writing only to those of the same type.
141 * And, of course also not the stream which has already been written to.
142 */
143 topology = ast_channel_get_stream_topology(chan);
144
145 for (i = 0; i < ast_stream_topology_get_count(topology); ++i) {
146 struct ast_stream *stream = ast_stream_topology_get_stream(topology, i);
147 if (num != i && ast_stream_get_type(stream) == type) {
148 if (ast_write_stream(chan, i, frame)) {
149 return stream_echo_write_error(chan, frame, i);
150 }
151 }
152 }
153
154 return 0;
155}
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:5108
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 81 of file app_stream_echo.c.

82{
83 char frame_type[32];
84 const char *media_type;
85 struct ast_stream *stream;
86
88
89 stream = pos < 0 ?
92
94
95 ast_log(LOG_ERROR, "%s - unable to write frame type '%s' to stream type '%s' at "
96 "position '%d'\n", ast_channel_name(chan), frame_type, media_type,
98
99 return -1;
100}
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 338 of file app_stream_echo.c.

339{
341}
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 348 of file app_stream_echo.c.

◆ app

const char app[] = "StreamEcho"
static

Definition at line 79 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 348 of file app_stream_echo.c.