#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_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_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_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 234 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 50 of file format_pcm.c.
#define htoll | ( | b | ) | (b) |
#define htols | ( | b | ) | (b) |
#define ltohl | ( | b | ) | (b) |
#define ltohs | ( | b | ) | (b) |
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] |
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.
00500 { 00501 return ast_format_unregister(pcm_f.name) 00502 || ast_format_unregister(alaw_f.name) 00503 || ast_format_unregister(au_f.name) 00504 || ast_format_unregister(g722_f.name); 00505 }
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 }
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] |
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] |
struct ast_format g722_f [static] |
struct ast_format pcm_f [static] |
char ulaw_silence[BUF_SIZE] [static] |
Definition at line 52 of file format_pcm.c.