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
00032
00033
00034 #include "asterisk.h"
00035
00036 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
00037
00038 #include <fcntl.h>
00039 #include <stdlib.h>
00040 #include <unistd.h>
00041 #include <netinet/in.h>
00042 #include <string.h>
00043 #include <stdio.h>
00044 #include <sys/ioctl.h>
00045 #include <errno.h>
00046 #include <sys/mman.h>
00047 #include <zaptel/zaptel.h>
00048
00049 #include "asterisk/lock.h"
00050 #include "asterisk/translate.h"
00051 #include "asterisk/config.h"
00052 #include "asterisk/options.h"
00053 #include "asterisk/module.h"
00054 #include "asterisk/logger.h"
00055 #include "asterisk/channel.h"
00056 #include "asterisk/utils.h"
00057 #include "asterisk/linkedlists.h"
00058
00059 #define BUFFER_SAMPLES 8000
00060
00061 static unsigned int global_useplc = 0;
00062
00063 struct format_map {
00064 unsigned int map[32][32];
00065 };
00066
00067 static struct format_map global_format_map = { { { 0 } } };
00068
00069 struct translator {
00070 struct ast_translator t;
00071 AST_LIST_ENTRY(translator) entry;
00072 };
00073
00074 static AST_LIST_HEAD_STATIC(translators, translator);
00075
00076 struct pvt {
00077 int fd;
00078 int fake;
00079 #ifdef DEBUG_TRANSCODE
00080 int totalms;
00081 int lasttotalms;
00082 #endif
00083 struct zt_transcode_header *hdr;
00084 struct ast_frame f;
00085 };
00086
00087 static int zap_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
00088 {
00089 struct pvt *ztp = pvt->pvt;
00090 struct zt_transcode_header *hdr = ztp->hdr;
00091
00092 if (!f->subclass) {
00093
00094 ztp->fake = 2;
00095 pvt->samples = f->samples;
00096 return 0;
00097 }
00098
00099 if (!hdr->srclen)
00100
00101 hdr->srcoffset = 0;
00102
00103 if (hdr->srclen + f->datalen > sizeof(hdr->srcdata)) {
00104 ast_log(LOG_WARNING, "Out of space for codec translation!\n");
00105 return -1;
00106 }
00107
00108 if (hdr->srclen + f->datalen + hdr->srcoffset > sizeof(hdr->srcdata)) {
00109
00110 memmove(hdr->srcdata, hdr->srcdata + hdr->srcoffset, hdr->srclen);
00111 hdr->srcoffset = 0;
00112 }
00113
00114 memcpy(hdr->srcdata + hdr->srcoffset + hdr->srclen, f->data, f->datalen);
00115 hdr->srclen += f->datalen;
00116 pvt->samples += f->samples;
00117
00118 return -1;
00119 }
00120
00121 static struct ast_frame *zap_frameout(struct ast_trans_pvt *pvt)
00122 {
00123 struct pvt *ztp = pvt->pvt;
00124 struct zt_transcode_header *hdr = ztp->hdr;
00125 unsigned int x;
00126
00127 if (ztp->fake == 2) {
00128 ztp->fake = 1;
00129 ztp->f.frametype = AST_FRAME_VOICE;
00130 ztp->f.subclass = 0;
00131 ztp->f.samples = 160;
00132 ztp->f.data = NULL;
00133 ztp->f.offset = 0;
00134 ztp->f.datalen = 0;
00135 ztp->f.mallocd = 0;
00136 pvt->samples = 0;
00137 } else if (ztp->fake == 1) {
00138 return NULL;
00139 } else {
00140 if (hdr->dstlen) {
00141 #ifdef DEBUG_TRANSCODE
00142 ztp->totalms += hdr->dstsamples;
00143 if ((ztp->totalms - ztp->lasttotalms) > 8000) {
00144 printf("Whee %p, %d (%d to %d)\n", ztp, hdr->dstlen, ztp->lasttotalms, ztp->totalms);
00145 ztp->lasttotalms = ztp->totalms;
00146 }
00147 #endif
00148 ztp->f.frametype = AST_FRAME_VOICE;
00149 ztp->f.subclass = hdr->dstfmt;
00150 ztp->f.samples = hdr->dstsamples;
00151 ztp->f.data = hdr->dstdata + hdr->dstoffset;
00152 ztp->f.offset = hdr->dstoffset;
00153 ztp->f.datalen = hdr->dstlen;
00154 ztp->f.mallocd = 0;
00155 pvt->samples -= ztp->f.samples;
00156 hdr->dstlen = 0;
00157
00158 } else {
00159 if (hdr->srclen) {
00160 hdr->dstoffset = AST_FRIENDLY_OFFSET;
00161 x = ZT_TCOP_TRANSCODE;
00162 if (ioctl(ztp->fd, ZT_TRANSCODE_OP, &x))
00163 ast_log(LOG_WARNING, "Failed to transcode: %s\n", strerror(errno));
00164 }
00165 return NULL;
00166 }
00167 }
00168
00169 return &ztp->f;
00170 }
00171
00172 static void zap_destroy(struct ast_trans_pvt *pvt)
00173 {
00174 struct pvt *ztp = pvt->pvt;
00175
00176 munmap(ztp->hdr, sizeof(*ztp->hdr));
00177 close(ztp->fd);
00178 }
00179
00180 static int zap_translate(struct ast_trans_pvt *pvt, int dest, int source)
00181 {
00182
00183 int fd;
00184 unsigned int x = ZT_TCOP_ALLOCATE;
00185 struct pvt *ztp = pvt->pvt;
00186 struct zt_transcode_header *hdr;
00187 int flags;
00188
00189 if ((fd = open("/dev/zap/transcode", O_RDWR)) < 0)
00190 return -1;
00191 flags = fcntl(fd, F_GETFL);
00192 if (flags > - 1) {
00193 if (fcntl(fd, F_SETFL, flags | O_NONBLOCK))
00194 ast_log(LOG_WARNING, "Could not set non-block mode!\n");
00195 }
00196
00197
00198 if ((hdr = mmap(NULL, sizeof(*hdr), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED) {
00199 ast_log(LOG_ERROR, "Memory Map failed for transcoding (%s)\n", strerror(errno));
00200 close(fd);
00201
00202 return -1;
00203 }
00204
00205 if (hdr->magic != ZT_TRANSCODE_MAGIC) {
00206 ast_log(LOG_ERROR, "Transcoder header (%08x) wasn't magic. Abandoning\n", hdr->magic);
00207 munmap(hdr, sizeof(*hdr));
00208 close(fd);
00209
00210 return -1;
00211 }
00212
00213 hdr->srcfmt = (1 << source);
00214 hdr->dstfmt = (1 << dest);
00215 if (ioctl(fd, ZT_TRANSCODE_OP, &x)) {
00216 ast_log(LOG_ERROR, "Unable to attach transcoder: %s\n", strerror(errno));
00217 munmap(hdr, sizeof(*hdr));
00218 close(fd);
00219
00220 return -1;
00221 }
00222
00223 ztp = pvt->pvt;
00224 ztp->fd = fd;
00225 ztp->hdr = hdr;
00226
00227 return 0;
00228 }
00229
00230 static int zap_new(struct ast_trans_pvt *pvt)
00231 {
00232 return zap_translate(pvt, pvt->t->dstfmt, pvt->t->srcfmt);
00233 }
00234
00235 static struct ast_frame *fakesrc_sample(void)
00236 {
00237
00238 static struct ast_frame f = {
00239 .frametype = AST_FRAME_VOICE,
00240 .samples = 160,
00241 .src = __PRETTY_FUNCTION__
00242 };
00243
00244 return &f;
00245 }
00246
00247 static int register_translator(int dst, int src)
00248 {
00249 struct translator *zt;
00250 int res;
00251
00252 if (!(zt = ast_calloc(1, sizeof(*zt))))
00253 return -1;
00254
00255 snprintf((char *) (zt->t.name), sizeof(zt->t.name), "zap%sto%s",
00256 ast_getformatname((1 << src)), ast_getformatname((1 << dst)));
00257 zt->t.srcfmt = (1 << src);
00258 zt->t.dstfmt = (1 << dst);
00259 zt->t.newpvt = zap_new;
00260 zt->t.framein = zap_framein;
00261 zt->t.frameout = zap_frameout;
00262 zt->t.destroy = zap_destroy;
00263 zt->t.sample = fakesrc_sample;
00264 zt->t.useplc = global_useplc;
00265 zt->t.buf_size = BUFFER_SAMPLES * 2;
00266 zt->t.desc_size = sizeof(struct pvt);
00267 if ((res = ast_register_translator(&zt->t))) {
00268 free(zt);
00269 return -1;
00270 }
00271
00272 AST_LIST_LOCK(&translators);
00273 AST_LIST_INSERT_HEAD(&translators, zt, entry);
00274 AST_LIST_UNLOCK(&translators);
00275
00276 global_format_map.map[dst][src] = 1;
00277
00278 return res;
00279 }
00280
00281 static void drop_translator(int dst, int src)
00282 {
00283 struct translator *cur;
00284
00285 AST_LIST_LOCK(&translators);
00286 AST_LIST_TRAVERSE_SAFE_BEGIN(&translators, cur, entry) {
00287 if (cur->t.srcfmt != src)
00288 continue;
00289
00290 if (cur->t.dstfmt != dst)
00291 continue;
00292
00293 AST_LIST_REMOVE_CURRENT(&translators, entry);
00294 ast_unregister_translator(&cur->t);
00295 free(cur);
00296 global_format_map.map[dst][src] = 0;
00297 break;
00298 }
00299 AST_LIST_TRAVERSE_SAFE_END;
00300 AST_LIST_UNLOCK(&translators);
00301 }
00302
00303 static void unregister_translators(void)
00304 {
00305 struct translator *cur;
00306
00307 AST_LIST_LOCK(&translators);
00308 while ((cur = AST_LIST_REMOVE_HEAD(&translators, entry))) {
00309 ast_unregister_translator(&cur->t);
00310 free(cur);
00311 }
00312 AST_LIST_UNLOCK(&translators);
00313 }
00314
00315 static void parse_config(void)
00316 {
00317 struct ast_variable *var;
00318 struct ast_config *cfg = ast_config_load("codecs.conf");
00319
00320 if (!cfg)
00321 return;
00322
00323 for (var = ast_variable_browse(cfg, "plc"); var; var = var->next) {
00324 if (!strcasecmp(var->name, "genericplc")) {
00325 global_useplc = ast_true(var->value);
00326 if (option_verbose > 2)
00327 ast_verbose(VERBOSE_PREFIX_3 "codec_zap: %susing generic PLC\n",
00328 global_useplc ? "" : "not ");
00329 }
00330 }
00331
00332 ast_config_destroy(cfg);
00333 }
00334
00335 static void build_translators(struct format_map *map, unsigned int dstfmts, unsigned int srcfmts)
00336 {
00337 unsigned int src, dst;
00338
00339 for (src = 0; src < 32; src++) {
00340 for (dst = 0; dst < 32; dst++) {
00341 if (!(srcfmts & (1 << src)))
00342 continue;
00343
00344 if (!(dstfmts & (1 << dst)))
00345 continue;
00346
00347 if (global_format_map.map[dst][src])
00348 continue;
00349
00350 if (!register_translator(dst, src))
00351 map->map[dst][src] = 1;
00352 }
00353 }
00354 }
00355
00356 static int find_transcoders(void)
00357 {
00358 struct zt_transcode_info info = { 0, };
00359 struct format_map map = { { { 0 } } };
00360 int fd, res;
00361 unsigned int x, y;
00362
00363 info.op = ZT_TCOP_GETINFO;
00364 if ((fd = open("/dev/zap/transcode", O_RDWR)) < 0) {
00365 ast_log(LOG_DEBUG, "No Zaptel transcoder support!\n");
00366 return 0;
00367 }
00368 for (info.tcnum = 0; !(res = ioctl(fd, ZT_TRANSCODE_OP, &info)); info.tcnum++) {
00369 if (option_verbose > 1)
00370 ast_verbose(VERBOSE_PREFIX_2 "Found transcoder '%s'.\n", info.name);
00371 build_translators(&map, info.dstfmts, info.srcfmts);
00372 }
00373 close(fd);
00374
00375 if (!info.tcnum && (option_verbose > 1))
00376 ast_verbose(VERBOSE_PREFIX_2 "No hardware transcoders found.\n");
00377
00378 for (x = 0; x < 32; x++) {
00379 for (y = 0; y < 32; y++) {
00380 if (!map.map[x][y] && global_format_map.map[x][y])
00381 drop_translator(x, y);
00382 }
00383 }
00384
00385 return 0;
00386 }
00387
00388 static int reload(void)
00389 {
00390 struct translator *cur;
00391
00392 parse_config();
00393
00394 AST_LIST_LOCK(&translators);
00395 AST_LIST_TRAVERSE(&translators, cur, entry)
00396 cur->t.useplc = global_useplc;
00397 AST_LIST_UNLOCK(&translators);
00398
00399 return 0;
00400 }
00401
00402 static int unload_module(void)
00403 {
00404 unregister_translators();
00405
00406 return 0;
00407 }
00408
00409 static int load_module(void)
00410 {
00411 parse_config();
00412 find_transcoders();
00413
00414 return 0;
00415 }
00416
00417 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Generic Zaptel Transcoder Codec Translator",
00418 .load = load_module,
00419 .unload = unload_module,
00420 .reload = reload,
00421 );