#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_frame * | pcm_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_info * | ast_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] |
Definition in file format_pcm.c.
#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 |
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 |
#define BUF_SIZE 160 |
Definition at line 41 of file format_pcm.c.
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] |
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.
00494 { 00495 return ast_format_unregister(pcm_f.name) 00496 || ast_format_unregister(alaw_f.name) 00497 || ast_format_unregister(au_f.name) 00498 || ast_format_unregister(g722_f.name); 00499 }
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 }
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] |
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] |
struct ast_format g722_f [static] |
struct ast_format pcm_f [static] |
char ulaw_silence[BUF_SIZE] [static] |
Definition at line 43 of file format_pcm.c.