Sat Aug 6 00:39:56 2011

Asterisk developer's documentation


format_pcm.c File Reference

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

#include "asterisk.h"
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <sys/time.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/sched.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
#define htoll(b)   (b)
#define htols(b)   (b)
#define ltohl(b)   (b)
#define ltohs(b)   (b)

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_FIRST | AST_MODFLAG_BUILDSUM, .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 = "361d7bb937402d51e4658efb5b4d76e4" , .load = load_module, .unload = unload_module, }
static struct ast_format alaw_f
static char alaw_silence [BUF_SIZE]
static const 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 244 of file format_pcm.c.

Referenced by check_header(), and write_header().

#define AU_HDR_CHANNELS_OFF   5

Definition at line 242 of file format_pcm.c.

Referenced by check_header(), and write_header().

#define AU_HDR_DATA_SIZE_OFF   2

Definition at line 239 of file format_pcm.c.

Referenced by update_header(), and write_header().

#define AU_HDR_ENCODING_OFF   3

Definition at line 240 of file format_pcm.c.

Referenced by check_header(), and write_header().

#define AU_HDR_HDR_SIZE_OFF   1

Definition at line 238 of file format_pcm.c.

Referenced by check_header(), and write_header().

#define AU_HDR_MAGIC_OFF   0

Definition at line 237 of file format_pcm.c.

Referenced by check_header(), and write_header().

#define AU_HDR_SAMPLE_RATE_OFF   4

Definition at line 241 of file format_pcm.c.

Referenced by check_header(), and write_header().

#define AU_HEADER ( var   )     uint32_t var[6]

Definition at line 235 of file format_pcm.c.

Referenced by check_header(), and write_header().

#define AU_HEADER_SIZE   24

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

Referenced by check_header(), and write_header().

#define BUF_SIZE   160

Definition at line 50 of file format_pcm.c.

#define htoll (  )     (b)

Definition at line 248 of file format_pcm.c.

Referenced by update_header(), and write_header().

#define htols (  )     (b)

Definition at line 249 of file format_pcm.c.

Referenced by write_header().

#define ltohl (  )     (b)

Definition at line 250 of file format_pcm.c.

Referenced by check_header(), and check_header_fmt().

#define ltohs (  )     (b)

Definition at line 251 of file format_pcm.c.

Referenced by check_header(), and check_header_fmt().


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 510 of file format_pcm.c.

static void __unreg_module ( void   )  [static]

Definition at line 510 of file format_pcm.c.

static int au_open ( struct ast_filestream s  )  [static]

Definition at line 369 of file format_pcm.c.

References check_header(), and s.

00370 {
00371    if (check_header(s->f) < 0)
00372       return -1;
00373    return 0;
00374 }

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

Definition at line 376 of file format_pcm.c.

References s, and write_header().

00377 {
00378    if (write_header(s->f))
00379       return -1;
00380    return 0;
00381 }

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

Definition at line 384 of file format_pcm.c.

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

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

static off_t au_tell ( struct ast_filestream fs  )  [static]

Definition at line 422 of file format_pcm.c.

References AU_HEADER_SIZE, ast_filestream::f, and offset.

00423 {
00424    off_t offset = ftello(fs->f);
00425    return offset - AU_HEADER_SIZE;
00426 }

static int au_trunc ( struct ast_filestream fs  )  [static]

Definition at line 415 of file format_pcm.c.

References ast_filestream::f, and update_header().

00416 {
00417    if (ftruncate(fileno(fs->f), ftell(fs->f)))
00418       return -1;
00419    return update_header(fs->f);
00420 }

static int check_header ( FILE *  f  )  [static]

Definition at line 269 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, DEFAULT_SAMPLE_RATE, encoding, LOG_WARNING, and ltohl.

Referenced by au_open(), and wav_open().

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

static int load_module ( void   )  [static]

Definition at line 483 of file format_pcm.c.

References alaw_f, ast_format_register, AST_LIN2A, AST_LIN2MU, au_f, g722_f, and pcm_f.

00484 {
00485    int index;
00486 
00487    /* XXX better init ? */
00488    for (index = 0; index < (sizeof(ulaw_silence) / sizeof(ulaw_silence[0])); index++)
00489       ulaw_silence[index] = AST_LIN2MU(0);
00490    for (index = 0; index < (sizeof(alaw_silence) / sizeof(alaw_silence[0])); index++)
00491       alaw_silence[index] = AST_LIN2A(0);
00492 
00493    return ast_format_register(&pcm_f)
00494       || ast_format_register(&alaw_f)
00495       || ast_format_register(&au_f)
00496       || ast_format_register(&g722_f);
00497 }

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

Definition at line 89 of file format_pcm.c.

References AST_FORMAT_G722, AST_FRAME_SET_BUFFER, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_log(), BUF_SIZE, errno, LOG_WARNING, and s.

00090 {
00091    int res;
00092    
00093    /* Send a frame from the file to the appropriate channel */
00094 
00095    s->fr.frametype = AST_FRAME_VOICE;
00096    s->fr.subclass = s->fmt->format;
00097    s->fr.mallocd = 0;
00098    AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, BUF_SIZE);
00099    if ((res = fread(s->fr.data, 1, s->fr.datalen, s->f)) < 1) {
00100       if (res)
00101          ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno));
00102       return NULL;
00103    }
00104    s->fr.datalen = res;
00105    if (s->fmt->format == AST_FORMAT_G722)
00106       *whennext = s->fr.samples = res * 2;
00107    else
00108       *whennext = s->fr.samples = res;
00109    return &s->fr;
00110 }

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

Definition at line 112 of file format_pcm.c.

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

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

static off_t pcm_tell ( struct ast_filestream fs  )  [static]

Definition at line 166 of file format_pcm.c.

References ast_filestream::f.

00167 {
00168    return ftello(fs->f);
00169 }

static int pcm_trunc ( struct ast_filestream fs  )  [static]

Definition at line 161 of file format_pcm.c.

References ast_filestream::f.

00162 {
00163    return ftruncate(fileno(fs->f), ftello(fs->f));
00164 }

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

Definition at line 171 of file format_pcm.c.

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

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

static int unload_module ( void   )  [static]

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

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

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

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

static int write_header ( FILE *  f  )  [static]

Definition at line 349 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, htoll, and LOG_WARNING.

Referenced by au_rewrite(), and wav_rewrite().

00350 {
00351    AU_HEADER(header);
00352 
00353    header[AU_HDR_MAGIC_OFF] = htoll((uint32_t) AU_MAGIC);
00354    header[AU_HDR_HDR_SIZE_OFF] = htoll(AU_HEADER_SIZE);
00355    header[AU_HDR_DATA_SIZE_OFF] = 0;
00356    header[AU_HDR_ENCODING_OFF] = htoll(AU_ENC_8BIT_ULAW);
00357    header[AU_HDR_SAMPLE_RATE_OFF] = htoll(DEFAULT_SAMPLE_RATE);
00358    header[AU_HDR_CHANNELS_OFF] = htoll(1);
00359 
00360    /* Write an au header, ignoring sizes which will be filled in later */
00361    fseek(f, 0, SEEK_SET);
00362    if (fwrite(header, 1, AU_HEADER_SIZE, f) != AU_HEADER_SIZE) {
00363       ast_log(LOG_WARNING, "Unable to write header\n");
00364       return -1;
00365    }
00366    return 0;
00367 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_FIRST | AST_MODFLAG_BUILDSUM, .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 = "361d7bb937402d51e4658efb5b4d76e4" , .load = load_module, .unload = unload_module, } [static]

Definition at line 510 of file format_pcm.c.

struct ast_format alaw_f [static]

Definition at line 428 of file format_pcm.c.

Referenced by load_module(), and unload_module().

char alaw_silence[BUF_SIZE] [static]

Definition at line 53 of file format_pcm.c.

const struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 510 of file format_pcm.c.

struct ast_format au_f [static]

Definition at line 469 of file format_pcm.c.

Referenced by load_module(), and unload_module().

struct ast_format g722_f [static]

Definition at line 457 of file format_pcm.c.

Referenced by load_module(), and unload_module().

struct ast_format pcm_f [static]

Definition at line 445 of file format_pcm.c.

Referenced by load_module(), and unload_module().

char ulaw_silence[BUF_SIZE] [static]

Definition at line 52 of file format_pcm.c.


Generated on Sat Aug 6 00:39:56 2011 for Asterisk - the Open Source PBX by  doxygen 1.4.7