bridge_softmix.c 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 2007, Digium, Inc.
  5. *
  6. * Joshua Colp <jcolp@digium.com>
  7. *
  8. * See http://www.asterisk.org for more information about
  9. * the Asterisk project. Please do not directly contact
  10. * any of the maintainers of this project for assistance;
  11. * the project provides a web site, mailing lists and IRC
  12. * channels for your use.
  13. *
  14. * This program is free software, distributed under the terms of
  15. * the GNU General Public License Version 2. See the LICENSE file
  16. * at the top of the source tree.
  17. */
  18. /*! \file
  19. *
  20. * \brief Multi-party software based channel mixing
  21. *
  22. * \author Joshua Colp <jcolp@digium.com>
  23. *
  24. * \ingroup bridges
  25. *
  26. * \todo This bridge operates in 8 kHz mode unless a define is uncommented.
  27. * This needs to be improved so the bridge moves between the dominant codec as needed depending
  28. * on channels present in the bridge and transcoding capabilities.
  29. */
  30. /*** MODULEINFO
  31. <support_level>core</support_level>
  32. ***/
  33. #include "asterisk.h"
  34. ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  35. #include <stdio.h>
  36. #include <stdlib.h>
  37. #include <string.h>
  38. #include <sys/time.h>
  39. #include <signal.h>
  40. #include <errno.h>
  41. #include <unistd.h>
  42. #include "asterisk/module.h"
  43. #include "asterisk/channel.h"
  44. #include "asterisk/bridging.h"
  45. #include "asterisk/bridging_technology.h"
  46. #include "asterisk/frame.h"
  47. #include "asterisk/options.h"
  48. #include "asterisk/logger.h"
  49. #include "asterisk/slinfactory.h"
  50. #include "asterisk/astobj2.h"
  51. #include "asterisk/timing.h"
  52. /*! \brief Interval at which mixing will take place. Valid options are 10, 20, and 40. */
  53. #define SOFTMIX_INTERVAL 20
  54. /*! \brief Size of the buffer used for sample manipulation */
  55. #define SOFTMIX_DATALEN (160 * (SOFTMIX_INTERVAL / 10))
  56. /*! \brief Number of samples we are dealing with */
  57. #define SOFTMIX_SAMPLES (SOFTMIX_DATALEN / 2)
  58. /*! \brief Define used to turn on 16 kHz audio support */
  59. /* #define SOFTMIX_16_SUPPORT */
  60. /*! \brief Structure which contains per-channel mixing information */
  61. struct softmix_channel {
  62. /*! Lock to protect this structure */
  63. ast_mutex_t lock;
  64. /*! Factory which contains audio read in from the channel */
  65. struct ast_slinfactory factory;
  66. /*! Frame that contains mixed audio to be written out to the channel */
  67. struct ast_frame frame;
  68. /*! Bit used to indicate that the channel provided audio for this mixing interval */
  69. int have_audio:1;
  70. /*! Bit used to indicate that a frame is available to be written out to the channel */
  71. int have_frame:1;
  72. /*! Buffer containing final mixed audio from all sources */
  73. short final_buf[SOFTMIX_DATALEN];
  74. /*! Buffer containing only the audio from the channel */
  75. short our_buf[SOFTMIX_DATALEN];
  76. };
  77. /*! \brief Function called when a bridge is created */
  78. static int softmix_bridge_create(struct ast_bridge *bridge)
  79. {
  80. struct ast_timer *timer;
  81. if (!(timer = ast_timer_open())) {
  82. return -1;
  83. }
  84. bridge->bridge_pvt = timer;
  85. return 0;
  86. }
  87. /*! \brief Function called when a bridge is destroyed */
  88. static int softmix_bridge_destroy(struct ast_bridge *bridge)
  89. {
  90. if (!bridge->bridge_pvt) {
  91. return -1;
  92. }
  93. ast_timer_close((struct ast_timer *) bridge->bridge_pvt);
  94. return 0;
  95. }
  96. /*! \brief Function called when a channel is joined into the bridge */
  97. static int softmix_bridge_join(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
  98. {
  99. struct softmix_channel *sc = NULL;
  100. /* Create a new softmix_channel structure and allocate various things on it */
  101. if (!(sc = ast_calloc(1, sizeof(*sc)))) {
  102. return -1;
  103. }
  104. /* Can't forget the lock */
  105. ast_mutex_init(&sc->lock);
  106. /* Setup smoother */
  107. ast_slinfactory_init(&sc->factory);
  108. /* Setup frame parameters */
  109. sc->frame.frametype = AST_FRAME_VOICE;
  110. #ifdef SOFTMIX_16_SUPPORT
  111. sc->frame.subclass.codec = AST_FORMAT_SLINEAR16;
  112. #else
  113. sc->frame.subclass.codec = AST_FORMAT_SLINEAR;
  114. #endif
  115. sc->frame.data.ptr = sc->final_buf;
  116. sc->frame.datalen = SOFTMIX_DATALEN;
  117. sc->frame.samples = SOFTMIX_SAMPLES;
  118. /* Can't forget to record our pvt structure within the bridged channel structure */
  119. bridge_channel->bridge_pvt = sc;
  120. return 0;
  121. }
  122. /*! \brief Function called when a channel leaves the bridge */
  123. static int softmix_bridge_leave(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
  124. {
  125. struct softmix_channel *sc = bridge_channel->bridge_pvt;
  126. /* Drop mutex lock */
  127. ast_mutex_destroy(&sc->lock);
  128. /* Drop the factory */
  129. ast_slinfactory_destroy(&sc->factory);
  130. /* Eep! drop ourselves */
  131. ast_free(sc);
  132. return 0;
  133. }
  134. /*! \brief Function called when a channel writes a frame into the bridge */
  135. static enum ast_bridge_write_result softmix_bridge_write(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
  136. {
  137. struct softmix_channel *sc = bridge_channel->bridge_pvt;
  138. /* Only accept audio frames, all others are unsupported */
  139. if (frame->frametype != AST_FRAME_VOICE) {
  140. return AST_BRIDGE_WRITE_UNSUPPORTED;
  141. }
  142. ast_mutex_lock(&sc->lock);
  143. /* If a frame was provided add it to the smoother */
  144. #ifdef SOFTMIX_16_SUPPORT
  145. if (frame->frametype == AST_FRAME_VOICE && frame->subclass.codec == AST_FORMAT_SLINEAR16) {
  146. #else
  147. if (frame->frametype == AST_FRAME_VOICE && frame->subclass.codec == AST_FORMAT_SLINEAR) {
  148. #endif
  149. ast_slinfactory_feed(&sc->factory, frame);
  150. }
  151. /* If a frame is ready to be written out, do so */
  152. if (sc->have_frame) {
  153. ast_write(bridge_channel->chan, &sc->frame);
  154. sc->have_frame = 0;
  155. }
  156. /* Alllll done */
  157. ast_mutex_unlock(&sc->lock);
  158. return AST_BRIDGE_WRITE_SUCCESS;
  159. }
  160. /*! \brief Function called when the channel's thread is poked */
  161. static int softmix_bridge_poke(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
  162. {
  163. struct softmix_channel *sc = bridge_channel->bridge_pvt;
  164. ast_mutex_lock(&sc->lock);
  165. if (sc->have_frame) {
  166. ast_write(bridge_channel->chan, &sc->frame);
  167. sc->have_frame = 0;
  168. }
  169. ast_mutex_unlock(&sc->lock);
  170. return 0;
  171. }
  172. /*! \brief Function which acts as the mixing thread */
  173. static int softmix_bridge_thread(struct ast_bridge *bridge)
  174. {
  175. struct ast_timer *timer = (struct ast_timer *) bridge->bridge_pvt;
  176. int timingfd = ast_timer_fd(timer);
  177. ast_timer_set_rate(timer, (1000 / SOFTMIX_INTERVAL));
  178. while (!bridge->stop && !bridge->refresh && bridge->array_num) {
  179. struct ast_bridge_channel *bridge_channel = NULL;
  180. short buf[SOFTMIX_DATALEN] = {0, };
  181. int timeout = -1;
  182. /* Go through pulling audio from each factory that has it available */
  183. AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
  184. struct softmix_channel *sc = bridge_channel->bridge_pvt;
  185. ast_mutex_lock(&sc->lock);
  186. /* Try to get audio from the factory if available */
  187. if (ast_slinfactory_available(&sc->factory) >= SOFTMIX_SAMPLES && ast_slinfactory_read(&sc->factory, sc->our_buf, SOFTMIX_SAMPLES)) {
  188. short *data1, *data2;
  189. int i;
  190. /* Put into the local final buffer */
  191. for (i = 0, data1 = buf, data2 = sc->our_buf; i < SOFTMIX_DATALEN; i++, data1++, data2++)
  192. ast_slinear_saturated_add(data1, data2);
  193. /* Yay we have our own audio */
  194. sc->have_audio = 1;
  195. } else {
  196. /* Awww we don't have audio ;( */
  197. sc->have_audio = 0;
  198. }
  199. ast_mutex_unlock(&sc->lock);
  200. }
  201. /* Next step go through removing the channel's own audio and creating a good frame... */
  202. AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
  203. struct softmix_channel *sc = bridge_channel->bridge_pvt;
  204. int i = 0;
  205. /* Copy from local final buffer to our final buffer */
  206. memcpy(sc->final_buf, buf, sizeof(sc->final_buf));
  207. /* If we provided audio then take it out */
  208. if (sc->have_audio) {
  209. for (i = 0; i < SOFTMIX_DATALEN; i++) {
  210. ast_slinear_saturated_subtract(&sc->final_buf[i], &sc->our_buf[i]);
  211. }
  212. }
  213. /* The frame is now ready for use... */
  214. sc->have_frame = 1;
  215. /* Poke bridged channel thread just in case */
  216. pthread_kill(bridge_channel->thread, SIGURG);
  217. }
  218. ao2_unlock(bridge);
  219. /* Wait for the timing source to tell us to wake up and get things done */
  220. ast_waitfor_n_fd(&timingfd, 1, &timeout, NULL);
  221. ast_timer_ack(timer, 1);
  222. ao2_lock(bridge);
  223. }
  224. return 0;
  225. }
  226. static struct ast_bridge_technology softmix_bridge = {
  227. .name = "softmix",
  228. .capabilities = AST_BRIDGE_CAPABILITY_MULTIMIX | AST_BRIDGE_CAPABILITY_THREAD | AST_BRIDGE_CAPABILITY_MULTITHREADED,
  229. .preference = AST_BRIDGE_PREFERENCE_LOW,
  230. #ifdef SOFTMIX_16_SUPPORT
  231. .formats = AST_FORMAT_SLINEAR16,
  232. #else
  233. .formats = AST_FORMAT_SLINEAR,
  234. #endif
  235. .create = softmix_bridge_create,
  236. .destroy = softmix_bridge_destroy,
  237. .join = softmix_bridge_join,
  238. .leave = softmix_bridge_leave,
  239. .write = softmix_bridge_write,
  240. .thread = softmix_bridge_thread,
  241. .poke = softmix_bridge_poke,
  242. };
  243. static int unload_module(void)
  244. {
  245. return ast_bridge_technology_unregister(&softmix_bridge);
  246. }
  247. static int load_module(void)
  248. {
  249. return ast_bridge_technology_register(&softmix_bridge);
  250. }
  251. AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Multi-party software based channel mixing");