res_format_attr_silk.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 2011, Digium, Inc.
  5. *
  6. * David Vossel <dvossel@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. /*!
  19. * \file
  20. * \brief SILK format attribute interface
  21. *
  22. * \author David Vossel <dvossel@digium.com>
  23. */
  24. /*** MODULEINFO
  25. <support_level>core</support_level>
  26. ***/
  27. #include "asterisk.h"
  28. ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  29. #include "asterisk/module.h"
  30. #include "asterisk/format.h"
  31. /*!
  32. * \brief SILK attribute structure.
  33. *
  34. * \note The only attribute that affects compatibility here is the sample rate.
  35. */
  36. struct silk_attr {
  37. unsigned int samplerate;
  38. unsigned int maxbitrate;
  39. unsigned int dtx;
  40. unsigned int fec;
  41. unsigned int packetloss_percentage;
  42. };
  43. static int silk_sdp_parse(struct ast_format_attr *format_attr, const char *attributes)
  44. {
  45. struct silk_attr *attr = (struct silk_attr *) format_attr;
  46. unsigned int val;
  47. if (sscanf(attributes, "maxaveragebitrate=%30u", &val) == 1) {
  48. attr->maxbitrate = val;
  49. }
  50. if (sscanf(attributes, "usedtx=%30u", &val) == 1) {
  51. attr->dtx = val;
  52. }
  53. if (sscanf(attributes, "useinbandfec=%30u", &val) == 1) {
  54. attr->fec = val;
  55. }
  56. return 0;
  57. }
  58. static void silk_sdp_generate(const struct ast_format_attr *format_attr, unsigned int payload, struct ast_str **str)
  59. {
  60. struct silk_attr *attr = (struct silk_attr *) format_attr;
  61. if ((attr->maxbitrate > 5000) && (attr->maxbitrate < 40000)) {
  62. ast_str_append(str, 0, "a=fmtp:%u maxaveragebitrate=%u\r\n", payload, attr->maxbitrate);
  63. }
  64. ast_str_append(str, 0, "a=fmtp:%u usedtx=%u\r\n", payload, attr->dtx);
  65. ast_str_append(str, 0, "a=fmtp:%u useinbandfec=%u\r\n", payload, attr->fec);
  66. }
  67. static enum ast_format_cmp_res silk_cmp(const struct ast_format_attr *fattr1, const struct ast_format_attr *fattr2)
  68. {
  69. struct silk_attr *attr1 = (struct silk_attr *) fattr1;
  70. struct silk_attr *attr2 = (struct silk_attr *) fattr2;
  71. if (attr1->samplerate == attr2->samplerate) {
  72. return AST_FORMAT_CMP_EQUAL;
  73. }
  74. return AST_FORMAT_CMP_NOT_EQUAL;
  75. }
  76. static int silk_get_val(const struct ast_format_attr *fattr, int key, void *result)
  77. {
  78. const struct silk_attr *attr = (struct silk_attr *) fattr;
  79. int *val = result;
  80. switch (key) {
  81. case SILK_ATTR_KEY_SAMP_RATE:
  82. *val = attr->samplerate;
  83. break;
  84. case SILK_ATTR_KEY_MAX_BITRATE:
  85. *val = attr->maxbitrate;
  86. break;
  87. case SILK_ATTR_KEY_DTX:
  88. *val = attr->dtx;
  89. break;
  90. case SILK_ATTR_KEY_FEC:
  91. *val = attr->fec;
  92. break;
  93. case SILK_ATTR_KEY_PACKETLOSS_PERCENTAGE:
  94. *val = attr->packetloss_percentage;
  95. break;
  96. default:
  97. ast_log(LOG_WARNING, "unknown attribute type %d\n", key);
  98. return -1;
  99. }
  100. return 0;
  101. }
  102. static int silk_isset(const struct ast_format_attr *fattr, va_list ap)
  103. {
  104. enum silk_attr_keys key;
  105. const struct silk_attr *attr = (struct silk_attr *) fattr;
  106. for (key = va_arg(ap, int);
  107. key != AST_FORMAT_ATTR_END;
  108. key = va_arg(ap, int))
  109. {
  110. switch (key) {
  111. case SILK_ATTR_KEY_SAMP_RATE:
  112. if (attr->samplerate != (va_arg(ap, int))) {
  113. return -1;
  114. }
  115. break;
  116. case SILK_ATTR_KEY_MAX_BITRATE:
  117. if (attr->maxbitrate != (va_arg(ap, int))) {
  118. return -1;
  119. }
  120. break;
  121. case SILK_ATTR_KEY_DTX:
  122. if (attr->dtx != (va_arg(ap, int))) {
  123. return -1;
  124. }
  125. break;
  126. case SILK_ATTR_KEY_FEC:
  127. if (attr->fec != (va_arg(ap, int))) {
  128. return -1;
  129. }
  130. break;
  131. case SILK_ATTR_KEY_PACKETLOSS_PERCENTAGE:
  132. if (attr->packetloss_percentage != (va_arg(ap, int))) {
  133. return -1;
  134. }
  135. break;
  136. default:
  137. ast_log(LOG_WARNING, "unknown attribute type %u\n", key);
  138. return -1;
  139. }
  140. }
  141. return 0;
  142. }
  143. static int silk_getjoint(const struct ast_format_attr *fattr1, const struct ast_format_attr *fattr2, struct ast_format_attr *result)
  144. {
  145. struct silk_attr *attr1 = (struct silk_attr *) fattr1;
  146. struct silk_attr *attr2 = (struct silk_attr *) fattr2;
  147. struct silk_attr *attr_res = (struct silk_attr *) result;
  148. int joint = -1;
  149. attr_res->samplerate = attr1->samplerate & attr2->samplerate;
  150. /* sample rate is the only attribute that has any bearing on if joint capabilities exist or not */
  151. if (attr_res->samplerate) {
  152. joint = 0;
  153. }
  154. /* Take the lowest max bitrate */
  155. attr_res->maxbitrate = MIN(attr1->maxbitrate, attr2->maxbitrate);
  156. /* Only do dtx if both sides want it. DTX is a trade off between
  157. * computational complexity and bandwidth. */
  158. attr_res->dtx = attr1->dtx && attr2->dtx ? 1 : 0;
  159. /* Only do FEC if both sides want it. If a peer specifically requests not
  160. * to receive with FEC, it may be a waste of bandwidth. */
  161. attr_res->fec = attr1->fec && attr2->fec ? 1 : 0;
  162. /* Use the maximum packetloss percentage between the two attributes. This affects how
  163. * much redundancy is used in the FEC. */
  164. attr_res->packetloss_percentage = MAX(attr1->packetloss_percentage, attr2->packetloss_percentage);
  165. return joint;
  166. }
  167. static void silk_set(struct ast_format_attr *fattr, va_list ap)
  168. {
  169. enum silk_attr_keys key;
  170. struct silk_attr *attr = (struct silk_attr *) fattr;
  171. for (key = va_arg(ap, int);
  172. key != AST_FORMAT_ATTR_END;
  173. key = va_arg(ap, int))
  174. {
  175. switch (key) {
  176. case SILK_ATTR_KEY_SAMP_RATE:
  177. attr->samplerate = (va_arg(ap, int));
  178. break;
  179. case SILK_ATTR_KEY_MAX_BITRATE:
  180. attr->maxbitrate = (va_arg(ap, int));
  181. break;
  182. case SILK_ATTR_KEY_DTX:
  183. attr->dtx = (va_arg(ap, int));
  184. break;
  185. case SILK_ATTR_KEY_FEC:
  186. attr->fec = (va_arg(ap, int));
  187. break;
  188. case SILK_ATTR_KEY_PACKETLOSS_PERCENTAGE:
  189. attr->packetloss_percentage = (va_arg(ap, int));
  190. break;
  191. default:
  192. ast_log(LOG_WARNING, "unknown attribute type %u\n", key);
  193. }
  194. }
  195. }
  196. static struct ast_format_attr_interface silk_interface = {
  197. .id = AST_FORMAT_SILK,
  198. .format_attr_cmp = silk_cmp,
  199. .format_attr_get_joint = silk_getjoint,
  200. .format_attr_set = silk_set,
  201. .format_attr_isset = silk_isset,
  202. .format_attr_get_val = silk_get_val,
  203. .format_attr_sdp_parse = silk_sdp_parse,
  204. .format_attr_sdp_generate = silk_sdp_generate,
  205. };
  206. static int load_module(void)
  207. {
  208. if (ast_format_attr_reg_interface(&silk_interface)) {
  209. return AST_MODULE_LOAD_DECLINE;
  210. }
  211. return AST_MODULE_LOAD_SUCCESS;
  212. }
  213. static int unload_module(void)
  214. {
  215. ast_format_attr_unreg_interface(&silk_interface);
  216. return 0;
  217. }
  218. AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "SILK Format Attribute Module",
  219. .load = load_module,
  220. .unload = unload_module,
  221. .load_pri = AST_MODPRI_CHANNEL_DEPEND,
  222. );