#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 |
struct | translators |
the list of translators More... | |
Defines | |
#define | BUFFER_SAMPLES 8000 |
Functions | |
static void | __reg_module (void) |
static void | __unreg_module (void) |
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 ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .description = "Generic DAHDI Transcoder Codec Translator" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "f450f61f60e761b3aa089ebed76ca8a5" , .load = load_module, .unload = unload_module, .reload = reload, } |
static const struct ast_module_info * | ast_module_info = &__mod_info |
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 void __reg_module | ( | void | ) | [static] |
Definition at line 480 of file codec_dahdi.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 480 of file codec_dahdi.c.
static void build_translators | ( | struct format_map * | map, | |
unsigned int | dstfmts, | |||
unsigned int | srcfmts | |||
) | [static] |
Definition at line 390 of file codec_dahdi.c.
References global_format_map, map, format_map::map, and register_translator().
Referenced by find_transcoders().
00391 { 00392 unsigned int src, dst; 00393 00394 for (src = 0; src < 32; src++) { 00395 for (dst = 0; dst < 32; dst++) { 00396 if (!(srcfmts & (1 << src))) 00397 continue; 00398 00399 if (!(dstfmts & (1 << dst))) 00400 continue; 00401 00402 if (global_format_map.map[dst][src]) 00403 continue; 00404 00405 if (!register_translator(dst, src)) 00406 map->map[dst][src] = 1; 00407 } 00408 } 00409 }
static void drop_translator | ( | int | dst, | |
int | src | |||
) | [static] |
Definition at line 336 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, translator::entry, free, global_format_map, format_map::map, ast_translator::srcfmt, and translator::t.
Referenced by find_transcoders().
00337 { 00338 struct translator *cur; 00339 00340 AST_LIST_LOCK(&translators); 00341 AST_LIST_TRAVERSE_SAFE_BEGIN(&translators, cur, entry) { 00342 if (cur->t.srcfmt != src) 00343 continue; 00344 00345 if (cur->t.dstfmt != dst) 00346 continue; 00347 00348 AST_LIST_REMOVE_CURRENT(&translators, entry); 00349 ast_unregister_translator(&cur->t); 00350 free(cur); 00351 global_format_map.map[dst][src] = 0; 00352 break; 00353 } 00354 AST_LIST_TRAVERSE_SAFE_END; 00355 AST_LIST_UNLOCK(&translators); 00356 }
static struct ast_frame* fakesrc_sample | ( | void | ) | [static] |
Definition at line 290 of file codec_dahdi.c.
References AST_FRAME_VOICE, and f.
Referenced by register_translator().
00291 { 00292 /* Don't bother really trying to test hardware ones. */ 00293 static struct ast_frame f = { 00294 .frametype = AST_FRAME_VOICE, 00295 .samples = 160, 00296 .src = __PRETTY_FUNCTION__ 00297 }; 00298 00299 return &f; 00300 }
static int find_transcoders | ( | void | ) | [static] |
Definition at line 411 of file codec_dahdi.c.
References ast_atomic_fetchadd_int(), ast_log(), ast_verbose(), build_translators(), DAHDI_FILE_TRANSCODE, drop_translator(), errno, global_format_map, LOG_ERROR, format_map::map, map, option_verbose, and VERBOSE_PREFIX_2.
Referenced by load_module().
00412 { 00413 struct dahdi_transcoder_info info = { 0, }; 00414 struct format_map map = { { { 0 } } }; 00415 int fd, res; 00416 unsigned int x, y; 00417 00418 if ((fd = open(DAHDI_FILE_TRANSCODE, O_RDWR)) < 0) { 00419 ast_log(LOG_ERROR, "Failed to open " DAHDI_FILE_TRANSCODE ": %s\n", strerror(errno)); 00420 return 0; 00421 } 00422 00423 for (info.tcnum = 0; !(res = ioctl(fd, DAHDI_TC_GETINFO, &info)); info.tcnum++) { 00424 if (option_verbose > 1) 00425 ast_verbose(VERBOSE_PREFIX_2 "Found transcoder '%s'.\n", info.name); 00426 build_translators(&map, info.dstfmts, info.srcfmts); 00427 ast_atomic_fetchadd_int(&channels.total, info.numchannels / 2); 00428 } 00429 00430 close(fd); 00431 00432 if (!info.tcnum && (option_verbose > 1)) 00433 ast_verbose(VERBOSE_PREFIX_2 "No hardware transcoders found.\n"); 00434 00435 for (x = 0; x < 32; x++) { 00436 for (y = 0; y < 32; y++) { 00437 if (!map.map[x][y] && global_format_map.map[x][y]) 00438 drop_translator(x, y); 00439 } 00440 } 00441 00442 return 0; 00443 }
static int load_module | ( | void | ) | [static] |
Definition at line 467 of file codec_dahdi.c.
References ast_cli_register_multiple(), cli, find_transcoders(), and parse_config().
00468 { 00469 parse_config(); 00470 find_transcoders(); 00471 ast_cli_register_multiple(cli, sizeof(cli) / sizeof(cli[0])); 00472 00473 return 0; 00474 }
static void parse_config | ( | void | ) | [static] |
Definition at line 370 of file codec_dahdi.c.
References ast_config_load(), ast_true(), ast_variable_browse(), ast_verbose(), option_verbose, var, and VERBOSE_PREFIX_3.
00371 { 00372 struct ast_variable *var; 00373 struct ast_config *cfg = ast_config_load("codecs.conf"); 00374 00375 if (!cfg) 00376 return; 00377 00378 for (var = ast_variable_browse(cfg, "plc"); var; var = var->next) { 00379 if (!strcasecmp(var->name, "genericplc")) { 00380 global_useplc = ast_true(var->value); 00381 if (option_verbose > 2) 00382 ast_verbose(VERBOSE_PREFIX_3 "codec_zap: %susing generic PLC\n", 00383 global_useplc ? "" : "not "); 00384 } 00385 } 00386 00387 ast_config_destroy(cfg); 00388 }
static int register_translator | ( | int | dst, | |
int | src | |||
) | [static] |
Definition at line 302 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, translator::entry, fakesrc_sample(), free, global_format_map, format_map::map, zap_destroy(), zap_framein(), zap_frameout(), and zap_new().
Referenced by build_translators().
00303 { 00304 struct translator *zt; 00305 int res; 00306 00307 if (!(zt = ast_calloc(1, sizeof(*zt)))) 00308 return -1; 00309 00310 snprintf((char *) (zt->t.name), sizeof(zt->t.name), "zap%sto%s", 00311 ast_getformatname((1 << src)), ast_getformatname((1 << dst))); 00312 zt->t.srcfmt = (1 << src); 00313 zt->t.dstfmt = (1 << dst); 00314 zt->t.newpvt = zap_new; 00315 zt->t.framein = zap_framein; 00316 zt->t.frameout = zap_frameout; 00317 zt->t.destroy = zap_destroy; 00318 zt->t.sample = fakesrc_sample; 00319 zt->t.useplc = global_useplc; 00320 zt->t.buf_size = BUFFER_SAMPLES * 2; 00321 zt->t.desc_size = sizeof(struct pvt); 00322 if ((res = ast_register_translator(&zt->t))) { 00323 free(zt); 00324 return -1; 00325 } 00326 00327 AST_LIST_LOCK(&translators); 00328 AST_LIST_INSERT_HEAD(&translators, zt, entry); 00329 AST_LIST_UNLOCK(&translators); 00330 00331 global_format_map.map[dst][src] = 1; 00332 00333 return res; 00334 }
static int reload | ( | void | ) | [static] |
Definition at line 445 of file codec_dahdi.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, translator::entry, parse_config(), translator::t, and ast_translator::useplc.
00446 { 00447 struct translator *cur; 00448 00449 parse_config(); 00450 00451 AST_LIST_LOCK(&translators); 00452 AST_LIST_TRAVERSE(&translators, cur, entry) 00453 cur->t.useplc = global_useplc; 00454 AST_LIST_UNLOCK(&translators); 00455 00456 return 0; 00457 }
static int transcoder_show | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 115 of file codec_dahdi.c.
References ast_cli(), 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 459 of file codec_dahdi.c.
References ast_cli_unregister_multiple(), cli, and unregister_translators().
00460 { 00461 ast_cli_unregister_multiple(cli, sizeof(cli) / sizeof(cli[0])); 00462 unregister_translators(); 00463 00464 return 0; 00465 }
static void unregister_translators | ( | void | ) | [static] |
Definition at line 358 of file codec_dahdi.c.
References AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, ast_unregister_translator(), translator::entry, free, and translator::t.
Referenced by unload_module().
00359 { 00360 struct translator *cur; 00361 00362 AST_LIST_LOCK(&translators); 00363 while ((cur = AST_LIST_REMOVE_HEAD(&translators, entry))) { 00364 ast_unregister_translator(&cur->t); 00365 free(cur); 00366 } 00367 AST_LIST_UNLOCK(&translators); 00368 }
static void zap_destroy | ( | struct ast_trans_pvt * | pvt | ) | [static] |
Definition at line 209 of file codec_dahdi.c.
References ast_atomic_fetchadd_int(), AST_FORMAT_G723_1, AST_FORMAT_G729A, 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 285 of file codec_dahdi.c.
References ast_translator::dstfmt, ast_translator::srcfmt, ast_trans_pvt::t, and zap_translate().
Referenced by register_translator().
00286 { 00287 return zap_translate(pvt, pvt->t->dstfmt, pvt->t->srcfmt); 00288 }
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_atomic_fetchadd_int(), AST_FORMAT_G723_1, AST_FORMAT_G729A, ast_log(), DAHDI_FILE_TRANSCODE, 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 if ((fd = open(DAHDI_FILE_TRANSCODE, O_RDWR)) < 0) { 00234 ast_log(LOG_ERROR, "Failed to open " DAHDI_FILE_TRANSCODE ": %s\n", strerror(errno)); 00235 return -1; 00236 } 00237 00238 ztp->fmts.srcfmt = (1 << source); 00239 ztp->fmts.dstfmt = (1 << dest); 00240 00241 ast_log(LOG_VERBOSE, "Opening transcoder channel from %d to %d.\n", source, dest); 00242 00243 if (ioctl(fd, DAHDI_TC_ALLOCATE, &ztp->fmts)) { 00244 ast_log(LOG_ERROR, "Unable to attach to transcoder: %s\n", strerror(errno)); 00245 close(fd); 00246 00247 return -1; 00248 } 00249 00250 flags = fcntl(fd, F_GETFL); 00251 if (flags > - 1) { 00252 if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) 00253 ast_log(LOG_WARNING, "Could not set non-block mode!\n"); 00254 } 00255 00256 ztp->fd = fd; 00257 00258 switch (ztp->fmts.dstfmt) { 00259 case AST_FORMAT_G729A: 00260 ztp->samples = 160; 00261 break; 00262 case AST_FORMAT_G723_1: 00263 ztp->samples = 240; 00264 break; 00265 default: 00266 ztp->samples = 160; 00267 break; 00268 }; 00269 00270 switch (ztp->fmts.dstfmt) { 00271 case AST_FORMAT_G729A: 00272 ast_atomic_fetchadd_int(&channels.encoders, +1); 00273 break; 00274 case AST_FORMAT_G723_1: 00275 ast_atomic_fetchadd_int(&channels.encoders, +1); 00276 break; 00277 default: 00278 ast_atomic_fetchadd_int(&channels.decoders, +1); 00279 break; 00280 } 00281 00282 return 0; 00283 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .description = "Generic DAHDI Transcoder Codec Translator" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "f450f61f60e761b3aa089ebed76ca8a5" , .load = load_module, .unload = unload_module, .reload = reload, } [static] |
Definition at line 480 of file codec_dahdi.c.
const struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 480 of file codec_dahdi.c.
struct channel_usage channels [static] |
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.