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
00030
00031 #include <unistd.h>
00032 #include <netinet/in.h>
00033 #include <arpa/inet.h>
00034 #include <stdlib.h>
00035 #include <sys/time.h>
00036 #include <stdio.h>
00037 #include <errno.h>
00038 #include <string.h>
00039
00040 #include "asterisk.h"
00041
00042 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 7221 $")
00043
00044 #include "asterisk/lock.h"
00045 #include "asterisk/options.h"
00046 #include "asterisk/channel.h"
00047 #include "asterisk/file.h"
00048 #include "asterisk/logger.h"
00049 #include "asterisk/sched.h"
00050 #include "asterisk/module.h"
00051 #include "asterisk/endian.h"
00052
00053 #define RATE_40 0
00054 #define RATE_32 1
00055 #define RATE_24 2
00056 #define RATE_16 3
00057
00058
00059 #define FRAME_TIME 10
00060
00061
00062 static int frame_size[4] = {
00063 FRAME_TIME * 5,
00064 FRAME_TIME * 4,
00065 FRAME_TIME * 3,
00066 FRAME_TIME * 2
00067 };
00068
00069 struct ast_filestream {
00070
00071 void *reserved[AST_RESERVED_POINTERS];
00072
00073 FILE *f;
00074 int rate;
00075 struct ast_frame fr;
00076 char waste[AST_FRIENDLY_OFFSET];
00077 char empty;
00078 unsigned char g726[FRAME_TIME * 5];
00079 };
00080
00081 AST_MUTEX_DEFINE_STATIC(g726_lock);
00082 static int glistcnt = 0;
00083
00084 static char *desc = "Raw G.726 (16/24/32/40kbps) data";
00085 static char *name40 = "g726-40";
00086 static char *name32 = "g726-32";
00087 static char *name24 = "g726-24";
00088 static char *name16 = "g726-16";
00089 static char *exts40 = "g726-40";
00090 static char *exts32 = "g726-32";
00091 static char *exts24 = "g726-24";
00092 static char *exts16 = "g726-16";
00093
00094
00095
00096
00097 static struct ast_filestream *g726_40_open(FILE *f)
00098 {
00099
00100
00101
00102 struct ast_filestream *tmp;
00103 if ((tmp = malloc(sizeof(struct ast_filestream)))) {
00104 memset(tmp, 0, sizeof(struct ast_filestream));
00105 if (ast_mutex_lock(&g726_lock)) {
00106 ast_log(LOG_WARNING, "Unable to lock g726 list.\n");
00107 free(tmp);
00108 return NULL;
00109 }
00110 tmp->f = f;
00111 tmp->rate = RATE_40;
00112 tmp->fr.data = tmp->g726;
00113 tmp->fr.frametype = AST_FRAME_VOICE;
00114 tmp->fr.subclass = AST_FORMAT_G726;
00115
00116 tmp->fr.src = name40;
00117 tmp->fr.mallocd = 0;
00118 glistcnt++;
00119 if (option_debug)
00120 ast_log(LOG_DEBUG, "Created filestream G.726-%dk.\n",
00121 40 - tmp->rate * 8);
00122 ast_mutex_unlock(&g726_lock);
00123 ast_update_use_count();
00124 }
00125 return tmp;
00126 }
00127
00128 static struct ast_filestream *g726_32_open(FILE *f)
00129 {
00130
00131
00132
00133 struct ast_filestream *tmp;
00134 if ((tmp = malloc(sizeof(struct ast_filestream)))) {
00135 memset(tmp, 0, sizeof(struct ast_filestream));
00136 if (ast_mutex_lock(&g726_lock)) {
00137 ast_log(LOG_WARNING, "Unable to lock g726 list.\n");
00138 free(tmp);
00139 return NULL;
00140 }
00141 tmp->f = f;
00142 tmp->rate = RATE_32;
00143 tmp->fr.data = tmp->g726;
00144 tmp->fr.frametype = AST_FRAME_VOICE;
00145 tmp->fr.subclass = AST_FORMAT_G726;
00146
00147 tmp->fr.src = name32;
00148 tmp->fr.mallocd = 0;
00149 glistcnt++;
00150 if (option_debug)
00151 ast_log(LOG_DEBUG, "Created filestream G.726-%dk.\n",
00152 40 - tmp->rate * 8);
00153 ast_mutex_unlock(&g726_lock);
00154 ast_update_use_count();
00155 }
00156 return tmp;
00157 }
00158
00159 static struct ast_filestream *g726_24_open(FILE *f)
00160 {
00161
00162
00163
00164 struct ast_filestream *tmp;
00165 if ((tmp = malloc(sizeof(struct ast_filestream)))) {
00166 memset(tmp, 0, sizeof(struct ast_filestream));
00167 if (ast_mutex_lock(&g726_lock)) {
00168 ast_log(LOG_WARNING, "Unable to lock g726 list.\n");
00169 free(tmp);
00170 return NULL;
00171 }
00172 tmp->f = f;
00173 tmp->rate = RATE_24;
00174 tmp->fr.data = tmp->g726;
00175 tmp->fr.frametype = AST_FRAME_VOICE;
00176 tmp->fr.subclass = AST_FORMAT_G726;
00177
00178 tmp->fr.src = name24;
00179 tmp->fr.mallocd = 0;
00180 glistcnt++;
00181 if (option_debug)
00182 ast_log(LOG_DEBUG, "Created filestream G.726-%dk.\n",
00183 40 - tmp->rate * 8);
00184 ast_mutex_unlock(&g726_lock);
00185 ast_update_use_count();
00186 }
00187 return tmp;
00188 }
00189
00190 static struct ast_filestream *g726_16_open(FILE *f)
00191 {
00192
00193
00194
00195 struct ast_filestream *tmp;
00196 if ((tmp = malloc(sizeof(struct ast_filestream)))) {
00197 memset(tmp, 0, sizeof(struct ast_filestream));
00198 if (ast_mutex_lock(&g726_lock)) {
00199 ast_log(LOG_WARNING, "Unable to lock g726 list.\n");
00200 free(tmp);
00201 return NULL;
00202 }
00203 tmp->f = f;
00204 tmp->rate = RATE_16;
00205 tmp->fr.data = tmp->g726;
00206 tmp->fr.frametype = AST_FRAME_VOICE;
00207 tmp->fr.subclass = AST_FORMAT_G726;
00208
00209 tmp->fr.src = name16;
00210 tmp->fr.mallocd = 0;
00211 glistcnt++;
00212 if (option_debug)
00213 ast_log(LOG_DEBUG, "Created filestream G.726-%dk.\n",
00214 40 - tmp->rate * 8);
00215 ast_mutex_unlock(&g726_lock);
00216 ast_update_use_count();
00217 }
00218 return tmp;
00219 }
00220
00221 static struct ast_filestream *g726_40_rewrite(FILE *f, const char *comment)
00222 {
00223
00224
00225
00226 struct ast_filestream *tmp;
00227 if ((tmp = malloc(sizeof(struct ast_filestream)))) {
00228 memset(tmp, 0, sizeof(struct ast_filestream));
00229 if (ast_mutex_lock(&g726_lock)) {
00230 ast_log(LOG_WARNING, "Unable to lock g726 list.\n");
00231 free(tmp);
00232 return NULL;
00233 }
00234 tmp->f = f;
00235 tmp->rate = RATE_40;
00236 glistcnt++;
00237 if (option_debug)
00238 ast_log(LOG_DEBUG, "Created filestream G.726-%dk.\n",
00239 40 - tmp->rate * 8);
00240 ast_mutex_unlock(&g726_lock);
00241 ast_update_use_count();
00242 } else
00243 ast_log(LOG_WARNING, "Out of memory\n");
00244 return tmp;
00245 }
00246
00247 static struct ast_filestream *g726_32_rewrite(FILE *f, const char *comment)
00248 {
00249
00250
00251
00252 struct ast_filestream *tmp;
00253 if ((tmp = malloc(sizeof(struct ast_filestream)))) {
00254 memset(tmp, 0, sizeof(struct ast_filestream));
00255 if (ast_mutex_lock(&g726_lock)) {
00256 ast_log(LOG_WARNING, "Unable to lock g726 list.\n");
00257 free(tmp);
00258 return NULL;
00259 }
00260 tmp->f = f;
00261 tmp->rate = RATE_32;
00262 glistcnt++;
00263 if (option_debug)
00264 ast_log(LOG_DEBUG, "Created filestream G.726-%dk.\n",
00265 40 - tmp->rate * 8);
00266 ast_mutex_unlock(&g726_lock);
00267 ast_update_use_count();
00268 } else
00269 ast_log(LOG_WARNING, "Out of memory\n");
00270 return tmp;
00271 }
00272
00273 static struct ast_filestream *g726_24_rewrite(FILE *f, const char *comment)
00274 {
00275
00276
00277
00278 struct ast_filestream *tmp;
00279 if ((tmp = malloc(sizeof(struct ast_filestream)))) {
00280 memset(tmp, 0, sizeof(struct ast_filestream));
00281 if (ast_mutex_lock(&g726_lock)) {
00282 ast_log(LOG_WARNING, "Unable to lock g726 list.\n");
00283 free(tmp);
00284 return NULL;
00285 }
00286 tmp->f = f;
00287 tmp->rate = RATE_24;
00288 glistcnt++;
00289 if (option_debug)
00290 ast_log(LOG_DEBUG, "Created filestream G.726-%dk.\n",
00291 40 - tmp->rate * 8);
00292 ast_mutex_unlock(&g726_lock);
00293 ast_update_use_count();
00294 } else
00295 ast_log(LOG_WARNING, "Out of memory\n");
00296 return tmp;
00297 }
00298
00299 static struct ast_filestream *g726_16_rewrite(FILE *f, const char *comment)
00300 {
00301
00302
00303
00304 struct ast_filestream *tmp;
00305 if ((tmp = malloc(sizeof(struct ast_filestream)))) {
00306 memset(tmp, 0, sizeof(struct ast_filestream));
00307 if (ast_mutex_lock(&g726_lock)) {
00308 ast_log(LOG_WARNING, "Unable to lock g726 list.\n");
00309 free(tmp);
00310 return NULL;
00311 }
00312 tmp->f = f;
00313 tmp->rate = RATE_16;
00314 glistcnt++;
00315 if (option_debug)
00316 ast_log(LOG_DEBUG, "Created filestream G.726-%dk.\n",
00317 40 - tmp->rate * 8);
00318 ast_mutex_unlock(&g726_lock);
00319 ast_update_use_count();
00320 } else
00321 ast_log(LOG_WARNING, "Out of memory\n");
00322 return tmp;
00323 }
00324
00325
00326
00327
00328 static void g726_close(struct ast_filestream *s)
00329 {
00330 if (ast_mutex_lock(&g726_lock)) {
00331 ast_log(LOG_WARNING, "Unable to lock g726 list.\n");
00332 return;
00333 }
00334 glistcnt--;
00335 if (option_debug)
00336 ast_log(LOG_DEBUG, "Closed filestream G.726-%dk.\n", 40 - s->rate * 8);
00337 ast_mutex_unlock(&g726_lock);
00338 ast_update_use_count();
00339 fclose(s->f);
00340 free(s);
00341 s = NULL;
00342 }
00343
00344 static struct ast_frame *g726_read(struct ast_filestream *s, int *whennext)
00345 {
00346 int res;
00347
00348 s->fr.frametype = AST_FRAME_VOICE;
00349 s->fr.subclass = AST_FORMAT_G726;
00350 s->fr.offset = AST_FRIENDLY_OFFSET;
00351 s->fr.samples = 8 * FRAME_TIME;
00352 s->fr.datalen = frame_size[s->rate];
00353 s->fr.mallocd = 0;
00354 s->fr.data = s->g726;
00355 if ((res = fread(s->g726, 1, s->fr.datalen, s->f)) != s->fr.datalen) {
00356 if (res)
00357 ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno));
00358 return NULL;
00359 }
00360 *whennext = s->fr.samples;
00361 return &s->fr;
00362 }
00363
00364 static int g726_write(struct ast_filestream *fs, struct ast_frame *f)
00365 {
00366 int res;
00367 if (f->frametype != AST_FRAME_VOICE) {
00368 ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
00369 return -1;
00370 }
00371 if (f->subclass != AST_FORMAT_G726) {
00372 ast_log(LOG_WARNING, "Asked to write non-G726 frame (%d)!\n",
00373 f->subclass);
00374 return -1;
00375 }
00376 if (f->datalen % frame_size[fs->rate]) {
00377 ast_log(LOG_WARNING, "Invalid data length %d, should be multiple of %d\n",
00378 f->datalen, frame_size[fs->rate]);
00379 return -1;
00380 }
00381 if ((res = fwrite(f->data, 1, f->datalen, fs->f)) != f->datalen) {
00382 ast_log(LOG_WARNING, "Bad write (%d/%d): %s\n",
00383 res, frame_size[fs->rate], strerror(errno));
00384 return -1;
00385 }
00386 return 0;
00387 }
00388
00389 static char *g726_getcomment(struct ast_filestream *s)
00390 {
00391 return NULL;
00392 }
00393
00394 static int g726_seek(struct ast_filestream *fs, long sample_offset, int whence)
00395 {
00396 return -1;
00397 }
00398
00399 static int g726_trunc(struct ast_filestream *fs)
00400 {
00401 return -1;
00402 }
00403
00404 static long g726_tell(struct ast_filestream *fs)
00405 {
00406 return -1;
00407 }
00408
00409
00410
00411
00412 int load_module()
00413 {
00414 int res;
00415
00416 res = ast_format_register(name40, exts40, AST_FORMAT_G726,
00417 g726_40_open,
00418 g726_40_rewrite,
00419 g726_write,
00420 g726_seek,
00421 g726_trunc,
00422 g726_tell,
00423 g726_read,
00424 g726_close,
00425 g726_getcomment);
00426 if (res) {
00427 ast_log(LOG_WARNING, "Failed to register format %s.\n", name40);
00428 return(-1);
00429 }
00430 res = ast_format_register(name32, exts32, AST_FORMAT_G726,
00431 g726_32_open,
00432 g726_32_rewrite,
00433 g726_write,
00434 g726_seek,
00435 g726_trunc,
00436 g726_tell,
00437 g726_read,
00438 g726_close,
00439 g726_getcomment);
00440 if (res) {
00441 ast_log(LOG_WARNING, "Failed to register format %s.\n", name32);
00442 return(-1);
00443 }
00444 res = ast_format_register(name24, exts24, AST_FORMAT_G726,
00445 g726_24_open,
00446 g726_24_rewrite,
00447 g726_write,
00448 g726_seek,
00449 g726_trunc,
00450 g726_tell,
00451 g726_read,
00452 g726_close,
00453 g726_getcomment);
00454 if (res) {
00455 ast_log(LOG_WARNING, "Failed to register format %s.\n", name24);
00456 return(-1);
00457 }
00458 res = ast_format_register(name16, exts16, AST_FORMAT_G726,
00459 g726_16_open,
00460 g726_16_rewrite,
00461 g726_write,
00462 g726_seek,
00463 g726_trunc,
00464 g726_tell,
00465 g726_read,
00466 g726_close,
00467 g726_getcomment);
00468 if (res) {
00469 ast_log(LOG_WARNING, "Failed to register format %s.\n", name16);
00470 return(-1);
00471 }
00472 return(0);
00473 }
00474
00475 int unload_module()
00476 {
00477 int res;
00478
00479 res = ast_format_unregister(name16);
00480 if (res) {
00481 ast_log(LOG_WARNING, "Failed to unregister format %s.\n", name16);
00482 return(-1);
00483 }
00484 res = ast_format_unregister(name24);
00485 if (res) {
00486 ast_log(LOG_WARNING, "Failed to unregister format %s.\n", name24);
00487 return(-1);
00488 }
00489 res = ast_format_unregister(name32);
00490 if (res) {
00491 ast_log(LOG_WARNING, "Failed to unregister format %s.\n", name32);
00492 return(-1);
00493 }
00494 res = ast_format_unregister(name40);
00495 if (res) {
00496 ast_log(LOG_WARNING, "Failed to unregister format %s.\n", name40);
00497 return(-1);
00498 }
00499 return(0);
00500 }
00501
00502 int usecount()
00503 {
00504 return glistcnt;
00505 }
00506
00507 char *description()
00508 {
00509 return desc;
00510 }
00511
00512 char *key()
00513 {
00514 return ASTERISK_GPL_KEY;
00515 }
00516