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