#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 "asterisk/lock.h"
#include "asterisk/translate.h"
#include "asterisk/config.h"
#include "asterisk/options.h"
#include "asterisk/module.h"
#include "asterisk/cli.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/utils.h"
#include "asterisk/linkedlists.h"
#include "asterisk/dahdi_compat.h"
Go to the source code of this file.
Data Structures | |
struct | channel_usage |
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 DAHDI 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 | transcoder_show (int fd, int argc, char **argv) |
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 channel_usage | channels |
static struct ast_cli_entry | cli [] |
static struct ast_cli_entry | cli_deprecated [] |
static struct format_map | global_format_map = { { { 0 } } } |
static unsigned int | global_useplc = 0 |
static char | show_transcoder_usage [] |
static char | transcoder_show_usage [] |
Definition in file codec_dahdi.c.
#define BUFFER_SAMPLES 8000 |
Definition at line 60 of file codec_dahdi.c.
static AST_LIST_HEAD_STATIC | ( | translators | , | |
translator | ||||
) | [static] |
AST_MODULE_INFO | ( | ASTERISK_GPL_KEY | , | |
AST_MODFLAG_DEFAULT | , | |||
"Generic DAHDI 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 397 of file codec_dahdi.c.
References global_format_map, map, format_map::map, and register_translator().
Referenced by find_transcoders().
00398 { 00399 unsigned int src, dst; 00400 00401 for (src = 0; src < 32; src++) { 00402 for (dst = 0; dst < 32; dst++) { 00403 if (!(srcfmts & (1 << src))) 00404 continue; 00405 00406 if (!(dstfmts & (1 << dst))) 00407 continue; 00408 00409 if (global_format_map.map[dst][src]) 00410 continue; 00411 00412 if (!register_translator(dst, src)) 00413 map->map[dst][src] = 1; 00414 } 00415 } 00416 }
static void drop_translator | ( | int | dst, | |
int | src | |||
) | [static] |
Definition at line 343 of file codec_dahdi.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().
00344 { 00345 struct translator *cur; 00346 00347 AST_LIST_LOCK(&translators); 00348 AST_LIST_TRAVERSE_SAFE_BEGIN(&translators, cur, entry) { 00349 if (cur->t.srcfmt != src) 00350 continue; 00351 00352 if (cur->t.dstfmt != dst) 00353 continue; 00354 00355 AST_LIST_REMOVE_CURRENT(&translators, entry); 00356 ast_unregister_translator(&cur->t); 00357 free(cur); 00358 global_format_map.map[dst][src] = 0; 00359 break; 00360 } 00361 AST_LIST_TRAVERSE_SAFE_END; 00362 AST_LIST_UNLOCK(&translators); 00363 }
static struct ast_frame* fakesrc_sample | ( | void | ) | [static] |
Definition at line 297 of file codec_dahdi.c.
References AST_FRAME_VOICE, and f.
Referenced by register_translator().
00298 { 00299 /* Don't bother really trying to test hardware ones. */ 00300 static struct ast_frame f = { 00301 .frametype = AST_FRAME_VOICE, 00302 .samples = 160, 00303 .src = __PRETTY_FUNCTION__ 00304 }; 00305 00306 return &f; 00307 }
static int find_transcoders | ( | void | ) | [static] |
Definition at line 418 of file codec_dahdi.c.
References ast_log(), ast_verbose(), build_translators(), channels, drop_translator(), errno, global_format_map, LOG_ERROR, format_map::map, map, option_verbose, channel_usage::total, and VERBOSE_PREFIX_2.
Referenced by load_module().
00419 { 00420 struct dahdi_transcoder_info info = { 0, }; 00421 struct format_map map = { { { 0 } } }; 00422 int fd, res; 00423 unsigned int x, y; 00424 00425 #ifdef HAVE_ZAPTEL 00426 if ((fd = open("/dev/zap/transcode", O_RDWR)) < 0) { 00427 ast_log(LOG_ERROR, "Failed to open /dev/zap/transcode: %s\n", strerror(errno)); 00428 return 0; 00429 } 00430 #else 00431 if ((fd = open("/dev/dahdi/transcode", O_RDWR)) < 0) { 00432 ast_log(LOG_ERROR, "Failed to open /dev/dahdi/transcode: %s\n", strerror(errno)); 00433 return 0; 00434 } 00435 #endif 00436 00437 for (info.tcnum = 0; !(res = ioctl(fd, DAHDI_TC_GETINFO, &info)); info.tcnum++) { 00438 if (option_verbose > 1) 00439 ast_verbose(VERBOSE_PREFIX_2 "Found transcoder '%s'.\n", info.name); 00440 build_translators(&map, info.dstfmts, info.srcfmts); 00441 ast_atomic_fetchadd_int(&channels.total, info.numchannels / 2); 00442 } 00443 00444 close(fd); 00445 00446 if (!info.tcnum && (option_verbose > 1)) 00447 ast_verbose(VERBOSE_PREFIX_2 "No hardware transcoders found.\n"); 00448 00449 for (x = 0; x < 32; x++) { 00450 for (y = 0; y < 32; y++) { 00451 if (!map.map[x][y] && global_format_map.map[x][y]) 00452 drop_translator(x, y); 00453 } 00454 } 00455 00456 return 0; 00457 }
static int load_module | ( | void | ) | [static] |
Definition at line 481 of file codec_dahdi.c.
References ast_cli_register_multiple(), cli, find_transcoders(), and parse_config().
00482 { 00483 parse_config(); 00484 find_transcoders(); 00485 ast_cli_register_multiple(cli, sizeof(cli) / sizeof(cli[0])); 00486 00487 return 0; 00488 }
static void parse_config | ( | void | ) | [static] |
Definition at line 377 of file codec_dahdi.c.
References ast_config_load(), ast_true(), ast_variable_browse(), ast_verbose(), option_verbose, var, and VERBOSE_PREFIX_3.
00378 { 00379 struct ast_variable *var; 00380 struct ast_config *cfg = ast_config_load("codecs.conf"); 00381 00382 if (!cfg) 00383 return; 00384 00385 for (var = ast_variable_browse(cfg, "plc"); var; var = var->next) { 00386 if (!strcasecmp(var->name, "genericplc")) { 00387 global_useplc = ast_true(var->value); 00388 if (option_verbose > 2) 00389 ast_verbose(VERBOSE_PREFIX_3 "codec_zap: %susing generic PLC\n", 00390 global_useplc ? "" : "not "); 00391 } 00392 } 00393 00394 ast_config_destroy(cfg); 00395 }
static int register_translator | ( | int | dst, | |
int | src | |||
) | [static] |
Definition at line 309 of file codec_dahdi.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().
00310 { 00311 struct translator *zt; 00312 int res; 00313 00314 if (!(zt = ast_calloc(1, sizeof(*zt)))) 00315 return -1; 00316 00317 snprintf((char *) (zt->t.name), sizeof(zt->t.name), "zap%sto%s", 00318 ast_getformatname((1 << src)), ast_getformatname((1 << dst))); 00319 zt->t.srcfmt = (1 << src); 00320 zt->t.dstfmt = (1 << dst); 00321 zt->t.newpvt = zap_new; 00322 zt->t.framein = zap_framein; 00323 zt->t.frameout = zap_frameout; 00324 zt->t.destroy = zap_destroy; 00325 zt->t.sample = fakesrc_sample; 00326 zt->t.useplc = global_useplc; 00327 zt->t.buf_size = BUFFER_SAMPLES * 2; 00328 zt->t.desc_size = sizeof(struct pvt); 00329 if ((res = ast_register_translator(&zt->t))) { 00330 free(zt); 00331 return -1; 00332 } 00333 00334 AST_LIST_LOCK(&translators); 00335 AST_LIST_INSERT_HEAD(&translators, zt, entry); 00336 AST_LIST_UNLOCK(&translators); 00337 00338 global_format_map.map[dst][src] = 1; 00339 00340 return res; 00341 }
static int reload | ( | void | ) | [static] |
Definition at line 459 of file codec_dahdi.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, parse_config(), translator::t, and ast_translator::useplc.
00460 { 00461 struct translator *cur; 00462 00463 parse_config(); 00464 00465 AST_LIST_LOCK(&translators); 00466 AST_LIST_TRAVERSE(&translators, cur, entry) 00467 cur->t.useplc = global_useplc; 00468 AST_LIST_UNLOCK(&translators); 00469 00470 return 0; 00471 }
static int transcoder_show | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 115 of file codec_dahdi.c.
References ast_cli(), channels, copy(), and RESULT_SUCCESS.
00116 { 00117 struct channel_usage copy; 00118 00119 copy = channels; 00120 00121 if (copy.total == 0) 00122 ast_cli(fd, "No DAHDI transcoders found.\n"); 00123 else 00124 ast_cli(fd, "%d/%d encoders/decoders of %d channels are in use.\n", copy.encoders, copy.decoders, copy.total); 00125 00126 return RESULT_SUCCESS; 00127 }
static int unload_module | ( | void | ) | [static] |
Definition at line 473 of file codec_dahdi.c.
References ast_cli_unregister_multiple(), cli, and unregister_translators().
00474 { 00475 ast_cli_unregister_multiple(cli, sizeof(cli) / sizeof(cli[0])); 00476 unregister_translators(); 00477 00478 return 0; 00479 }
static void unregister_translators | ( | void | ) | [static] |
Definition at line 365 of file codec_dahdi.c.
References AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, ast_unregister_translator(), free, and translator::t.
Referenced by unload_module().
00366 { 00367 struct translator *cur; 00368 00369 AST_LIST_LOCK(&translators); 00370 while ((cur = AST_LIST_REMOVE_HEAD(&translators, entry))) { 00371 ast_unregister_translator(&cur->t); 00372 free(cur); 00373 } 00374 AST_LIST_UNLOCK(&translators); 00375 }
static void zap_destroy | ( | struct ast_trans_pvt * | pvt | ) | [static] |
Definition at line 209 of file codec_dahdi.c.
References AST_FORMAT_G723_1, AST_FORMAT_G729A, channels, channel_usage::decoders, channel_usage::encoders, pvt::fd, pvt::fmts, and ast_trans_pvt::pvt.
Referenced by register_translator().
00210 { 00211 struct pvt *ztp = pvt->pvt; 00212 00213 switch (ztp->fmts.dstfmt) { 00214 case AST_FORMAT_G729A: 00215 case AST_FORMAT_G723_1: 00216 ast_atomic_fetchadd_int(&channels.encoders, -1); 00217 break; 00218 default: 00219 ast_atomic_fetchadd_int(&channels.decoders, -1); 00220 break; 00221 } 00222 00223 close(ztp->fd); 00224 }
static int zap_framein | ( | struct ast_trans_pvt * | pvt, | |
struct ast_frame * | f | |||
) | [static] |
Definition at line 129 of file codec_dahdi.c.
References ast_log(), errno, f, pvt::fake, pvt::fd, LOG_ERROR, ast_trans_pvt::pvt, and ast_trans_pvt::samples.
Referenced by register_translator().
00130 { 00131 int res; 00132 struct pvt *ztp = pvt->pvt; 00133 00134 if (f->subclass) { 00135 /* Give the frame to the hardware transcoder... */ 00136 res = write(ztp->fd, f->data, f->datalen); 00137 if (-1 == res) { 00138 ast_log(LOG_ERROR, "Failed to write to transcoder: %s\n", strerror(errno)); 00139 } 00140 if (f->datalen != res) { 00141 ast_log(LOG_ERROR, "Requested write of %d bytes, but only wrote %d bytes.\n", f->datalen, res); 00142 } 00143 res = -1; 00144 pvt->samples += f->samples; 00145 } else { 00146 /* Fake a return frame for calculation purposes */ 00147 ztp->fake = 2; 00148 pvt->samples = f->samples; 00149 res = 0; 00150 } 00151 return res; 00152 }
static struct ast_frame* zap_frameout | ( | struct ast_trans_pvt * | pvt | ) | [static] |
Definition at line 154 of file codec_dahdi.c.
References AST_FRAME_VOICE, AST_FRFLAG_FROM_TRANSLATOR, AST_FRIENDLY_OFFSET, ast_log(), ast_set_flag, ast_translator::buf_size, ast_frame::data, ast_frame::datalen, ast_trans_pvt::datalen, ast_translator::dstfmt, errno, ast_trans_pvt::f, pvt::fake, pvt::fd, ast_frame::frametype, LOG_ERROR, ast_frame::mallocd, ast_translator::name, ast_frame::offset, ast_trans_pvt::outbuf, ast_trans_pvt::pvt, ast_trans_pvt::samples, pvt::samples, ast_frame::samples, ast_frame::src, ast_frame::subclass, and ast_trans_pvt::t.
Referenced by register_translator().
00155 { 00156 struct pvt *ztp = pvt->pvt; 00157 00158 if (0 == ztp->fake) { 00159 int res; 00160 /* Let's check to see if there is a new frame for us.... */ 00161 res = read(ztp->fd, pvt->outbuf + pvt->datalen, pvt->t->buf_size - pvt->datalen); 00162 if (-1 == res) { 00163 if (EWOULDBLOCK == errno) { 00164 /* Nothing waiting... */ 00165 return NULL; 00166 } else { 00167 ast_log(LOG_ERROR, "Failed to read from transcoder: %s\n", strerror(errno)); 00168 return NULL; 00169 } 00170 } else { 00171 pvt->f.samples = ztp->samples; 00172 pvt->f.datalen = res; 00173 pvt->datalen = 0; 00174 pvt->f.frametype = AST_FRAME_VOICE; 00175 pvt->f.subclass = 1 << (pvt->t->dstfmt); 00176 pvt->f.mallocd = 0; 00177 pvt->f.offset = AST_FRIENDLY_OFFSET; 00178 pvt->f.src = pvt->t->name; 00179 pvt->f.data = pvt->outbuf; 00180 ast_set_flag(&pvt->f, AST_FRFLAG_FROM_TRANSLATOR); 00181 00182 return &pvt->f; 00183 } 00184 00185 } else if (2 == ztp->fake) { 00186 00187 ztp->fake = 1; 00188 pvt->f.frametype = AST_FRAME_VOICE; 00189 pvt->f.subclass = 0; 00190 pvt->f.samples = 160; 00191 pvt->f.data = NULL; 00192 pvt->f.offset = 0; 00193 pvt->f.datalen = 0; 00194 pvt->f.mallocd = 0; 00195 ast_set_flag(&pvt->f, AST_FRFLAG_FROM_TRANSLATOR); 00196 pvt->samples = 0; 00197 00198 return &pvt->f; 00199 00200 } else if (1 == ztp->fake) { 00201 00202 return NULL; 00203 00204 } 00205 /* Shouldn't get here... */ 00206 return NULL; 00207 }
static int zap_new | ( | struct ast_trans_pvt * | pvt | ) | [static] |
Definition at line 292 of file codec_dahdi.c.
References ast_translator::dstfmt, ast_translator::srcfmt, ast_trans_pvt::t, and zap_translate().
Referenced by register_translator().
00293 { 00294 return zap_translate(pvt, pvt->t->dstfmt, pvt->t->srcfmt); 00295 }
static int zap_translate | ( | struct ast_trans_pvt * | pvt, | |
int | dest, | |||
int | source | |||
) | [static] |
Definition at line 226 of file codec_dahdi.c.
References AST_FORMAT_G723_1, AST_FORMAT_G729A, ast_log(), channels, channel_usage::decoders, channel_usage::encoders, errno, pvt::fd, pvt::fmts, LOG_ERROR, LOG_VERBOSE, LOG_WARNING, ast_trans_pvt::pvt, and pvt::samples.
Referenced by zap_new().
00227 { 00228 /* Request translation through zap if possible */ 00229 int fd; 00230 struct pvt *ztp = pvt->pvt; 00231 int flags; 00232 00233 #ifdef HAVE_ZAPTEL 00234 if ((fd = open("/dev/zap/transcode", O_RDWR)) < 0) { 00235 ast_log(LOG_ERROR, "Failed to open /dev/zap/transcode: %s\n", strerror(errno)); 00236 return -1; 00237 } 00238 #else 00239 if ((fd = open("/dev/dahdi/transcode", O_RDWR)) < 0) { 00240 ast_log(LOG_ERROR, "Failed to open /dev/dahdi/transcode: %s\n", strerror(errno)); 00241 return -1; 00242 } 00243 #endif 00244 00245 ztp->fmts.srcfmt = (1 << source); 00246 ztp->fmts.dstfmt = (1 << dest); 00247 00248 ast_log(LOG_VERBOSE, "Opening transcoder channel from %d to %d.\n", source, dest); 00249 00250 if (ioctl(fd, DAHDI_TC_ALLOCATE, &ztp->fmts)) { 00251 ast_log(LOG_ERROR, "Unable to attach to transcoder: %s\n", strerror(errno)); 00252 close(fd); 00253 00254 return -1; 00255 } 00256 00257 flags = fcntl(fd, F_GETFL); 00258 if (flags > - 1) { 00259 if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) 00260 ast_log(LOG_WARNING, "Could not set non-block mode!\n"); 00261 } 00262 00263 ztp->fd = fd; 00264 00265 switch (ztp->fmts.dstfmt) { 00266 case AST_FORMAT_G729A: 00267 ztp->samples = 160; 00268 break; 00269 case AST_FORMAT_G723_1: 00270 ztp->samples = 240; 00271 break; 00272 default: 00273 ztp->samples = 160; 00274 break; 00275 }; 00276 00277 switch (ztp->fmts.dstfmt) { 00278 case AST_FORMAT_G729A: 00279 ast_atomic_fetchadd_int(&channels.encoders, +1); 00280 break; 00281 case AST_FORMAT_G723_1: 00282 ast_atomic_fetchadd_int(&channels.encoders, +1); 00283 break; 00284 default: 00285 ast_atomic_fetchadd_int(&channels.decoders, +1); 00286 break; 00287 } 00288 00289 return 0; 00290 }
struct channel_usage channels [static] |
Referenced by ast_active_channels(), ast_begin_shutdown(), ast_channel_alloc(), ast_channel_free(), ast_channel_register(), ast_channel_unregister(), ast_get_channel_tech(), ast_request(), channel_find_locked(), check_header(), find_transcoders(), show_channeltype(), show_channeltype_deprecated(), show_channeltypes(), transcoder_show(), zap_destroy(), and zap_translate().
struct ast_cli_entry cli[] [static] |
struct ast_cli_entry cli_deprecated[] [static] |
Definition at line 80 of file codec_dahdi.c.
struct format_map global_format_map = { { { 0 } } } [static] |
Definition at line 99 of file codec_dahdi.c.
Referenced by build_translators(), drop_translator(), find_transcoders(), and register_translator().
unsigned int global_useplc = 0 [static] |
Definition at line 62 of file codec_dahdi.c.
char show_transcoder_usage[] [static] |
Initial value:
"Usage: show transcoder\n" " Displays channel utilization of DAHDI transcoder(s).\n"
Definition at line 70 of file codec_dahdi.c.
char transcoder_show_usage[] [static] |
Initial value:
"Usage: transcoder show\n" " Displays channel utilization of DAHDI transcoder(s).\n"
Definition at line 74 of file codec_dahdi.c.