#include "asterisk.h"
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <netinet/in.h>
#include <string.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <sys/mman.h>
#include <zaptel/zaptel.h>
#include "asterisk/lock.h"
#include "asterisk/translate.h"
#include "asterisk/config.h"
#include "asterisk/options.h"
#include "asterisk/module.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/utils.h"
#include "asterisk/linkedlists.h"
Include dependency graph for codec_zap.c:
Go to the source code of this file.
Data Structures | |
struct | format_map |
struct | pvt |
struct | translator |
Defines | |
#define | BUFFER_SAMPLES 8000 |
Functions | |
static | AST_LIST_HEAD_STATIC (translators, translator) |
AST_MODULE_INFO (ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT,"Generic Zaptel Transcoder Codec Translator",.load=load_module,.unload=unload_module,.reload=reload,) | |
static void | build_translators (struct format_map *map, unsigned int dstfmts, unsigned int srcfmts) |
static void | drop_translator (int dst, int src) |
static struct ast_frame * | fakesrc_sample (void) |
static int | find_transcoders (void) |
static int | load_module (void) |
static void | parse_config (void) |
static int | register_translator (int dst, int src) |
static int | reload (void) |
static int | unload_module (void) |
static void | unregister_translators (void) |
static void | zap_destroy (struct ast_trans_pvt *pvt) |
static int | zap_framein (struct ast_trans_pvt *pvt, struct ast_frame *f) |
static struct ast_frame * | zap_frameout (struct ast_trans_pvt *pvt) |
static int | zap_new (struct ast_trans_pvt *pvt) |
static int | zap_translate (struct ast_trans_pvt *pvt, int dest, int source) |
Variables | |
static struct format_map | global_format_map = { { { 0 } } } |
static unsigned int | global_useplc = 0 |
Definition in file codec_zap.c.
#define BUFFER_SAMPLES 8000 |
Definition at line 59 of file codec_zap.c.
static AST_LIST_HEAD_STATIC | ( | translators | , | |
translator | ||||
) | [static] |
AST_MODULE_INFO | ( | ASTERISK_GPL_KEY | , | |
AST_MODFLAG_DEFAULT | , | |||
"Generic Zaptel Transcoder Codec Translator" | , | |||
. | load = load_module , |
|||
. | unload = unload_module , |
|||
. | reload = reload | |||
) |
static void build_translators | ( | struct format_map * | map, | |
unsigned int | dstfmts, | |||
unsigned int | srcfmts | |||
) | [static] |
Definition at line 335 of file codec_zap.c.
References global_format_map, map, format_map::map, and register_translator().
Referenced by find_transcoders().
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 }
static void drop_translator | ( | int | dst, | |
int | src | |||
) | [static] |
Definition at line 281 of file codec_zap.c.
References AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_unregister_translator(), ast_translator::dstfmt, free, global_format_map, format_map::map, ast_translator::srcfmt, and translator::t.
Referenced by find_transcoders().
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 }
static struct ast_frame* fakesrc_sample | ( | void | ) | [static] |
Definition at line 235 of file codec_zap.c.
References AST_FRAME_VOICE, and f.
Referenced by register_translator().
00236 { 00237 /* Don't bother really trying to test hardware ones. */ 00238 static struct ast_frame f = { 00239 .frametype = AST_FRAME_VOICE, 00240 .samples = 160, 00241 .src = __PRETTY_FUNCTION__ 00242 }; 00243 00244 return &f; 00245 }
static int find_transcoders | ( | void | ) | [static] |
Definition at line 356 of file codec_zap.c.
References ast_log(), ast_verbose(), build_translators(), drop_translator(), global_format_map, LOG_DEBUG, format_map::map, map, option_verbose, and VERBOSE_PREFIX_2.
Referenced by load_module().
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 }
static int load_module | ( | void | ) | [static] |
Definition at line 409 of file codec_zap.c.
References find_transcoders(), and parse_config().
00410 { 00411 parse_config(); 00412 find_transcoders(); 00413 00414 return 0; 00415 }
static void parse_config | ( | void | ) | [static] |
Definition at line 315 of file codec_zap.c.
References ast_config_load(), ast_true(), ast_variable_browse(), ast_verbose(), option_verbose, var, and VERBOSE_PREFIX_3.
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 }
static int register_translator | ( | int | dst, | |
int | src | |||
) | [static] |
Definition at line 247 of file codec_zap.c.
References ast_calloc, ast_getformatname(), AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_register_translator, BUFFER_SAMPLES, fakesrc_sample(), free, global_format_map, format_map::map, zap_destroy(), zap_framein(), zap_frameout(), and zap_new().
Referenced by build_translators().
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 }
static int reload | ( | void | ) | [static] |
Definition at line 388 of file codec_zap.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, parse_config(), translator::t, and ast_translator::useplc.
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 }
static int unload_module | ( | void | ) | [static] |
Definition at line 402 of file codec_zap.c.
References unregister_translators().
00403 { 00404 unregister_translators(); 00405 00406 return 0; 00407 }
static void unregister_translators | ( | void | ) | [static] |
Definition at line 303 of file codec_zap.c.
References AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, ast_unregister_translator(), free, and translator::t.
Referenced by unload_module().
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 }
static void zap_destroy | ( | struct ast_trans_pvt * | pvt | ) | [static] |
Definition at line 172 of file codec_zap.c.
References pvt::fd, pvt::hdr, and ast_trans_pvt::pvt.
Referenced by register_translator().
00173 { 00174 struct pvt *ztp = pvt->pvt; 00175 00176 munmap(ztp->hdr, sizeof(*ztp->hdr)); 00177 close(ztp->fd); 00178 }
static int zap_framein | ( | struct ast_trans_pvt * | pvt, | |
struct ast_frame * | f | |||
) | [static] |
Definition at line 87 of file codec_zap.c.
References ast_log(), f, pvt::fake, pvt::hdr, LOG_WARNING, ast_trans_pvt::pvt, and ast_trans_pvt::samples.
Referenced by register_translator().
00088 { 00089 struct pvt *ztp = pvt->pvt; 00090 struct zt_transcode_header *hdr = ztp->hdr; 00091 00092 if (!f->subclass) { 00093 /* Fake a return frame for calculation purposes */ 00094 ztp->fake = 2; 00095 pvt->samples = f->samples; 00096 return 0; 00097 } 00098 00099 if (!hdr->srclen) 00100 /* Copy at front of buffer */ 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 /* Very unlikely */ 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 }
static struct ast_frame* zap_frameout | ( | struct ast_trans_pvt * | pvt | ) | [static] |
Definition at line 121 of file codec_zap.c.
References AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_log(), ast_frame::data, ast_frame::datalen, pvt::f, pvt::fake, pvt::fd, ast_frame::frametype, pvt::hdr, LOG_WARNING, ast_frame::mallocd, ast_frame::offset, ast_trans_pvt::pvt, ast_trans_pvt::samples, ast_frame::samples, and ast_frame::subclass.
Referenced by register_translator().
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 }
static int zap_new | ( | struct ast_trans_pvt * | pvt | ) | [static] |
Definition at line 230 of file codec_zap.c.
References ast_translator::dstfmt, ast_translator::srcfmt, ast_trans_pvt::t, and zap_translate().
Referenced by register_translator().
00231 { 00232 return zap_translate(pvt, pvt->t->dstfmt, pvt->t->srcfmt); 00233 }
static int zap_translate | ( | struct ast_trans_pvt * | pvt, | |
int | dest, | |||
int | source | |||
) | [static] |
Definition at line 180 of file codec_zap.c.
References ast_log(), pvt::fd, pvt::hdr, LOG_ERROR, LOG_WARNING, and ast_trans_pvt::pvt.
Referenced by zap_new().
00181 { 00182 /* Request translation through zap if possible */ 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 }
struct format_map global_format_map = { { { 0 } } } [static] |
Definition at line 67 of file codec_zap.c.
Referenced by build_translators(), drop_translator(), find_transcoders(), and register_translator().
unsigned int global_useplc = 0 [static] |
Definition at line 61 of file codec_zap.c.