frame.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 1999 - 2005, Digium, Inc.
  5. *
  6. * Mark Spencer <markster@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 Frame and codec manipulation routines
  21. *
  22. * \author Mark Spencer <markster@digium.com>
  23. */
  24. /*** MODULEINFO
  25. <support_level>core</support_level>
  26. ***/
  27. #include "asterisk.h"
  28. #include "asterisk/_private.h"
  29. #include "asterisk/lock.h"
  30. #include "asterisk/frame.h"
  31. #include "asterisk/format_cache.h"
  32. #include "asterisk/channel.h"
  33. #include "asterisk/cli.h"
  34. #include "asterisk/term.h"
  35. #include "asterisk/utils.h"
  36. #include "asterisk/threadstorage.h"
  37. #include "asterisk/linkedlists.h"
  38. #include "asterisk/translate.h"
  39. #include "asterisk/dsp.h"
  40. #include "asterisk/file.h"
  41. #include <math.h>
  42. #if (defined(LOW_MEMORY) || defined(MALLOC_DEBUG)) && !defined(NO_FRAME_CACHE)
  43. #define NO_FRAME_CACHE
  44. #endif
  45. #if !defined(NO_FRAME_CACHE)
  46. static void frame_cache_cleanup(void *data);
  47. /*! \brief A per-thread cache of frame headers */
  48. AST_THREADSTORAGE_CUSTOM(frame_cache, NULL, frame_cache_cleanup);
  49. /*!
  50. * \brief Maximum ast_frame cache size
  51. *
  52. * In most cases where the frame header cache will be useful, the size
  53. * of the cache will stay very small. However, it is not always the case that
  54. * the same thread that allocates the frame will be the one freeing them, so
  55. * sometimes a thread will never have any frames in its cache, or the cache
  56. * will never be pulled from. For the latter case, we limit the maximum size.
  57. */
  58. #define FRAME_CACHE_MAX_SIZE 10
  59. /*! \brief This is just so ast_frames, a list head struct for holding a list of
  60. * ast_frame structures, is defined. */
  61. AST_LIST_HEAD_NOLOCK(ast_frames, ast_frame);
  62. struct ast_frame_cache {
  63. struct ast_frames list;
  64. size_t size;
  65. };
  66. #endif
  67. struct ast_frame ast_null_frame = { AST_FRAME_NULL, };
  68. static struct ast_frame *ast_frame_header_new(const char *file, int line, const char *func)
  69. {
  70. struct ast_frame *f;
  71. #if !defined(NO_FRAME_CACHE)
  72. struct ast_frame_cache *frames;
  73. if ((frames = ast_threadstorage_get(&frame_cache, sizeof(*frames)))) {
  74. if ((f = AST_LIST_REMOVE_HEAD(&frames->list, frame_list))) {
  75. size_t mallocd_len = f->mallocd_hdr_len;
  76. memset(f, 0, sizeof(*f));
  77. f->mallocd_hdr_len = mallocd_len;
  78. frames->size--;
  79. return f;
  80. }
  81. }
  82. #endif
  83. if (!(f = __ast_calloc(1, sizeof(*f), file, line, func))) {
  84. return NULL;
  85. }
  86. f->mallocd_hdr_len = sizeof(*f);
  87. return f;
  88. }
  89. #if !defined(NO_FRAME_CACHE)
  90. static void frame_cache_cleanup(void *data)
  91. {
  92. struct ast_frame_cache *frames = data;
  93. struct ast_frame *f;
  94. while ((f = AST_LIST_REMOVE_HEAD(&frames->list, frame_list)))
  95. ast_free(f);
  96. ast_free(frames);
  97. }
  98. #endif
  99. static void __frame_free(struct ast_frame *fr, int cache)
  100. {
  101. if (!fr->mallocd)
  102. return;
  103. #if !defined(NO_FRAME_CACHE)
  104. if (fr->mallocd == AST_MALLOCD_HDR
  105. && cache
  106. && ast_opt_cache_media_frames) {
  107. /* Cool, only the header is malloc'd, let's just cache those for now
  108. * to keep things simple... */
  109. struct ast_frame_cache *frames;
  110. frames = ast_threadstorage_get(&frame_cache, sizeof(*frames));
  111. if (frames && frames->size < FRAME_CACHE_MAX_SIZE) {
  112. if (fr->frametype == AST_FRAME_VOICE
  113. || fr->frametype == AST_FRAME_VIDEO
  114. || fr->frametype == AST_FRAME_IMAGE) {
  115. ao2_cleanup(fr->subclass.format);
  116. } else if (fr->frametype == AST_FRAME_CONTROL && fr->subclass.integer == AST_CONTROL_ANSWER) {
  117. ao2_cleanup(fr->subclass.topology);
  118. }
  119. AST_LIST_INSERT_HEAD(&frames->list, fr, frame_list);
  120. frames->size++;
  121. return;
  122. }
  123. }
  124. #endif
  125. if (fr->mallocd & AST_MALLOCD_DATA) {
  126. if (fr->data.ptr) {
  127. ast_free(fr->data.ptr - fr->offset);
  128. }
  129. }
  130. if (fr->mallocd & AST_MALLOCD_SRC) {
  131. ast_free((void *) fr->src);
  132. }
  133. if (fr->mallocd & AST_MALLOCD_HDR) {
  134. if (fr->frametype == AST_FRAME_VOICE
  135. || fr->frametype == AST_FRAME_VIDEO
  136. || fr->frametype == AST_FRAME_IMAGE) {
  137. ao2_cleanup(fr->subclass.format);
  138. } else if (fr->frametype == AST_FRAME_CONTROL && fr->subclass.integer == AST_CONTROL_ANSWER) {
  139. ao2_cleanup(fr->subclass.topology);
  140. }
  141. ast_free(fr);
  142. } else {
  143. fr->mallocd = 0;
  144. }
  145. }
  146. void ast_frame_free(struct ast_frame *frame, int cache)
  147. {
  148. struct ast_frame *next;
  149. while (frame) {
  150. next = AST_LIST_NEXT(frame, frame_list);
  151. __frame_free(frame, cache);
  152. frame = next;
  153. }
  154. }
  155. void ast_frame_dtor(struct ast_frame *f)
  156. {
  157. ast_frfree(f);
  158. }
  159. /*!
  160. * \brief 'isolates' a frame by duplicating non-malloc'ed components
  161. * (header, src, data).
  162. * On return all components are malloc'ed
  163. */
  164. struct ast_frame *__ast_frisolate(struct ast_frame *fr, const char *file, int line, const char *func)
  165. {
  166. struct ast_frame *out;
  167. void *newdata;
  168. /* if none of the existing frame is malloc'd, let ast_frdup() do it
  169. since it is more efficient
  170. */
  171. if (fr->mallocd == 0) {
  172. return __ast_frdup(fr, file, line, func);
  173. }
  174. /* if everything is already malloc'd, we are done */
  175. if ((fr->mallocd & (AST_MALLOCD_HDR | AST_MALLOCD_SRC | AST_MALLOCD_DATA)) ==
  176. (AST_MALLOCD_HDR | AST_MALLOCD_SRC | AST_MALLOCD_DATA)) {
  177. return fr;
  178. }
  179. if (!(fr->mallocd & AST_MALLOCD_HDR)) {
  180. /* Allocate a new header if needed */
  181. if (!(out = ast_frame_header_new(file, line, func))) {
  182. return NULL;
  183. }
  184. out->frametype = fr->frametype;
  185. out->subclass = fr->subclass;
  186. if ((fr->frametype == AST_FRAME_VOICE) || (fr->frametype == AST_FRAME_VIDEO) ||
  187. (fr->frametype == AST_FRAME_IMAGE)) {
  188. ao2_bump(out->subclass.format);
  189. } else if (fr->frametype == AST_FRAME_VOICE && fr->subclass.integer == AST_CONTROL_ANSWER) {
  190. ao2_bump(out->subclass.topology);
  191. }
  192. out->datalen = fr->datalen;
  193. out->samples = fr->samples;
  194. out->mallocd = AST_MALLOCD_HDR;
  195. out->offset = fr->offset;
  196. /* Copy the timing data */
  197. ast_copy_flags(out, fr, AST_FLAGS_ALL);
  198. if (ast_test_flag(fr, AST_FRFLAG_HAS_TIMING_INFO)) {
  199. out->ts = fr->ts;
  200. out->len = fr->len;
  201. out->seqno = fr->seqno;
  202. }
  203. out->stream_num = fr->stream_num;
  204. } else {
  205. out = fr;
  206. }
  207. if (fr->src) {
  208. /* The original frame has a source string */
  209. if (!(fr->mallocd & AST_MALLOCD_SRC)) {
  210. /*
  211. * The original frame has a non-malloced source string.
  212. *
  213. * Duplicate the string and put it into the isolated frame
  214. * which may also be the original frame.
  215. */
  216. newdata = ast_strdup(fr->src);
  217. if (!newdata) {
  218. if (out != fr) {
  219. ast_frame_free(out, 0);
  220. }
  221. return NULL;
  222. }
  223. out->src = newdata;
  224. out->mallocd |= AST_MALLOCD_SRC;
  225. } else if (out != fr) {
  226. /* Steal the source string from the original frame. */
  227. out->src = fr->src;
  228. fr->src = NULL;
  229. fr->mallocd &= ~AST_MALLOCD_SRC;
  230. out->mallocd |= AST_MALLOCD_SRC;
  231. }
  232. }
  233. if (!(fr->mallocd & AST_MALLOCD_DATA)) {
  234. /* The original frame has a non-malloced data buffer. */
  235. if (!fr->datalen && fr->frametype != AST_FRAME_TEXT) {
  236. /* Actually it's just an int so we can simply copy it. */
  237. out->data.uint32 = fr->data.uint32;
  238. return out;
  239. }
  240. /*
  241. * Duplicate the data buffer and put it into the isolated frame
  242. * which may also be the original frame.
  243. */
  244. newdata = ast_malloc(fr->datalen + AST_FRIENDLY_OFFSET);
  245. if (!newdata) {
  246. if (out != fr) {
  247. ast_frame_free(out, 0);
  248. }
  249. return NULL;
  250. }
  251. newdata += AST_FRIENDLY_OFFSET;
  252. out->offset = AST_FRIENDLY_OFFSET;
  253. memcpy(newdata, fr->data.ptr, fr->datalen);
  254. out->data.ptr = newdata;
  255. out->mallocd |= AST_MALLOCD_DATA;
  256. } else if (out != fr) {
  257. /* Steal the data buffer from the original frame. */
  258. out->data = fr->data;
  259. memset(&fr->data, 0, sizeof(fr->data));
  260. fr->mallocd &= ~AST_MALLOCD_DATA;
  261. out->mallocd |= AST_MALLOCD_DATA;
  262. }
  263. return out;
  264. }
  265. struct ast_frame *__ast_frdup(const struct ast_frame *f, const char *file, int line, const char *func)
  266. {
  267. struct ast_frame *out = NULL;
  268. int len, srclen = 0;
  269. void *buf = NULL;
  270. #if !defined(NO_FRAME_CACHE)
  271. struct ast_frame_cache *frames;
  272. #endif
  273. /* Start with standard stuff */
  274. len = sizeof(*out) + AST_FRIENDLY_OFFSET + f->datalen;
  275. /* If we have a source, add space for it */
  276. /*
  277. * XXX Watch out here - if we receive a src which is not terminated
  278. * properly, we can be easily attacked. Should limit the size we deal with.
  279. */
  280. if (f->src)
  281. srclen = strlen(f->src);
  282. if (srclen > 0)
  283. len += srclen + 1;
  284. #if !defined(NO_FRAME_CACHE)
  285. if ((frames = ast_threadstorage_get(&frame_cache, sizeof(*frames)))) {
  286. AST_LIST_TRAVERSE_SAFE_BEGIN(&frames->list, out, frame_list) {
  287. if (out->mallocd_hdr_len >= len) {
  288. size_t mallocd_len = out->mallocd_hdr_len;
  289. AST_LIST_REMOVE_CURRENT(frame_list);
  290. memset(out, 0, sizeof(*out));
  291. out->mallocd_hdr_len = mallocd_len;
  292. buf = out;
  293. frames->size--;
  294. break;
  295. }
  296. }
  297. AST_LIST_TRAVERSE_SAFE_END;
  298. }
  299. #endif
  300. if (!buf) {
  301. if (!(buf = __ast_calloc(1, len, file, line, func)))
  302. return NULL;
  303. out = buf;
  304. out->mallocd_hdr_len = len;
  305. }
  306. out->frametype = f->frametype;
  307. out->subclass = f->subclass;
  308. if ((f->frametype == AST_FRAME_VOICE) || (f->frametype == AST_FRAME_VIDEO) ||
  309. (f->frametype == AST_FRAME_IMAGE)) {
  310. ao2_bump(out->subclass.format);
  311. } else if (f->frametype == AST_FRAME_CONTROL && f->subclass.integer == AST_CONTROL_ANSWER) {
  312. ao2_bump(out->subclass.topology);
  313. }
  314. out->datalen = f->datalen;
  315. out->samples = f->samples;
  316. out->delivery = f->delivery;
  317. /* Even though this new frame was allocated from the heap, we can't mark it
  318. * with AST_MALLOCD_HDR, AST_MALLOCD_DATA and AST_MALLOCD_SRC, because that
  319. * would cause ast_frfree() to attempt to individually free each of those
  320. * under the assumption that they were separately allocated. Since this frame
  321. * was allocated in a single allocation, we'll only mark it as if the header
  322. * was heap-allocated; this will result in the entire frame being properly freed.
  323. */
  324. out->mallocd = AST_MALLOCD_HDR;
  325. out->offset = AST_FRIENDLY_OFFSET;
  326. /* Make sure that empty text frames have a valid data.ptr */
  327. if (out->datalen || f->frametype == AST_FRAME_TEXT) {
  328. out->data.ptr = buf + sizeof(*out) + AST_FRIENDLY_OFFSET;
  329. memcpy(out->data.ptr, f->data.ptr, out->datalen);
  330. } else {
  331. out->data.uint32 = f->data.uint32;
  332. }
  333. if (srclen > 0) {
  334. /* This may seem a little strange, but it's to avoid a gcc (4.2.4) compiler warning */
  335. char *src;
  336. out->src = buf + sizeof(*out) + AST_FRIENDLY_OFFSET + f->datalen;
  337. src = (char *) out->src;
  338. /* Must have space since we allocated for it */
  339. strcpy(src, f->src);
  340. }
  341. ast_copy_flags(out, f, AST_FLAGS_ALL);
  342. out->ts = f->ts;
  343. out->len = f->len;
  344. out->seqno = f->seqno;
  345. out->stream_num = f->stream_num;
  346. return out;
  347. }
  348. void ast_swapcopy_samples(void *dst, const void *src, int samples)
  349. {
  350. int i;
  351. unsigned short *dst_s = dst;
  352. const unsigned short *src_s = src;
  353. for (i = 0; i < samples; i++)
  354. dst_s[i] = (src_s[i]<<8) | (src_s[i]>>8);
  355. }
  356. char *ast_frame_subclass2str(struct ast_frame *f, char *subclass, size_t slen, char *moreinfo, size_t mlen)
  357. {
  358. switch(f->frametype) {
  359. case AST_FRAME_DTMF_BEGIN:
  360. if (slen > 1) {
  361. subclass[0] = f->subclass.integer;
  362. subclass[1] = '\0';
  363. }
  364. break;
  365. case AST_FRAME_DTMF_END:
  366. if (slen > 1) {
  367. subclass[0] = f->subclass.integer;
  368. subclass[1] = '\0';
  369. }
  370. break;
  371. case AST_FRAME_CONTROL:
  372. switch (f->subclass.integer) {
  373. case AST_CONTROL_HANGUP:
  374. ast_copy_string(subclass, "Hangup", slen);
  375. break;
  376. case AST_CONTROL_RING:
  377. ast_copy_string(subclass, "Ring", slen);
  378. break;
  379. case AST_CONTROL_RINGING:
  380. ast_copy_string(subclass, "Ringing", slen);
  381. break;
  382. case AST_CONTROL_ANSWER:
  383. ast_copy_string(subclass, "Answer", slen);
  384. break;
  385. case AST_CONTROL_BUSY:
  386. ast_copy_string(subclass, "Busy", slen);
  387. break;
  388. case AST_CONTROL_TAKEOFFHOOK:
  389. ast_copy_string(subclass, "Take Off Hook", slen);
  390. break;
  391. case AST_CONTROL_OFFHOOK:
  392. ast_copy_string(subclass, "Line Off Hook", slen);
  393. break;
  394. case AST_CONTROL_CONGESTION:
  395. ast_copy_string(subclass, "Congestion", slen);
  396. break;
  397. case AST_CONTROL_FLASH:
  398. ast_copy_string(subclass, "Flash", slen);
  399. break;
  400. case AST_CONTROL_WINK:
  401. ast_copy_string(subclass, "Wink", slen);
  402. break;
  403. case AST_CONTROL_OPTION:
  404. ast_copy_string(subclass, "Option", slen);
  405. break;
  406. case AST_CONTROL_RADIO_KEY:
  407. ast_copy_string(subclass, "Key Radio", slen);
  408. break;
  409. case AST_CONTROL_RADIO_UNKEY:
  410. ast_copy_string(subclass, "Unkey Radio", slen);
  411. break;
  412. case AST_CONTROL_PROGRESS:
  413. ast_copy_string(subclass, "Progress", slen);
  414. break;
  415. case AST_CONTROL_PROCEEDING:
  416. ast_copy_string(subclass, "Proceeding", slen);
  417. break;
  418. case AST_CONTROL_HOLD:
  419. ast_copy_string(subclass, "Hold", slen);
  420. break;
  421. case AST_CONTROL_UNHOLD:
  422. ast_copy_string(subclass, "Unhold", slen);
  423. break;
  424. case AST_CONTROL_VIDUPDATE:
  425. ast_copy_string(subclass, "Video Update", slen);
  426. break;
  427. case AST_CONTROL_T38_PARAMETERS: {
  428. char *message = "Unknown";
  429. if (f->datalen != sizeof(struct ast_control_t38_parameters)) {
  430. message = "Invalid";
  431. } else {
  432. struct ast_control_t38_parameters *parameters = f->data.ptr;
  433. enum ast_control_t38 state = parameters->request_response;
  434. if (state == AST_T38_REQUEST_NEGOTIATE)
  435. message = "Negotiation Requested";
  436. else if (state == AST_T38_REQUEST_TERMINATE)
  437. message = "Negotiation Request Terminated";
  438. else if (state == AST_T38_NEGOTIATED)
  439. message = "Negotiated";
  440. else if (state == AST_T38_TERMINATED)
  441. message = "Terminated";
  442. else if (state == AST_T38_REFUSED)
  443. message = "Refused";
  444. }
  445. snprintf(subclass, slen, "T38_Parameters/%s", message);
  446. break;
  447. }
  448. case AST_CONTROL_STREAM_STOP:
  449. ast_copy_string(subclass, "Stop stream", slen);
  450. break;
  451. case AST_CONTROL_STREAM_SUSPEND:
  452. ast_copy_string(subclass, "Suspend stream", slen);
  453. break;
  454. case AST_CONTROL_STREAM_RESTART:
  455. ast_copy_string(subclass, "Restart stream", slen);
  456. break;
  457. case AST_CONTROL_STREAM_REVERSE:
  458. ast_copy_string(subclass, "Reverse stream", slen);
  459. break;
  460. case AST_CONTROL_STREAM_FORWARD:
  461. ast_copy_string(subclass, "Forward stream", slen);
  462. break;
  463. case AST_CONTROL_RECORD_CANCEL:
  464. ast_copy_string(subclass, "Cancel stream", slen);
  465. break;
  466. case AST_CONTROL_RECORD_STOP:
  467. ast_copy_string(subclass, "Record stop", slen);
  468. break;
  469. case AST_CONTROL_RECORD_SUSPEND:
  470. ast_copy_string(subclass, "Record suspend", slen);
  471. break;
  472. case AST_CONTROL_RECORD_MUTE:
  473. ast_copy_string(subclass, "Record mute", slen);
  474. break;
  475. case AST_CONTROL_SRCUPDATE:
  476. ast_copy_string(subclass, "Media source update", slen);
  477. break;
  478. case AST_CONTROL_TRANSFER:
  479. ast_copy_string(subclass, "Transfer", slen);
  480. break;
  481. case AST_CONTROL_CONNECTED_LINE:
  482. ast_copy_string(subclass, "Connected line update", slen);
  483. break;
  484. case AST_CONTROL_REDIRECTING:
  485. ast_copy_string(subclass, "Redirect", slen);
  486. break;
  487. case AST_CONTROL_CC:
  488. ast_copy_string(subclass, "CC", slen);
  489. break;
  490. case AST_CONTROL_SRCCHANGE:
  491. ast_copy_string(subclass, "Media SSRC change", slen);
  492. break;
  493. case AST_CONTROL_READ_ACTION:
  494. ast_copy_string(subclass, "Read action", slen);
  495. break;
  496. case AST_CONTROL_AOC:
  497. ast_copy_string(subclass, "AOC", slen);
  498. break;
  499. case AST_CONTROL_END_OF_Q:
  500. ast_copy_string(subclass, "Endof Q", slen);
  501. break;
  502. case AST_CONTROL_INCOMPLETE:
  503. ast_copy_string(subclass, "Incomplete", slen);
  504. break;
  505. case AST_CONTROL_MCID:
  506. ast_copy_string(subclass, "MCID", slen);
  507. break;
  508. case AST_CONTROL_UPDATE_RTP_PEER:
  509. ast_copy_string(subclass, "Update RTP peer", slen);
  510. break;
  511. case AST_CONTROL_PVT_CAUSE_CODE:
  512. ast_copy_string(subclass, "Private Cause Code", slen);
  513. break;
  514. case AST_CONTROL_MASQUERADE_NOTIFY:
  515. ast_copy_string(subclass, "Masquerade notify", slen);
  516. break;
  517. case AST_CONTROL_STREAM_TOPOLOGY_REQUEST_CHANGE:
  518. ast_copy_string(subclass, "Stream topology request change", slen);
  519. break;
  520. case AST_CONTROL_STREAM_TOPOLOGY_CHANGED:
  521. ast_copy_string(subclass, "Stream topology changed", slen);
  522. break;
  523. case AST_CONTROL_STREAM_TOPOLOGY_SOURCE_CHANGED:
  524. ast_copy_string(subclass, "Stream topology source changed", slen);
  525. break;
  526. case -1:
  527. ast_copy_string(subclass, "Stop generators", slen);
  528. break;
  529. default:
  530. snprintf(subclass, slen, "Unknown control '%d'", f->subclass.integer);
  531. }
  532. break;
  533. case AST_FRAME_NULL:
  534. ast_copy_string(subclass, "N/A", slen);
  535. break;
  536. case AST_FRAME_IAX:
  537. /* Should never happen */
  538. snprintf(subclass, slen, "IAX Frametype %d", f->subclass.integer);
  539. break;
  540. case AST_FRAME_BRIDGE_ACTION:
  541. /* Should never happen */
  542. snprintf(subclass, slen, "Bridge Frametype %d", f->subclass.integer);
  543. break;
  544. case AST_FRAME_BRIDGE_ACTION_SYNC:
  545. /* Should never happen */
  546. snprintf(subclass, slen, "Synchronous Bridge Frametype %d", f->subclass.integer);
  547. break;
  548. case AST_FRAME_TEXT:
  549. ast_copy_string(subclass, "N/A", slen);
  550. if (moreinfo) {
  551. ast_copy_string(moreinfo, f->data.ptr, mlen);
  552. }
  553. break;
  554. case AST_FRAME_IMAGE:
  555. snprintf(subclass, slen, "Image format %s\n", ast_format_get_name(f->subclass.format));
  556. break;
  557. case AST_FRAME_HTML:
  558. switch (f->subclass.integer) {
  559. case AST_HTML_URL:
  560. ast_copy_string(subclass, "URL", slen);
  561. if (moreinfo) {
  562. ast_copy_string(moreinfo, f->data.ptr, mlen);
  563. }
  564. break;
  565. case AST_HTML_DATA:
  566. ast_copy_string(subclass, "Data", slen);
  567. break;
  568. case AST_HTML_BEGIN:
  569. ast_copy_string(subclass, "Begin", slen);
  570. break;
  571. case AST_HTML_END:
  572. ast_copy_string(subclass, "End", slen);
  573. break;
  574. case AST_HTML_LDCOMPLETE:
  575. ast_copy_string(subclass, "Load Complete", slen);
  576. break;
  577. case AST_HTML_NOSUPPORT:
  578. ast_copy_string(subclass, "No Support", slen);
  579. break;
  580. case AST_HTML_LINKURL:
  581. ast_copy_string(subclass, "Link URL", slen);
  582. if (moreinfo) {
  583. ast_copy_string(moreinfo, f->data.ptr, mlen);
  584. }
  585. break;
  586. case AST_HTML_UNLINK:
  587. ast_copy_string(subclass, "Unlink", slen);
  588. break;
  589. case AST_HTML_LINKREJECT:
  590. ast_copy_string(subclass, "Link Reject", slen);
  591. break;
  592. default:
  593. snprintf(subclass, slen, "Unknown HTML frame '%d'\n", f->subclass.integer);
  594. break;
  595. }
  596. break;
  597. case AST_FRAME_MODEM:
  598. switch (f->subclass.integer) {
  599. case AST_MODEM_T38:
  600. ast_copy_string(subclass, "T.38", slen);
  601. break;
  602. case AST_MODEM_V150:
  603. ast_copy_string(subclass, "V.150", slen);
  604. break;
  605. default:
  606. snprintf(subclass, slen, "Unknown MODEM frame '%d'\n", f->subclass.integer);
  607. break;
  608. }
  609. break;
  610. case AST_FRAME_RTCP:
  611. ast_copy_string(subclass, "RTCP", slen);
  612. default:
  613. ast_copy_string(subclass, "Unknown Subclass", slen);
  614. break;
  615. }
  616. return subclass;
  617. }
  618. char *ast_frame_type2str(enum ast_frame_type frame_type, char *ftype, size_t len)
  619. {
  620. switch (frame_type) {
  621. case AST_FRAME_DTMF_BEGIN:
  622. ast_copy_string(ftype, "DTMF Begin", len);
  623. break;
  624. case AST_FRAME_DTMF_END:
  625. ast_copy_string(ftype, "DTMF End", len);
  626. break;
  627. case AST_FRAME_CONTROL:
  628. ast_copy_string(ftype, "Control", len);
  629. break;
  630. case AST_FRAME_NULL:
  631. ast_copy_string(ftype, "Null Frame", len);
  632. break;
  633. case AST_FRAME_IAX:
  634. /* Should never happen */
  635. ast_copy_string(ftype, "IAX Specific", len);
  636. break;
  637. case AST_FRAME_BRIDGE_ACTION:
  638. /* Should never happen */
  639. ast_copy_string(ftype, "Bridge Specific", len);
  640. break;
  641. case AST_FRAME_BRIDGE_ACTION_SYNC:
  642. /* Should never happen */
  643. ast_copy_string(ftype, "Bridge Specific", len);
  644. break;
  645. case AST_FRAME_TEXT:
  646. ast_copy_string(ftype, "Text", len);
  647. break;
  648. case AST_FRAME_TEXT_DATA:
  649. ast_copy_string(ftype, "Text Data", len);
  650. break;
  651. case AST_FRAME_IMAGE:
  652. ast_copy_string(ftype, "Image", len);
  653. break;
  654. case AST_FRAME_HTML:
  655. ast_copy_string(ftype, "HTML", len);
  656. break;
  657. case AST_FRAME_MODEM:
  658. ast_copy_string(ftype, "Modem", len);
  659. break;
  660. case AST_FRAME_VOICE:
  661. ast_copy_string(ftype, "Voice", len);
  662. break;
  663. case AST_FRAME_VIDEO:
  664. ast_copy_string(ftype, "Video", len);
  665. break;
  666. case AST_FRAME_RTCP:
  667. ast_copy_string(ftype, "RTCP", len);
  668. break;
  669. default:
  670. snprintf(ftype, len, "Unknown Frametype '%u'", frame_type);
  671. break;
  672. }
  673. return ftype;
  674. }
  675. /*! Dump a frame for debugging purposes */
  676. void ast_frame_dump(const char *name, struct ast_frame *f, char *prefix)
  677. {
  678. const char noname[] = "unknown";
  679. char ftype[40] = "Unknown Frametype";
  680. char cft[80];
  681. char subclass[40] = "Unknown Subclass";
  682. char csub[80];
  683. char moreinfo[40] = "";
  684. char cn[60];
  685. char cp[40];
  686. char cmn[40];
  687. if (!name) {
  688. name = noname;
  689. }
  690. if (!f) {
  691. ast_verb(-1, "%s [ %s (NULL) ] [%s]\n",
  692. term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
  693. term_color(cft, "HANGUP", COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
  694. term_color(cn, name, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
  695. return;
  696. }
  697. /* XXX We should probably print one each of voice and video when the format changes XXX */
  698. if (f->frametype == AST_FRAME_VOICE) {
  699. return;
  700. }
  701. if (f->frametype == AST_FRAME_VIDEO) {
  702. return;
  703. }
  704. if (f->frametype == AST_FRAME_RTCP) {
  705. return;
  706. }
  707. ast_frame_type2str(f->frametype, ftype, sizeof(ftype));
  708. ast_frame_subclass2str(f, subclass, sizeof(subclass), moreinfo, sizeof(moreinfo));
  709. if (!ast_strlen_zero(moreinfo))
  710. ast_verb(-1, "%s [ TYPE: %s (%u) SUBCLASS: %s (%d) '%s' ] [%s]\n",
  711. term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
  712. term_color(cft, ftype, COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
  713. f->frametype,
  714. term_color(csub, subclass, COLOR_BRCYAN, COLOR_BLACK, sizeof(csub)),
  715. f->subclass.integer,
  716. term_color(cmn, moreinfo, COLOR_BRGREEN, COLOR_BLACK, sizeof(cmn)),
  717. term_color(cn, name, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
  718. else
  719. ast_verb(-1, "%s [ TYPE: %s (%u) SUBCLASS: %s (%d) ] [%s]\n",
  720. term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
  721. term_color(cft, ftype, COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
  722. f->frametype,
  723. term_color(csub, subclass, COLOR_BRCYAN, COLOR_BLACK, sizeof(csub)),
  724. f->subclass.integer,
  725. term_color(cn, name, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
  726. }
  727. int ast_frame_adjust_volume(struct ast_frame *f, int adjustment)
  728. {
  729. int count;
  730. short *fdata = f->data.ptr;
  731. short adjust_value = abs(adjustment);
  732. if ((f->frametype != AST_FRAME_VOICE) || !(ast_format_cache_is_slinear(f->subclass.format))) {
  733. return -1;
  734. }
  735. if (!adjustment) {
  736. return 0;
  737. }
  738. for (count = 0; count < f->samples; count++) {
  739. if (adjustment > 0) {
  740. ast_slinear_saturated_multiply(&fdata[count], &adjust_value);
  741. } else if (adjustment < 0) {
  742. ast_slinear_saturated_divide(&fdata[count], &adjust_value);
  743. }
  744. }
  745. return 0;
  746. }
  747. int ast_frame_adjust_volume_float(struct ast_frame *f, float adjustment)
  748. {
  749. int count;
  750. short *fdata = f->data.ptr;
  751. float adjust_value = fabs(adjustment);
  752. if ((f->frametype != AST_FRAME_VOICE) || !(ast_format_cache_is_slinear(f->subclass.format))) {
  753. return -1;
  754. }
  755. if (!adjustment) {
  756. return 0;
  757. }
  758. for (count = 0; count < f->samples; count++) {
  759. if (adjustment > 0) {
  760. ast_slinear_saturated_multiply_float(&fdata[count], &adjust_value);
  761. } else if (adjustment < 0) {
  762. ast_slinear_saturated_divide_float(&fdata[count], &adjust_value);
  763. }
  764. }
  765. return 0;
  766. }
  767. int ast_frame_slinear_sum(struct ast_frame *f1, struct ast_frame *f2)
  768. {
  769. int count;
  770. short *data1, *data2;
  771. if ((f1->frametype != AST_FRAME_VOICE) || (ast_format_cmp(f1->subclass.format, ast_format_slin) != AST_FORMAT_CMP_NOT_EQUAL))
  772. return -1;
  773. if ((f2->frametype != AST_FRAME_VOICE) || (ast_format_cmp(f2->subclass.format, ast_format_slin) != AST_FORMAT_CMP_NOT_EQUAL))
  774. return -1;
  775. if (f1->samples != f2->samples)
  776. return -1;
  777. for (count = 0, data1 = f1->data.ptr, data2 = f2->data.ptr;
  778. count < f1->samples;
  779. count++, data1++, data2++)
  780. ast_slinear_saturated_add(data1, data2);
  781. return 0;
  782. }
  783. int ast_frame_clear(struct ast_frame *frame)
  784. {
  785. struct ast_frame *next;
  786. for (next = AST_LIST_NEXT(frame, frame_list);
  787. frame;
  788. frame = next, next = frame ? AST_LIST_NEXT(frame, frame_list) : NULL) {
  789. memset(frame->data.ptr, 0, frame->datalen);
  790. }
  791. return 0;
  792. }