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: 233782 $")
00032
00033 #include <unistd.h>
00034 #include <netinet/in.h>
00035 #include <arpa/inet.h>
00036 #include <stdlib.h>
00037 #include <sys/time.h>
00038 #include <stdio.h>
00039 #include <errno.h>
00040 #include <string.h>
00041
00042 #include "asterisk/lock.h"
00043 #include "asterisk/channel.h"
00044 #include "asterisk/file.h"
00045 #include "asterisk/logger.h"
00046 #include "asterisk/sched.h"
00047 #include "asterisk/module.h"
00048 #include "asterisk/endian.h"
00049
00050
00051
00052
00053
00054 #define BUF_SIZE 20
00055 #define G729A_SAMPLES 160
00056
00057 static struct ast_frame *g729_read(struct ast_filestream *s, int *whennext)
00058 {
00059 int res;
00060
00061 s->fr.frametype = AST_FRAME_VOICE;
00062 s->fr.subclass = AST_FORMAT_G729A;
00063 s->fr.mallocd = 0;
00064 s->fr.samples = G729A_SAMPLES;
00065 AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, BUF_SIZE);
00066 if ((res = fread(s->fr.data, 1, s->fr.datalen, s->f)) != s->fr.datalen) {
00067 if (res && (res != 10))
00068 ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno));
00069 return NULL;
00070 }
00071 *whennext = s->fr.samples;
00072 return &s->fr;
00073 }
00074
00075 static int g729_write(struct ast_filestream *fs, struct ast_frame *f)
00076 {
00077 int res;
00078 if (f->frametype != AST_FRAME_VOICE) {
00079 ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
00080 return -1;
00081 }
00082 if (f->subclass != AST_FORMAT_G729A) {
00083 ast_log(LOG_WARNING, "Asked to write non-G729 frame (%d)!\n", f->subclass);
00084 return -1;
00085 }
00086 if (f->datalen % 10) {
00087 ast_log(LOG_WARNING, "Invalid data length, %d, should be multiple of 10\n", f->datalen);
00088 return -1;
00089 }
00090 if ((res = fwrite(f->data, 1, f->datalen, fs->f)) != f->datalen) {
00091 ast_log(LOG_WARNING, "Bad write (%d/10): %s\n", res, strerror(errno));
00092 return -1;
00093 }
00094 return 0;
00095 }
00096
00097 static int g729_seek(struct ast_filestream *fs, off_t sample_offset, int whence)
00098 {
00099 long bytes;
00100 off_t min,cur,max,offset=0;
00101 min = 0;
00102 cur = ftello(fs->f);
00103 fseeko(fs->f, 0, SEEK_END);
00104 max = ftello(fs->f);
00105
00106 bytes = BUF_SIZE * (sample_offset / G729A_SAMPLES);
00107 if (whence == SEEK_SET)
00108 offset = bytes;
00109 else if (whence == SEEK_CUR || whence == SEEK_FORCECUR)
00110 offset = cur + bytes;
00111 else if (whence == SEEK_END)
00112 offset = max - bytes;
00113 if (whence != SEEK_FORCECUR) {
00114 offset = (offset > max)?max:offset;
00115 }
00116
00117 offset = (offset < min)?min:offset;
00118 if (fseeko(fs->f, offset, SEEK_SET) < 0)
00119 return -1;
00120 return 0;
00121 }
00122
00123 static int g729_trunc(struct ast_filestream *fs)
00124 {
00125
00126 if (ftruncate(fileno(fs->f), ftello(fs->f)) < 0)
00127 return -1;
00128 return 0;
00129 }
00130
00131 static off_t g729_tell(struct ast_filestream *fs)
00132 {
00133 off_t offset = ftello(fs->f);
00134 return (offset/BUF_SIZE)*G729A_SAMPLES;
00135 }
00136
00137 static const struct ast_format g729_f = {
00138 .name = "g729",
00139 .exts = "g729",
00140 .format = AST_FORMAT_G729A,
00141 .write = g729_write,
00142 .seek = g729_seek,
00143 .trunc = g729_trunc,
00144 .tell = g729_tell,
00145 .read = g729_read,
00146 .buf_size = BUF_SIZE + AST_FRIENDLY_OFFSET,
00147 };
00148
00149 static int load_module(void)
00150 {
00151 return ast_format_register(&g729_f);
00152 }
00153
00154 static int unload_module(void)
00155 {
00156 return ast_format_unregister(g729_f.name);
00157 }
00158
00159 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_FIRST, "Raw G729 data",
00160 .load = load_module,
00161 .unload = unload_module,
00162 );