Mon Jun 27 16:51:14 2011

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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .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 231 of file format_pcm.c.

Referenced by check_header(), and write_header().

#define AU_HDR_CHANNELS_OFF   5

Definition at line 229 of file format_pcm.c.

Referenced by check_header(), and write_header().

#define AU_HDR_DATA_SIZE_OFF   2

Definition at line 226 of file format_pcm.c.

Referenced by update_header(), and write_header().

#define AU_HDR_ENCODING_OFF   3

Definition at line 227 of file format_pcm.c.

Referenced by check_header(), and write_header().

#define AU_HDR_HDR_SIZE_OFF   1

Definition at line 225 of file format_pcm.c.

Referenced by check_header(), and write_header().

#define AU_HDR_MAGIC_OFF   0

Definition at line 224 of file format_pcm.c.

Referenced by check_header(), and write_header().

#define AU_HDR_SAMPLE_RATE_OFF   4

Definition at line 228 of file format_pcm.c.

Referenced by check_header(), and write_header().

#define AU_HEADER ( var   )     uint32_t var[6]

Definition at line 222 of file format_pcm.c.

Referenced by check_header(), and write_header().

#define AU_HEADER_SIZE   24

Definition at line 221 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 233 of file format_pcm.c.

Referenced by check_header(), and write_header().

#define BUF_SIZE   160

Definition at line 37 of file format_pcm.c.


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 501 of file format_pcm.c.

static void __unreg_module ( void   )  [static]

Definition at line 501 of file format_pcm.c.

static int au_open ( struct ast_filestream s  )  [static]

Definition at line 356 of file format_pcm.c.

References check_header(), and ast_filestream::f.

00357 {
00358    if (check_header(s->f) < 0)
00359       return -1;
00360    return 0;
00361 }

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

Definition at line 363 of file format_pcm.c.

References ast_filestream::f, and write_header().

00364 {
00365    if (write_header(s->f))
00366       return -1;
00367    return 0;
00368 }

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

Definition at line 371 of file format_pcm.c.

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

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

static off_t au_tell ( struct ast_filestream fs  )  [static]

Definition at line 410 of file format_pcm.c.

References AU_HEADER_SIZE, and ast_filestream::f.

00411 {
00412    off_t offset = ftello(fs->f);
00413    return offset - AU_HEADER_SIZE;
00414 }

static int au_trunc ( struct ast_filestream fs  )  [static]

Definition at line 403 of file format_pcm.c.

References ast_filestream::f, and update_header().

00404 {
00405    if (ftruncate(fileno(fs->f), ftell(fs->f)))
00406       return -1;
00407    return update_header(fs->f);
00408 }

static int check_header ( FILE *  f  )  [static]

Definition at line 256 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().

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

static int load_module ( void   )  [static]

Definition at line 471 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.

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

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

Definition at line 76 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.

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

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

Definition at line 99 of file format_pcm.c.

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

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

static off_t pcm_tell ( struct ast_filestream fs  )  [static]

Definition at line 153 of file format_pcm.c.

References ast_filestream::f.

00154 {
00155    return ftello(fs->f);
00156 }

static int pcm_trunc ( struct ast_filestream fs  )  [static]

Definition at line 148 of file format_pcm.c.

References ast_filestream::f.

00149 {
00150    return ftruncate(fileno(fs->f), ftello(fs->f));
00151 }

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

Definition at line 158 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, fwrite, LOG_WARNING, and pd.

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

static int unload_module ( void   )  [static]

Definition at line 489 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 304 of file format_pcm.c.

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

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

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

static int write_header ( FILE *  f  )  [static]

Definition at line 336 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, fwrite, and LOG_WARNING.

Referenced by au_rewrite(), and wav_rewrite().

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


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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_APP_DEPEND } [static]

Definition at line 501 of file format_pcm.c.

struct ast_format alaw_f [static]

Definition at line 416 of file format_pcm.c.

Referenced by load_module(), and unload_module().

char alaw_silence[BUF_SIZE] [static]

Definition at line 40 of file format_pcm.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 501 of file format_pcm.c.

struct ast_format au_f [static]

Definition at line 457 of file format_pcm.c.

Referenced by load_module(), and unload_module().

struct ast_format g722_f [static]

Definition at line 445 of file format_pcm.c.

Referenced by load_module(), and unload_module().

struct ast_format pcm_f [static]

Definition at line 433 of file format_pcm.c.

Referenced by load_module(), and unload_module().

char ulaw_silence[BUF_SIZE] [static]

Definition at line 39 of file format_pcm.c.


Generated on Mon Jun 27 16:51:14 2011 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7