res_format_attr_silk.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  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 enum ast_format_cmp_res silk_cmp(const struct ast_format_attr *fattr1, const struct ast_format_attr *fattr2)
  44. {
  45. struct silk_attr *attr1 = (struct silk_attr *) fattr1;
  46. struct silk_attr *attr2 = (struct silk_attr *) fattr2;
  47. if (attr1->samplerate == attr2->samplerate) {
  48. return AST_FORMAT_CMP_EQUAL;
  49. }
  50. return AST_FORMAT_CMP_NOT_EQUAL;
  51. }
  52. static int silk_get_val(const struct ast_format_attr *fattr, int key, void *result)
  53. {
  54. const struct silk_attr *attr = (struct silk_attr *) fattr;
  55. int *val = result;
  56. switch (key) {
  57. case SILK_ATTR_KEY_SAMP_RATE:
  58. *val = attr->samplerate;
  59. break;
  60. case SILK_ATTR_KEY_MAX_BITRATE:
  61. *val = attr->maxbitrate;
  62. break;
  63. case SILK_ATTR_KEY_DTX:
  64. *val = attr->dtx;
  65. break;
  66. case SILK_ATTR_KEY_FEC:
  67. *val = attr->fec;
  68. break;
  69. case SILK_ATTR_KEY_PACKETLOSS_PERCENTAGE:
  70. *val = attr->packetloss_percentage;
  71. break;
  72. default:
  73. return -1;
  74. ast_log(LOG_WARNING, "unknown attribute type %d\n", key);
  75. }
  76. return 0;
  77. }
  78. static int silk_isset(const struct ast_format_attr *fattr, va_list ap)
  79. {
  80. enum silk_attr_keys key;
  81. const struct silk_attr *attr = (struct silk_attr *) fattr;
  82. for (key = va_arg(ap, int);
  83. key != AST_FORMAT_ATTR_END;
  84. key = va_arg(ap, int))
  85. {
  86. switch (key) {
  87. case SILK_ATTR_KEY_SAMP_RATE:
  88. if (attr->samplerate != (va_arg(ap, int))) {
  89. return -1;
  90. }
  91. break;
  92. case SILK_ATTR_KEY_MAX_BITRATE:
  93. if (attr->maxbitrate != (va_arg(ap, int))) {
  94. return -1;
  95. }
  96. break;
  97. case SILK_ATTR_KEY_DTX:
  98. if (attr->dtx != (va_arg(ap, int))) {
  99. return -1;
  100. }
  101. break;
  102. case SILK_ATTR_KEY_FEC:
  103. if (attr->fec != (va_arg(ap, int))) {
  104. return -1;
  105. }
  106. break;
  107. case SILK_ATTR_KEY_PACKETLOSS_PERCENTAGE:
  108. if (attr->packetloss_percentage != (va_arg(ap, int))) {
  109. return -1;
  110. }
  111. break;
  112. default:
  113. return -1;
  114. ast_log(LOG_WARNING, "unknown attribute type %d\n", key);
  115. }
  116. }
  117. return 0;
  118. }
  119. static int silk_getjoint(const struct ast_format_attr *fattr1, const struct ast_format_attr *fattr2, struct ast_format_attr *result)
  120. {
  121. struct silk_attr *attr1 = (struct silk_attr *) fattr1;
  122. struct silk_attr *attr2 = (struct silk_attr *) fattr2;
  123. struct silk_attr *attr_res = (struct silk_attr *) result;
  124. int joint = -1;
  125. attr_res->samplerate = attr1->samplerate & attr2->samplerate;
  126. /* sample rate is the only attribute that has any bearing on if joint capabilities exist or not */
  127. if (attr_res->samplerate) {
  128. joint = 0;
  129. }
  130. /* Take the lowest max bitrate */
  131. attr_res->maxbitrate = MIN(attr1->maxbitrate, attr2->maxbitrate);
  132. /* Only do dtx if both sides want it. DTX is a trade off between
  133. * computational complexity and bandwidth. */
  134. attr_res->dtx = attr1->dtx && attr2->dtx ? 1 : 0;
  135. /* Only do FEC if both sides want it. If a peer specifically requests not
  136. * to receive with FEC, it may be a waste of bandwidth. */
  137. attr_res->fec = attr1->fec && attr2->fec ? 1 : 0;
  138. /* Use the maximum packetloss percentage between the two attributes. This affects how
  139. * much redundancy is used in the FEC. */
  140. attr_res->packetloss_percentage = MAX(attr1->packetloss_percentage, attr2->packetloss_percentage);
  141. return joint;
  142. }
  143. static void silk_set(struct ast_format_attr *fattr, va_list ap)
  144. {
  145. enum silk_attr_keys key;
  146. struct silk_attr *attr = (struct silk_attr *) fattr;
  147. for (key = va_arg(ap, int);
  148. key != AST_FORMAT_ATTR_END;
  149. key = va_arg(ap, int))
  150. {
  151. switch (key) {
  152. case SILK_ATTR_KEY_SAMP_RATE:
  153. attr->samplerate = (va_arg(ap, int));
  154. break;
  155. case SILK_ATTR_KEY_MAX_BITRATE:
  156. attr->maxbitrate = (va_arg(ap, int));
  157. break;
  158. case SILK_ATTR_KEY_DTX:
  159. attr->dtx = (va_arg(ap, int));
  160. break;
  161. case SILK_ATTR_KEY_FEC:
  162. attr->fec = (va_arg(ap, int));
  163. break;
  164. case SILK_ATTR_KEY_PACKETLOSS_PERCENTAGE:
  165. attr->packetloss_percentage = (va_arg(ap, int));
  166. break;
  167. default:
  168. ast_log(LOG_WARNING, "unknown attribute type %d\n", key);
  169. }
  170. }
  171. }
  172. static struct ast_format_attr_interface silk_interface = {
  173. .id = AST_FORMAT_SILK,
  174. .format_attr_cmp = silk_cmp,
  175. .format_attr_get_joint = silk_getjoint,
  176. .format_attr_set = silk_set,
  177. .format_attr_isset = silk_isset,
  178. .format_attr_get_val = silk_get_val,
  179. };
  180. static int load_module(void)
  181. {
  182. if (ast_format_attr_reg_interface(&silk_interface)) {
  183. return AST_MODULE_LOAD_DECLINE;
  184. }
  185. return AST_MODULE_LOAD_SUCCESS;
  186. }
  187. static int unload_module(void)
  188. {
  189. ast_format_attr_unreg_interface(&silk_interface);
  190. return 0;
  191. }
  192. AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "SILK Format Attribute Module",
  193. .load = load_module,
  194. .unload = unload_module,
  195. .load_pri = AST_MODPRI_CHANNEL_DEPEND,
  196. );