format.c 10.0 KB

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