00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "asterisk.h"
00030
00031 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 117802 $")
00032
00033 #include "asterisk/mod_format.h"
00034 #include "asterisk/module.h"
00035 #include "asterisk/endian.h"
00036
00037
00038
00039
00040
00041 #define BUF_SIZE 20
00042 #define G729A_SAMPLES 160
00043
00044 static struct ast_frame *g729_read(struct ast_filestream *s, int *whennext)
00045 {
00046 int res;
00047
00048 s->fr.frametype = AST_FRAME_VOICE;
00049 s->fr.subclass = AST_FORMAT_G729A;
00050 s->fr.mallocd = 0;
00051 s->fr.samples = G729A_SAMPLES;
00052 AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, BUF_SIZE);
00053 if ((res = fread(s->fr.data.ptr, 1, s->fr.datalen, s->f)) != s->fr.datalen) {
00054 if (res && (res != 10))
00055 ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno));
00056 return NULL;
00057 }
00058 *whennext = s->fr.samples;
00059 return &s->fr;
00060 }
00061
00062 static int g729_write(struct ast_filestream *fs, struct ast_frame *f)
00063 {
00064 int res;
00065 if (f->frametype != AST_FRAME_VOICE) {
00066 ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
00067 return -1;
00068 }
00069 if (f->subclass != AST_FORMAT_G729A) {
00070 ast_log(LOG_WARNING, "Asked to write non-G729 frame (%d)!\n", f->subclass);
00071 return -1;
00072 }
00073 if (f->datalen % 10) {
00074 ast_log(LOG_WARNING, "Invalid data length, %d, should be multiple of 10\n", f->datalen);
00075 return -1;
00076 }
00077 if ((res = fwrite(f->data.ptr, 1, f->datalen, fs->f)) != f->datalen) {
00078 ast_log(LOG_WARNING, "Bad write (%d/10): %s\n", res, strerror(errno));
00079 return -1;
00080 }
00081 return 0;
00082 }
00083
00084 static int g729_seek(struct ast_filestream *fs, off_t sample_offset, int whence)
00085 {
00086 long bytes;
00087 off_t min,cur,max,offset=0;
00088 min = 0;
00089 cur = ftello(fs->f);
00090 fseeko(fs->f, 0, SEEK_END);
00091 max = ftello(fs->f);
00092
00093 bytes = BUF_SIZE * (sample_offset / G729A_SAMPLES);
00094 if (whence == SEEK_SET)
00095 offset = bytes;
00096 else if (whence == SEEK_CUR || whence == SEEK_FORCECUR)
00097 offset = cur + bytes;
00098 else if (whence == SEEK_END)
00099 offset = max - bytes;
00100 if (whence != SEEK_FORCECUR) {
00101 offset = (offset > max)?max:offset;
00102 }
00103
00104 offset = (offset < min)?min:offset;
00105 if (fseeko(fs->f, offset, SEEK_SET) < 0)
00106 return -1;
00107 return 0;
00108 }
00109
00110 static int g729_trunc(struct ast_filestream *fs)
00111 {
00112
00113 if (ftruncate(fileno(fs->f), ftello(fs->f)) < 0)
00114 return -1;
00115 return 0;
00116 }
00117
00118 static off_t g729_tell(struct ast_filestream *fs)
00119 {
00120 off_t offset = ftello(fs->f);
00121 return (offset/BUF_SIZE)*G729A_SAMPLES;
00122 }
00123
00124 static const struct ast_format g729_f = {
00125 .name = "g729",
00126 .exts = "g729",
00127 .format = AST_FORMAT_G729A,
00128 .write = g729_write,
00129 .seek = g729_seek,
00130 .trunc = g729_trunc,
00131 .tell = g729_tell,
00132 .read = g729_read,
00133 .buf_size = BUF_SIZE + AST_FRIENDLY_OFFSET,
00134 };
00135
00136 static int load_module(void)
00137 {
00138 if (ast_format_register(&g729_f))
00139 return AST_MODULE_LOAD_FAILURE;
00140 return AST_MODULE_LOAD_SUCCESS;
00141 }
00142
00143 static int unload_module(void)
00144 {
00145 return ast_format_unregister(g729_f.name);
00146 }
00147
00148 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Raw G729 data");