26
26
#include "asterisk.h"
28
ASTERISK_FILE_VERSION(__FILE__, "$Revision: 195212 $")
28
ASTERISK_FILE_VERSION(__FILE__, "$Revision: 208501 $")
30
30
#include "asterisk/_private.h"
31
31
#include "asterisk/lock.h"
40
40
#include "asterisk/dsp.h"
41
41
#include "asterisk/file.h"
45
static AST_LIST_HEAD_STATIC(headerlist, ast_frame);
48
43
#if !defined(LOW_MEMORY)
49
44
static void frame_cache_cleanup(void *data);
320
315
f->mallocd_hdr_len = sizeof(*f);
322
AST_LIST_LOCK(&headerlist);
324
AST_LIST_INSERT_HEAD(&headerlist, f, frame_list);
325
AST_LIST_UNLOCK(&headerlist);
344
void ast_frame_free(struct ast_frame *fr, int cache)
333
static void __frame_free(struct ast_frame *fr, int cache)
346
335
if (ast_test_flag(fr, AST_FRFLAG_FROM_TRANSLATOR)) {
347
336
ast_translate_frame_freed(fr);
360
349
* to keep things simple... */
361
350
struct ast_frame_cache *frames;
363
if ((frames = ast_threadstorage_get(&frame_cache, sizeof(*frames)))
364
&& frames->size < FRAME_CACHE_MAX_SIZE) {
352
if ((frames = ast_threadstorage_get(&frame_cache, sizeof(*frames))) &&
353
(frames->size < FRAME_CACHE_MAX_SIZE)) {
365
354
AST_LIST_INSERT_HEAD(&frames->list, fr, frame_list);
376
365
if (fr->mallocd & AST_MALLOCD_SRC) {
378
ast_free((char *)fr->src);
367
ast_free((void *) fr->src);
380
369
if (fr->mallocd & AST_MALLOCD_HDR) {
382
AST_LIST_LOCK(&headerlist);
384
AST_LIST_REMOVE(&headerlist, fr, frame_list);
385
AST_LIST_UNLOCK(&headerlist);
375
void ast_frame_free(struct ast_frame *frame, int cache)
377
struct ast_frame *next;
379
for (next = AST_LIST_NEXT(frame, frame_list);
381
frame = next, next = frame ? AST_LIST_NEXT(frame, frame_list) : NULL) {
382
__frame_free(frame, cache);
392
387
* \brief 'isolates' a frame by duplicating non-malloc'ed components
393
388
* (header, src, data).
398
393
struct ast_frame *out;
401
ast_clear_flag(fr, AST_FRFLAG_FROM_TRANSLATOR);
402
ast_clear_flag(fr, AST_FRFLAG_FROM_DSP);
396
/* if none of the existing frame is malloc'd, let ast_frdup() do it
397
since it is more efficient
399
if (fr->mallocd == 0) {
400
return ast_frdup(fr);
403
/* if everything is already malloc'd, we are done */
404
if ((fr->mallocd & (AST_MALLOCD_HDR | AST_MALLOCD_SRC | AST_MALLOCD_DATA)) ==
405
(AST_MALLOCD_HDR | AST_MALLOCD_SRC | AST_MALLOCD_DATA)) {
404
409
if (!(fr->mallocd & AST_MALLOCD_HDR)) {
405
410
/* Allocate a new header if needed */
406
if (!(out = ast_frame_header_new()))
411
if (!(out = ast_frame_header_new())) {
408
414
out->frametype = fr->frametype;
409
415
out->subclass = fr->subclass;
410
416
out->datalen = fr->datalen;
411
417
out->samples = fr->samples;
412
418
out->offset = fr->offset;
413
out->data = fr->data;
414
419
/* Copy the timing data */
415
420
ast_copy_flags(out, fr, AST_FRFLAG_HAS_TIMING_INFO);
416
421
if (ast_test_flag(fr, AST_FRFLAG_HAS_TIMING_INFO)) {
418
423
out->len = fr->len;
419
424
out->seqno = fr->seqno;
427
ast_clear_flag(fr, AST_FRFLAG_FROM_TRANSLATOR);
428
ast_clear_flag(fr, AST_FRFLAG_FROM_DSP);
429
ast_clear_flag(fr, AST_FRFLAG_FROM_FILESTREAM);
424
if (!(fr->mallocd & AST_MALLOCD_SRC)) {
426
if (!(out->src = ast_strdup(fr->src))) {
433
if (!(fr->mallocd & AST_MALLOCD_SRC) && fr->src) {
434
if (!(out->src = ast_strdup(fr->src))) {
433
441
out->src = fr->src;
443
fr->mallocd &= ~AST_MALLOCD_SRC;
435
446
if (!(fr->mallocd & AST_MALLOCD_DATA)) {
436
447
if (!(newdata = ast_malloc(fr->datalen + AST_FRIENDLY_OFFSET))) {
437
if (out->src != fr->src)
448
if (out->src != fr->src) {
438
449
ast_free((void *) out->src);
443
456
newdata += AST_FRIENDLY_OFFSET;
445
458
out->datalen = fr->datalen;
446
459
memcpy(newdata, fr->data.ptr, fr->datalen);
447
460
out->data.ptr = newdata;
462
out->data = fr->data;
463
memset(&fr->data, 0, sizeof(fr->data));
464
fr->mallocd &= ~AST_MALLOCD_DATA;
450
467
out->mallocd = AST_MALLOCD_HDR | AST_MALLOCD_SRC | AST_MALLOCD_DATA;
822
839
case AST_CONTROL_UNHOLD:
823
840
strcpy(subclass, "Unhold");
825
case AST_CONTROL_T38:
826
if (f->datalen != sizeof(enum ast_control_t38)) {
842
case AST_CONTROL_T38_PARAMETERS:
843
if (f->datalen != sizeof(struct ast_control_t38_parameters *)) {
827
844
message = "Invalid";
829
enum ast_control_t38 state = *((enum ast_control_t38 *) f->data.ptr);
846
struct ast_control_t38_parameters *parameters = f->data.ptr;
847
enum ast_control_t38 state = parameters->request_response;
830
848
if (state == AST_T38_REQUEST_NEGOTIATE)
831
849
message = "Negotiation Requested";
832
850
else if (state == AST_T38_REQUEST_TERMINATE)
838
856
else if (state == AST_T38_REFUSED)
839
857
message = "Refused";
841
snprintf(subclass, sizeof(subclass), "T38/%s", message);
859
snprintf(subclass, sizeof(subclass), "T38_Parameters/%s", message);
844
862
strcpy(subclass, "Stop generators");
943
static char *show_frame_stats(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
950
e->command = "core show frame stats";
952
"Usage: core show frame stats\n"
953
" Displays debugging statistics from framer\n";
960
return CLI_SHOWUSAGE;
961
AST_LIST_LOCK(&headerlist);
962
ast_cli(a->fd, " Framer Statistics \n");
963
ast_cli(a->fd, "---------------------------\n");
964
ast_cli(a->fd, "Total allocated headers: %d\n", headers);
965
ast_cli(a->fd, "Queue Dump:\n");
966
AST_LIST_TRAVERSE(&headerlist, f, frame_list)
967
ast_cli(a->fd, "%d. Type %d, subclass %d from %s\n", x++, f->frametype, f->subclass, f->src ? f->src : "<Unknown>");
968
AST_LIST_UNLOCK(&headerlist);
973
960
/* Builtin Asterisk CLI-commands for debugging */
974
961
static struct ast_cli_entry my_clis[] = {
975
962
AST_CLI_DEFINE(show_codecs, "Displays a list of codecs"),
976
963
AST_CLI_DEFINE(show_codec_n, "Shows a specific codec"),
978
AST_CLI_DEFINE(show_frame_stats, "Shows frame statistics"),
982
966
int init_framer(void)