slinfactory.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 2005, Anthony Minessale II.
  5. *
  6. * Anthony Minessale <anthmct@yahoo.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 A machine to gather up arbitrary frames and convert them
  21. * to raw slinear on demand.
  22. *
  23. * \author Anthony Minessale <anthmct@yahoo.com>
  24. */
  25. /*** MODULEINFO
  26. <support_level>core</support_level>
  27. ***/
  28. #include "asterisk.h"
  29. ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  30. #include "asterisk/frame.h"
  31. #include "asterisk/format_cache.h"
  32. #include "asterisk/slinfactory.h"
  33. #include "asterisk/translate.h"
  34. #include "asterisk/astobj2.h"
  35. void ast_slinfactory_init(struct ast_slinfactory *sf)
  36. {
  37. memset(sf, 0, sizeof(*sf));
  38. sf->offset = sf->hold;
  39. sf->output_format = ao2_bump(ast_format_slin);
  40. }
  41. int ast_slinfactory_init_with_format(struct ast_slinfactory *sf, struct ast_format *slin_out)
  42. {
  43. memset(sf, 0, sizeof(*sf));
  44. sf->offset = sf->hold;
  45. if (!ast_format_cache_is_slinear(slin_out)) {
  46. return -1;
  47. }
  48. sf->output_format = ao2_bump(slin_out);
  49. return 0;
  50. }
  51. void ast_slinfactory_destroy(struct ast_slinfactory *sf)
  52. {
  53. struct ast_frame *f;
  54. if (sf->trans) {
  55. ast_translator_free_path(sf->trans);
  56. sf->trans = NULL;
  57. }
  58. while ((f = AST_LIST_REMOVE_HEAD(&sf->queue, frame_list))) {
  59. ast_frfree(f);
  60. }
  61. ao2_cleanup(sf->output_format);
  62. sf->output_format = NULL;
  63. ao2_cleanup(sf->format);
  64. sf->format = NULL;
  65. }
  66. int ast_slinfactory_feed(struct ast_slinfactory *sf, struct ast_frame *f)
  67. {
  68. struct ast_frame *begin_frame = f, *duped_frame = NULL, *frame_ptr;
  69. unsigned int x = 0;
  70. /* In some cases, we can be passed a frame which has no data in it, but
  71. * which has a positive number of samples defined. Once such situation is
  72. * when a jitter buffer is in use and the jitter buffer interpolates a frame.
  73. * The frame it produces has data set to NULL, datalen set to 0, and samples
  74. * set to either 160 or 240.
  75. */
  76. if (!f->data.ptr) {
  77. return 0;
  78. }
  79. if (ast_format_cmp(f->subclass.format, sf->output_format) == AST_FORMAT_CMP_NOT_EQUAL) {
  80. if (sf->trans && (ast_format_cmp(f->subclass.format, sf->format) == AST_FORMAT_CMP_NOT_EQUAL)) {
  81. ast_translator_free_path(sf->trans);
  82. sf->trans = NULL;
  83. }
  84. if (!sf->trans) {
  85. if (!(sf->trans = ast_translator_build_path(sf->output_format, f->subclass.format))) {
  86. ast_log(LOG_WARNING, "Cannot build a path from %s (%u)to %s (%u)\n",
  87. ast_format_get_name(f->subclass.format),
  88. ast_format_get_codec_id(f->subclass.format),
  89. ast_format_get_name(sf->output_format),
  90. ast_format_get_codec_id(sf->output_format));
  91. return 0;
  92. }
  93. ao2_replace(sf->format, f->subclass.format);
  94. }
  95. if (!(begin_frame = ast_translate(sf->trans, f, 0))) {
  96. return 0;
  97. }
  98. if (!(duped_frame = ast_frisolate(begin_frame))) {
  99. return 0;
  100. }
  101. if (duped_frame != begin_frame) {
  102. ast_frfree(begin_frame);
  103. }
  104. } else {
  105. if (sf->trans) {
  106. ast_translator_free_path(sf->trans);
  107. sf->trans = NULL;
  108. }
  109. if (!(duped_frame = ast_frdup(f)))
  110. return 0;
  111. }
  112. AST_LIST_TRAVERSE(&sf->queue, frame_ptr, frame_list) {
  113. x++;
  114. }
  115. /* if the frame was translated, the translator may have returned multiple
  116. frames, so process each of them
  117. */
  118. for (begin_frame = duped_frame; begin_frame; begin_frame = AST_LIST_NEXT(begin_frame, frame_list)) {
  119. AST_LIST_INSERT_TAIL(&sf->queue, begin_frame, frame_list);
  120. sf->size += begin_frame->samples;
  121. }
  122. return x;
  123. }
  124. int ast_slinfactory_read(struct ast_slinfactory *sf, short *buf, size_t samples)
  125. {
  126. struct ast_frame *frame_ptr;
  127. unsigned int sofar = 0, ineed, remain;
  128. short *frame_data, *offset = buf;
  129. while (sofar < samples) {
  130. ineed = samples - sofar;
  131. if (sf->holdlen) {
  132. if (sf->holdlen <= ineed) {
  133. memcpy(offset, sf->offset, sf->holdlen * sizeof(*offset));
  134. sofar += sf->holdlen;
  135. offset += sf->holdlen;
  136. sf->holdlen = 0;
  137. sf->offset = sf->hold;
  138. } else {
  139. remain = sf->holdlen - ineed;
  140. memcpy(offset, sf->offset, ineed * sizeof(*offset));
  141. sofar += ineed;
  142. sf->offset += ineed;
  143. sf->holdlen = remain;
  144. }
  145. continue;
  146. }
  147. if ((frame_ptr = AST_LIST_REMOVE_HEAD(&sf->queue, frame_list))) {
  148. frame_data = frame_ptr->data.ptr;
  149. if (frame_ptr->samples <= ineed) {
  150. memcpy(offset, frame_data, frame_ptr->samples * sizeof(*offset));
  151. sofar += frame_ptr->samples;
  152. offset += frame_ptr->samples;
  153. } else {
  154. remain = frame_ptr->samples - ineed;
  155. memcpy(offset, frame_data, ineed * sizeof(*offset));
  156. sofar += ineed;
  157. frame_data += ineed;
  158. if (remain > (AST_SLINFACTORY_MAX_HOLD - sf->holdlen)) {
  159. remain = AST_SLINFACTORY_MAX_HOLD - sf->holdlen;
  160. }
  161. memcpy(sf->hold, frame_data, remain * sizeof(*offset));
  162. sf->holdlen = remain;
  163. }
  164. ast_frfree(frame_ptr);
  165. } else {
  166. break;
  167. }
  168. }
  169. sf->size -= sofar;
  170. return sofar;
  171. }
  172. unsigned int ast_slinfactory_available(const struct ast_slinfactory *sf)
  173. {
  174. return sf->size;
  175. }
  176. void ast_slinfactory_flush(struct ast_slinfactory *sf)
  177. {
  178. struct ast_frame *fr = NULL;
  179. if (sf->trans) {
  180. ast_translator_free_path(sf->trans);
  181. sf->trans = NULL;
  182. }
  183. while ((fr = AST_LIST_REMOVE_HEAD(&sf->queue, frame_list)))
  184. ast_frfree(fr);
  185. sf->size = sf->holdlen = 0;
  186. sf->offset = sf->hold;
  187. return;
  188. }