main/frame.c File Reference

Frame and codec manipulation routines. More...

#include "asterisk.h"
#include "asterisk/_private.h"
#include "asterisk/lock.h"
#include "asterisk/frame.h"
#include "asterisk/format_cache.h"
#include "asterisk/channel.h"
#include "asterisk/cli.h"
#include "asterisk/term.h"
#include "asterisk/utils.h"
#include "asterisk/threadstorage.h"
#include "asterisk/linkedlists.h"
#include "asterisk/translate.h"
#include "asterisk/dsp.h"
#include "asterisk/file.h"

Include dependency graph for main/frame.c:

Go to the source code of this file.

Data Structures

struct  ast_frame_cache
struct  ast_frames
 This is just so ast_frames, a list head struct for holding a list of ast_frame structures, is defined. More...

Defines

#define FRAME_CACHE_MAX_SIZE   10
 Maximum ast_frame cache size.

Functions

static void __frame_free (struct ast_frame *fr, int cache)
static void __init_frame_cache (void)
 A per-thread cache of frame headers.
int ast_frame_adjust_volume (struct ast_frame *f, int adjustment)
 Adjusts the volume of the audio samples contained in a frame.
int ast_frame_clear (struct ast_frame *frame)
 Clear all audio samples from an ast_frame. The frame must be AST_FRAME_VOICE and AST_FORMAT_SLINEAR.
void ast_frame_dtor (struct ast_frame *f)
 NULL-safe wrapper for ast_frfree, good for RAII_VAR.
void ast_frame_dump (const char *name, struct ast_frame *f, char *prefix)
void ast_frame_free (struct ast_frame *frame, int cache)
 Requests a frame to be allocated.
static struct ast_frameast_frame_header_new (void)
int ast_frame_slinear_sum (struct ast_frame *f1, struct ast_frame *f2)
 Sums two frames of audio samples.
void ast_frame_subclass2str (struct ast_frame *f, char *subclass, size_t slen, char *moreinfo, size_t mlen)
 Copy the discription of a frame's subclass into the provided string.
void ast_frame_type2str (enum ast_frame_type frame_type, char *ftype, size_t len)
 Copy the discription of a frame type into the provided string.
struct ast_frameast_frdup (const struct ast_frame *f)
 Copies a frame.
struct ast_frameast_frisolate (struct ast_frame *fr)
 'isolates' a frame by duplicating non-malloc'ed components (header, src, data). On return all components are malloc'ed
void ast_swapcopy_samples (void *dst, const void *src, int samples)
static void frame_cache_cleanup (void *data)

Variables

struct ast_frame ast_null_frame = { AST_FRAME_NULL, }
static struct ast_threadstorage frame_cache = { .once = PTHREAD_ONCE_INIT , .key_init = __init_frame_cache , .custom_init = NULL , }


Detailed Description

Frame and codec manipulation routines.

Author:
Mark Spencer <markster@digium.com>

Definition in file main/frame.c.


Define Documentation

#define FRAME_CACHE_MAX_SIZE   10

Maximum ast_frame cache size.

In most cases where the frame header cache will be useful, the size of the cache will stay very small. However, it is not always the case that the same thread that allocates the frame will be the one freeing them, so sometimes a thread will never have any frames in its cache, or the cache will never be pulled from. For the latter case, we limit the maximum size.

Definition at line 63 of file main/frame.c.


Function Documentation

static void __frame_free ( struct ast_frame fr,
int  cache 
) [static]

Definition at line 119 of file main/frame.c.

References ao2_cleanup, AST_FRAME_IMAGE, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_free, AST_LIST_INSERT_HEAD, AST_MALLOCD_DATA, AST_MALLOCD_HDR, AST_MALLOCD_SRC, ast_threadstorage_get(), ast_frame::data, ast_frame_subclass::format, frame_cache, FRAME_CACHE_MAX_SIZE, frames, ast_frame::frametype, ast_frame_cache::list, ast_frame::mallocd, ast_frame::offset, ast_frame::ptr, ast_frame_cache::size, ast_frame::src, and ast_frame::subclass.

Referenced by ast_frame_free().

00120 {
00121    if (!fr->mallocd)
00122       return;
00123 
00124 #if !defined(LOW_MEMORY)
00125    if (cache && fr->mallocd == AST_MALLOCD_HDR) {
00126       /* Cool, only the header is malloc'd, let's just cache those for now
00127        * to keep things simple... */
00128       struct ast_frame_cache *frames;
00129       if ((frames = ast_threadstorage_get(&frame_cache, sizeof(*frames))) &&
00130           (frames->size < FRAME_CACHE_MAX_SIZE)) {
00131          if ((fr->frametype == AST_FRAME_VOICE) || (fr->frametype == AST_FRAME_VIDEO) ||
00132             (fr->frametype == AST_FRAME_IMAGE)) {
00133             ao2_cleanup(fr->subclass.format);
00134          }
00135 
00136          AST_LIST_INSERT_HEAD(&frames->list, fr, frame_list);
00137          frames->size++;
00138          return;
00139       }
00140    }
00141 #endif
00142 
00143    if (fr->mallocd & AST_MALLOCD_DATA) {
00144       if (fr->data.ptr)
00145          ast_free(fr->data.ptr - fr->offset);
00146    }
00147    if (fr->mallocd & AST_MALLOCD_SRC) {
00148       if (fr->src)
00149          ast_free((void *) fr->src);
00150    }
00151    if (fr->mallocd & AST_MALLOCD_HDR) {
00152       if ((fr->frametype == AST_FRAME_VOICE) || (fr->frametype == AST_FRAME_VIDEO) ||
00153          (fr->frametype == AST_FRAME_IMAGE)) {
00154          ao2_cleanup(fr->subclass.format);
00155       }
00156 
00157       ast_free(fr);
00158    } else {
00159       fr->mallocd = 0;
00160    }
00161 }

static void __init_frame_cache ( void   )  [static]

A per-thread cache of frame headers.

Definition at line 52 of file main/frame.c.

00069 {

int ast_frame_adjust_volume ( struct ast_frame f,
int  adjustment 
)

Adjusts the volume of the audio samples contained in a frame.

Parameters:
f The frame containing the samples (must be AST_FRAME_VOICE and AST_FORMAT_SLINEAR)
adjustment The number of dB to adjust up or down.
Returns:
0 for success, non-zero for an error

Definition at line 650 of file main/frame.c.

References abs, ast_format_cache_is_slinear(), AST_FRAME_VOICE, ast_slinear_saturated_divide(), ast_slinear_saturated_multiply(), ast_frame::data, ast_frame_subclass::format, ast_frame::frametype, ast_frame::ptr, ast_frame::samples, and ast_frame::subclass.

Referenced by audiohook_read_frame_single(), audiohook_volume_callback(), conf_run(), and volume_callback().

00651 {
00652    int count;
00653    short *fdata = f->data.ptr;
00654    short adjust_value = abs(adjustment);
00655 
00656    if ((f->frametype != AST_FRAME_VOICE) || !(ast_format_cache_is_slinear(f->subclass.format))) {
00657       return -1;
00658    }
00659 
00660    if (!adjustment) {
00661       return 0;
00662    }
00663 
00664    for (count = 0; count < f->samples; count++) {
00665       if (adjustment > 0) {
00666          ast_slinear_saturated_multiply(&fdata[count], &adjust_value);
00667       } else if (adjustment < 0) {
00668          ast_slinear_saturated_divide(&fdata[count], &adjust_value);
00669       }
00670    }
00671 
00672    return 0;
00673 }

int ast_frame_clear ( struct ast_frame frame  ) 

Clear all audio samples from an ast_frame. The frame must be AST_FRAME_VOICE and AST_FORMAT_SLINEAR.

Definition at line 697 of file main/frame.c.

References AST_LIST_NEXT, ast_frame::data, ast_frame::datalen, ast_frame::next, NULL, and ast_frame::ptr.

Referenced by ast_audiohook_write_frame().

00698 {
00699    struct ast_frame *next;
00700 
00701    for (next = AST_LIST_NEXT(frame, frame_list);
00702        frame;
00703        frame = next, next = frame ? AST_LIST_NEXT(frame, frame_list) : NULL) {
00704       memset(frame->data.ptr, 0, frame->datalen);
00705    }
00706    return 0;
00707 }

void ast_frame_dtor ( struct ast_frame frame  ) 

NULL-safe wrapper for ast_frfree, good for RAII_VAR.

Parameters:
frame Frame to free, or head of list to free.

Definition at line 175 of file main/frame.c.

References ast_frfree.

Referenced by __ast_play_and_record(), and stasis_app_exec().

00176 {
00177    if (f) {
00178       ast_frfree(f);
00179    }
00180 }

void ast_frame_dump ( const char *  name,
struct ast_frame f,
char *  prefix 
)

Dump a frame for debugging purposes

Definition at line 597 of file main/frame.c.

References ast_frame_subclass2str(), ast_frame_type2str(), AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_strlen_zero, ast_verb, COLOR_BLACK, COLOR_BRCYAN, COLOR_BRGREEN, COLOR_BRMAGENTA, COLOR_BRRED, COLOR_YELLOW, ast_frame::frametype, ast_frame_subclass::integer, ast_frame::subclass, and term_color().

Referenced by __ast_read(), and ast_write().

00598 {
00599    const char noname[] = "unknown";
00600    char ftype[40] = "Unknown Frametype";
00601    char cft[80];
00602    char subclass[40] = "Unknown Subclass";
00603    char csub[80];
00604    char moreinfo[40] = "";
00605    char cn[60];
00606    char cp[40];
00607    char cmn[40];
00608 
00609    if (!name) {
00610       name = noname;
00611    }
00612 
00613    if (!f) {
00614       ast_verb(-1, "%s [ %s (NULL) ] [%s]\n",
00615          term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
00616          term_color(cft, "HANGUP", COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
00617          term_color(cn, name, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
00618       return;
00619    }
00620    /* XXX We should probably print one each of voice and video when the format changes XXX */
00621    if (f->frametype == AST_FRAME_VOICE) {
00622       return;
00623    }
00624    if (f->frametype == AST_FRAME_VIDEO) {
00625       return;
00626    }
00627 
00628    ast_frame_type2str(f->frametype, ftype, sizeof(ftype));
00629    ast_frame_subclass2str(f, subclass, sizeof(subclass), moreinfo, sizeof(moreinfo));
00630 
00631    if (!ast_strlen_zero(moreinfo))
00632       ast_verb(-1, "%s [ TYPE: %s (%u) SUBCLASS: %s (%d) '%s' ] [%s]\n",
00633              term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
00634              term_color(cft, ftype, COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
00635              f->frametype,
00636              term_color(csub, subclass, COLOR_BRCYAN, COLOR_BLACK, sizeof(csub)),
00637              f->subclass.integer,
00638              term_color(cmn, moreinfo, COLOR_BRGREEN, COLOR_BLACK, sizeof(cmn)),
00639              term_color(cn, name, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
00640    else
00641       ast_verb(-1, "%s [ TYPE: %s (%u) SUBCLASS: %s (%d) ] [%s]\n",
00642              term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
00643              term_color(cft, ftype, COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
00644              f->frametype,
00645              term_color(csub, subclass, COLOR_BRCYAN, COLOR_BLACK, sizeof(csub)),
00646              f->subclass.integer,
00647              term_color(cn, name, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
00648 }

void ast_frame_free ( struct ast_frame fr,
int  cache 
)

Requests a frame to be allocated.

Parameters:
source Request a frame be allocated. source is an optional source of the frame, len is the requested length, or "0" if the caller will supply the buffer
Frees a frame or list of frames
Parameters:
fr Frame to free, or head of list to free
cache Whether to consider this frame for frame caching

Definition at line 164 of file main/frame.c.

References __frame_free(), AST_LIST_NEXT, ast_frame::next, and NULL.

Referenced by mixmonitor_thread().

00165 {
00166    struct ast_frame *next;
00167 
00168    for (next = AST_LIST_NEXT(frame, frame_list);
00169         frame;
00170         frame = next, next = frame ? AST_LIST_NEXT(frame, frame_list) : NULL) {
00171       __frame_free(frame, cache);
00172    }
00173 }

static struct ast_frame* ast_frame_header_new ( void   )  [static, read]

Definition at line 77 of file main/frame.c.

References ast_calloc, ast_calloc_cache, AST_LIST_REMOVE_HEAD, AST_MALLOCD_HDR, ast_threadstorage_get(), f, frame_cache, frames, ast_frame_cache::list, ast_frame::mallocd, ast_frame::mallocd_hdr_len, NULL, and ast_frame_cache::size.

Referenced by ast_frisolate().

00078 {
00079    struct ast_frame *f;
00080 
00081 #if !defined(LOW_MEMORY)
00082    struct ast_frame_cache *frames;
00083 
00084    if ((frames = ast_threadstorage_get(&frame_cache, sizeof(*frames)))) {
00085       if ((f = AST_LIST_REMOVE_HEAD(&frames->list, frame_list))) {
00086          size_t mallocd_len = f->mallocd_hdr_len;
00087          memset(f, 0, sizeof(*f));
00088          f->mallocd_hdr_len = mallocd_len;
00089          f->mallocd = AST_MALLOCD_HDR;
00090          frames->size--;
00091          return f;
00092       }
00093    }
00094    if (!(f = ast_calloc_cache(1, sizeof(*f))))
00095       return NULL;
00096 #else
00097    if (!(f = ast_calloc(1, sizeof(*f))))
00098       return NULL;
00099 #endif
00100 
00101    f->mallocd_hdr_len = sizeof(*f);
00102 
00103    return f;
00104 }

int ast_frame_slinear_sum ( struct ast_frame f1,
struct ast_frame f2 
)

Sums two frames of audio samples.

Parameters:
f1 The first frame (which will contain the result)
f2 The second frame
Returns:
0 for success, non-zero for an error
The frames must be AST_FRAME_VOICE and must contain AST_FORMAT_SLINEAR samples, and must contain the same number of samples.

Definition at line 675 of file main/frame.c.

References ast_format_cmp(), AST_FORMAT_CMP_NOT_EQUAL, ast_format_slin, AST_FRAME_VOICE, ast_slinear_saturated_add(), ast_frame::data, ast_frame_subclass::format, ast_frame::frametype, ast_frame::ptr, ast_frame::samples, and ast_frame::subclass.

00676 {
00677    int count;
00678    short *data1, *data2;
00679 
00680    if ((f1->frametype != AST_FRAME_VOICE) || (ast_format_cmp(f1->subclass.format, ast_format_slin) != AST_FORMAT_CMP_NOT_EQUAL))
00681       return -1;
00682 
00683    if ((f2->frametype != AST_FRAME_VOICE) || (ast_format_cmp(f2->subclass.format, ast_format_slin) != AST_FORMAT_CMP_NOT_EQUAL))
00684       return -1;
00685 
00686    if (f1->samples != f2->samples)
00687       return -1;
00688 
00689    for (count = 0, data1 = f1->data.ptr, data2 = f2->data.ptr;
00690         count < f1->samples;
00691         count++, data1++, data2++)
00692       ast_slinear_saturated_add(data1, data2);
00693 
00694    return 0;
00695 }

void ast_frame_subclass2str ( struct ast_frame f,
char *  subclass,
size_t  slen,
char *  moreinfo,
size_t  mlen 
)

Copy the discription of a frame's subclass into the provided string.

Parameters:
f The frame to get the information from
subclass Buffer to fill with subclass information
slen Length of subclass buffer
moreinfo Buffer to fill with additional information
mlen Length of moreinfo buffer
Since:
11

Definition at line 372 of file main/frame.c.

References AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_FLASH, AST_CONTROL_HANGUP, AST_CONTROL_HOLD, AST_CONTROL_OFFHOOK, AST_CONTROL_OPTION, AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, AST_CONTROL_RING, AST_CONTROL_RINGING, AST_CONTROL_T38_PARAMETERS, AST_CONTROL_TAKEOFFHOOK, AST_CONTROL_UNHOLD, AST_CONTROL_WINK, ast_copy_string(), ast_format_get_name(), AST_FRAME_BRIDGE_ACTION, AST_FRAME_BRIDGE_ACTION_SYNC, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_HTML, AST_FRAME_IAX, AST_FRAME_IMAGE, AST_FRAME_MODEM, AST_FRAME_NULL, AST_FRAME_TEXT, AST_HTML_BEGIN, AST_HTML_DATA, AST_HTML_END, AST_HTML_LDCOMPLETE, AST_HTML_LINKREJECT, AST_HTML_LINKURL, AST_HTML_NOSUPPORT, AST_HTML_UNLINK, AST_HTML_URL, AST_MODEM_T38, AST_MODEM_V150, AST_T38_NEGOTIATED, AST_T38_REFUSED, AST_T38_REQUEST_NEGOTIATE, AST_T38_REQUEST_TERMINATE, AST_T38_TERMINATED, ast_frame::data, ast_frame::datalen, ast_frame_subclass::format, ast_frame::frametype, ast_frame_subclass::integer, ast_frame::ptr, ast_control_t38_parameters::request_response, and ast_frame::subclass.

Referenced by ast_frame_dump().

00373 {
00374    switch(f->frametype) {
00375    case AST_FRAME_DTMF_BEGIN:
00376       if (slen > 1) {
00377          subclass[0] = f->subclass.integer;
00378          subclass[1] = '\0';
00379       }
00380       break;
00381    case AST_FRAME_DTMF_END:
00382       if (slen > 1) {
00383          subclass[0] = f->subclass.integer;
00384          subclass[1] = '\0';
00385       }
00386       break;
00387    case AST_FRAME_CONTROL:
00388       switch (f->subclass.integer) {
00389       case AST_CONTROL_HANGUP:
00390          ast_copy_string(subclass, "Hangup", slen);
00391          break;
00392       case AST_CONTROL_RING:
00393          ast_copy_string(subclass, "Ring", slen);
00394          break;
00395       case AST_CONTROL_RINGING:
00396          ast_copy_string(subclass, "Ringing", slen);
00397          break;
00398       case AST_CONTROL_ANSWER:
00399          ast_copy_string(subclass, "Answer", slen);
00400          break;
00401       case AST_CONTROL_BUSY:
00402          ast_copy_string(subclass, "Busy", slen);
00403          break;
00404       case AST_CONTROL_TAKEOFFHOOK:
00405          ast_copy_string(subclass, "Take Off Hook", slen);
00406          break;
00407       case AST_CONTROL_OFFHOOK:
00408          ast_copy_string(subclass, "Line Off Hook", slen);
00409          break;
00410       case AST_CONTROL_CONGESTION:
00411          ast_copy_string(subclass, "Congestion", slen);
00412          break;
00413       case AST_CONTROL_FLASH:
00414          ast_copy_string(subclass, "Flash", slen);
00415          break;
00416       case AST_CONTROL_WINK:
00417          ast_copy_string(subclass, "Wink", slen);
00418          break;
00419       case AST_CONTROL_OPTION:
00420          ast_copy_string(subclass, "Option", slen);
00421          break;
00422       case AST_CONTROL_RADIO_KEY:
00423          ast_copy_string(subclass, "Key Radio", slen);
00424          break;
00425       case AST_CONTROL_RADIO_UNKEY:
00426          ast_copy_string(subclass, "Unkey Radio", slen);
00427          break;
00428       case AST_CONTROL_HOLD:
00429          ast_copy_string(subclass, "Hold", slen);
00430          break;
00431       case AST_CONTROL_UNHOLD:
00432          ast_copy_string(subclass, "Unhold", slen);
00433          break;
00434       case AST_CONTROL_T38_PARAMETERS: {
00435          char *message = "Unknown";
00436          if (f->datalen != sizeof(struct ast_control_t38_parameters)) {
00437             message = "Invalid";
00438          } else {
00439             struct ast_control_t38_parameters *parameters = f->data.ptr;
00440             enum ast_control_t38 state = parameters->request_response;
00441             if (state == AST_T38_REQUEST_NEGOTIATE)
00442                message = "Negotiation Requested";
00443             else if (state == AST_T38_REQUEST_TERMINATE)
00444                message = "Negotiation Request Terminated";
00445             else if (state == AST_T38_NEGOTIATED)
00446                message = "Negotiated";
00447             else if (state == AST_T38_TERMINATED)
00448                message = "Terminated";
00449             else if (state == AST_T38_REFUSED)
00450                message = "Refused";
00451          }
00452          snprintf(subclass, slen, "T38_Parameters/%s", message);
00453          break;
00454       }
00455       case -1:
00456          ast_copy_string(subclass, "Stop generators", slen);
00457          break;
00458       default:
00459          snprintf(subclass, slen, "Unknown control '%d'", f->subclass.integer);
00460       }
00461       break;
00462    case AST_FRAME_NULL:
00463       ast_copy_string(subclass, "N/A", slen);
00464       break;
00465    case AST_FRAME_IAX:
00466       /* Should never happen */
00467       snprintf(subclass, slen, "IAX Frametype %d", f->subclass.integer);
00468       break;
00469    case AST_FRAME_BRIDGE_ACTION:
00470       /* Should never happen */
00471       snprintf(subclass, slen, "Bridge Frametype %d", f->subclass.integer);
00472       break;
00473    case AST_FRAME_BRIDGE_ACTION_SYNC:
00474       /* Should never happen */
00475       snprintf(subclass, slen, "Synchronous Bridge Frametype %d", f->subclass.integer);
00476       break;
00477    case AST_FRAME_TEXT:
00478       ast_copy_string(subclass, "N/A", slen);
00479       if (moreinfo) {
00480          ast_copy_string(moreinfo, f->data.ptr, mlen);
00481       }
00482       break;
00483    case AST_FRAME_IMAGE:
00484       snprintf(subclass, slen, "Image format %s\n", ast_format_get_name(f->subclass.format));
00485       break;
00486    case AST_FRAME_HTML:
00487       switch (f->subclass.integer) {
00488       case AST_HTML_URL:
00489          ast_copy_string(subclass, "URL", slen);
00490          if (moreinfo) {
00491             ast_copy_string(moreinfo, f->data.ptr, mlen);
00492          }
00493          break;
00494       case AST_HTML_DATA:
00495          ast_copy_string(subclass, "Data", slen);
00496          break;
00497       case AST_HTML_BEGIN:
00498          ast_copy_string(subclass, "Begin", slen);
00499          break;
00500       case AST_HTML_END:
00501          ast_copy_string(subclass, "End", slen);
00502          break;
00503       case AST_HTML_LDCOMPLETE:
00504          ast_copy_string(subclass, "Load Complete", slen);
00505          break;
00506       case AST_HTML_NOSUPPORT:
00507          ast_copy_string(subclass, "No Support", slen);
00508          break;
00509       case AST_HTML_LINKURL:
00510          ast_copy_string(subclass, "Link URL", slen);
00511          if (moreinfo) {
00512             ast_copy_string(moreinfo, f->data.ptr, mlen);
00513          }
00514          break;
00515       case AST_HTML_UNLINK:
00516          ast_copy_string(subclass, "Unlink", slen);
00517          break;
00518       case AST_HTML_LINKREJECT:
00519          ast_copy_string(subclass, "Link Reject", slen);
00520          break;
00521       default:
00522          snprintf(subclass, slen, "Unknown HTML frame '%d'\n", f->subclass.integer);
00523          break;
00524       }
00525       break;
00526    case AST_FRAME_MODEM:
00527       switch (f->subclass.integer) {
00528       case AST_MODEM_T38:
00529          ast_copy_string(subclass, "T.38", slen);
00530          break;
00531       case AST_MODEM_V150:
00532          ast_copy_string(subclass, "V.150", slen);
00533          break;
00534       default:
00535          snprintf(subclass, slen, "Unknown MODEM frame '%d'\n", f->subclass.integer);
00536          break;
00537       }
00538       break;
00539    default:
00540       ast_copy_string(subclass, "Unknown Subclass", slen);
00541       break;
00542    }
00543 }

void ast_frame_type2str ( enum ast_frame_type  frame_type,
char *  ftype,
size_t  len 
)

Copy the discription of a frame type into the provided string.

Parameters:
frame_type The frame type to be described
ftype Buffer to fill with frame type description
len Length of subclass buffer
Since:
11

Definition at line 545 of file main/frame.c.

References ast_copy_string(), AST_FRAME_BRIDGE_ACTION, AST_FRAME_BRIDGE_ACTION_SYNC, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_HTML, AST_FRAME_IAX, AST_FRAME_IMAGE, AST_FRAME_MODEM, AST_FRAME_NULL, AST_FRAME_TEXT, AST_FRAME_VIDEO, and AST_FRAME_VOICE.

Referenced by ast_frame_dump().

00546 {
00547    switch (frame_type) {
00548    case AST_FRAME_DTMF_BEGIN:
00549       ast_copy_string(ftype, "DTMF Begin", len);
00550       break;
00551    case AST_FRAME_DTMF_END:
00552       ast_copy_string(ftype, "DTMF End", len);
00553       break;
00554    case AST_FRAME_CONTROL:
00555       ast_copy_string(ftype, "Control", len);
00556       break;
00557    case AST_FRAME_NULL:
00558       ast_copy_string(ftype, "Null Frame", len);
00559       break;
00560    case AST_FRAME_IAX:
00561       /* Should never happen */
00562       ast_copy_string(ftype, "IAX Specific", len);
00563       break;
00564    case AST_FRAME_BRIDGE_ACTION:
00565       /* Should never happen */
00566       ast_copy_string(ftype, "Bridge Specific", len);
00567       break;
00568    case AST_FRAME_BRIDGE_ACTION_SYNC:
00569       /* Should never happen */
00570       ast_copy_string(ftype, "Bridge Specific", len);
00571       break;
00572    case AST_FRAME_TEXT:
00573       ast_copy_string(ftype, "Text", len);
00574       break;
00575    case AST_FRAME_IMAGE:
00576       ast_copy_string(ftype, "Image", len);
00577       break;
00578    case AST_FRAME_HTML:
00579       ast_copy_string(ftype, "HTML", len);
00580       break;
00581    case AST_FRAME_MODEM:
00582       ast_copy_string(ftype, "Modem", len);
00583       break;
00584    case AST_FRAME_VOICE:
00585       ast_copy_string(ftype, "Voice", len);
00586       break;
00587    case AST_FRAME_VIDEO:
00588       ast_copy_string(ftype, "Video", len);
00589       break;
00590    default:
00591       snprintf(ftype, len, "Unknown Frametype '%u'", frame_type);
00592       break;
00593    }
00594 }

struct ast_frame* ast_frdup ( const struct ast_frame fr  )  [read]

Copies a frame.

Parameters:
fr frame to copy Duplicates a frame -- should only rarely be used, typically frisolate is good enough
Returns:
Returns a frame on success, NULL on error

Definition at line 275 of file main/frame.c.

References ao2_bump, ast_calloc_cache, ast_copy_flags, AST_FLAGS_ALL, AST_FRAME_IMAGE, AST_FRAME_VIDEO, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_MALLOCD_HDR, ast_threadstorage_get(), buf, ast_frame::data, ast_frame::datalen, ast_frame::delivery, ast_frame_subclass::format, frame_cache, frames, ast_frame::frametype, ast_frame::len, len(), ast_frame_cache::list, ast_frame::mallocd, ast_frame::mallocd_hdr_len, NULL, ast_frame::offset, out, ast_frame::ptr, ast_frame::samples, ast_frame::seqno, ast_frame_cache::size, ast_frame::src, ast_frame::subclass, ast_frame::ts, and ast_frame::uint32.

Referenced by __ast_queue_frame(), ast_bridge_channel_queue_frame(), ast_bridge_queue_action(), ast_frisolate(), ast_indicate_data(), ast_jb_put(), ast_rtp_write(), ast_slinfactory_feed(), audiohook_read_frame_both(), audiohook_read_frame_single(), autoservice_run(), hook_event_cb(), multicast_rtp_write(), ooh323_rtp_read(), process_dtmf_rfc2833(), recordthread(), smart_bridge_operation(), and t38_parameters_task_data_alloc().

00276 {
00277    struct ast_frame *out = NULL;
00278    int len, srclen = 0;
00279    void *buf = NULL;
00280 
00281 #if !defined(LOW_MEMORY)
00282    struct ast_frame_cache *frames;
00283 #endif
00284 
00285    /* Start with standard stuff */
00286    len = sizeof(*out) + AST_FRIENDLY_OFFSET + f->datalen;
00287    /* If we have a source, add space for it */
00288    /*
00289     * XXX Watch out here - if we receive a src which is not terminated
00290     * properly, we can be easily attacked. Should limit the size we deal with.
00291     */
00292    if (f->src)
00293       srclen = strlen(f->src);
00294    if (srclen > 0)
00295       len += srclen + 1;
00296 
00297 #if !defined(LOW_MEMORY)
00298    if ((frames = ast_threadstorage_get(&frame_cache, sizeof(*frames)))) {
00299       AST_LIST_TRAVERSE_SAFE_BEGIN(&frames->list, out, frame_list) {
00300          if (out->mallocd_hdr_len >= len) {
00301             size_t mallocd_len = out->mallocd_hdr_len;
00302 
00303             AST_LIST_REMOVE_CURRENT(frame_list);
00304             memset(out, 0, sizeof(*out));
00305             out->mallocd_hdr_len = mallocd_len;
00306             buf = out;
00307             frames->size--;
00308             break;
00309          }
00310       }
00311       AST_LIST_TRAVERSE_SAFE_END;
00312    }
00313 #endif
00314 
00315    if (!buf) {
00316       if (!(buf = ast_calloc_cache(1, len)))
00317          return NULL;
00318       out = buf;
00319       out->mallocd_hdr_len = len;
00320    }
00321 
00322    out->frametype = f->frametype;
00323    if ((f->frametype == AST_FRAME_VOICE) || (f->frametype == AST_FRAME_VIDEO) ||
00324       (f->frametype == AST_FRAME_IMAGE)) {
00325       out->subclass.format = ao2_bump(f->subclass.format);
00326    } else {
00327       memcpy(&out->subclass, &f->subclass, sizeof(out->subclass));
00328    }
00329    out->datalen = f->datalen;
00330    out->samples = f->samples;
00331    out->delivery = f->delivery;
00332    /* Even though this new frame was allocated from the heap, we can't mark it
00333     * with AST_MALLOCD_HDR, AST_MALLOCD_DATA and AST_MALLOCD_SRC, because that
00334     * would cause ast_frfree() to attempt to individually free each of those
00335     * under the assumption that they were separately allocated. Since this frame
00336     * was allocated in a single allocation, we'll only mark it as if the header
00337     * was heap-allocated; this will result in the entire frame being properly freed.
00338     */
00339    out->mallocd = AST_MALLOCD_HDR;
00340    out->offset = AST_FRIENDLY_OFFSET;
00341    if (out->datalen) {
00342       out->data.ptr = buf + sizeof(*out) + AST_FRIENDLY_OFFSET;
00343       memcpy(out->data.ptr, f->data.ptr, out->datalen);
00344    } else {
00345       out->data.uint32 = f->data.uint32;
00346    }
00347    if (srclen > 0) {
00348       /* This may seem a little strange, but it's to avoid a gcc (4.2.4) compiler warning */
00349       char *src;
00350       out->src = buf + sizeof(*out) + AST_FRIENDLY_OFFSET + f->datalen;
00351       src = (char *) out->src;
00352       /* Must have space since we allocated for it */
00353       strcpy(src, f->src);
00354    }
00355    ast_copy_flags(out, f, AST_FLAGS_ALL);
00356    out->ts = f->ts;
00357    out->len = f->len;
00358    out->seqno = f->seqno;
00359    return out;
00360 }

struct ast_frame* ast_frisolate ( struct ast_frame fr  )  [read]

'isolates' a frame by duplicating non-malloc'ed components (header, src, data). On return all components are malloc'ed

Makes a frame independent of any static storage.

Definition at line 187 of file main/frame.c.

References ao2_bump, ast_copy_flags, AST_FLAGS_ALL, ast_frame_header_new(), AST_FRAME_IMAGE, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frdup(), ast_free, AST_FRFLAG_HAS_TIMING_INFO, AST_FRIENDLY_OFFSET, ast_malloc, AST_MALLOCD_DATA, AST_MALLOCD_HDR, AST_MALLOCD_SRC, ast_strdup, ast_test_flag, ast_frame::data, ast_frame::datalen, ast_frame_subclass::format, ast_frame::frametype, ast_frame::len, ast_frame::mallocd, NULL, ast_frame::offset, out, ast_frame::ptr, ast_frame::samples, ast_frame::seqno, ast_frame::src, ast_frame::subclass, ast_frame::ts, and ast_frame::uint32.

Referenced by __ast_answer(), ast_dsp_process(), ast_rtp_read(), ast_safe_sleep_conditional(), ast_slinfactory_feed(), ast_trans_frameout(), ast_write(), autoservice_run(), create_test_frame(), dahdi_decoder_frameout(), dahdi_encoder_frameout(), fax_gateway_framehook(), fax_gateway_request_t38(), hook_event_cb(), jpeg_read_image(), lintospeex_frameout(), read_frame(), spandsp_fax_gw_t30_gen(), spandsp_fax_read(), and t38_tx_packet_handler().

00188 {
00189    struct ast_frame *out;
00190    void *newdata;
00191 
00192    /* if none of the existing frame is malloc'd, let ast_frdup() do it
00193       since it is more efficient
00194    */
00195    if (fr->mallocd == 0) {
00196       return ast_frdup(fr);
00197    }
00198 
00199    /* if everything is already malloc'd, we are done */
00200    if ((fr->mallocd & (AST_MALLOCD_HDR | AST_MALLOCD_SRC | AST_MALLOCD_DATA)) ==
00201        (AST_MALLOCD_HDR | AST_MALLOCD_SRC | AST_MALLOCD_DATA)) {
00202       return fr;
00203    }
00204 
00205    if (!(fr->mallocd & AST_MALLOCD_HDR)) {
00206       /* Allocate a new header if needed */
00207       if (!(out = ast_frame_header_new())) {
00208          return NULL;
00209       }
00210       out->frametype = fr->frametype;
00211       if ((fr->frametype == AST_FRAME_VOICE) || (fr->frametype == AST_FRAME_VIDEO) ||
00212          (fr->frametype == AST_FRAME_IMAGE)) {
00213          out->subclass.format = ao2_bump(fr->subclass.format);
00214       } else {
00215          memcpy(&out->subclass, &fr->subclass, sizeof(out->subclass));
00216       }
00217       out->datalen = fr->datalen;
00218       out->samples = fr->samples;
00219       out->offset = fr->offset;
00220       /* Copy the timing data */
00221       ast_copy_flags(out, fr, AST_FLAGS_ALL);
00222       if (ast_test_flag(fr, AST_FRFLAG_HAS_TIMING_INFO)) {
00223          out->ts = fr->ts;
00224          out->len = fr->len;
00225          out->seqno = fr->seqno;
00226       }
00227    } else {
00228       out = fr;
00229    }
00230 
00231    if (!(fr->mallocd & AST_MALLOCD_SRC) && fr->src) {
00232       if (!(out->src = ast_strdup(fr->src))) {
00233          if (out != fr) {
00234             ast_free(out);
00235          }
00236          return NULL;
00237       }
00238    } else {
00239       out->src = fr->src;
00240       fr->src = NULL;
00241       fr->mallocd &= ~AST_MALLOCD_SRC;
00242    }
00243 
00244    if (!(fr->mallocd & AST_MALLOCD_DATA))  {
00245       if (!fr->datalen) {
00246          out->data.uint32 = fr->data.uint32;
00247          out->mallocd = AST_MALLOCD_HDR | AST_MALLOCD_SRC;
00248          return out;
00249       }
00250       if (!(newdata = ast_malloc(fr->datalen + AST_FRIENDLY_OFFSET))) {
00251          if (out->src != fr->src) {
00252             ast_free((void *) out->src);
00253          }
00254          if (out != fr) {
00255             ast_free(out);
00256          }
00257          return NULL;
00258       }
00259       newdata += AST_FRIENDLY_OFFSET;
00260       out->offset = AST_FRIENDLY_OFFSET;
00261       out->datalen = fr->datalen;
00262       memcpy(newdata, fr->data.ptr, fr->datalen);
00263       out->data.ptr = newdata;
00264    } else {
00265       out->data = fr->data;
00266       memset(&fr->data, 0, sizeof(fr->data));
00267       fr->mallocd &= ~AST_MALLOCD_DATA;
00268    }
00269 
00270    out->mallocd = AST_MALLOCD_HDR | AST_MALLOCD_SRC | AST_MALLOCD_DATA;
00271 
00272    return out;
00273 }

void ast_swapcopy_samples ( void *  dst,
const void *  src,
int  samples 
)

Definition at line 362 of file main/frame.c.

Referenced by __ast_smoother_feed(), iax_frame_wrap(), phone_write_buf(), and smoother_frame_feed().

00363 {
00364    int i;
00365    unsigned short *dst_s = dst;
00366    const unsigned short *src_s = src;
00367 
00368    for (i = 0; i < samples; i++)
00369       dst_s[i] = (src_s[i]<<8) | (src_s[i]>>8);
00370 }

static void frame_cache_cleanup ( void *  data  )  [static]

Definition at line 107 of file main/frame.c.

References ast_free, AST_LIST_REMOVE_HEAD, f, frames, and ast_frame_cache::list.

00108 {
00109    struct ast_frame_cache *frames = data;
00110    struct ast_frame *f;
00111 
00112    while ((f = AST_LIST_REMOVE_HEAD(&frames->list, frame_list)))
00113       ast_free(f);
00114 
00115    ast_free(frames);
00116 }


Variable Documentation

struct ast_frame ast_null_frame = { AST_FRAME_NULL, }

struct ast_threadstorage frame_cache = { .once = PTHREAD_ONCE_INIT , .key_init = __init_frame_cache , .custom_init = NULL , } [static]

Definition at line 52 of file main/frame.c.


Generated on Thu Apr 16 06:31:08 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6