Mon Mar 19 11:30:47 2012

Asterisk developer's documentation


format_pcm.c File Reference

Flat, binary, ulaw PCM file format. More...

#include "asterisk.h"
#include "asterisk/mod_format.h"
#include "asterisk/module.h"
#include "asterisk/endian.h"
#include "asterisk/ulaw.h"
#include "asterisk/alaw.h"

Go to the source code of this file.

Defines

#define AU_ENC_8BIT_ULAW   1
#define AU_HDR_CHANNELS_OFF   5
#define AU_HDR_DATA_SIZE_OFF   2
#define AU_HDR_ENCODING_OFF   3
#define AU_HDR_HDR_SIZE_OFF   1
#define AU_HDR_MAGIC_OFF   0
#define AU_HDR_SAMPLE_RATE_OFF   4
#define AU_HEADER(var)   uint32_t var[6]
#define AU_HEADER_SIZE   24
#define AU_MAGIC   0x2e736e64
#define BUF_SIZE   160

Functions

static void __reg_module (void)
static void __unreg_module (void)
static int au_open (struct ast_filestream *s)
static int au_rewrite (struct ast_filestream *s, const char *comment)
static int au_seek (struct ast_filestream *fs, off_t sample_offset, int whence)
static off_t au_tell (struct ast_filestream *fs)
static int au_trunc (struct ast_filestream *fs)
static int check_header (FILE *f)
static int load_module (void)
static struct ast_framepcm_read (struct ast_filestream *s, int *whennext)
static int pcm_seek (struct ast_filestream *fs, off_t sample_offset, int whence)
static off_t pcm_tell (struct ast_filestream *fs)
static int pcm_trunc (struct ast_filestream *fs)
static int pcm_write (struct ast_filestream *fs, struct ast_frame *f)
static int unload_module (void)
static int update_header (FILE *f)
static int write_header (FILE *f)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Raw/Sun uLaw/ALaw 8KHz (PCM,PCMA,AU), G.722 16Khz" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "88eaa8f5c1bd988bedd71113385e0886" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_APP_DEPEND }
static struct ast_format alaw_f
static char alaw_silence [BUF_SIZE]
static struct ast_module_infoast_module_info = &__mod_info
static struct ast_format au_f
static struct ast_format g722_f
static struct ast_format pcm_f
static char ulaw_silence [BUF_SIZE]


Detailed Description

Flat, binary, ulaw PCM file format.

Definition in file format_pcm.c.


Define Documentation

#define AU_ENC_8BIT_ULAW   1

Definition at line 235 of file format_pcm.c.

Referenced by check_header(), and write_header().

#define AU_HDR_CHANNELS_OFF   5

Definition at line 233 of file format_pcm.c.

Referenced by check_header(), and write_header().

#define AU_HDR_DATA_SIZE_OFF   2

Definition at line 230 of file format_pcm.c.

Referenced by update_header(), and write_header().

#define AU_HDR_ENCODING_OFF   3

Definition at line 231 of file format_pcm.c.

Referenced by check_header(), and write_header().

#define AU_HDR_HDR_SIZE_OFF   1

Definition at line 229 of file format_pcm.c.

Referenced by check_header(), and write_header().

#define AU_HDR_MAGIC_OFF   0

Definition at line 228 of file format_pcm.c.

Referenced by check_header(), and write_header().

#define AU_HDR_SAMPLE_RATE_OFF   4

Definition at line 232 of file format_pcm.c.

Referenced by check_header(), and write_header().

#define AU_HEADER ( var   )     uint32_t var[6]

Definition at line 226 of file format_pcm.c.

Referenced by check_header(), and write_header().

#define AU_HEADER_SIZE   24

Definition at line 225 of file format_pcm.c.

Referenced by au_seek(), au_tell(), check_header(), update_header(), and write_header().

#define AU_MAGIC   0x2e736e64

Definition at line 237 of file format_pcm.c.

Referenced by check_header(), and write_header().

#define BUF_SIZE   160

Definition at line 41 of file format_pcm.c.


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 505 of file format_pcm.c.

static void __unreg_module ( void   )  [static]

Definition at line 505 of file format_pcm.c.

static int au_open ( struct ast_filestream s  )  [static]

Definition at line 360 of file format_pcm.c.

References check_header(), and ast_filestream::f.

00361 {
00362    if (check_header(s->f) < 0)
00363       return -1;
00364    return 0;
00365 }

static int au_rewrite ( struct ast_filestream s,
const char *  comment 
) [static]

Definition at line 367 of file format_pcm.c.

References ast_filestream::f, and write_header().

00368 {
00369    if (write_header(s->f))
00370       return -1;
00371    return 0;
00372 }

static int au_seek ( struct ast_filestream fs,
off_t  sample_offset,
int  whence 
) [static]

Definition at line 375 of file format_pcm.c.

References AST_FORMAT_G722, AU_HEADER_SIZE, ast_filestream::f, ast_filestream::fmt, ast_format::format, and SEEK_FORCECUR.

00376 {
00377    off_t min, max, cur;
00378    long offset = 0, bytes;
00379 
00380    if (fs->fmt->format == AST_FORMAT_G722)
00381       bytes = sample_offset / 2;
00382    else
00383       bytes = sample_offset;
00384 
00385    min = AU_HEADER_SIZE;
00386    cur = ftello(fs->f);
00387    fseek(fs->f, 0, SEEK_END);
00388    max = ftello(fs->f);
00389 
00390    if (whence == SEEK_SET)
00391       offset = bytes + min;
00392    else if (whence == SEEK_CUR || whence == SEEK_FORCECUR)
00393       offset = bytes + cur;
00394    else if (whence == SEEK_END)
00395       offset = max - bytes;
00396 
00397    if (whence != SEEK_FORCECUR) {
00398       offset = (offset > max) ? max : offset;
00399    }
00400 
00401    /* always protect the header space. */
00402    offset = (offset < min) ? min : offset;
00403 
00404    return fseeko(fs->f, offset, SEEK_SET);
00405 }

static off_t au_tell ( struct ast_filestream fs  )  [static]

Definition at line 414 of file format_pcm.c.

References AU_HEADER_SIZE, and ast_filestream::f.

00415 {
00416    off_t offset = ftello(fs->f);
00417    return offset - AU_HEADER_SIZE;
00418 }

static int au_trunc ( struct ast_filestream fs  )  [static]

Definition at line 407 of file format_pcm.c.

References ast_filestream::f, and update_header().

00408 {
00409    if (ftruncate(fileno(fs->f), ftell(fs->f)))
00410       return -1;
00411    return update_header(fs->f);
00412 }

static int check_header ( FILE *  f  )  [static]

Definition at line 260 of file format_pcm.c.

References ast_log(), AU_ENC_8BIT_ULAW, AU_HDR_CHANNELS_OFF, AU_HDR_ENCODING_OFF, AU_HDR_HDR_SIZE_OFF, AU_HDR_MAGIC_OFF, AU_HDR_SAMPLE_RATE_OFF, AU_HEADER, AU_HEADER_SIZE, AU_MAGIC, channels, DEFAULT_SAMPLE_RATE, encoding, and LOG_WARNING.

Referenced by au_open(), and wav_open().

00261 {
00262    AU_HEADER(header);
00263    uint32_t magic;
00264    uint32_t hdr_size;
00265    uint32_t data_size;
00266    uint32_t encoding;
00267    uint32_t sample_rate;
00268    uint32_t channels;
00269 
00270    if (fread(header, 1, AU_HEADER_SIZE, f) != AU_HEADER_SIZE) {
00271       ast_log(LOG_WARNING, "Read failed (header)\n");
00272       return -1;
00273    }
00274    magic = ltohl(header[AU_HDR_MAGIC_OFF]);
00275    if (magic != (uint32_t) AU_MAGIC) {
00276       ast_log(LOG_WARNING, "Bad magic: 0x%x\n", magic);
00277    }
00278    hdr_size = ltohl(header[AU_HDR_HDR_SIZE_OFF]);
00279    if (hdr_size < AU_HEADER_SIZE) {
00280       hdr_size = AU_HEADER_SIZE;
00281    }
00282 /* data_size = ltohl(header[AU_HDR_DATA_SIZE_OFF]); */
00283    encoding = ltohl(header[AU_HDR_ENCODING_OFF]);
00284    if (encoding != AU_ENC_8BIT_ULAW) {
00285       ast_log(LOG_WARNING, "Unexpected format: %d. Only 8bit ULAW allowed (%d)\n", encoding, AU_ENC_8BIT_ULAW);
00286       return -1;
00287    }
00288    sample_rate = ltohl(header[AU_HDR_SAMPLE_RATE_OFF]);
00289    if (sample_rate != DEFAULT_SAMPLE_RATE) {
00290       ast_log(LOG_WARNING, "Sample rate can only be 8000 not %d\n", sample_rate);
00291       return -1;
00292    }
00293    channels = ltohl(header[AU_HDR_CHANNELS_OFF]);
00294    if (channels != 1) {
00295       ast_log(LOG_WARNING, "Not in mono: channels=%d\n", channels);
00296       return -1;
00297    }
00298    /* Skip to data */
00299    fseek(f, 0, SEEK_END);
00300    data_size = ftell(f) - hdr_size;
00301    if (fseek(f, hdr_size, SEEK_SET) == -1 ) {
00302       ast_log(LOG_WARNING, "Failed to skip to data: %d\n", hdr_size);
00303       return -1;
00304    }
00305    return data_size;
00306 }

static int load_module ( void   )  [static]

Definition at line 475 of file format_pcm.c.

References alaw_f, ARRAY_LEN, ast_format_register, AST_LIN2A, AST_LIN2MU, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, au_f, g722_f, and pcm_f.

00476 {
00477    int i;
00478 
00479    /* XXX better init ? */
00480    for (i = 0; i < ARRAY_LEN(ulaw_silence); i++)
00481       ulaw_silence[i] = AST_LIN2MU(0);
00482    for (i = 0; i < ARRAY_LEN(alaw_silence); i++)
00483       alaw_silence[i] = AST_LIN2A(0);
00484 
00485    if ( ast_format_register(&pcm_f)
00486       || ast_format_register(&alaw_f)
00487       || ast_format_register(&au_f)
00488       || ast_format_register(&g722_f) )
00489       return AST_MODULE_LOAD_FAILURE;
00490    return AST_MODULE_LOAD_SUCCESS;
00491 }

static struct ast_frame* pcm_read ( struct ast_filestream s,
int *  whennext 
) [static]

Definition at line 80 of file format_pcm.c.

References AST_FORMAT_G722, AST_FRAME_SET_BUFFER, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_log(), ast_filestream::buf, BUF_SIZE, ast_frame_subclass::codec, ast_frame::data, ast_frame::datalen, errno, ast_filestream::f, ast_filestream::fmt, ast_format::format, ast_filestream::fr, ast_frame::frametype, LOG_WARNING, ast_frame::mallocd, ast_frame::ptr, ast_frame::samples, and ast_frame::subclass.

00081 {
00082    int res;
00083    
00084    /* Send a frame from the file to the appropriate channel */
00085 
00086    s->fr.frametype = AST_FRAME_VOICE;
00087    s->fr.subclass.codec = s->fmt->format;
00088    s->fr.mallocd = 0;
00089    AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, BUF_SIZE);
00090    if ((res = fread(s->fr.data.ptr, 1, s->fr.datalen, s->f)) < 1) {
00091       if (res)
00092          ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno));
00093       return NULL;
00094    }
00095    s->fr.datalen = res;
00096    if (s->fmt->format == AST_FORMAT_G722)
00097       *whennext = s->fr.samples = res * 2;
00098    else
00099       *whennext = s->fr.samples = res;
00100    return &s->fr;
00101 }

static int pcm_seek ( struct ast_filestream fs,
off_t  sample_offset,
int  whence 
) [static]

Definition at line 103 of file format_pcm.c.

References AST_FORMAT_ALAW, ast_log(), BUF_SIZE, ast_filestream::f, ast_filestream::fmt, ast_format::format, LOG_WARNING, ast_frame::offset, SEEK_FORCECUR, and ast_frame::src.

00104 {
00105    off_t cur, max, offset = 0;
00106    int ret = -1;  /* assume error */
00107 
00108    cur = ftello(fs->f);
00109    fseeko(fs->f, 0, SEEK_END);
00110    max = ftello(fs->f);
00111 
00112    switch (whence) {
00113    case SEEK_SET:
00114       offset = sample_offset;
00115       break;
00116    case SEEK_END:
00117       offset = max - sample_offset;
00118       break;
00119    case SEEK_CUR:
00120    case SEEK_FORCECUR:
00121       offset = cur + sample_offset;
00122       break;
00123    default:
00124       ast_log(LOG_WARNING, "invalid whence %d, assuming SEEK_SET\n", whence);
00125       offset = sample_offset;
00126    }
00127    if (offset < 0) {
00128       ast_log(LOG_WARNING, "negative offset %ld, resetting to 0\n", (long) offset);
00129       offset = 0;
00130    }
00131    if (whence == SEEK_FORCECUR && offset > max) { /* extend the file */
00132       size_t left = offset - max;
00133       const char *src = (fs->fmt->format == AST_FORMAT_ALAW) ? alaw_silence : ulaw_silence;
00134 
00135       while (left) {
00136          size_t written = fwrite(src, 1, (left > BUF_SIZE) ? BUF_SIZE : left, fs->f);
00137          if (written == -1)
00138             break;   /* error */
00139          left -= written;
00140       }
00141       ret = 0; /* successful */
00142    } else {
00143       if (offset > max) {
00144          ast_log(LOG_WARNING, "offset too large %ld, truncating to %ld\n", (long) offset, (long) max);
00145          offset = max;
00146       }
00147       ret = fseeko(fs->f, offset, SEEK_SET);
00148    }
00149    return ret;
00150 }

static off_t pcm_tell ( struct ast_filestream fs  )  [static]

Definition at line 157 of file format_pcm.c.

References ast_filestream::f.

00158 {
00159    return ftello(fs->f);
00160 }

static int pcm_trunc ( struct ast_filestream fs  )  [static]

Definition at line 152 of file format_pcm.c.

References ast_filestream::f.

00153 {
00154    return ftruncate(fileno(fs->f), ftello(fs->f));
00155 }

static int pcm_write ( struct ast_filestream fs,
struct ast_frame f 
) [static]

Definition at line 162 of file format_pcm.c.

References ast_filestream::_private, AST_FORMAT_ALAW, AST_FRAME_VOICE, ast_getformatname(), ast_log(), errno, ast_filestream::f, f, ast_filestream::fmt, ast_format::format, LOG_WARNING, and pd.

00163 {
00164    int res;
00165 
00166    if (f->frametype != AST_FRAME_VOICE) {
00167       ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
00168       return -1;
00169    }
00170    if (f->subclass.codec != fs->fmt->format) {
00171       ast_log(LOG_WARNING, "Asked to write incompatible format frame (%s)!\n", ast_getformatname(f->subclass.codec));
00172       return -1;
00173    }
00174 
00175 #ifdef REALTIME_WRITE
00176    if (s->fmt->format == AST_FORMAT_ALAW) {
00177       struct pcm_desc *pd = (struct pcm_desc *)fs->_private;
00178       struct stat stat_buf;
00179       unsigned long cur_time = get_time();
00180       unsigned long fpos = ( cur_time - pd->start_time ) * 8;  /* 8 bytes per msec */
00181       /* Check if we have written to this position yet. If we have, then increment pos by one frame
00182       *  for some degree of protection against receiving packets in the same clock tick.
00183       */
00184       
00185       fstat(fileno(fs->f), &stat_buf );
00186       if (stat_buf.st_size > fpos )
00187          fpos += f->datalen;  /* Incrementing with the size of this current frame */
00188 
00189       if (stat_buf.st_size < fpos) {
00190          /* fill the gap with 0x55 rather than 0. */
00191          char buf[1024];
00192          unsigned long cur, to_write;
00193 
00194          cur = stat_buf.st_size;
00195          if (fseek(fs->f, cur, SEEK_SET) < 0) {
00196             ast_log( LOG_WARNING, "Cannot seek in file: %s\n", strerror(errno) );
00197             return -1;
00198          }
00199          memset(buf, 0x55, 512);
00200          while (cur < fpos) {
00201             to_write = fpos - cur;
00202             if (to_write > sizeof(buf))
00203                to_write = sizeof(buf);
00204             fwrite(buf, 1, to_write, fs->f);
00205             cur += to_write;
00206          }
00207       }
00208 
00209       if (fseek(s->f, fpos, SEEK_SET) < 0) {
00210          ast_log( LOG_WARNING, "Cannot seek in file: %s\n", strerror(errno) );
00211          return -1;
00212       }
00213    }
00214 #endif   /* REALTIME_WRITE */
00215    
00216    if ((res = fwrite(f->data.ptr, 1, f->datalen, fs->f)) != f->datalen) {
00217       ast_log(LOG_WARNING, "Bad write (%d/%d): %s\n", res, f->datalen, strerror(errno));
00218       return -1;
00219    }
00220    return 0;
00221 }

static int unload_module ( void   )  [static]

Definition at line 493 of file format_pcm.c.

References alaw_f, ast_format_unregister(), au_f, g722_f, ast_format::name, and pcm_f.

static int update_header ( FILE *  f  )  [static]

Definition at line 308 of file format_pcm.c.

References ast_log(), AU_HDR_DATA_SIZE_OFF, AU_HEADER_SIZE, and LOG_WARNING.

Referenced by au_trunc(), wav_close(), and wav_trunc().

00309 {
00310    off_t cur, end;
00311    uint32_t datalen;
00312    int bytes;
00313 
00314    cur = ftell(f);
00315    fseek(f, 0, SEEK_END);
00316    end = ftell(f);
00317    /* data starts 24 bytes in */
00318    bytes = end - AU_HEADER_SIZE;
00319    datalen = htoll(bytes);
00320 
00321    if (cur < 0) {
00322       ast_log(LOG_WARNING, "Unable to find our position\n");
00323       return -1;
00324    }
00325    if (fseek(f, AU_HDR_DATA_SIZE_OFF * sizeof(uint32_t), SEEK_SET)) {
00326       ast_log(LOG_WARNING, "Unable to set our position\n");
00327       return -1;
00328    }
00329    if (fwrite(&datalen, 1, sizeof(datalen), f) != sizeof(datalen)) {
00330       ast_log(LOG_WARNING, "Unable to set write file size\n");
00331       return -1;
00332    }
00333    if (fseek(f, cur, SEEK_SET)) {
00334       ast_log(LOG_WARNING, "Unable to return to position\n");
00335       return -1;
00336    }
00337    return 0;
00338 }

static int write_header ( FILE *  f  )  [static]

Definition at line 340 of file format_pcm.c.

References ast_log(), AU_ENC_8BIT_ULAW, AU_HDR_CHANNELS_OFF, AU_HDR_DATA_SIZE_OFF, AU_HDR_ENCODING_OFF, AU_HDR_HDR_SIZE_OFF, AU_HDR_MAGIC_OFF, AU_HDR_SAMPLE_RATE_OFF, AU_HEADER, AU_HEADER_SIZE, AU_MAGIC, DEFAULT_SAMPLE_RATE, and LOG_WARNING.

Referenced by au_rewrite(), and wav_rewrite().

00341 {
00342    AU_HEADER(header);
00343 
00344    header[AU_HDR_MAGIC_OFF] = htoll((uint32_t) AU_MAGIC);
00345    header[AU_HDR_HDR_SIZE_OFF] = htoll(AU_HEADER_SIZE);
00346    header[AU_HDR_DATA_SIZE_OFF] = 0;
00347    header[AU_HDR_ENCODING_OFF] = htoll(AU_ENC_8BIT_ULAW);
00348    header[AU_HDR_SAMPLE_RATE_OFF] = htoll(DEFAULT_SAMPLE_RATE);
00349    header[AU_HDR_CHANNELS_OFF] = htoll(1);
00350 
00351    /* Write an au header, ignoring sizes which will be filled in later */
00352    fseek(f, 0, SEEK_SET);
00353    if (fwrite(header, 1, AU_HEADER_SIZE, f) != AU_HEADER_SIZE) {
00354       ast_log(LOG_WARNING, "Unable to write header\n");
00355       return -1;
00356    }
00357    return 0;
00358 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Raw/Sun uLaw/ALaw 8KHz (PCM,PCMA,AU), G.722 16Khz" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "88eaa8f5c1bd988bedd71113385e0886" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_APP_DEPEND } [static]

Definition at line 505 of file format_pcm.c.

struct ast_format alaw_f [static]

Definition at line 420 of file format_pcm.c.

Referenced by load_module(), and unload_module().

char alaw_silence[BUF_SIZE] [static]

Definition at line 44 of file format_pcm.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 505 of file format_pcm.c.

struct ast_format au_f [static]

Definition at line 461 of file format_pcm.c.

Referenced by load_module(), and unload_module().

struct ast_format g722_f [static]

Definition at line 449 of file format_pcm.c.

Referenced by load_module(), and unload_module().

struct ast_format pcm_f [static]

Definition at line 437 of file format_pcm.c.

Referenced by load_module(), and unload_module().

char ulaw_silence[BUF_SIZE] [static]

Definition at line 43 of file format_pcm.c.


Generated on Mon Mar 19 11:30:48 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7