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 <sys/time.h>
00033 #include <stdio.h>
00034 #include <errno.h>
00035 #include <string.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 #include "asterisk/endian.h"
00048
00049
00050
00051
00052
00053 struct ast_filestream {
00054 void *reserved[AST_RESERVED_POINTERS];
00055
00056
00057
00058 FILE *f;
00059 struct ast_frame fr;
00060 char waste[AST_FRIENDLY_OFFSET];
00061 char empty;
00062 unsigned char ilbc[50];
00063 };
00064
00065
00066 AST_MUTEX_DEFINE_STATIC(ilbc_lock);
00067 static int glistcnt = 0;
00068
00069 static char *name = "iLBC";
00070 static char *desc = "Raw iLBC data";
00071 static char *exts = "ilbc";
00072
00073 static struct ast_filestream *ilbc_open(FILE *f)
00074 {
00075
00076
00077
00078 struct ast_filestream *tmp;
00079 if ((tmp = malloc(sizeof(struct ast_filestream)))) {
00080 memset(tmp, 0, sizeof(struct ast_filestream));
00081 if (ast_mutex_lock(&ilbc_lock)) {
00082 ast_log(LOG_WARNING, "Unable to lock ilbc list\n");
00083 free(tmp);
00084 return NULL;
00085 }
00086 tmp->f = f;
00087 tmp->fr.data = tmp->ilbc;
00088 tmp->fr.frametype = AST_FRAME_VOICE;
00089 tmp->fr.subclass = AST_FORMAT_ILBC;
00090
00091 tmp->fr.src = name;
00092 tmp->fr.mallocd = 0;
00093 glistcnt++;
00094 ast_mutex_unlock(&ilbc_lock);
00095 ast_update_use_count();
00096 }
00097 return tmp;
00098 }
00099
00100 static struct ast_filestream *ilbc_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(&ilbc_lock)) {
00109 ast_log(LOG_WARNING, "Unable to lock ilbc list\n");
00110 free(tmp);
00111 return NULL;
00112 }
00113 tmp->f = f;
00114 glistcnt++;
00115 ast_mutex_unlock(&ilbc_lock);
00116 ast_update_use_count();
00117 } else
00118 ast_log(LOG_WARNING, "Out of memory\n");
00119 return tmp;
00120 }
00121
00122 static void ilbc_close(struct ast_filestream *s)
00123 {
00124 if (ast_mutex_lock(&ilbc_lock)) {
00125 ast_log(LOG_WARNING, "Unable to lock ilbc list\n");
00126 return;
00127 }
00128 glistcnt--;
00129 ast_mutex_unlock(&ilbc_lock);
00130 ast_update_use_count();
00131 fclose(s->f);
00132 free(s);
00133 s = NULL;
00134 }
00135
00136 static struct ast_frame *ilbc_read(struct ast_filestream *s, int *whennext)
00137 {
00138 int res;
00139
00140 s->fr.frametype = AST_FRAME_VOICE;
00141 s->fr.subclass = AST_FORMAT_ILBC;
00142 s->fr.offset = AST_FRIENDLY_OFFSET;
00143 s->fr.samples = 240;
00144 s->fr.datalen = 50;
00145 s->fr.mallocd = 0;
00146 s->fr.data = s->ilbc;
00147 if ((res = fread(s->ilbc, 1, 50, s->f)) != 50) {
00148 if (res)
00149 ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno));
00150 return NULL;
00151 }
00152 *whennext = s->fr.samples;
00153 return &s->fr;
00154 }
00155
00156 static int ilbc_write(struct ast_filestream *fs, struct ast_frame *f)
00157 {
00158 int res;
00159 if (f->frametype != AST_FRAME_VOICE) {
00160 ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
00161 return -1;
00162 }
00163 if (f->subclass != AST_FORMAT_ILBC) {
00164 ast_log(LOG_WARNING, "Asked to write non-iLBC frame (%d)!\n", f->subclass);
00165 return -1;
00166 }
00167 if (f->datalen % 50) {
00168 ast_log(LOG_WARNING, "Invalid data length, %d, should be multiple of 50\n", f->datalen);
00169 return -1;
00170 }
00171 if ((res = fwrite(f->data, 1, f->datalen, fs->f)) != f->datalen) {
00172 ast_log(LOG_WARNING, "Bad write (%d/50): %s\n", res, strerror(errno));
00173 return -1;
00174 }
00175 return 0;
00176 }
00177
00178 static char *ilbc_getcomment(struct ast_filestream *s)
00179 {
00180 return NULL;
00181 }
00182
00183 static int ilbc_seek(struct ast_filestream *fs, long sample_offset, int whence)
00184 {
00185 long bytes;
00186 off_t min,cur,max,offset=0;
00187 min = 0;
00188 cur = ftell(fs->f);
00189 fseek(fs->f, 0, SEEK_END);
00190 max = ftell(fs->f);
00191
00192 bytes = 50 * (sample_offset / 240);
00193 if (whence == SEEK_SET)
00194 offset = bytes;
00195 else if (whence == SEEK_CUR || whence == SEEK_FORCECUR)
00196 offset = cur + bytes;
00197 else if (whence == SEEK_END)
00198 offset = max - bytes;
00199 if (whence != SEEK_FORCECUR) {
00200 offset = (offset > max)?max:offset;
00201 }
00202
00203 offset = (offset < min)?min:offset;
00204 if (fseek(fs->f, offset, SEEK_SET) < 0)
00205 return -1;
00206 return 0;
00207 }
00208
00209 static int ilbc_trunc(struct ast_filestream *fs)
00210 {
00211
00212 if (ftruncate(fileno(fs->f), ftell(fs->f)) < 0)
00213 return -1;
00214 return 0;
00215 }
00216
00217 static long ilbc_tell(struct ast_filestream *fs)
00218 {
00219 off_t offset;
00220 offset = ftell(fs->f);
00221 return (offset/50)*240;
00222 }
00223
00224 int load_module()
00225 {
00226 return ast_format_register(name, exts, AST_FORMAT_ILBC,
00227 ilbc_open,
00228 ilbc_rewrite,
00229 ilbc_write,
00230 ilbc_seek,
00231 ilbc_trunc,
00232 ilbc_tell,
00233 ilbc_read,
00234 ilbc_close,
00235 ilbc_getcomment);
00236
00237
00238 }
00239
00240 int unload_module()
00241 {
00242 return ast_format_unregister(name);
00243 }
00244
00245 int usecount()
00246 {
00247 return glistcnt;
00248 }
00249
00250 char *description()
00251 {
00252 return desc;
00253 }
00254
00255
00256 char *key()
00257 {
00258 return ASTERISK_GPL_KEY;
00259 }