frame.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708
  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. ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  29. #include "asterisk/_private.h"
  30. #include "asterisk/lock.h"
  31. #include "asterisk/frame.h"
  32. #include "asterisk/format_cache.h"
  33. #include "asterisk/channel.h"
  34. #include "asterisk/cli.h"
  35. #include "asterisk/term.h"
  36. #include "asterisk/utils.h"
  37. #include "asterisk/threadstorage.h"
  38. #include "asterisk/linkedlists.h"
  39. #include "asterisk/translate.h"
  40. #include "asterisk/dsp.h"
  41. #include "asterisk/file.h"
  42. #if !defined(LOW_MEMORY)
  43. static void frame_cache_cleanup(void *data);
  44. /*! \brief A per-thread cache of frame headers */
  45. AST_THREADSTORAGE_CUSTOM(frame_cache, NULL, frame_cache_cleanup);
  46. /*!
  47. * \brief Maximum ast_frame cache size
  48. *
  49. * In most cases where the frame header cache will be useful, the size
  50. * of the cache will stay very small. However, it is not always the case that
  51. * the same thread that allocates the frame will be the one freeing them, so
  52. * sometimes a thread will never have any frames in its cache, or the cache
  53. * will never be pulled from. For the latter case, we limit the maximum size.
  54. */
  55. #define FRAME_CACHE_MAX_SIZE 10
  56. /*! \brief This is just so ast_frames, a list head struct for holding a list of
  57. * ast_frame structures, is defined. */
  58. AST_LIST_HEAD_NOLOCK(ast_frames, ast_frame);
  59. struct ast_frame_cache {
  60. struct ast_frames list;
  61. size_t size;
  62. };
  63. #endif
  64. struct ast_frame ast_null_frame = { AST_FRAME_NULL, };
  65. static struct ast_frame *ast_frame_header_new(void)
  66. {
  67. struct ast_frame *f;
  68. #if !defined(LOW_MEMORY)
  69. struct ast_frame_cache *frames;
  70. if ((frames = ast_threadstorage_get(&frame_cache, sizeof(*frames)))) {
  71. if ((f = AST_LIST_REMOVE_HEAD(&frames->list, frame_list))) {
  72. size_t mallocd_len = f->mallocd_hdr_len;
  73. memset(f, 0, sizeof(*f));
  74. f->mallocd_hdr_len = mallocd_len;
  75. f->mallocd = AST_MALLOCD_HDR;
  76. frames->size--;
  77. return f;
  78. }
  79. }
  80. if (!(f = ast_calloc_cache(1, sizeof(*f))))
  81. return NULL;
  82. #else
  83. if (!(f = ast_calloc(1, sizeof(*f))))
  84. return NULL;
  85. #endif
  86. f->mallocd_hdr_len = sizeof(*f);
  87. return f;
  88. }
  89. #if !defined(LOW_MEMORY)
  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(LOW_MEMORY)
  104. if (cache && fr->mallocd == AST_MALLOCD_HDR) {
  105. /* Cool, only the header is malloc'd, let's just cache those for now
  106. * to keep things simple... */
  107. struct ast_frame_cache *frames;
  108. if ((frames = ast_threadstorage_get(&frame_cache, sizeof(*frames))) &&
  109. (frames->size < FRAME_CACHE_MAX_SIZE)) {
  110. if ((fr->frametype == AST_FRAME_VOICE) || (fr->frametype == AST_FRAME_VIDEO) ||
  111. (fr->frametype == AST_FRAME_IMAGE)) {
  112. ao2_cleanup(fr->subclass.format);
  113. }
  114. AST_LIST_INSERT_HEAD(&frames->list, fr, frame_list);
  115. frames->size++;
  116. return;
  117. }
  118. }
  119. #endif
  120. if (fr->mallocd & AST_MALLOCD_DATA) {
  121. if (fr->data.ptr)
  122. ast_free(fr->data.ptr - fr->offset);
  123. }
  124. if (fr->mallocd & AST_MALLOCD_SRC) {
  125. if (fr->src)
  126. ast_free((void *) fr->src);
  127. }
  128. if (fr->mallocd & AST_MALLOCD_HDR) {
  129. if ((fr->frametype == AST_FRAME_VOICE) || (fr->frametype == AST_FRAME_VIDEO) ||
  130. (fr->frametype == AST_FRAME_IMAGE)) {
  131. ao2_cleanup(fr->subclass.format);
  132. }
  133. ast_free(fr);
  134. } else {
  135. fr->mallocd = 0;
  136. }
  137. }
  138. void ast_frame_free(struct ast_frame *frame, int cache)
  139. {
  140. struct ast_frame *next;
  141. for (next = AST_LIST_NEXT(frame, frame_list);
  142. frame;
  143. frame = next, next = frame ? AST_LIST_NEXT(frame, frame_list) : NULL) {
  144. __frame_free(frame, cache);
  145. }
  146. }
  147. void ast_frame_dtor(struct ast_frame *f)
  148. {
  149. if (f) {
  150. ast_frfree(f);
  151. }
  152. }
  153. /*!
  154. * \brief 'isolates' a frame by duplicating non-malloc'ed components
  155. * (header, src, data).
  156. * On return all components are malloc'ed
  157. */
  158. struct ast_frame *ast_frisolate(struct ast_frame *fr)
  159. {
  160. struct ast_frame *out;
  161. void *newdata;
  162. /* if none of the existing frame is malloc'd, let ast_frdup() do it
  163. since it is more efficient
  164. */
  165. if (fr->mallocd == 0) {
  166. return ast_frdup(fr);
  167. }
  168. /* if everything is already malloc'd, we are done */
  169. if ((fr->mallocd & (AST_MALLOCD_HDR | AST_MALLOCD_SRC | AST_MALLOCD_DATA)) ==
  170. (AST_MALLOCD_HDR | AST_MALLOCD_SRC | AST_MALLOCD_DATA)) {
  171. return fr;
  172. }
  173. if (!(fr->mallocd & AST_MALLOCD_HDR)) {
  174. /* Allocate a new header if needed */
  175. if (!(out = ast_frame_header_new())) {
  176. return NULL;
  177. }
  178. out->frametype = fr->frametype;
  179. if ((fr->frametype == AST_FRAME_VOICE) || (fr->frametype == AST_FRAME_VIDEO) ||
  180. (fr->frametype == AST_FRAME_IMAGE)) {
  181. out->subclass.format = ao2_bump(fr->subclass.format);
  182. } else {
  183. memcpy(&out->subclass, &fr->subclass, sizeof(out->subclass));
  184. }
  185. out->datalen = fr->datalen;
  186. out->samples = fr->samples;
  187. out->offset = fr->offset;
  188. /* Copy the timing data */
  189. ast_copy_flags(out, fr, AST_FLAGS_ALL);
  190. if (ast_test_flag(fr, AST_FRFLAG_HAS_TIMING_INFO)) {
  191. out->ts = fr->ts;
  192. out->len = fr->len;
  193. out->seqno = fr->seqno;
  194. }
  195. } else {
  196. out = fr;
  197. }
  198. if (!(fr->mallocd & AST_MALLOCD_SRC) && fr->src) {
  199. if (!(out->src = ast_strdup(fr->src))) {
  200. if (out != fr) {
  201. ast_free(out);
  202. }
  203. return NULL;
  204. }
  205. } else {
  206. out->src = fr->src;
  207. fr->src = NULL;
  208. fr->mallocd &= ~AST_MALLOCD_SRC;
  209. }
  210. if (!(fr->mallocd & AST_MALLOCD_DATA)) {
  211. if (!fr->datalen) {
  212. out->data.uint32 = fr->data.uint32;
  213. out->mallocd = AST_MALLOCD_HDR | AST_MALLOCD_SRC;
  214. return out;
  215. }
  216. if (!(newdata = ast_malloc(fr->datalen + AST_FRIENDLY_OFFSET))) {
  217. if (out->src != fr->src) {
  218. ast_free((void *) out->src);
  219. }
  220. if (out != fr) {
  221. ast_free(out);
  222. }
  223. return NULL;
  224. }
  225. newdata += AST_FRIENDLY_OFFSET;
  226. out->offset = AST_FRIENDLY_OFFSET;
  227. out->datalen = fr->datalen;
  228. memcpy(newdata, fr->data.ptr, fr->datalen);
  229. out->data.ptr = newdata;
  230. } else {
  231. out->data = fr->data;
  232. memset(&fr->data, 0, sizeof(fr->data));
  233. fr->mallocd &= ~AST_MALLOCD_DATA;
  234. }
  235. out->mallocd = AST_MALLOCD_HDR | AST_MALLOCD_SRC | AST_MALLOCD_DATA;
  236. return out;
  237. }
  238. struct ast_frame *ast_frdup(const struct ast_frame *f)
  239. {
  240. struct ast_frame *out = NULL;
  241. int len, srclen = 0;
  242. void *buf = NULL;
  243. #if !defined(LOW_MEMORY)
  244. struct ast_frame_cache *frames;
  245. #endif
  246. /* Start with standard stuff */
  247. len = sizeof(*out) + AST_FRIENDLY_OFFSET + f->datalen;
  248. /* If we have a source, add space for it */
  249. /*
  250. * XXX Watch out here - if we receive a src which is not terminated
  251. * properly, we can be easily attacked. Should limit the size we deal with.
  252. */
  253. if (f->src)
  254. srclen = strlen(f->src);
  255. if (srclen > 0)
  256. len += srclen + 1;
  257. #if !defined(LOW_MEMORY)
  258. if ((frames = ast_threadstorage_get(&frame_cache, sizeof(*frames)))) {
  259. AST_LIST_TRAVERSE_SAFE_BEGIN(&frames->list, out, frame_list) {
  260. if (out->mallocd_hdr_len >= len) {
  261. size_t mallocd_len = out->mallocd_hdr_len;
  262. AST_LIST_REMOVE_CURRENT(frame_list);
  263. memset(out, 0, sizeof(*out));
  264. out->mallocd_hdr_len = mallocd_len;
  265. buf = out;
  266. frames->size--;
  267. break;
  268. }
  269. }
  270. AST_LIST_TRAVERSE_SAFE_END;
  271. }
  272. #endif
  273. if (!buf) {
  274. if (!(buf = ast_calloc_cache(1, len)))
  275. return NULL;
  276. out = buf;
  277. out->mallocd_hdr_len = len;
  278. }
  279. out->frametype = f->frametype;
  280. if ((f->frametype == AST_FRAME_VOICE) || (f->frametype == AST_FRAME_VIDEO) ||
  281. (f->frametype == AST_FRAME_IMAGE)) {
  282. out->subclass.format = ao2_bump(f->subclass.format);
  283. } else {
  284. memcpy(&out->subclass, &f->subclass, sizeof(out->subclass));
  285. }
  286. out->datalen = f->datalen;
  287. out->samples = f->samples;
  288. out->delivery = f->delivery;
  289. /* Even though this new frame was allocated from the heap, we can't mark it
  290. * with AST_MALLOCD_HDR, AST_MALLOCD_DATA and AST_MALLOCD_SRC, because that
  291. * would cause ast_frfree() to attempt to individually free each of those
  292. * under the assumption that they were separately allocated. Since this frame
  293. * was allocated in a single allocation, we'll only mark it as if the header
  294. * was heap-allocated; this will result in the entire frame being properly freed.
  295. */
  296. out->mallocd = AST_MALLOCD_HDR;
  297. out->offset = AST_FRIENDLY_OFFSET;
  298. if (out->datalen) {
  299. out->data.ptr = buf + sizeof(*out) + AST_FRIENDLY_OFFSET;
  300. memcpy(out->data.ptr, f->data.ptr, out->datalen);
  301. } else {
  302. out->data.uint32 = f->data.uint32;
  303. }
  304. if (srclen > 0) {
  305. /* This may seem a little strange, but it's to avoid a gcc (4.2.4) compiler warning */
  306. char *src;
  307. out->src = buf + sizeof(*out) + AST_FRIENDLY_OFFSET + f->datalen;
  308. src = (char *) out->src;
  309. /* Must have space since we allocated for it */
  310. strcpy(src, f->src);
  311. }
  312. ast_copy_flags(out, f, AST_FLAGS_ALL);
  313. out->ts = f->ts;
  314. out->len = f->len;
  315. out->seqno = f->seqno;
  316. return out;
  317. }
  318. void ast_swapcopy_samples(void *dst, const void *src, int samples)
  319. {
  320. int i;
  321. unsigned short *dst_s = dst;
  322. const unsigned short *src_s = src;
  323. for (i = 0; i < samples; i++)
  324. dst_s[i] = (src_s[i]<<8) | (src_s[i]>>8);
  325. }
  326. void ast_frame_subclass2str(struct ast_frame *f, char *subclass, size_t slen, char *moreinfo, size_t mlen)
  327. {
  328. switch(f->frametype) {
  329. case AST_FRAME_DTMF_BEGIN:
  330. if (slen > 1) {
  331. subclass[0] = f->subclass.integer;
  332. subclass[1] = '\0';
  333. }
  334. break;
  335. case AST_FRAME_DTMF_END:
  336. if (slen > 1) {
  337. subclass[0] = f->subclass.integer;
  338. subclass[1] = '\0';
  339. }
  340. break;
  341. case AST_FRAME_CONTROL:
  342. switch (f->subclass.integer) {
  343. case AST_CONTROL_HANGUP:
  344. ast_copy_string(subclass, "Hangup", slen);
  345. break;
  346. case AST_CONTROL_RING:
  347. ast_copy_string(subclass, "Ring", slen);
  348. break;
  349. case AST_CONTROL_RINGING:
  350. ast_copy_string(subclass, "Ringing", slen);
  351. break;
  352. case AST_CONTROL_ANSWER:
  353. ast_copy_string(subclass, "Answer", slen);
  354. break;
  355. case AST_CONTROL_BUSY:
  356. ast_copy_string(subclass, "Busy", slen);
  357. break;
  358. case AST_CONTROL_TAKEOFFHOOK:
  359. ast_copy_string(subclass, "Take Off Hook", slen);
  360. break;
  361. case AST_CONTROL_OFFHOOK:
  362. ast_copy_string(subclass, "Line Off Hook", slen);
  363. break;
  364. case AST_CONTROL_CONGESTION:
  365. ast_copy_string(subclass, "Congestion", slen);
  366. break;
  367. case AST_CONTROL_FLASH:
  368. ast_copy_string(subclass, "Flash", slen);
  369. break;
  370. case AST_CONTROL_WINK:
  371. ast_copy_string(subclass, "Wink", slen);
  372. break;
  373. case AST_CONTROL_OPTION:
  374. ast_copy_string(subclass, "Option", slen);
  375. break;
  376. case AST_CONTROL_RADIO_KEY:
  377. ast_copy_string(subclass, "Key Radio", slen);
  378. break;
  379. case AST_CONTROL_RADIO_UNKEY:
  380. ast_copy_string(subclass, "Unkey Radio", slen);
  381. break;
  382. case AST_CONTROL_HOLD:
  383. ast_copy_string(subclass, "Hold", slen);
  384. break;
  385. case AST_CONTROL_UNHOLD:
  386. ast_copy_string(subclass, "Unhold", slen);
  387. break;
  388. case AST_CONTROL_T38_PARAMETERS: {
  389. char *message = "Unknown";
  390. if (f->datalen != sizeof(struct ast_control_t38_parameters)) {
  391. message = "Invalid";
  392. } else {
  393. struct ast_control_t38_parameters *parameters = f->data.ptr;
  394. enum ast_control_t38 state = parameters->request_response;
  395. if (state == AST_T38_REQUEST_NEGOTIATE)
  396. message = "Negotiation Requested";
  397. else if (state == AST_T38_REQUEST_TERMINATE)
  398. message = "Negotiation Request Terminated";
  399. else if (state == AST_T38_NEGOTIATED)
  400. message = "Negotiated";
  401. else if (state == AST_T38_TERMINATED)
  402. message = "Terminated";
  403. else if (state == AST_T38_REFUSED)
  404. message = "Refused";
  405. }
  406. snprintf(subclass, slen, "T38_Parameters/%s", message);
  407. break;
  408. }
  409. case -1:
  410. ast_copy_string(subclass, "Stop generators", slen);
  411. break;
  412. default:
  413. snprintf(subclass, slen, "Unknown control '%d'", f->subclass.integer);
  414. }
  415. break;
  416. case AST_FRAME_NULL:
  417. ast_copy_string(subclass, "N/A", slen);
  418. break;
  419. case AST_FRAME_IAX:
  420. /* Should never happen */
  421. snprintf(subclass, slen, "IAX Frametype %d", f->subclass.integer);
  422. break;
  423. case AST_FRAME_BRIDGE_ACTION:
  424. /* Should never happen */
  425. snprintf(subclass, slen, "Bridge Frametype %d", f->subclass.integer);
  426. break;
  427. case AST_FRAME_BRIDGE_ACTION_SYNC:
  428. /* Should never happen */
  429. snprintf(subclass, slen, "Synchronous Bridge Frametype %d", f->subclass.integer);
  430. break;
  431. case AST_FRAME_TEXT:
  432. ast_copy_string(subclass, "N/A", slen);
  433. if (moreinfo) {
  434. ast_copy_string(moreinfo, f->data.ptr, mlen);
  435. }
  436. break;
  437. case AST_FRAME_IMAGE:
  438. snprintf(subclass, slen, "Image format %s\n", ast_format_get_name(f->subclass.format));
  439. break;
  440. case AST_FRAME_HTML:
  441. switch (f->subclass.integer) {
  442. case AST_HTML_URL:
  443. ast_copy_string(subclass, "URL", slen);
  444. if (moreinfo) {
  445. ast_copy_string(moreinfo, f->data.ptr, mlen);
  446. }
  447. break;
  448. case AST_HTML_DATA:
  449. ast_copy_string(subclass, "Data", slen);
  450. break;
  451. case AST_HTML_BEGIN:
  452. ast_copy_string(subclass, "Begin", slen);
  453. break;
  454. case AST_HTML_END:
  455. ast_copy_string(subclass, "End", slen);
  456. break;
  457. case AST_HTML_LDCOMPLETE:
  458. ast_copy_string(subclass, "Load Complete", slen);
  459. break;
  460. case AST_HTML_NOSUPPORT:
  461. ast_copy_string(subclass, "No Support", slen);
  462. break;
  463. case AST_HTML_LINKURL:
  464. ast_copy_string(subclass, "Link URL", slen);
  465. if (moreinfo) {
  466. ast_copy_string(moreinfo, f->data.ptr, mlen);
  467. }
  468. break;
  469. case AST_HTML_UNLINK:
  470. ast_copy_string(subclass, "Unlink", slen);
  471. break;
  472. case AST_HTML_LINKREJECT:
  473. ast_copy_string(subclass, "Link Reject", slen);
  474. break;
  475. default:
  476. snprintf(subclass, slen, "Unknown HTML frame '%d'\n", f->subclass.integer);
  477. break;
  478. }
  479. break;
  480. case AST_FRAME_MODEM:
  481. switch (f->subclass.integer) {
  482. case AST_MODEM_T38:
  483. ast_copy_string(subclass, "T.38", slen);
  484. break;
  485. case AST_MODEM_V150:
  486. ast_copy_string(subclass, "V.150", slen);
  487. break;
  488. default:
  489. snprintf(subclass, slen, "Unknown MODEM frame '%d'\n", f->subclass.integer);
  490. break;
  491. }
  492. break;
  493. default:
  494. ast_copy_string(subclass, "Unknown Subclass", slen);
  495. break;
  496. }
  497. }
  498. void ast_frame_type2str(enum ast_frame_type frame_type, char *ftype, size_t len)
  499. {
  500. switch (frame_type) {
  501. case AST_FRAME_DTMF_BEGIN:
  502. ast_copy_string(ftype, "DTMF Begin", len);
  503. break;
  504. case AST_FRAME_DTMF_END:
  505. ast_copy_string(ftype, "DTMF End", len);
  506. break;
  507. case AST_FRAME_CONTROL:
  508. ast_copy_string(ftype, "Control", len);
  509. break;
  510. case AST_FRAME_NULL:
  511. ast_copy_string(ftype, "Null Frame", len);
  512. break;
  513. case AST_FRAME_IAX:
  514. /* Should never happen */
  515. ast_copy_string(ftype, "IAX Specific", len);
  516. break;
  517. case AST_FRAME_BRIDGE_ACTION:
  518. /* Should never happen */
  519. ast_copy_string(ftype, "Bridge Specific", len);
  520. break;
  521. case AST_FRAME_BRIDGE_ACTION_SYNC:
  522. /* Should never happen */
  523. ast_copy_string(ftype, "Bridge Specific", len);
  524. break;
  525. case AST_FRAME_TEXT:
  526. ast_copy_string(ftype, "Text", len);
  527. break;
  528. case AST_FRAME_IMAGE:
  529. ast_copy_string(ftype, "Image", len);
  530. break;
  531. case AST_FRAME_HTML:
  532. ast_copy_string(ftype, "HTML", len);
  533. break;
  534. case AST_FRAME_MODEM:
  535. ast_copy_string(ftype, "Modem", len);
  536. break;
  537. case AST_FRAME_VOICE:
  538. ast_copy_string(ftype, "Voice", len);
  539. break;
  540. case AST_FRAME_VIDEO:
  541. ast_copy_string(ftype, "Video", len);
  542. break;
  543. default:
  544. snprintf(ftype, len, "Unknown Frametype '%u'", frame_type);
  545. break;
  546. }
  547. }
  548. /*! Dump a frame for debugging purposes */
  549. void ast_frame_dump(const char *name, struct ast_frame *f, char *prefix)
  550. {
  551. const char noname[] = "unknown";
  552. char ftype[40] = "Unknown Frametype";
  553. char cft[80];
  554. char subclass[40] = "Unknown Subclass";
  555. char csub[80];
  556. char moreinfo[40] = "";
  557. char cn[60];
  558. char cp[40];
  559. char cmn[40];
  560. if (!name) {
  561. name = noname;
  562. }
  563. if (!f) {
  564. ast_verb(-1, "%s [ %s (NULL) ] [%s]\n",
  565. term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
  566. term_color(cft, "HANGUP", COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
  567. term_color(cn, name, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
  568. return;
  569. }
  570. /* XXX We should probably print one each of voice and video when the format changes XXX */
  571. if (f->frametype == AST_FRAME_VOICE) {
  572. return;
  573. }
  574. if (f->frametype == AST_FRAME_VIDEO) {
  575. return;
  576. }
  577. ast_frame_type2str(f->frametype, ftype, sizeof(ftype));
  578. ast_frame_subclass2str(f, subclass, sizeof(subclass), moreinfo, sizeof(moreinfo));
  579. if (!ast_strlen_zero(moreinfo))
  580. ast_verb(-1, "%s [ TYPE: %s (%u) SUBCLASS: %s (%d) '%s' ] [%s]\n",
  581. term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
  582. term_color(cft, ftype, COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
  583. f->frametype,
  584. term_color(csub, subclass, COLOR_BRCYAN, COLOR_BLACK, sizeof(csub)),
  585. f->subclass.integer,
  586. term_color(cmn, moreinfo, COLOR_BRGREEN, COLOR_BLACK, sizeof(cmn)),
  587. term_color(cn, name, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
  588. else
  589. ast_verb(-1, "%s [ TYPE: %s (%u) SUBCLASS: %s (%d) ] [%s]\n",
  590. term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
  591. term_color(cft, ftype, COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
  592. f->frametype,
  593. term_color(csub, subclass, COLOR_BRCYAN, COLOR_BLACK, sizeof(csub)),
  594. f->subclass.integer,
  595. term_color(cn, name, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
  596. }
  597. int ast_frame_adjust_volume(struct ast_frame *f, int adjustment)
  598. {
  599. int count;
  600. short *fdata = f->data.ptr;
  601. short adjust_value = abs(adjustment);
  602. if ((f->frametype != AST_FRAME_VOICE) || !(ast_format_cache_is_slinear(f->subclass.format))) {
  603. return -1;
  604. }
  605. if (!adjustment) {
  606. return 0;
  607. }
  608. for (count = 0; count < f->samples; count++) {
  609. if (adjustment > 0) {
  610. ast_slinear_saturated_multiply(&fdata[count], &adjust_value);
  611. } else if (adjustment < 0) {
  612. ast_slinear_saturated_divide(&fdata[count], &adjust_value);
  613. }
  614. }
  615. return 0;
  616. }
  617. int ast_frame_slinear_sum(struct ast_frame *f1, struct ast_frame *f2)
  618. {
  619. int count;
  620. short *data1, *data2;
  621. if ((f1->frametype != AST_FRAME_VOICE) || (ast_format_cmp(f1->subclass.format, ast_format_slin) != AST_FORMAT_CMP_NOT_EQUAL))
  622. return -1;
  623. if ((f2->frametype != AST_FRAME_VOICE) || (ast_format_cmp(f2->subclass.format, ast_format_slin) != AST_FORMAT_CMP_NOT_EQUAL))
  624. return -1;
  625. if (f1->samples != f2->samples)
  626. return -1;
  627. for (count = 0, data1 = f1->data.ptr, data2 = f2->data.ptr;
  628. count < f1->samples;
  629. count++, data1++, data2++)
  630. ast_slinear_saturated_add(data1, data2);
  631. return 0;
  632. }
  633. int ast_frame_clear(struct ast_frame *frame)
  634. {
  635. struct ast_frame *next;
  636. for (next = AST_LIST_NEXT(frame, frame_list);
  637. frame;
  638. frame = next, next = frame ? AST_LIST_NEXT(frame, frame_list) : NULL) {
  639. memset(frame->data.ptr, 0, frame->datalen);
  640. }
  641. return 0;
  642. }