1 /*
2  * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
3  * Copyright (C) 2005-2014, Anthony Minessale II <anthm@freeswitch.org>
4  *
5  * Version: MPL 1.1
6  *
7  * The contents of this file are subject to the Mozilla Public License Version
8  * 1.1 (the "License"); you may not use this file except in compliance with
9  * the License. You may obtain a copy of the License at
10  * http://www.mozilla.org/MPL/
11  *
12  * Software distributed under the License is distributed on an "AS IS" basis,
13  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14  * for the specific language governing rights and limitations under the
15  * License.
16  *
17  * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
18  *
19  * The Initial Developer of the Original Code is
20  * Anthony Minessale II <anthm@freeswitch.org>
21  * Portions created by the Initial Developer are Copyright (C)
22  * the Initial Developer. All Rights Reserved.
23  *
24  * Contributor(s):
25  *
26  * Anthony Minessale II <anthm@freeswitch.org>
27  * Andrey Volk <andywolk@gmail.com>
28  *
29  *
30  * switch_loadable_module.h -- Loadable Modules
31  *
32  */
33 /*! \file switch_loadable_module.h
34     \brief Loadable Module Routines
35 
36 	This module is the gateway between external modules and the core of the application.
37 	it contains all the access points to the various pluggable interfaces including the codecs
38 	and API modules.
39 
40 */
41 
42 #ifndef SWITCH_LOADABLE_MODULE_H
43 #define SWITCH_LOADABLE_MODULE_H
44 
45 #include <switch_log.h>
46 #include <switch.h>
47 #include <switch_module_interfaces.h>
48 
49 SWITCH_BEGIN_EXTERN_C
50 /*!
51   \defgroup mods Loadable Module Functions
52   \ingroup core1
53   \{
54 */
55 
56 /*! \brief List of loadable module types */
57 	typedef enum {
58 		SWITCH_LOADABLE_MODULE_TYPE_PRELOAD,
59 		SWITCH_LOADABLE_MODULE_TYPE_COMMON,
60 		SWITCH_LOADABLE_MODULE_TYPE_POSTLOAD
61 	} switch_loadable_module_type_t;
62 
63 /*! \brief The abstraction of a loadable module */
64 	struct switch_loadable_module_interface {
65 	/*! the name of the module */
66 	const char *module_name;
67 	/*! the table of endpoints the module has implemented */
68 	switch_endpoint_interface_t *endpoint_interface;
69 	/*! the table of timers the module has implemented */
70 	switch_timer_interface_t *timer_interface;
71 	/*! the table of dialplans the module has implemented */
72 	switch_dialplan_interface_t *dialplan_interface;
73 	/*! the table of codecs the module has implemented */
74 	switch_codec_interface_t *codec_interface;
75 	/*! the table of applications the module has implemented */
76 	switch_application_interface_t *application_interface;
77 	/*! the table of chat applications the module has implemented */
78 	switch_chat_application_interface_t *chat_application_interface;
79 	/*! the table of api functions the module has implemented */
80 	switch_api_interface_t *api_interface;
81 	/*! the table of json api functions the module has implemented */
82 	switch_json_api_interface_t *json_api_interface;
83 	/*! the table of file formats the module has implemented */
84 	switch_file_interface_t *file_interface;
85 	/*! the table of speech interfaces the module has implemented */
86 	switch_speech_interface_t *speech_interface;
87 	/*! the table of directory interfaces the module has implemented */
88 	switch_directory_interface_t *directory_interface;
89 	/*! the table of chat interfaces the module has implemented */
90 	switch_chat_interface_t *chat_interface;
91 	/*! the table of say interfaces the module has implemented */
92 	switch_say_interface_t *say_interface;
93 	/*! the table of asr interfaces the module has implemented */
94 	switch_asr_interface_t *asr_interface;
95 	/*! the table of management interfaces the module has implemented */
96 	switch_management_interface_t *management_interface;
97 	/*! the table of limit interfaces the module has implemented */
98 	switch_limit_interface_t *limit_interface;
99 	/*! the table of database interfaces the module has implemented */
100 	switch_database_interface_t *database_interface;
101 	switch_thread_rwlock_t *rwlock;
102 	int refs;
103 	switch_memory_pool_t *pool;
104 };
105 
106 /*!
107   \brief Initilize the module backend and load all the modules
108   \return SWITCH_STATUS_SUCCESS when complete
109  */
110 SWITCH_DECLARE(switch_status_t) switch_loadable_module_init(switch_bool_t autoload);
111 
112 /*!
113   \brief Shutdown the module backend and call the shutdown routine in all loaded modules
114  */
115 SWITCH_DECLARE(void) switch_loadable_module_shutdown(void);
116 
117 /*!
118   \brief Retrieve the endpoint interface by it's registered name
119   \param name the name of the endpoint
120   \return the desired endpoint interface
121  */
122 SWITCH_DECLARE(switch_endpoint_interface_t *) switch_loadable_module_get_endpoint_interface(const char *name);
123 
124 /*!
125   \brief Retrieve the codec interface by it's registered name
126   \param name the name of the codec
127   \return the desired codec interface
128  */
129 SWITCH_DECLARE(switch_codec_interface_t *) switch_loadable_module_get_codec_interface(const char *name, const char *modname);
130 
131 SWITCH_DECLARE(char *) switch_parse_codec_buf(char *buf, uint32_t *interval, uint32_t *rate, uint32_t *bit, uint32_t *channels, char **modname, char **fmtp);
132 
133 /*!
134   \brief Retrieve the dialplan interface by it's registered name
135   \param name the name of the dialplan
136   \return the desired dialplan interface
137  */
138 SWITCH_DECLARE(switch_dialplan_interface_t *) switch_loadable_module_get_dialplan_interface(const char *name);
139 
140 /*!
141   \brief Enumerates a list of all modules discovered in a directory
142   \param the directory to look for modules in
143   \param memory pool
144   \param callback function to call for each module found
145   \param user data argument to pass to the callback function
146   \return the resulting status
147  */
148 SWITCH_DECLARE(switch_status_t) switch_loadable_module_enumerate_available(const char *dir_path, switch_modulename_callback_func_t callback, void *user_data);
149 
150 
151 /*!
152   \brief Enumerates a list of all currently loaded modules
153   \param callback function to call for each module found
154   \param user data argument to pass to the callback function
155   \return the resulting status
156  */
157 SWITCH_DECLARE(switch_status_t) switch_loadable_module_enumerate_loaded(switch_modulename_callback_func_t callback, void *user_data);
158 
159 /*!
160   \brief build a dynamic module object and register it (for use in double embeded modules)
161   \param filename the name of the modules source file
162   \param switch_module_load the function to call when the module is loaded
163   \param switch_module_runtime a function requested to be started in it's own thread once loaded
164   \param switch_module_shutdown the function to call when the system is shutdown
165   \param runtime start the runtime thread or not
166   \return the resulting status
167   \note only use this function if you are making a module that in turn gateways module loading to another technology
168  */
169 SWITCH_DECLARE(switch_status_t) switch_loadable_module_build_dynamic(char *filename,
170 																	 switch_module_load_t switch_module_load,
171 																	 switch_module_runtime_t switch_module_runtime,
172 																	 switch_module_shutdown_t switch_module_shutdown, switch_bool_t runtime);
173 
174 
175 /*!
176   \brief Retrieve the timer interface by it's registered name
177   \param name the name of the timer
178   \return the desired timer interface
179  */
180 SWITCH_DECLARE(switch_timer_interface_t *) switch_loadable_module_get_timer_interface(const char *name);
181 
182 /*!
183   \brief Retrieve the application interface by it's registered name
184   \param name the name of the application
185   \return the desired application interface
186  */
187 SWITCH_DECLARE(switch_application_interface_t *) switch_loadable_module_get_application_interface(const char *name);
188 
189 /*!
190   \brief Retrieve the chat application interface by it's registered name
191   \param name the name of the chat application
192   \return the desired chat application interface
193  */
194 SWITCH_DECLARE(switch_chat_application_interface_t *) switch_loadable_module_get_chat_application_interface(const char *name);
195 
196 SWITCH_DECLARE(switch_status_t) switch_core_execute_chat_app(switch_event_t *message, const char *app, const char *data);
197 
198 /*!
199   \brief Retrieve the API interface by it's registered name
200   \param name the name of the API
201   \return the desired API interface
202  */
203 SWITCH_DECLARE(switch_api_interface_t *) switch_loadable_module_get_api_interface(const char *name);
204 
205 /*!
206   \brief Retrieve the JSON API interface by it's registered name
207   \param name the name of the API
208   \return the desired API interface
209  */
210 SWITCH_DECLARE(switch_json_api_interface_t *) switch_loadable_module_get_json_api_interface(const char *name);
211 
212 /*!
213   \brief Retrieve the file format interface by it's registered name
214   \param name the name of the file format
215   \return the desired file format interface
216  */
217 SWITCH_DECLARE(switch_file_interface_t *) switch_loadable_module_get_file_interface(const char *name, const char *modname);
218 
219 /*!
220 \brief Retrieve the database interface by it's registered name
221 \param name the name of the dsn prefix
222 \return the desired database format interface
223 */
224 SWITCH_DECLARE(switch_database_interface_t *) switch_loadable_module_get_database_interface(const char *name, const char *modname);
225 
226 /*!
227   \brief Retrieve the speech interface by it's registered name
228   \param name the name of the speech interface
229   \return the desired speech interface
230  */
231 SWITCH_DECLARE(switch_speech_interface_t *) switch_loadable_module_get_speech_interface(const char *name);
232 
233 /*!
234   \brief Retrieve the asr interface by it's registered name
235   \param name the name of the asr interface
236   \return the desired asr interface
237  */
238 SWITCH_DECLARE(switch_asr_interface_t *) switch_loadable_module_get_asr_interface(const char *name);
239 
240 /*!
241   \brief Retrieve the directory interface by it's registered name
242   \param name the name of the directory interface
243   \return the desired directory interface
244  */
245 SWITCH_DECLARE(switch_directory_interface_t *) switch_loadable_module_get_directory_interface(const char *name);
246 
247 /*!
248   \brief Retrieve the chat interface by it's registered name
249   \param name the name of the chat interface
250   \return the desired chat interface
251  */
252 SWITCH_DECLARE(switch_chat_interface_t *) switch_loadable_module_get_chat_interface(const char *name);
253 
254 /*!
255   \brief Retrieve the say interface by it's registered name
256   \param name the name of the say interface
257   \return the desired say interface
258  */
259 SWITCH_DECLARE(switch_say_interface_t *) switch_loadable_module_get_say_interface(const char *name);
260 
261 /*!
262   \brief Retrieve the management interface by it's registered name
263   \param relative_oid the relative oid of the management interface
264   \return the desired management interface
265  */
266 SWITCH_DECLARE(switch_management_interface_t *) switch_loadable_module_get_management_interface(const char *relative_oid);
267 
268 /*!
269   \brief Retrieve the limit interface by it's registered name
270   \param name the name of the limit interface
271   \return the desired limit interface
272  */
273 SWITCH_DECLARE(switch_limit_interface_t *) switch_loadable_module_get_limit_interface(const char *name);
274 
275 /*!
276   \brief Retrieve the list of loaded codecs into an array
277   \param array the array to populate
278   \param arraylen the max size in elements of the array
279   \return the number of elements added to the array
280  */
281 SWITCH_DECLARE(int) switch_loadable_module_get_codecs(const switch_codec_implementation_t **array, int arraylen);
282 
283 
284 /*!
285   \brief Retrieve the list of loaded codecs into an array based on another array showing the sorted order
286   \param array the array to populate
287   \param arraylen the max size in elements of the array
288   \param prefs the array of preferred codec names
289   \param preflen the size in elements of the prefs
290   \return the number of elements added to the array
291   \note this function only considers codecs that are listed in the "prefs" array and ignores the rest.
292 */
293 SWITCH_DECLARE(int) switch_loadable_module_get_codecs_sorted(const switch_codec_implementation_t **array, char fmtp_array[SWITCH_MAX_CODECS][MAX_FMTP_LEN], int arraylen, char **prefs, int preflen);
294 
295 /*!
296   \brief Execute a registered API command
297   \param cmd the name of the API command to execute
298   \param arg the optional arguement to the command
299   \param session an optional session
300   \param stream stream for output
301   \return the status returned by the API call
302 */
303 SWITCH_DECLARE(switch_status_t) switch_api_execute(const char *cmd, const char *arg, switch_core_session_t *session, switch_stream_handle_t *stream);
304 
305 /*!
306   \brief Execute a registered JSON API command
307   \param json the name of the JSON API command to execute
308   \param arg the optional arguement to the command
309   \param session an optional session
310   \param stream stream for output
311   \return the status returned by the API call
312 */
313 SWITCH_DECLARE(switch_status_t) switch_json_api_execute(cJSON *json, switch_core_session_t *session, cJSON **retval);
314 
315 /*!
316   \brief Load a module
317   \param dir the directory where the module resides
318   \param fname the file name of the module
319   \param runtime option to start the runtime thread if it exists
320   \param err pointer to error message
321   \return the status
322 */
323 SWITCH_DECLARE(switch_status_t) switch_loadable_module_load_module(const char *dir, const char *fname, switch_bool_t runtime, const char **err);
324 
325 /*!
326   \brief Check if a module is loaded
327   \param mod the module name
328   \return the status
329 */
330 SWITCH_DECLARE(switch_status_t) switch_loadable_module_exists(const char *mod);
331 
332 /*!
333 \brief Protect module from beeing unloaded
334 \param mod the module name
335 \return the status
336 */
337 SWITCH_DECLARE(switch_status_t) switch_loadable_module_protect(const char *mod);
338 
339 /*!
340   \brief Unoad a module
341   \param dir the directory where the module resides
342   \param fname the file name of the module
343   \param err pointer to error message
344   \return the status
345 */
346 SWITCH_DECLARE(switch_status_t) switch_loadable_module_unload_module(const char *dir, const char *fname, switch_bool_t force, const char **err);
347 
348 /* Prototypes of module interface functions */
349 
350 /*!
351   \brief Load a module
352   \param module_interface a pointer to a pointer to aim at your module's local interface
353   \param filename the path to the module's dll or so file
354   \return SWITCH_STATUS_SUCCESS on a successful load
355 */
356 SWITCH_MOD_DECLARE(switch_status_t) switch_module_load(switch_loadable_module_interface_t ** module_interface, const char *filename);
357 SWITCH_MOD_DECLARE(switch_status_t) switch_module_runtime(void);
358 
359 /*!
360   \brief Shutdown a module
361   \return SWITCH_STATUS_SUCCESS on a successful shutdown
362 */
363 SWITCH_MOD_DECLARE(switch_status_t) switch_module_shutdown(void);
364 
365 #define SWITCH_ADD_API(api_int, int_name, descript, funcptr, syntax_string) \
366 	for (;;) { \
367 	api_int = (switch_api_interface_t *)switch_loadable_module_create_interface(*module_interface, SWITCH_API_INTERFACE); \
368 	api_int->interface_name = int_name; \
369 	api_int->desc = descript; \
370 	api_int->function = funcptr; \
371 	api_int->syntax = syntax_string; \
372 	break; \
373 	}
374 
375 #define SWITCH_ADD_JSON_API(json_api_int, int_name, descript, funcptr, syntax_string) \
376 	for (;;) { \
377 	json_api_int = (switch_json_api_interface_t *)switch_loadable_module_create_interface(*module_interface, SWITCH_JSON_API_INTERFACE); \
378 	json_api_int->interface_name = int_name; \
379 	json_api_int->desc = descript; \
380 	json_api_int->function = funcptr; \
381 	json_api_int->syntax = syntax_string; \
382 	break; \
383 	}
384 
385 #define SWITCH_ADD_CHAT(chat_int, int_name, funcptr) \
386 	for (;;) { \
387 	chat_int = (switch_chat_interface_t *)switch_loadable_module_create_interface(*module_interface, SWITCH_CHAT_INTERFACE); \
388 	chat_int->chat_send = funcptr; \
389 	chat_int->interface_name = int_name; \
390 	break; \
391 	}
392 
393 #define SWITCH_ADD_APP(app_int, int_name, short_descript, long_descript, funcptr, syntax_string, app_flags) \
394 	for (;;) { \
395 	app_int = (switch_application_interface_t *)switch_loadable_module_create_interface(*module_interface, SWITCH_APPLICATION_INTERFACE); \
396 	app_int->interface_name = int_name; \
397 	app_int->application_function = funcptr; \
398 	app_int->short_desc = short_descript; \
399 	app_int->long_desc = long_descript; \
400 	app_int->syntax = syntax_string; \
401 	app_int->flags = app_flags; \
402 	break; \
403 	}
404 
405 #define SWITCH_ADD_CHAT_APP(app_int, int_name, short_descript, long_descript, funcptr, syntax_string, app_flags) \
406 	for (;;) { \
407 	app_int = (switch_chat_application_interface_t *)switch_loadable_module_create_interface(*module_interface, SWITCH_CHAT_APPLICATION_INTERFACE); \
408 	app_int->interface_name = int_name; \
409 	app_int->chat_application_function = funcptr; \
410 	app_int->short_desc = short_descript; \
411 	app_int->long_desc = long_descript; \
412 	app_int->syntax = syntax_string; \
413 	app_int->flags = app_flags; \
414 	break; \
415 	}
416 
417 #define SWITCH_ADD_DIALPLAN(dp_int, int_name, funcptr) \
418 	for (;;) { \
419 	dp_int = (switch_dialplan_interface_t *)switch_loadable_module_create_interface(*module_interface, SWITCH_DIALPLAN_INTERFACE); \
420 	dp_int->hunt_function = funcptr; \
421 	dp_int->interface_name = int_name; \
422 	break; \
423 	}
424 
425 #define SWITCH_ADD_LIMIT(limit_int, int_name, incrptr, releaseptr, usageptr, resetptr, statusptr, interval_resetptr) \
426 	for (;;) { \
427 	limit_int = (switch_limit_interface_t *)switch_loadable_module_create_interface(*module_interface, SWITCH_LIMIT_INTERFACE); \
428 	limit_int->incr = incrptr; \
429 	limit_int->release = releaseptr; \
430 	limit_int->usage = usageptr; \
431 	limit_int->reset = resetptr; \
432 	limit_int->interval_reset = interval_resetptr; \
433 	limit_int->status = statusptr; \
434 	limit_int->interface_name = int_name; \
435 	break; \
436 	}
437 
438 SWITCH_DECLARE(uint32_t) switch_core_codec_next_id(void);
439 
440 #define SWITCH_ADD_CODEC(codec_int, int_name) \
441 	for (;;) { \
442 		codec_int = (switch_codec_interface_t *)switch_loadable_module_create_interface(*module_interface, SWITCH_CODEC_INTERFACE); \
443 		codec_int->modname = switch_core_strdup(pool, (*module_interface)->module_name);	\
444 		codec_int->interface_name = switch_core_strdup(pool, int_name);	\
445 		codec_int->codec_id = switch_core_codec_next_id();				\
446 		break;															\
447 	}
448 
switch_check_interval(uint32_t rate,uint32_t ptime)449 	 static inline int switch_check_interval(uint32_t rate, uint32_t ptime)
450 {
451 	uint32_t max_ms = 0, ptime_div = 0;
452 
453 	switch (rate) {
454 	case 22050:
455 	case 11025:
456 		if (ptime < 120)
457 			return 1;
458 		break;
459 	case 48000:
460 	case 44100:
461 		max_ms = 40;
462 		ptime_div = 2;
463 		break;
464 	case 32000:
465 	case 24000:
466 	case 16000:
467 		max_ms = 60;
468 		ptime_div = 2;
469 		break;
470 	case 12000:
471 		max_ms = 100;
472 		ptime_div = 2;
473 		break;
474 	case 8000:
475 		max_ms = 120;
476 		ptime_div = 2;
477 		break;
478 	}
479 
480 	if (max_ms && ptime_div && (ptime <= max_ms && (ptime % ptime_div) == 0) && ((rate / 1000) * ptime) < SWITCH_RECOMMENDED_BUFFER_SIZE) {
481 		return 1;
482 	}
483 
484 	return 0;
485 }
486 
switch_core_codec_add_implementation(switch_memory_pool_t * pool,switch_codec_interface_t * codec_interface,const switch_codec_type_t codec_type,switch_payload_t ianacode,const char * iananame,char * fmtp,uint32_t samples_per_second,uint32_t actual_samples_per_second,int bits_per_second,int microseconds_per_packet,uint32_t samples_per_packet,uint32_t decoded_bytes_per_packet,uint32_t encoded_bytes_per_packet,uint8_t number_of_channels,int codec_frames_per_packet,switch_core_codec_init_func_t init,switch_core_codec_encode_func_t encode,switch_core_codec_decode_func_t decode,switch_core_codec_destroy_func_t destroy)487 static inline void switch_core_codec_add_implementation(switch_memory_pool_t *pool, switch_codec_interface_t *codec_interface,
488 														/*! enumeration defining the type of the codec */
489 														const switch_codec_type_t codec_type,
490 														/*! the IANA code number */
491 														switch_payload_t ianacode,
492 														/*! the IANA code name */
493 														const char *iananame,
494 														/*! default fmtp to send (can be overridden by the init function) */
495 														char *fmtp,
496 														/*! samples transferred per second */
497 														uint32_t samples_per_second,
498 														/*! actual samples transferred per second for those who are not moron g722 RFC writers */
499 														uint32_t actual_samples_per_second,
500 														/*! bits transferred per second */
501 														int bits_per_second,
502 														/*! number of microseconds that denote one frame */
503 														int microseconds_per_packet,
504 														/*! number of samples that denote one frame */
505 														uint32_t samples_per_packet,
506 														/*! number of bytes that denote one frame decompressed */
507 														uint32_t decoded_bytes_per_packet,
508 														/*! number of bytes that denote one frame compressed */
509 														uint32_t encoded_bytes_per_packet,
510 														/*! number of channels represented */
511 														uint8_t number_of_channels,
512 														/*! number of frames to send in one network packet */
513 														int codec_frames_per_packet,
514 														/*! function to initialize a codec handle using this implementation */
515 														switch_core_codec_init_func_t init,
516 														/*! function to encode raw data into encoded data */
517 														switch_core_codec_encode_func_t encode,
518 														/*! function to decode encoded data into raw data */
519 														switch_core_codec_decode_func_t decode,
520 														/*! deinitalize a codec handle using this implementation */
521 														switch_core_codec_destroy_func_t destroy)
522 {
523 
524 	if (decoded_bytes_per_packet > SWITCH_RECOMMENDED_BUFFER_SIZE) {
525 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Rejected codec name: %s rate: %u ptime: %d channels %d not enough buffer space %u > %d\n",
526 						  iananame, actual_samples_per_second, microseconds_per_packet / 1000, number_of_channels, decoded_bytes_per_packet, SWITCH_RECOMMENDED_BUFFER_SIZE);
527 	} else if (codec_type == SWITCH_CODEC_TYPE_VIDEO || switch_check_interval(actual_samples_per_second, microseconds_per_packet / 1000)) {
528 		switch_codec_implementation_t *impl = (switch_codec_implementation_t *) switch_core_alloc(pool, sizeof(*impl));
529 		impl->codec_type = codec_type;
530 		impl->ianacode = ianacode;
531 		impl->iananame = switch_core_strdup(pool, iananame);
532 		impl->fmtp = switch_core_strdup(pool, fmtp);
533 		impl->samples_per_second = samples_per_second;
534 		impl->actual_samples_per_second = actual_samples_per_second;
535 		impl->bits_per_second = bits_per_second;
536 		impl->microseconds_per_packet = microseconds_per_packet;
537 		impl->samples_per_packet = samples_per_packet;
538 		impl->decoded_bytes_per_packet = decoded_bytes_per_packet;
539 		impl->encoded_bytes_per_packet = encoded_bytes_per_packet;
540 		impl->number_of_channels = number_of_channels;
541 		impl->codec_frames_per_packet = codec_frames_per_packet;
542 		impl->init = init;
543 		impl->encode = encode;
544 		impl->decode = decode;
545 		impl->destroy = destroy;
546 		impl->codec_id = codec_interface->codec_id;
547 		impl->next = codec_interface->implementations;
548 		impl->impl_id = switch_core_codec_next_id();
549 		impl->modname = codec_interface->modname;
550 		codec_interface->implementations = impl;
551 	} else {
552 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Rejected codec name: %s rate: %u ptime: %d channels: %d\n",
553 						  iananame, actual_samples_per_second, microseconds_per_packet / 1000, number_of_channels);
554 	}
555 }
556 
557 ///\}
558 
switch_core_codec_add_video_implementation(switch_memory_pool_t * pool,switch_codec_interface_t * codec_interface,switch_payload_t ianacode,const char * iananame,char * fmtp,switch_core_codec_init_func_t init,switch_core_codec_video_encode_func_t encode,switch_core_codec_video_decode_func_t decode,switch_core_codec_control_func_t control,switch_core_codec_destroy_func_t destroy)559 static inline void switch_core_codec_add_video_implementation(switch_memory_pool_t *pool, switch_codec_interface_t *codec_interface,
560 															  /*! the IANA code number */
561 															  switch_payload_t ianacode,
562 															  /*! the IANA code name */
563 															  const char *iananame,
564 															  /*! default fmtp to send (can be overridden by the init function) */
565 															  char *fmtp,
566 															  switch_core_codec_init_func_t init,
567 															  /*! function to encode raw data into encoded data */
568 															  switch_core_codec_video_encode_func_t encode,
569 															  /*! function to decode encoded data into raw data */
570 															  switch_core_codec_video_decode_func_t decode,
571 															  /*! function to send control messages to the codec */
572 															  switch_core_codec_control_func_t control,
573 															  /*! deinitalize a codec handle using this implementation */
574 															  switch_core_codec_destroy_func_t destroy)
575 {
576 
577     switch_codec_implementation_t *impl = (switch_codec_implementation_t *) switch_core_alloc(pool, sizeof(*impl));
578     memset(impl, 0, sizeof(*impl));
579     impl->codec_type = SWITCH_CODEC_TYPE_VIDEO;
580     impl->ianacode = ianacode;
581     impl->iananame = switch_core_strdup(pool, iananame);
582     impl->fmtp = switch_core_strdup(pool, fmtp);
583     impl->samples_per_second = 90000;
584     impl->actual_samples_per_second = 90000;
585     impl->bits_per_second = 0;
586     impl->microseconds_per_packet = 0;
587     impl->samples_per_packet = 0;
588     impl->number_of_channels = 1;
589     impl->codec_frames_per_packet = 1;
590     impl->init = init;
591     impl->encode_video = encode;
592     impl->decode_video = decode;
593 	impl->codec_control = control;
594     impl->destroy = destroy;
595     impl->codec_id = codec_interface->codec_id;
596     impl->next = codec_interface->implementations;
597     impl->impl_id = switch_core_codec_next_id();
598 	impl->modname = codec_interface->modname;
599     codec_interface->implementations = impl;
600 }
601 
602 #define SWITCH_DECLARE_STATIC_MODULE(init, load, run, shut) void init(void) { \
603 		switch_loadable_module_build_dynamic(__FILE__, load, run, shut, SWITCH_FALSE); \
604 	}
605 
606 
switch_core_codec_ready(switch_codec_t * codec)607 static inline switch_bool_t switch_core_codec_ready(switch_codec_t *codec)
608 {
609 	return (codec && (codec->flags & SWITCH_CODEC_FLAG_READY) && codec->mutex && codec->codec_interface && codec->implementation) ? SWITCH_TRUE : SWITCH_FALSE;
610 }
611 
612 
613 SWITCH_DECLARE(switch_core_recover_callback_t) switch_core_get_secondary_recover_callback(const char *key);
614 SWITCH_DECLARE(switch_status_t) switch_core_register_secondary_recover_callback(const char *key, switch_core_recover_callback_t cb);
615 SWITCH_DECLARE(void) switch_core_unregister_secondary_recover_callback(const char *key);
616 
617 SWITCH_END_EXTERN_C
618 #endif
619 /* For Emacs:
620  * Local Variables:
621  * mode:c
622  * indent-tabs-mode:t
623  * tab-width:4
624  * c-basic-offset:4
625  * End:
626  * For VIM:
627  * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
628  */
629