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 #include <unistd.h>
00029 #include <netinet/in.h>
00030 #include <arpa/inet.h>
00031 #include <stdlib.h>
00032 #include <stdio.h>
00033 #include <errno.h>
00034 #include <string.h>
00035 #include <sys/time.h>
00036
00037 #include "asterisk.h"
00038
00039 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 7221 $")
00040
00041 #include "asterisk/lock.h"
00042 #include "asterisk/channel.h"
00043 #include "asterisk/file.h"
00044 #include "asterisk/logger.h"
00045 #include "asterisk/sched.h"
00046 #include "asterisk/module.h"
00047
00048 #include "../channels/adtranvofr.h"
00049
00050
00051 #define G723_MAX_SIZE 1024
00052
00053 struct ast_filestream {
00054
00055 void *reserved[AST_RESERVED_POINTERS];
00056
00057 FILE *f;
00058 struct ast_filestream *next;
00059 struct ast_frame *fr;
00060 struct timeval orig;
00061 char buf[G723_MAX_SIZE + AST_FRIENDLY_OFFSET];
00062 };
00063
00064
00065 AST_MUTEX_DEFINE_STATIC(g723_lock);
00066 static int glistcnt = 0;
00067
00068 static char *name = "g723sf";
00069 static char *desc = "G.723.1 Simple Timestamp File Format";
00070 static char *exts = "g723|g723sf";
00071
00072 static struct ast_filestream *g723_open(FILE *f)
00073 {
00074
00075
00076
00077 struct ast_filestream *tmp;
00078 if ((tmp = malloc(sizeof(struct ast_filestream)))) {
00079 memset(tmp, 0, sizeof(struct ast_filestream));
00080 if (ast_mutex_lock(&g723_lock)) {
00081 ast_log(LOG_WARNING, "Unable to lock g723 list\n");
00082 free(tmp);
00083 return NULL;
00084 }
00085 tmp->f = f;
00086 tmp->fr = (struct ast_frame *)tmp->buf;
00087 tmp->fr->data = tmp->buf + sizeof(struct ast_frame);
00088 tmp->fr->frametype = AST_FRAME_VOICE;
00089 tmp->fr->subclass = AST_FORMAT_G723_1;
00090
00091 tmp->fr->src = name;
00092 tmp->fr->mallocd = 0;
00093 glistcnt++;
00094 ast_mutex_unlock(&g723_lock);
00095 ast_update_use_count();
00096 }
00097 return tmp;
00098 }
00099
00100 static struct ast_filestream *g723_rewrite(FILE *f, const char *comment)
00101 {
00102
00103
00104
00105 struct ast_filestream *tmp;
00106 if ((tmp = malloc(sizeof(struct ast_filestream)))) {
00107 memset(tmp, 0, sizeof(struct ast_filestream));
00108 if (ast_mutex_lock(&g723_lock)) {
00109 ast_log(LOG_WARNING, "Unable to lock g723 list\n");
00110 free(tmp);
00111 return NULL;
00112 }
00113 tmp->f = f;
00114 glistcnt++;
00115 ast_mutex_unlock(&g723_lock);
00116 ast_update_use_count();
00117 } else
00118 ast_log(LOG_WARNING, "Out of memory\n");
00119 return tmp;
00120 }
00121
00122 static struct ast_frame *g723_read(struct ast_filestream *s, int *whennext)
00123 {
00124 unsigned short size;
00125 int res;
00126 int delay;
00127
00128 if (fread(&delay, 1, 4, s->f) == 4)
00129 delay = ntohl(delay);
00130 else
00131 delay = -1;
00132 if (fread(&size, 1, 2, s->f) != 2) {
00133
00134
00135 return NULL;
00136 }
00137
00138 size = ntohs(size);
00139 if (size > G723_MAX_SIZE - sizeof(struct ast_frame)) {
00140 ast_log(LOG_WARNING, "Size %d is invalid\n", size);
00141
00142
00143
00144 return NULL;
00145 }
00146
00147 s->fr->offset = AST_FRIENDLY_OFFSET;
00148 s->fr->datalen = size;
00149 s->fr->data = s->buf + sizeof(struct ast_frame) + AST_FRIENDLY_OFFSET;
00150 if ((res = fread(s->fr->data, 1, size, s->f)) != size) {
00151 ast_log(LOG_WARNING, "Short read (%d of %d bytes) (%s)!\n", res, size, strerror(errno));
00152 return NULL;
00153 }
00154 #if 0
00155
00156 if (delay < 50)
00157 s->fr->timelen = 30;
00158 else
00159 s->fr->timelen = delay;
00160 #else
00161 s->fr->samples = 240;
00162 #endif
00163 *whennext = s->fr->samples;
00164 return s->fr;
00165 }
00166
00167 static void g723_close(struct ast_filestream *s)
00168 {
00169 if (ast_mutex_lock(&g723_lock)) {
00170 ast_log(LOG_WARNING, "Unable to lock g723 list\n");
00171 return;
00172 }
00173 glistcnt--;
00174 ast_mutex_unlock(&g723_lock);
00175 ast_update_use_count();
00176 fclose(s->f);
00177 free(s);
00178 s = NULL;
00179 }
00180
00181
00182 static int g723_write(struct ast_filestream *fs, struct ast_frame *f)
00183 {
00184 u_int32_t delay;
00185 u_int16_t size;
00186 int res;
00187 if (fs->fr) {
00188 ast_log(LOG_WARNING, "Asked to write on a read stream??\n");
00189 return -1;
00190 }
00191 if (f->frametype != AST_FRAME_VOICE) {
00192 ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
00193 return -1;
00194 }
00195 if (f->subclass != AST_FORMAT_G723_1) {
00196 ast_log(LOG_WARNING, "Asked to write non-g723 frame!\n");
00197 return -1;
00198 }
00199 delay = 0;
00200 if (f->datalen <= 0) {
00201 ast_log(LOG_WARNING, "Short frame ignored (%d bytes long?)\n", f->datalen);
00202 return 0;
00203 }
00204 if ((res = fwrite(&delay, 1, 4, fs->f)) != 4) {
00205 ast_log(LOG_WARNING, "Unable to write delay: res=%d (%s)\n", res, strerror(errno));
00206 return -1;
00207 }
00208 size = htons(f->datalen);
00209 if ((res = fwrite(&size, 1, 2, fs->f)) != 2) {
00210 ast_log(LOG_WARNING, "Unable to write size: res=%d (%s)\n", res, strerror(errno));
00211 return -1;
00212 }
00213 if ((res = fwrite(f->data, 1, f->datalen, fs->f)) != f->datalen) {
00214 ast_log(LOG_WARNING, "Unable to write frame: res=%d (%s)\n", res, strerror(errno));
00215 return -1;
00216 }
00217 return 0;
00218 }
00219
00220 static int g723_seek(struct ast_filestream *fs, long sample_offset, int whence)
00221 {
00222 return -1;
00223 }
00224
00225 static int g723_trunc(struct ast_filestream *fs)
00226 {
00227
00228 if (ftruncate(fileno(fs->f), ftell(fs->f)) < 0)
00229 return -1;
00230 return 0;
00231 }
00232
00233 static long g723_tell(struct ast_filestream *fs)
00234 {
00235 return -1;
00236 }
00237
00238 static char *g723_getcomment(struct ast_filestream *s)
00239 {
00240 return NULL;
00241 }
00242
00243 int load_module()
00244 {
00245 return ast_format_register(name, exts, AST_FORMAT_G723_1,
00246 g723_open,
00247 g723_rewrite,
00248 g723_write,
00249 g723_seek,
00250 g723_trunc,
00251 g723_tell,
00252 g723_read,
00253 g723_close,
00254 g723_getcomment);
00255
00256
00257 }
00258
00259 int unload_module()
00260 {
00261 return ast_format_unregister(name);
00262 }
00263
00264 int usecount()
00265 {
00266 return glistcnt;
00267 }
00268
00269 char *description()
00270 {
00271 return desc;
00272 }
00273
00274
00275 char *key()
00276 {
00277 return ASTERISK_GPL_KEY;
00278 }