format.c 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 2014, 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 Media Format API
  21. *
  22. * \author Joshua Colp <jcolp@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/logger.h"
  30. #include "asterisk/codec.h"
  31. #include "asterisk/format.h"
  32. #include "asterisk/astobj2.h"
  33. #include "asterisk/strings.h"
  34. /*! \brief Number of buckets to use for format interfaces (should be prime for performance reasons) */
  35. #define FORMAT_INTERFACE_BUCKETS 53
  36. /*! \brief Definition of a media format */
  37. struct ast_format {
  38. /*! Name of the format */
  39. const char *name;
  40. /*! \brief Pointer to the codec in use for this format */
  41. struct ast_codec *codec;
  42. /*! \brief Attribute specific data, implementation specific */
  43. void *attribute_data;
  44. /*! \brief Pointer to the optional format interface */
  45. const struct ast_format_interface *interface;
  46. };
  47. /*! \brief Structure used when registering a format interface */
  48. struct format_interface {
  49. /*! \brief Pointer to the format interface itself */
  50. const struct ast_format_interface *interface;
  51. /*! \brief Name of the codec the interface is for */
  52. char codec[0];
  53. };
  54. /*! \brief Container for registered format interfaces */
  55. static struct ao2_container *interfaces;
  56. static int format_interface_hash(const void *obj, int flags)
  57. {
  58. const struct format_interface *format_interface;
  59. const char *key;
  60. switch (flags & OBJ_SEARCH_MASK) {
  61. case OBJ_SEARCH_KEY:
  62. key = obj;
  63. return ast_str_hash(key);
  64. case OBJ_SEARCH_OBJECT:
  65. format_interface = obj;
  66. return ast_str_hash(format_interface->codec);
  67. default:
  68. /* Hash can only work on something with a full key. */
  69. ast_assert(0);
  70. return 0;
  71. }
  72. }
  73. static int format_interface_cmp(void *obj, void *arg, int flags)
  74. {
  75. const struct format_interface *left = obj;
  76. const struct format_interface *right = arg;
  77. const char *right_key = arg;
  78. int cmp;
  79. switch (flags & OBJ_SEARCH_MASK) {
  80. case OBJ_SEARCH_OBJECT:
  81. cmp = strcmp(left->codec, right->codec);
  82. break;
  83. case OBJ_SEARCH_KEY:
  84. cmp = strcmp(left->codec, right_key);
  85. break;
  86. case OBJ_SEARCH_PARTIAL_KEY:
  87. cmp = strncmp(left->codec, right_key, strlen(right_key));
  88. break;
  89. default:
  90. ast_assert(0);
  91. cmp = 0;
  92. break;
  93. }
  94. if (cmp) {
  95. return 0;
  96. }
  97. return CMP_MATCH;
  98. }
  99. /*! \brief Function called when the process is shutting down */
  100. static void format_shutdown(void)
  101. {
  102. ao2_cleanup(interfaces);
  103. interfaces = NULL;
  104. }
  105. int ast_format_init(void)
  106. {
  107. interfaces = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_RWLOCK, FORMAT_INTERFACE_BUCKETS, format_interface_hash,
  108. format_interface_cmp);
  109. if (!interfaces) {
  110. return -1;
  111. }
  112. ast_register_cleanup(format_shutdown);
  113. return 0;
  114. }
  115. int __ast_format_interface_register(const char *codec, const struct ast_format_interface *interface, struct ast_module *mod)
  116. {
  117. SCOPED_AO2WRLOCK(lock, interfaces);
  118. struct format_interface *format_interface;
  119. if (!interface->format_clone || !interface->format_destroy) {
  120. ast_log(LOG_ERROR, "Format interface for codec '%s' does not implement required callbacks\n", codec);
  121. return -1;
  122. }
  123. format_interface = ao2_find(interfaces, codec, OBJ_SEARCH_KEY | OBJ_NOLOCK);
  124. if (format_interface) {
  125. ast_log(LOG_ERROR, "A format interface is already present for codec '%s'\n", codec);
  126. ao2_ref(format_interface, -1);
  127. return -1;
  128. }
  129. format_interface = ao2_alloc_options(sizeof(*format_interface) + strlen(codec) + 1,
  130. NULL, AO2_ALLOC_OPT_LOCK_NOLOCK);
  131. if (!format_interface) {
  132. return -1;
  133. }
  134. format_interface->interface = interface;
  135. strcpy(format_interface->codec, codec); /* Safe */
  136. ao2_link_flags(interfaces, format_interface, OBJ_NOLOCK);
  137. ao2_ref(format_interface, -1);
  138. ast_verb(2, "Registered format interface for codec '%s'\n", codec);
  139. return 0;
  140. }
  141. void *ast_format_get_attribute_data(const struct ast_format *format)
  142. {
  143. return format->attribute_data;
  144. }
  145. void ast_format_set_attribute_data(struct ast_format *format, void *attribute_data)
  146. {
  147. format->attribute_data = attribute_data;
  148. }
  149. /*! \brief Destructor for media formats */
  150. static void format_destroy(void *obj)
  151. {
  152. struct ast_format *format = obj;
  153. if (format->interface) {
  154. format->interface->format_destroy(format);
  155. }
  156. ao2_cleanup(format->codec);
  157. }
  158. struct ast_format *ast_format_create_named(const char *format_name, struct ast_codec *codec)
  159. {
  160. struct ast_format *format;
  161. struct format_interface *format_interface;
  162. format = ao2_t_alloc_options(sizeof(*format), format_destroy,
  163. AO2_ALLOC_OPT_LOCK_NOLOCK, S_OR(codec->description, ""));
  164. if (!format) {
  165. return NULL;
  166. }
  167. format->name = format_name;
  168. format->codec = ao2_bump(codec);
  169. format_interface = ao2_find(interfaces, codec->name, OBJ_SEARCH_KEY);
  170. if (format_interface) {
  171. format->interface = format_interface->interface;
  172. ao2_ref(format_interface, -1);
  173. }
  174. return format;
  175. }
  176. struct ast_format *ast_format_clone(const struct ast_format *format)
  177. {
  178. struct ast_format *cloned = ast_format_create_named(format->name, format->codec);
  179. if (!cloned) {
  180. return NULL;
  181. }
  182. if (cloned->interface && cloned->interface->format_clone(format, cloned)) {
  183. ao2_ref(cloned, -1);
  184. return NULL;
  185. }
  186. return cloned;
  187. }
  188. struct ast_format *ast_format_create(struct ast_codec *codec)
  189. {
  190. return ast_format_create_named(codec->name, codec);
  191. }
  192. enum ast_format_cmp_res ast_format_cmp(const struct ast_format *format1, const struct ast_format *format2)
  193. {
  194. const struct ast_format_interface *interface;
  195. if (format1 == NULL || format2 == NULL) {
  196. return AST_FORMAT_CMP_NOT_EQUAL;
  197. }
  198. if (format1 == format2) {
  199. return AST_FORMAT_CMP_EQUAL;
  200. }
  201. if (format1->codec != format2->codec) {
  202. return AST_FORMAT_CMP_NOT_EQUAL;
  203. }
  204. interface = format1->interface ? format1->interface : format2->interface;
  205. if (interface && interface->format_cmp) {
  206. return interface->format_cmp(format1, format2);
  207. }
  208. return AST_FORMAT_CMP_EQUAL;
  209. }
  210. struct ast_format *ast_format_joint(const struct ast_format *format1, const struct ast_format *format2)
  211. {
  212. const struct ast_format_interface *interface;
  213. if (format1->codec != format2->codec) {
  214. return NULL;
  215. }
  216. /* If the two formats are the same structure OR if the codec is the same and no attributes
  217. * exist we can immediately return a format with reference count bumped up, since they are
  218. * the same.
  219. */
  220. if ((ast_format_cmp(format1, format2) == AST_FORMAT_CMP_EQUAL && !format1->attribute_data && !format2->attribute_data)) {
  221. return ao2_bump((struct ast_format*)format1);
  222. }
  223. interface = format1->interface ? format1->interface : format2->interface;
  224. /* If there is attribute data on either there has to be an interface */
  225. return interface->format_get_joint(format1, format2);
  226. }
  227. struct ast_format *ast_format_attribute_set(const struct ast_format *format, const char *name, const char *value)
  228. {
  229. const struct ast_format_interface *interface = format->interface;
  230. if (!interface) {
  231. struct format_interface *format_interface = ao2_find(interfaces, format->codec->name, OBJ_SEARCH_KEY);
  232. if (format_interface) {
  233. interface = format_interface->interface;
  234. ao2_ref(format_interface, -1);
  235. }
  236. }
  237. if (!interface || !interface->format_attribute_set) {
  238. return ao2_bump((struct ast_format*)format);
  239. }
  240. return interface->format_attribute_set(format, name, value);
  241. }
  242. struct ast_format *ast_format_parse_sdp_fmtp(const struct ast_format *format, const char *attributes)
  243. {
  244. const struct ast_format_interface *interface = format->interface;
  245. if (!interface) {
  246. struct format_interface *format_interface = ao2_find(interfaces, format->codec->name, OBJ_SEARCH_KEY);
  247. if (format_interface) {
  248. interface = format_interface->interface;
  249. ao2_ref(format_interface, -1);
  250. }
  251. }
  252. if (!interface || !interface->format_parse_sdp_fmtp) {
  253. return ao2_bump((struct ast_format*)format);
  254. }
  255. return interface->format_parse_sdp_fmtp(format, attributes);
  256. }
  257. void ast_format_generate_sdp_fmtp(const struct ast_format *format, unsigned int payload, struct ast_str **str)
  258. {
  259. if (!format->interface || !format->interface->format_generate_sdp_fmtp) {
  260. return;
  261. }
  262. format->interface->format_generate_sdp_fmtp(format, payload, str);
  263. }
  264. struct ast_codec *ast_format_get_codec(const struct ast_format *format)
  265. {
  266. return ao2_bump(format->codec);
  267. }
  268. unsigned int ast_format_get_codec_id(const struct ast_format *format)
  269. {
  270. return format->codec->id;
  271. }
  272. const char *ast_format_get_name(const struct ast_format *format)
  273. {
  274. return format->name;
  275. }
  276. const char *ast_format_get_codec_name(const struct ast_format *format)
  277. {
  278. return format->codec->name;
  279. }
  280. int ast_format_can_be_smoothed(const struct ast_format *format)
  281. {
  282. return format->codec->smooth;
  283. }
  284. enum ast_media_type ast_format_get_type(const struct ast_format *format)
  285. {
  286. return format->codec->type;
  287. }
  288. unsigned int ast_format_get_default_ms(const struct ast_format *format)
  289. {
  290. return format->codec->default_ms;
  291. }
  292. unsigned int ast_format_get_minimum_ms(const struct ast_format *format)
  293. {
  294. return format->codec->minimum_ms;
  295. }
  296. unsigned int ast_format_get_maximum_ms(const struct ast_format *format)
  297. {
  298. return format->codec->maximum_ms;
  299. }
  300. unsigned int ast_format_get_minimum_bytes(const struct ast_format *format)
  301. {
  302. return format->codec->minimum_bytes;
  303. }
  304. unsigned int ast_format_get_sample_rate(const struct ast_format *format)
  305. {
  306. return format->codec->sample_rate ?: 8000;
  307. }
  308. unsigned int ast_format_determine_length(const struct ast_format *format, unsigned int samples)
  309. {
  310. return ast_codec_determine_length(format->codec, samples);
  311. }