#include "asterisk.h"
#include <fcntl.h>
#include <netinet/in.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/poll.h>
#include <dahdi/user.h>
#include "asterisk/lock.h"
#include "asterisk/translate.h"
#include "asterisk/config.h"
#include "asterisk/module.h"
#include "asterisk/cli.h"
#include "asterisk/channel.h"
#include "asterisk/utils.h"
#include "asterisk/linkedlists.h"
#include "asterisk/ulaw.h"
Go to the source code of this file.
Data Structures | |
struct | channel_usage |
struct | codec_dahdi_pvt |
struct | format_map |
struct | translator |
struct | translators |
the list of translators More... | |
Defines | |
#define | BUFFER_SIZE 8000 |
#define | G723_SAMPLES 240 |
#define | G729_SAMPLES 160 |
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 int | dahdi_decoder_framein (struct ast_trans_pvt *pvt, struct ast_frame *f) |
static struct ast_frame * | dahdi_decoder_frameout (struct ast_trans_pvt *pvt) |
static void | dahdi_destroy (struct ast_trans_pvt *pvt) |
static int | dahdi_encoder_framein (struct ast_trans_pvt *pvt, struct ast_frame *f) |
static struct ast_frame * | dahdi_encoder_frameout (struct ast_trans_pvt *pvt) |
static int | dahdi_new (struct ast_trans_pvt *pvt) |
static int | dahdi_translate (struct ast_trans_pvt *pvt, int dest, int source) |
static void | dahdi_write_frame (struct codec_dahdi_pvt *dahdip, const uint8_t *buffer, const ssize_t count) |
static void | drop_translator (int dst, int src) |
static struct ast_frame * | fakesrc_sample (void) |
static int | find_transcoders (void) |
static char * | handle_cli_transcoder_show (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static int | is_encoder (struct translator *zt) |
static int | lintoulaw (struct ast_trans_pvt *pvt, struct ast_frame *f) |
static int | load_module (void) |
static int | parse_config (int reload) |
static int | register_translator (int dst, int src) |
static int | reload (void) |
static int | ulawtolin (struct ast_trans_pvt *pvt) |
static int | unload_module (void) |
static void | unregister_translators (void) |
Variables | |
static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .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 = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, .reload = reload, } |
static struct ast_module_info * | ast_module_info = &__mod_info |
static struct channel_usage | channels |
static struct ast_cli_entry | cli [] |
static struct format_map | global_format_map = { { { 0 } } } |
static unsigned int | global_useplc = 0 |
Definition in file codec_dahdi.c.
#define BUFFER_SIZE 8000 |
#define G723_SAMPLES 240 |
Definition at line 56 of file codec_dahdi.c.
Referenced by dahdi_translate(), and register_translator().
#define G729_SAMPLES 160 |
Definition at line 57 of file codec_dahdi.c.
Referenced by dahdi_translate(), and register_translator().
static void __reg_module | ( | void | ) | [static] |
Definition at line 706 of file codec_dahdi.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 706 of file codec_dahdi.c.
static void build_translators | ( | struct format_map * | map, | |
unsigned int | dstfmts, | |||
unsigned int | srcfmts | |||
) | [static] |
Definition at line 597 of file codec_dahdi.c.
References global_format_map, map, format_map::map, and register_translator().
00598 { 00599 unsigned int src, dst; 00600 00601 for (src = 0; src < 32; src++) { 00602 for (dst = 0; dst < 32; dst++) { 00603 if (!(srcfmts & (1 << src))) 00604 continue; 00605 00606 if (!(dstfmts & (1 << dst))) 00607 continue; 00608 00609 if (global_format_map.map[dst][src]) 00610 continue; 00611 00612 if (!register_translator(dst, src)) 00613 map->map[dst][src] = 1; 00614 } 00615 } 00616 }
static int dahdi_decoder_framein | ( | struct ast_trans_pvt * | pvt, | |
struct ast_frame * | f | |||
) | [static] |
Definition at line 281 of file codec_dahdi.c.
References ast_log(), dahdi_write_frame(), ast_trans_pvt::datalen, f, codec_dahdi_pvt::fake, LOG_ERROR, ast_trans_pvt::pvt, codec_dahdi_pvt::required_samples, and ast_trans_pvt::samples.
Referenced by register_translator().
00282 { 00283 struct codec_dahdi_pvt *dahdip = pvt->pvt; 00284 00285 if (!f->subclass) { 00286 /* We're just faking a return for calculation purposes. */ 00287 dahdip->fake = 2; 00288 pvt->samples = f->samples; 00289 return 0; 00290 } 00291 00292 if (!f->datalen) { 00293 if (f->samples != dahdip->required_samples) { 00294 ast_log(LOG_ERROR, "%d != %d %d\n", f->samples, dahdip->required_samples, f->datalen); 00295 } 00296 } 00297 dahdi_write_frame(dahdip, f->data.ptr, f->datalen); 00298 pvt->samples += f->samples; 00299 pvt->datalen = 0; 00300 return -1; 00301 }
static struct ast_frame* dahdi_decoder_frameout | ( | struct ast_trans_pvt * | pvt | ) | [static] |
Definition at line 303 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_trans_pvt::c, ast_frame::data, ast_trans_pvt::datalen, ast_frame::datalen, ast_translator::dstfmt, errno, ast_trans_pvt::f, codec_dahdi_pvt::fake, codec_dahdi_pvt::fd, ast_frame::frametype, LOG_ERROR, ast_frame::mallocd, ast_translator::name, ast_frame::offset, ast_trans_pvt::outbuf, ast_frame::ptr, ast_trans_pvt::pvt, codec_dahdi_pvt::required_samples, ast_trans_pvt::samples, ast_frame::samples, codec_dahdi_pvt::softslin, ast_frame::src, ast_frame::subclass, ast_trans_pvt::t, codec_dahdi_pvt::ulaw_buffer, and ulawtolin.
Referenced by register_translator().
00304 { 00305 int res; 00306 struct codec_dahdi_pvt *dahdip = pvt->pvt; 00307 00308 if (2 == dahdip->fake) { 00309 dahdip->fake = 1; 00310 pvt->f.frametype = AST_FRAME_VOICE; 00311 pvt->f.subclass = 0; 00312 pvt->f.samples = dahdip->required_samples; 00313 pvt->f.data.ptr = NULL; 00314 pvt->f.offset = 0; 00315 pvt->f.datalen = 0; 00316 pvt->f.mallocd = 0; 00317 ast_set_flag(&pvt->f, AST_FRFLAG_FROM_TRANSLATOR); 00318 pvt->samples = 0; 00319 return &pvt->f; 00320 } else if (1 == dahdip->fake) { 00321 pvt->samples = 0; 00322 dahdip->fake = 0; 00323 return NULL; 00324 } 00325 00326 /* Let's check to see if there is a new frame for us.... */ 00327 if (dahdip->softslin) { 00328 res = read(dahdip->fd, dahdip->ulaw_buffer, sizeof(dahdip->ulaw_buffer)); 00329 } else { 00330 res = read(dahdip->fd, pvt->outbuf.c + pvt->datalen, pvt->t->buf_size - pvt->datalen); 00331 } 00332 00333 if (-1 == res) { 00334 if (EWOULDBLOCK == errno) { 00335 /* Nothing waiting... */ 00336 return NULL; 00337 } else { 00338 ast_log(LOG_ERROR, "Failed to read from transcoder: %s\n", strerror(errno)); 00339 return NULL; 00340 } 00341 } else { 00342 if (dahdip->softslin) { 00343 ulawtolin(pvt); 00344 pvt->f.datalen = res * 2; 00345 } else { 00346 pvt->f.datalen = res; 00347 } 00348 pvt->datalen = 0; 00349 pvt->f.frametype = AST_FRAME_VOICE; 00350 pvt->f.subclass = 1 << (pvt->t->dstfmt); 00351 pvt->f.mallocd = 0; 00352 pvt->f.offset = AST_FRIENDLY_OFFSET; 00353 pvt->f.src = pvt->t->name; 00354 pvt->f.data.ptr = pvt->outbuf.c; 00355 pvt->f.samples = dahdip->required_samples; 00356 ast_set_flag(&pvt->f, AST_FRFLAG_FROM_TRANSLATOR); 00357 pvt->samples = 0; 00358 00359 return &pvt->f; 00360 } 00361 00362 /* Shouldn't get here... */ 00363 return NULL; 00364 }
static void dahdi_destroy | ( | struct ast_trans_pvt * | pvt | ) | [static] |
Definition at line 367 of file codec_dahdi.c.
References ast_atomic_fetchadd_int(), AST_FORMAT_G723_1, AST_FORMAT_G729A, codec_dahdi_pvt::fd, codec_dahdi_pvt::fmts, and ast_trans_pvt::pvt.
Referenced by register_translator().
00368 { 00369 struct codec_dahdi_pvt *dahdip = pvt->pvt; 00370 00371 switch (dahdip->fmts.dstfmt) { 00372 case AST_FORMAT_G729A: 00373 case AST_FORMAT_G723_1: 00374 ast_atomic_fetchadd_int(&channels.encoders, -1); 00375 break; 00376 default: 00377 ast_atomic_fetchadd_int(&channels.decoders, -1); 00378 break; 00379 } 00380 00381 close(dahdip->fd); 00382 }
static int dahdi_encoder_framein | ( | struct ast_trans_pvt * | pvt, | |
struct ast_frame * | f | |||
) | [static] |
Definition at line 184 of file codec_dahdi.c.
References ast_log(), dahdi_write_frame(), ast_trans_pvt::datalen, f, codec_dahdi_pvt::fake, lintoulaw, LOG_ERROR, ast_trans_pvt::pvt, codec_dahdi_pvt::required_samples, ast_trans_pvt::samples, codec_dahdi_pvt::samples_in_buffer, codec_dahdi_pvt::softslin, and codec_dahdi_pvt::ulaw_buffer.
Referenced by register_translator().
00185 { 00186 struct codec_dahdi_pvt *dahdip = pvt->pvt; 00187 00188 if (!f->subclass) { 00189 /* We're just faking a return for calculation purposes. */ 00190 dahdip->fake = 2; 00191 pvt->samples = f->samples; 00192 return 0; 00193 } 00194 00195 /* Buffer up the packets and send them to the hardware if we 00196 * have enough samples set up. */ 00197 if (dahdip->softslin) { 00198 if (lintoulaw(pvt, f)) { 00199 return -1; 00200 } 00201 } else { 00202 /* NOTE: If softslin support is not needed, and the sample 00203 * size is equal to the required sample size, we wouldn't 00204 * need this copy operation. But at the time this was 00205 * written, only softslin is supported. */ 00206 if (dahdip->samples_in_buffer + f->samples > sizeof(dahdip->ulaw_buffer)) { 00207 ast_log(LOG_ERROR, "Out of buffer space.\n"); 00208 return -1; 00209 } 00210 memcpy(&dahdip->ulaw_buffer[dahdip->samples_in_buffer], f->data.ptr, f->samples); 00211 dahdip->samples_in_buffer += f->samples; 00212 } 00213 00214 while (dahdip->samples_in_buffer > dahdip->required_samples) { 00215 dahdi_write_frame(dahdip, dahdip->ulaw_buffer, dahdip->required_samples); 00216 dahdip->samples_in_buffer -= dahdip->required_samples; 00217 if (dahdip->samples_in_buffer) { 00218 /* Shift any remaining bytes down. */ 00219 memmove(dahdip->ulaw_buffer, &dahdip->ulaw_buffer[dahdip->required_samples], 00220 dahdip->samples_in_buffer); 00221 } 00222 } 00223 pvt->samples += f->samples; 00224 pvt->datalen = 0; 00225 return -1; 00226 }
static struct ast_frame* dahdi_encoder_frameout | ( | struct ast_trans_pvt * | pvt | ) | [static] |
Definition at line 228 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_trans_pvt::c, ast_frame::data, ast_trans_pvt::datalen, ast_frame::datalen, ast_translator::dstfmt, errno, ast_trans_pvt::f, codec_dahdi_pvt::fake, codec_dahdi_pvt::fd, ast_frame::frametype, LOG_ERROR, ast_frame::mallocd, ast_translator::name, ast_frame::offset, ast_trans_pvt::outbuf, ast_frame::ptr, ast_trans_pvt::pvt, codec_dahdi_pvt::required_samples, ast_trans_pvt::samples, ast_frame::samples, ast_frame::src, ast_frame::subclass, and ast_trans_pvt::t.
Referenced by register_translator().
00229 { 00230 struct codec_dahdi_pvt *dahdip = pvt->pvt; 00231 int res; 00232 00233 if (2 == dahdip->fake) { 00234 dahdip->fake = 1; 00235 pvt->f.frametype = AST_FRAME_VOICE; 00236 pvt->f.subclass = 0; 00237 pvt->f.samples = dahdip->required_samples; 00238 pvt->f.data.ptr = NULL; 00239 pvt->f.offset = 0; 00240 pvt->f.datalen = 0; 00241 pvt->f.mallocd = 0; 00242 ast_set_flag(&pvt->f, AST_FRFLAG_FROM_TRANSLATOR); 00243 pvt->samples = 0; 00244 00245 return &pvt->f; 00246 00247 } else if (1 == dahdip->fake) { 00248 dahdip->fake = 0; 00249 return NULL; 00250 } 00251 00252 res = read(dahdip->fd, pvt->outbuf.c + pvt->datalen, pvt->t->buf_size - pvt->datalen); 00253 if (-1 == res) { 00254 if (EWOULDBLOCK == errno) { 00255 /* Nothing waiting... */ 00256 return NULL; 00257 } else { 00258 ast_log(LOG_ERROR, "Failed to read from transcoder: %s\n", strerror(errno)); 00259 return NULL; 00260 } 00261 } else { 00262 pvt->f.datalen = res; 00263 pvt->f.samples = dahdip->required_samples; 00264 pvt->f.frametype = AST_FRAME_VOICE; 00265 pvt->f.subclass = 1 << (pvt->t->dstfmt); 00266 pvt->f.mallocd = 0; 00267 pvt->f.offset = AST_FRIENDLY_OFFSET; 00268 pvt->f.src = pvt->t->name; 00269 pvt->f.data.ptr = pvt->outbuf.c; 00270 ast_set_flag(&pvt->f, AST_FRFLAG_FROM_TRANSLATOR); 00271 00272 pvt->samples = 0; 00273 pvt->datalen = 0; 00274 return &pvt->f; 00275 } 00276 00277 /* Shouldn't get here... */ 00278 return NULL; 00279 }
static int dahdi_new | ( | struct ast_trans_pvt * | pvt | ) | [static] |
Definition at line 457 of file codec_dahdi.c.
References dahdi_translate(), ast_translator::dstfmt, ast_translator::srcfmt, and ast_trans_pvt::t.
00458 { 00459 return dahdi_translate(pvt, pvt->t->dstfmt, pvt->t->srcfmt); 00460 }
static int dahdi_translate | ( | struct ast_trans_pvt * | pvt, | |
int | dest, | |||
int | source | |||
) | [static] |
Definition at line 384 of file codec_dahdi.c.
References ast_atomic_fetchadd_int(), AST_FORMAT_G723_1, AST_FORMAT_G729A, AST_FORMAT_SLINEAR, AST_FORMAT_ULAW, ast_log(), errno, codec_dahdi_pvt::fd, codec_dahdi_pvt::fmts, G723_SAMPLES, G729_SAMPLES, LOG_DEBUG, LOG_ERROR, LOG_WARNING, ast_trans_pvt::pvt, codec_dahdi_pvt::required_samples, and codec_dahdi_pvt::softslin.
Referenced by dahdi_new().
00385 { 00386 /* Request translation through zap if possible */ 00387 int fd; 00388 struct codec_dahdi_pvt *dahdip = pvt->pvt; 00389 int flags; 00390 int tried_once = 0; 00391 const char *dev_filename = "/dev/dahdi/transcode"; 00392 00393 if ((fd = open(dev_filename, O_RDWR)) < 0) { 00394 ast_log(LOG_ERROR, "Failed to open %s: %s\n", dev_filename, strerror(errno)); 00395 return -1; 00396 } 00397 00398 dahdip->fmts.srcfmt = (1 << source); 00399 dahdip->fmts.dstfmt = (1 << dest); 00400 00401 ast_log(LOG_DEBUG, "Opening transcoder channel from %d to %d.\n", source, dest); 00402 00403 retry: 00404 if (ioctl(fd, DAHDI_TC_ALLOCATE, &dahdip->fmts)) { 00405 if ((ENODEV == errno) && !tried_once) { 00406 /* We requested to translate to/from an unsupported 00407 * format. Most likely this is because signed linear 00408 * was not supported by any hardware devices even 00409 * though this module always registers signed linear 00410 * support. In this case we'll retry, requesting 00411 * support for ULAW instead of signed linear and then 00412 * we'll just convert from ulaw to signed linear in 00413 * software. */ 00414 if (AST_FORMAT_SLINEAR == dahdip->fmts.srcfmt) { 00415 ast_log(LOG_DEBUG, "Using soft_slin support on source\n"); 00416 dahdip->softslin = 1; 00417 dahdip->fmts.srcfmt = AST_FORMAT_ULAW; 00418 } else if (AST_FORMAT_SLINEAR == dahdip->fmts.dstfmt) { 00419 ast_log(LOG_DEBUG, "Using soft_slin support on destination\n"); 00420 dahdip->softslin = 1; 00421 dahdip->fmts.dstfmt = AST_FORMAT_ULAW; 00422 } 00423 tried_once = 1; 00424 goto retry; 00425 } 00426 ast_log(LOG_ERROR, "Unable to attach to transcoder: %s\n", strerror(errno)); 00427 close(fd); 00428 00429 return -1; 00430 } 00431 00432 flags = fcntl(fd, F_GETFL); 00433 if (flags > - 1) { 00434 if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) 00435 ast_log(LOG_WARNING, "Could not set non-block mode!\n"); 00436 } 00437 00438 dahdip->fd = fd; 00439 00440 dahdip->required_samples = ((dahdip->fmts.dstfmt|dahdip->fmts.srcfmt)&AST_FORMAT_G723_1) ? G723_SAMPLES : G729_SAMPLES; 00441 00442 switch (dahdip->fmts.dstfmt) { 00443 case AST_FORMAT_G729A: 00444 ast_atomic_fetchadd_int(&channels.encoders, +1); 00445 break; 00446 case AST_FORMAT_G723_1: 00447 ast_atomic_fetchadd_int(&channels.encoders, +1); 00448 break; 00449 default: 00450 ast_atomic_fetchadd_int(&channels.decoders, +1); 00451 break; 00452 } 00453 00454 return 0; 00455 }
static void dahdi_write_frame | ( | struct codec_dahdi_pvt * | dahdip, | |
const uint8_t * | buffer, | |||
const ssize_t | count | |||
) | [static] |
Definition at line 165 of file codec_dahdi.c.
References ast_log(), errno, codec_dahdi_pvt::fd, LOG_ERROR, and option_verbose.
Referenced by dahdi_decoder_framein(), and dahdi_encoder_framein().
00166 { 00167 int res; 00168 struct pollfd p = {0}; 00169 if (!count) return; 00170 res = write(dahdip->fd, buffer, count); 00171 if (option_verbose > 10) { 00172 if (-1 == res) { 00173 ast_log(LOG_ERROR, "Failed to write to transcoder: %s\n", strerror(errno)); 00174 } 00175 if (count != res) { 00176 ast_log(LOG_ERROR, "Requested write of %zd bytes, but only wrote %d bytes.\n", count, res); 00177 } 00178 } 00179 p.fd = dahdip->fd; 00180 p.events = POLLOUT; 00181 res = poll(&p, 1, 50); 00182 }
static void drop_translator | ( | int | dst, | |
int | src | |||
) | [static] |
Definition at line 540 of file codec_dahdi.c.
References ast_free, 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, global_format_map, format_map::map, ast_translator::srcfmt, and translator::t.
00541 { 00542 struct translator *cur; 00543 00544 AST_LIST_LOCK(&translators); 00545 AST_LIST_TRAVERSE_SAFE_BEGIN(&translators, cur, entry) { 00546 if (cur->t.srcfmt != src) 00547 continue; 00548 00549 if (cur->t.dstfmt != dst) 00550 continue; 00551 00552 AST_LIST_REMOVE_CURRENT(entry); 00553 ast_unregister_translator(&cur->t); 00554 ast_free(cur); 00555 global_format_map.map[dst][src] = 0; 00556 break; 00557 } 00558 AST_LIST_TRAVERSE_SAFE_END; 00559 AST_LIST_UNLOCK(&translators); 00560 }
static struct ast_frame* fakesrc_sample | ( | void | ) | [static] |
Definition at line 462 of file codec_dahdi.c.
References AST_FRAME_VOICE, and f.
Referenced by register_translator().
00463 { 00464 /* Don't bother really trying to test hardware ones. */ 00465 static struct ast_frame f = { 00466 .frametype = AST_FRAME_VOICE, 00467 .samples = 160, 00468 .src = __PRETTY_FUNCTION__ 00469 }; 00470 00471 return &f; 00472 }
static int find_transcoders | ( | void | ) | [static] |
Definition at line 618 of file codec_dahdi.c.
References AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, AST_FORMAT_ULAW, ast_log(), ast_verbose, errno, LOG_ERROR, map, option_verbose, and VERBOSE_PREFIX_2.
Referenced by load_module().
00619 { 00620 struct dahdi_transcoder_info info = { 0, }; 00621 struct format_map map = { { { 0 } } }; 00622 int fd, res; 00623 unsigned int x, y; 00624 00625 if ((fd = open("/dev/dahdi/transcode", O_RDWR)) < 0) { 00626 ast_log(LOG_ERROR, "Failed to open /dev/dahdi/transcode: %s\n", strerror(errno)); 00627 return 0; 00628 } 00629 00630 for (info.tcnum = 0; !(res = ioctl(fd, DAHDI_TC_GETINFO, &info)); info.tcnum++) { 00631 if (option_verbose > 1) 00632 ast_verbose(VERBOSE_PREFIX_2 "Found transcoder '%s'.\n", info.name); 00633 00634 /* Complex codecs need to support signed linear. If the 00635 * hardware transcoder does not natively support signed linear 00636 * format, we will emulate it in software directly in this 00637 * module. Also, do not allow direct ulaw/alaw to complex 00638 * codec translation, since that will prevent the generic PLC 00639 * functions from working. */ 00640 if (info.dstfmts & (AST_FORMAT_ULAW | AST_FORMAT_ALAW)) { 00641 info.dstfmts |= AST_FORMAT_SLINEAR; 00642 info.dstfmts &= ~(AST_FORMAT_ULAW | AST_FORMAT_ALAW); 00643 } 00644 if (info.srcfmts & (AST_FORMAT_ULAW | AST_FORMAT_ALAW)) { 00645 info.srcfmts |= AST_FORMAT_SLINEAR; 00646 info.srcfmts &= ~(AST_FORMAT_ULAW | AST_FORMAT_ALAW); 00647 } 00648 00649 build_translators(&map, info.dstfmts, info.srcfmts); 00650 ast_atomic_fetchadd_int(&channels.total, info.numchannels / 2); 00651 00652 } 00653 00654 close(fd); 00655 00656 if (!info.tcnum && (option_verbose > 1)) 00657 ast_verbose(VERBOSE_PREFIX_2 "No hardware transcoders found.\n"); 00658 00659 for (x = 0; x < 32; x++) { 00660 for (y = 0; y < 32; y++) { 00661 if (!map.map[x][y] && global_format_map.map[x][y]) 00662 drop_translator(x, y); 00663 } 00664 } 00665 00666 return 0; 00667 }
static char * handle_cli_transcoder_show | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 137 of file codec_dahdi.c.
References ast_cli_args::argc, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, copy(), ast_cli_args::fd, and ast_cli_entry::usage.
00138 { 00139 struct channel_usage copy; 00140 00141 switch (cmd) { 00142 case CLI_INIT: 00143 e->command = "transcoder show"; 00144 e->usage = 00145 "Usage: transcoder show\n" 00146 " Displays channel utilization of DAHDI transcoder(s).\n"; 00147 return NULL; 00148 case CLI_GENERATE: 00149 return NULL; 00150 } 00151 00152 if (a->argc != 2) 00153 return CLI_SHOWUSAGE; 00154 00155 copy = channels; 00156 00157 if (copy.total == 0) 00158 ast_cli(a->fd, "No DAHDI transcoders found.\n"); 00159 else 00160 ast_cli(a->fd, "%d/%d encoders/decoders of %d channels are in use.\n", copy.encoders, copy.decoders, copy.total); 00161 00162 return CLI_SUCCESS; 00163 }
static int is_encoder | ( | struct translator * | zt | ) | [static] |
Definition at line 474 of file codec_dahdi.c.
References AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, AST_FORMAT_ULAW, ast_translator::srcfmt, and translator::t.
Referenced by register_translator().
00475 { 00476 if (zt->t.srcfmt&(AST_FORMAT_ULAW|AST_FORMAT_ALAW|AST_FORMAT_SLINEAR)) { 00477 return 1; 00478 } else { 00479 return 0; 00480 } 00481 }
static int lintoulaw | ( | struct ast_trans_pvt * | pvt, | |
struct ast_frame * | f | |||
) | [static] |
Definition at line 117 of file codec_dahdi.c.
References AST_LIN2MU, ast_log(), f, LOG_ERROR, ast_trans_pvt::pvt, codec_dahdi_pvt::samples_in_buffer, and codec_dahdi_pvt::ulaw_buffer.
00118 { 00119 struct codec_dahdi_pvt *dahdip = pvt->pvt; 00120 int i = f->samples; 00121 uint8_t *dst = &dahdip->ulaw_buffer[dahdip->samples_in_buffer]; 00122 int16_t *src = f->data.ptr; 00123 00124 if (dahdip->samples_in_buffer + i > sizeof(dahdip->ulaw_buffer)) { 00125 ast_log(LOG_ERROR, "Out of buffer space!\n"); 00126 return -i; 00127 } 00128 00129 while (i--) { 00130 *dst++ = AST_LIN2MU(*src++); 00131 } 00132 00133 dahdip->samples_in_buffer += f->samples; 00134 return 0; 00135 }
static int load_module | ( | void | ) | [static] |
Definition at line 692 of file codec_dahdi.c.
References ARRAY_LEN, ast_cli_register_multiple(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_ulaw_init(), cli, find_transcoders(), and parse_config().
00693 { 00694 ast_ulaw_init(); 00695 if (parse_config(0)) 00696 return AST_MODULE_LOAD_DECLINE; 00697 find_transcoders(); 00698 ast_cli_register_multiple(cli, ARRAY_LEN(cli)); 00699 return AST_MODULE_LOAD_SUCCESS; 00700 }
static int parse_config | ( | int | reload | ) | [static] |
Definition at line 574 of file codec_dahdi.c.
References ast_config_load, ast_true(), ast_variable_browse(), ast_verb, CONFIG_FLAG_FILEUNCHANGED, config_flags, CONFIG_STATUS_FILEUNCHANGED, and var.
00575 { 00576 struct ast_variable *var; 00577 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 00578 struct ast_config *cfg = ast_config_load("codecs.conf", config_flags); 00579 00580 if (cfg == NULL) 00581 return 0; 00582 if (cfg == CONFIG_STATUS_FILEUNCHANGED) 00583 return 0; 00584 00585 for (var = ast_variable_browse(cfg, "plc"); var; var = var->next) { 00586 if (!strcasecmp(var->name, "genericplc")) { 00587 global_useplc = ast_true(var->value); 00588 ast_verb(3, "codec_dahdi: %susing generic PLC\n", 00589 global_useplc ? "" : "not "); 00590 } 00591 } 00592 00593 ast_config_destroy(cfg); 00594 return 0; 00595 }
static int register_translator | ( | int | dst, | |
int | src | |||
) | [static] |
Definition at line 483 of file codec_dahdi.c.
References ast_calloc, AST_FORMAT_G723_1, ast_free, ast_getformatname(), AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_register_translator, BUFFER_SIZE, dahdi_decoder_framein(), dahdi_decoder_frameout(), dahdi_destroy(), dahdi_encoder_framein(), dahdi_encoder_frameout(), dahdi_new(), translator::entry, fakesrc_sample(), G723_SAMPLES, G729_SAMPLES, global_format_map, is_encoder(), and format_map::map.
Referenced by build_translators().
00484 { 00485 struct translator *zt; 00486 int res; 00487 00488 if (!(zt = ast_calloc(1, sizeof(*zt)))) { 00489 return -1; 00490 } 00491 00492 snprintf((char *) (zt->t.name), sizeof(zt->t.name), "zap%sto%s", 00493 ast_getformatname((1 << src)), ast_getformatname((1 << dst))); 00494 zt->t.srcfmt = (1 << src); 00495 zt->t.dstfmt = (1 << dst); 00496 zt->t.buf_size = BUFFER_SIZE; 00497 if (is_encoder(zt)) { 00498 zt->t.framein = dahdi_encoder_framein; 00499 zt->t.frameout = dahdi_encoder_frameout; 00500 #if 0 00501 zt->t.buffer_samples = 0; 00502 #endif 00503 } else { 00504 zt->t.framein = dahdi_decoder_framein; 00505 zt->t.frameout = dahdi_decoder_frameout; 00506 #if 0 00507 if (AST_FORMAT_G723_1 == zt->t.srcfmt) { 00508 zt->t.plc_samples = G723_SAMPLES; 00509 } else { 00510 zt->t.plc_samples = G729_SAMPLES; 00511 } 00512 zt->t.buffer_samples = zt->t.plc_samples * 8; 00513 #endif 00514 } 00515 zt->t.destroy = dahdi_destroy; 00516 zt->t.buffer_samples = 0; 00517 zt->t.newpvt = dahdi_new; 00518 zt->t.sample = fakesrc_sample; 00519 #if 0 00520 zt->t.useplc = global_useplc; 00521 #endif 00522 zt->t.useplc = 0; 00523 zt->t.native_plc = 0; 00524 00525 zt->t.desc_size = sizeof(struct codec_dahdi_pvt); 00526 if ((res = ast_register_translator(&zt->t))) { 00527 ast_free(zt); 00528 return -1; 00529 } 00530 00531 AST_LIST_LOCK(&translators); 00532 AST_LIST_INSERT_HEAD(&translators, zt, entry); 00533 AST_LIST_UNLOCK(&translators); 00534 00535 global_format_map.map[dst][src] = 1; 00536 00537 return res; 00538 }
static int reload | ( | void | ) | [static] |
Definition at line 669 of file codec_dahdi.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, translator::entry, global_useplc, parse_config(), translator::t, and ast_translator::useplc.
00670 { 00671 struct translator *cur; 00672 00673 if (parse_config(1)) 00674 return AST_MODULE_LOAD_DECLINE; 00675 00676 AST_LIST_LOCK(&translators); 00677 AST_LIST_TRAVERSE(&translators, cur, entry) 00678 cur->t.useplc = global_useplc; 00679 AST_LIST_UNLOCK(&translators); 00680 00681 return AST_MODULE_LOAD_SUCCESS; 00682 }
static int ulawtolin | ( | struct ast_trans_pvt * | pvt | ) | [static] |
Definition at line 101 of file codec_dahdi.c.
References AST_MULAW, ast_trans_pvt::datalen, ast_trans_pvt::i16, ast_trans_pvt::outbuf, ast_trans_pvt::pvt, codec_dahdi_pvt::required_samples, and codec_dahdi_pvt::ulaw_buffer.
00102 { 00103 struct codec_dahdi_pvt *dahdip = pvt->pvt; 00104 int i = dahdip->required_samples; 00105 uint8_t *src = &dahdip->ulaw_buffer[0]; 00106 int16_t *dst = pvt->outbuf.i16 + pvt->datalen; 00107 00108 /* convert and copy in outbuf */ 00109 while (i--) { 00110 *dst++ = AST_MULAW(*src++); 00111 } 00112 00113 return 0; 00114 }
static int unload_module | ( | void | ) | [static] |
Definition at line 684 of file codec_dahdi.c.
References ARRAY_LEN, ast_cli_unregister_multiple(), cli, and unregister_translators().
00685 { 00686 ast_cli_unregister_multiple(cli, ARRAY_LEN(cli)); 00687 unregister_translators(); 00688 00689 return 0; 00690 }
static void unregister_translators | ( | void | ) | [static] |
Definition at line 562 of file codec_dahdi.c.
References ast_free, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, ast_unregister_translator(), translator::entry, and translator::t.
Referenced by unload_module().
00563 { 00564 struct translator *cur; 00565 00566 AST_LIST_LOCK(&translators); 00567 while ((cur = AST_LIST_REMOVE_HEAD(&translators, entry))) { 00568 ast_unregister_translator(&cur->t); 00569 ast_free(cur); 00570 } 00571 AST_LIST_UNLOCK(&translators); 00572 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .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 = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, .reload = reload, } [static] |
Definition at line 706 of file codec_dahdi.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 706 of file codec_dahdi.c.
struct channel_usage channels [static] |
struct ast_cli_entry cli[] [static] |
Initial value:
{ { .handler = handle_cli_transcoder_show , .summary = "Display DAHDI transcoder utilization." ,__VA_ARGS__ } }
Definition at line 69 of file codec_dahdi.c.
Referenced by load_module(), and unload_module().
struct format_map global_format_map = { { { 0 } } } [static] |
Definition at line 77 of file codec_dahdi.c.
Referenced by build_translators(), drop_translator(), and register_translator().
unsigned int global_useplc = 0 [static] |