#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 |
#define | ULAW_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_wait_for_packet (int fd) |
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 | register_translator (int dst, int src) |
static int | reload (void) |
static int | ulawtolin (struct ast_trans_pvt *pvt, int samples) |
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 = "ac1f6a56484a8820659555499174e588" , .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 } } } |
Definition in file codec_dahdi.c.
#define BUFFER_SIZE 8000 |
#define G723_SAMPLES 240 |
#define G729_SAMPLES 160 |
#define ULAW_SAMPLES 160 |
static void __reg_module | ( | void | ) | [static] |
Definition at line 670 of file codec_dahdi.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 670 of file codec_dahdi.c.
static void build_translators | ( | struct format_map * | map, | |
unsigned int | dstfmts, | |||
unsigned int | srcfmts | |||
) | [static] |
Definition at line 573 of file codec_dahdi.c.
References global_format_map, map, format_map::map, and register_translator().
00574 { 00575 unsigned int src, dst; 00576 00577 for (src = 0; src < 32; src++) { 00578 for (dst = 0; dst < 32; dst++) { 00579 if (!(srcfmts & (1 << src))) 00580 continue; 00581 00582 if (!(dstfmts & (1 << dst))) 00583 continue; 00584 00585 if (global_format_map.map[dst][src]) 00586 continue; 00587 00588 if (!register_translator(dst, src)) 00589 map->map[dst][src] = 1; 00590 } 00591 } 00592 }
static int dahdi_decoder_framein | ( | struct ast_trans_pvt * | pvt, | |
struct ast_frame * | f | |||
) | [static] |
Definition at line 289 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, ast_trans_pvt::samples, and codec_dahdi_pvt::samples_written_to_hardware.
Referenced by register_translator().
00290 { 00291 struct codec_dahdi_pvt *dahdip = pvt->pvt; 00292 00293 if (!f->subclass.codec) { 00294 /* We're just faking a return for calculation purposes. */ 00295 dahdip->fake = 2; 00296 pvt->samples = f->samples; 00297 return 0; 00298 } 00299 00300 if (!f->datalen) { 00301 if (f->samples != dahdip->required_samples) { 00302 ast_log(LOG_ERROR, "%d != %d %d\n", f->samples, dahdip->required_samples, f->datalen); 00303 } 00304 } 00305 dahdi_write_frame(dahdip, f->data.ptr, f->datalen); 00306 dahdip->samples_written_to_hardware += f->samples; 00307 pvt->samples += f->samples; 00308 pvt->datalen = 0; 00309 return -1; 00310 }
static struct ast_frame* dahdi_decoder_frameout | ( | struct ast_trans_pvt * | pvt | ) | [static] |
Definition at line 312 of file codec_dahdi.c.
References AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_frisolate(), ast_log(), ast_translator::buf_size, ast_trans_pvt::c, ast_frame_subclass::codec, dahdi_wait_for_packet(), 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::samples_written_to_hardware, codec_dahdi_pvt::softslin, ast_frame::src, ast_frame::subclass, ast_trans_pvt::t, codec_dahdi_pvt::ulaw_buffer, ULAW_SAMPLES, and ulawtolin.
Referenced by register_translator().
00313 { 00314 int res; 00315 struct codec_dahdi_pvt *dahdip = pvt->pvt; 00316 00317 if (2 == dahdip->fake) { 00318 dahdip->fake = 1; 00319 pvt->f.frametype = AST_FRAME_VOICE; 00320 pvt->f.subclass.codec = 0; 00321 pvt->f.samples = dahdip->required_samples; 00322 pvt->f.data.ptr = NULL; 00323 pvt->f.offset = 0; 00324 pvt->f.datalen = 0; 00325 pvt->f.mallocd = 0; 00326 pvt->samples = 0; 00327 return ast_frisolate(&pvt->f); 00328 } else if (1 == dahdip->fake) { 00329 pvt->samples = 0; 00330 dahdip->fake = 0; 00331 return NULL; 00332 } 00333 00334 if (dahdip->samples_written_to_hardware >= ULAW_SAMPLES) { 00335 dahdi_wait_for_packet(dahdip->fd); 00336 } 00337 00338 /* Let's check to see if there is a new frame for us.... */ 00339 if (dahdip->softslin) { 00340 res = read(dahdip->fd, dahdip->ulaw_buffer, sizeof(dahdip->ulaw_buffer)); 00341 } else { 00342 res = read(dahdip->fd, pvt->outbuf.c + pvt->datalen, pvt->t->buf_size - pvt->datalen); 00343 } 00344 00345 if (-1 == res) { 00346 if (EWOULDBLOCK == errno) { 00347 /* Nothing waiting... */ 00348 return NULL; 00349 } else { 00350 ast_log(LOG_ERROR, "Failed to read from transcoder: %s\n", strerror(errno)); 00351 return NULL; 00352 } 00353 } else { 00354 if (dahdip->softslin) { 00355 ulawtolin(pvt, res); 00356 pvt->f.datalen = res * 2; 00357 } else { 00358 pvt->f.datalen = res; 00359 } 00360 pvt->datalen = 0; 00361 pvt->f.frametype = AST_FRAME_VOICE; 00362 pvt->f.subclass.codec = 1 << (pvt->t->dstfmt); 00363 pvt->f.mallocd = 0; 00364 pvt->f.offset = AST_FRIENDLY_OFFSET; 00365 pvt->f.src = pvt->t->name; 00366 pvt->f.data.ptr = pvt->outbuf.c; 00367 pvt->f.samples = res; 00368 pvt->samples = 0; 00369 dahdip->samples_written_to_hardware = 00370 (dahdip->samples_written_to_hardware >= res) ? 00371 dahdip->samples_written_to_hardware - res : 0; 00372 00373 return ast_frisolate(&pvt->f); 00374 } 00375 00376 /* Shouldn't get here... */ 00377 return NULL; 00378 }
static void dahdi_destroy | ( | struct ast_trans_pvt * | pvt | ) | [static] |
Definition at line 381 of file codec_dahdi.c.
References ast_atomic_fetchadd_int(), AST_FORMAT_G723_1, AST_FORMAT_G729A, channels, channel_usage::decoders, channel_usage::encoders, codec_dahdi_pvt::fd, codec_dahdi_pvt::fmts, and ast_trans_pvt::pvt.
Referenced by register_translator().
00382 { 00383 struct codec_dahdi_pvt *dahdip = pvt->pvt; 00384 00385 switch (dahdip->fmts.dstfmt) { 00386 case AST_FORMAT_G729A: 00387 case AST_FORMAT_G723_1: 00388 ast_atomic_fetchadd_int(&channels.encoders, -1); 00389 break; 00390 default: 00391 ast_atomic_fetchadd_int(&channels.decoders, -1); 00392 break; 00393 } 00394 00395 close(dahdip->fd); 00396 }
static int dahdi_encoder_framein | ( | struct ast_trans_pvt * | pvt, | |
struct ast_frame * | f | |||
) | [static] |
Definition at line 177 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::samples_written_to_hardware, codec_dahdi_pvt::softslin, and codec_dahdi_pvt::ulaw_buffer.
Referenced by register_translator().
00178 { 00179 struct codec_dahdi_pvt *dahdip = pvt->pvt; 00180 00181 if (!f->subclass.codec) { 00182 /* We're just faking a return for calculation purposes. */ 00183 dahdip->fake = 2; 00184 pvt->samples = f->samples; 00185 return 0; 00186 } 00187 00188 /* Buffer up the packets and send them to the hardware if we 00189 * have enough samples set up. */ 00190 if (dahdip->softslin) { 00191 if (lintoulaw(pvt, f)) { 00192 return -1; 00193 } 00194 } else { 00195 /* NOTE: If softslin support is not needed, and the sample 00196 * size is equal to the required sample size, we wouldn't 00197 * need this copy operation. But at the time this was 00198 * written, only softslin is supported. */ 00199 if (dahdip->samples_in_buffer + f->samples > sizeof(dahdip->ulaw_buffer)) { 00200 ast_log(LOG_ERROR, "Out of buffer space.\n"); 00201 return -1; 00202 } 00203 memcpy(&dahdip->ulaw_buffer[dahdip->samples_in_buffer], f->data.ptr, f->samples); 00204 dahdip->samples_in_buffer += f->samples; 00205 } 00206 00207 while (dahdip->samples_in_buffer >= dahdip->required_samples) { 00208 dahdi_write_frame(dahdip, dahdip->ulaw_buffer, dahdip->required_samples); 00209 dahdip->samples_written_to_hardware += dahdip->required_samples; 00210 dahdip->samples_in_buffer -= dahdip->required_samples; 00211 if (dahdip->samples_in_buffer) { 00212 /* Shift any remaining bytes down. */ 00213 memmove(dahdip->ulaw_buffer, &dahdip->ulaw_buffer[dahdip->required_samples], 00214 dahdip->samples_in_buffer); 00215 } 00216 } 00217 pvt->samples += f->samples; 00218 pvt->datalen = 0; 00219 return -1; 00220 }
static struct ast_frame* dahdi_encoder_frameout | ( | struct ast_trans_pvt * | pvt | ) | [static] |
Definition at line 230 of file codec_dahdi.c.
References ast_codec_get_samples(), AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_frisolate(), ast_log(), ast_translator::buf_size, ast_trans_pvt::c, ast_frame_subclass::codec, dahdi_wait_for_packet(), 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::samples_written_to_hardware, ast_frame::src, ast_frame::subclass, and ast_trans_pvt::t.
Referenced by register_translator().
00231 { 00232 struct codec_dahdi_pvt *dahdip = pvt->pvt; 00233 int res; 00234 00235 if (2 == dahdip->fake) { 00236 dahdip->fake = 1; 00237 pvt->f.frametype = AST_FRAME_VOICE; 00238 pvt->f.subclass.codec = 0; 00239 pvt->f.samples = dahdip->required_samples; 00240 pvt->f.data.ptr = NULL; 00241 pvt->f.offset = 0; 00242 pvt->f.datalen = 0; 00243 pvt->f.mallocd = 0; 00244 pvt->samples = 0; 00245 00246 return ast_frisolate(&pvt->f); 00247 00248 } else if (1 == dahdip->fake) { 00249 dahdip->fake = 0; 00250 return NULL; 00251 } 00252 00253 if (dahdip->samples_written_to_hardware >= dahdip->required_samples) { 00254 dahdi_wait_for_packet(dahdip->fd); 00255 } 00256 00257 res = read(dahdip->fd, pvt->outbuf.c + pvt->datalen, pvt->t->buf_size - pvt->datalen); 00258 if (-1 == res) { 00259 if (EWOULDBLOCK == errno) { 00260 /* Nothing waiting... */ 00261 return NULL; 00262 } else { 00263 ast_log(LOG_ERROR, "Failed to read from transcoder: %s\n", strerror(errno)); 00264 return NULL; 00265 } 00266 } else { 00267 pvt->f.datalen = res; 00268 pvt->f.frametype = AST_FRAME_VOICE; 00269 pvt->f.subclass.codec = 1 << (pvt->t->dstfmt); 00270 pvt->f.mallocd = 0; 00271 pvt->f.offset = AST_FRIENDLY_OFFSET; 00272 pvt->f.src = pvt->t->name; 00273 pvt->f.data.ptr = pvt->outbuf.c; 00274 pvt->f.samples = ast_codec_get_samples(&pvt->f); 00275 00276 dahdip->samples_written_to_hardware = 00277 (dahdip->samples_written_to_hardware >= pvt->f.samples) ? 00278 dahdip->samples_written_to_hardware - pvt->f.samples : 0; 00279 00280 pvt->samples = 0; 00281 pvt->datalen = 0; 00282 return ast_frisolate(&pvt->f); 00283 } 00284 00285 /* Shouldn't get here... */ 00286 return NULL; 00287 }
static int dahdi_new | ( | struct ast_trans_pvt * | pvt | ) | [static] |
Definition at line 471 of file codec_dahdi.c.
References dahdi_translate(), ast_translator::dstfmt, ast_translator::srcfmt, and ast_trans_pvt::t.
00472 { 00473 return dahdi_translate(pvt, pvt->t->dstfmt, pvt->t->srcfmt); 00474 }
static int dahdi_translate | ( | struct ast_trans_pvt * | pvt, | |
int | dest, | |||
int | source | |||
) | [static] |
Definition at line 398 of file codec_dahdi.c.
References ast_atomic_fetchadd_int(), ast_debug, AST_FORMAT_G723_1, AST_FORMAT_G729A, AST_FORMAT_SLINEAR, AST_FORMAT_ULAW, ast_log(), channels, channel_usage::decoders, channel_usage::encoders, errno, codec_dahdi_pvt::fd, codec_dahdi_pvt::fmts, G723_SAMPLES, G729_SAMPLES, LOG_ERROR, LOG_WARNING, ast_trans_pvt::pvt, codec_dahdi_pvt::required_samples, and codec_dahdi_pvt::softslin.
Referenced by dahdi_new().
00399 { 00400 /* Request translation through zap if possible */ 00401 int fd; 00402 struct codec_dahdi_pvt *dahdip = pvt->pvt; 00403 int flags; 00404 int tried_once = 0; 00405 const char *dev_filename = "/dev/dahdi/transcode"; 00406 00407 if ((fd = open(dev_filename, O_RDWR)) < 0) { 00408 ast_log(LOG_ERROR, "Failed to open %s: %s\n", dev_filename, strerror(errno)); 00409 return -1; 00410 } 00411 00412 dahdip->fmts.srcfmt = (1 << source); 00413 dahdip->fmts.dstfmt = (1 << dest); 00414 00415 ast_debug(1, "Opening transcoder channel from %d to %d.\n", source, dest); 00416 00417 retry: 00418 if (ioctl(fd, DAHDI_TC_ALLOCATE, &dahdip->fmts)) { 00419 if ((ENODEV == errno) && !tried_once) { 00420 /* We requested to translate to/from an unsupported 00421 * format. Most likely this is because signed linear 00422 * was not supported by any hardware devices even 00423 * though this module always registers signed linear 00424 * support. In this case we'll retry, requesting 00425 * support for ULAW instead of signed linear and then 00426 * we'll just convert from ulaw to signed linear in 00427 * software. */ 00428 if (AST_FORMAT_SLINEAR == dahdip->fmts.srcfmt) { 00429 ast_debug(1, "Using soft_slin support on source\n"); 00430 dahdip->softslin = 1; 00431 dahdip->fmts.srcfmt = AST_FORMAT_ULAW; 00432 } else if (AST_FORMAT_SLINEAR == dahdip->fmts.dstfmt) { 00433 ast_debug(1, "Using soft_slin support on destination\n"); 00434 dahdip->softslin = 1; 00435 dahdip->fmts.dstfmt = AST_FORMAT_ULAW; 00436 } 00437 tried_once = 1; 00438 goto retry; 00439 } 00440 ast_log(LOG_ERROR, "Unable to attach to transcoder: %s\n", strerror(errno)); 00441 close(fd); 00442 00443 return -1; 00444 } 00445 00446 flags = fcntl(fd, F_GETFL); 00447 if (flags > - 1) { 00448 if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) 00449 ast_log(LOG_WARNING, "Could not set non-block mode!\n"); 00450 } 00451 00452 dahdip->fd = fd; 00453 00454 dahdip->required_samples = ((dahdip->fmts.dstfmt|dahdip->fmts.srcfmt)&AST_FORMAT_G723_1) ? G723_SAMPLES : G729_SAMPLES; 00455 00456 switch (dahdip->fmts.dstfmt) { 00457 case AST_FORMAT_G729A: 00458 ast_atomic_fetchadd_int(&channels.encoders, +1); 00459 break; 00460 case AST_FORMAT_G723_1: 00461 ast_atomic_fetchadd_int(&channels.encoders, +1); 00462 break; 00463 default: 00464 ast_atomic_fetchadd_int(&channels.decoders, +1); 00465 break; 00466 } 00467 00468 return 0; 00469 }
static void dahdi_wait_for_packet | ( | int | fd | ) | [static] |
Definition at line 222 of file codec_dahdi.c.
Referenced by dahdi_decoder_frameout(), and dahdi_encoder_frameout().
00223 { 00224 struct pollfd p = {0}; 00225 p.fd = fd; 00226 p.events = POLLIN; 00227 poll(&p, 1, 10); 00228 }
static void dahdi_write_frame | ( | struct codec_dahdi_pvt * | dahdip, | |
const uint8_t * | buffer, | |||
const ssize_t | count | |||
) | [static] |
Definition at line 162 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().
00163 { 00164 int res; 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 }
static void drop_translator | ( | int | dst, | |
int | src | |||
) | [static] |
Definition at line 539 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.
00540 { 00541 struct translator *cur; 00542 00543 AST_LIST_LOCK(&translators); 00544 AST_LIST_TRAVERSE_SAFE_BEGIN(&translators, cur, entry) { 00545 if (cur->t.srcfmt != src) 00546 continue; 00547 00548 if (cur->t.dstfmt != dst) 00549 continue; 00550 00551 AST_LIST_REMOVE_CURRENT(entry); 00552 ast_unregister_translator(&cur->t); 00553 ast_free(cur); 00554 global_format_map.map[dst][src] = 0; 00555 break; 00556 } 00557 AST_LIST_TRAVERSE_SAFE_END; 00558 AST_LIST_UNLOCK(&translators); 00559 }
static struct ast_frame* fakesrc_sample | ( | void | ) | [static] |
Definition at line 476 of file codec_dahdi.c.
References AST_FRAME_VOICE, and f.
Referenced by register_translator().
00477 { 00478 /* Don't bother really trying to test hardware ones. */ 00479 static struct ast_frame f = { 00480 .frametype = AST_FRAME_VOICE, 00481 .samples = 160, 00482 .src = __PRETTY_FUNCTION__ 00483 }; 00484 00485 return &f; 00486 }
static int find_transcoders | ( | void | ) | [static] |
Definition at line 594 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().
00595 { 00596 struct dahdi_transcoder_info info = { 0, }; 00597 struct format_map map = { { { 0 } } }; 00598 int fd, res; 00599 unsigned int x, y; 00600 00601 if ((fd = open("/dev/dahdi/transcode", O_RDWR)) < 0) { 00602 ast_log(LOG_ERROR, "Failed to open /dev/dahdi/transcode: %s\n", strerror(errno)); 00603 return 0; 00604 } 00605 00606 for (info.tcnum = 0; !(res = ioctl(fd, DAHDI_TC_GETINFO, &info)); info.tcnum++) { 00607 if (option_verbose > 1) 00608 ast_verbose(VERBOSE_PREFIX_2 "Found transcoder '%s'.\n", info.name); 00609 00610 /* Complex codecs need to support signed linear. If the 00611 * hardware transcoder does not natively support signed linear 00612 * format, we will emulate it in software directly in this 00613 * module. Also, do not allow direct ulaw/alaw to complex 00614 * codec translation, since that will prevent the generic PLC 00615 * functions from working. */ 00616 if (info.dstfmts & (AST_FORMAT_ULAW | AST_FORMAT_ALAW)) { 00617 info.dstfmts |= AST_FORMAT_SLINEAR; 00618 info.dstfmts &= ~(AST_FORMAT_ULAW | AST_FORMAT_ALAW); 00619 } 00620 if (info.srcfmts & (AST_FORMAT_ULAW | AST_FORMAT_ALAW)) { 00621 info.srcfmts |= AST_FORMAT_SLINEAR; 00622 info.srcfmts &= ~(AST_FORMAT_ULAW | AST_FORMAT_ALAW); 00623 } 00624 00625 build_translators(&map, info.dstfmts, info.srcfmts); 00626 ast_atomic_fetchadd_int(&channels.total, info.numchannels / 2); 00627 00628 } 00629 00630 close(fd); 00631 00632 if (!info.tcnum && (option_verbose > 1)) 00633 ast_verbose(VERBOSE_PREFIX_2 "No hardware transcoders found.\n"); 00634 00635 for (x = 0; x < 32; x++) { 00636 for (y = 0; y < 32; y++) { 00637 if (!map.map[x][y] && global_format_map.map[x][y]) 00638 drop_translator(x, y); 00639 } 00640 } 00641 00642 return 0; 00643 }
static char * handle_cli_transcoder_show | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 134 of file codec_dahdi.c.
References ast_cli_args::argc, ast_cli(), channels, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, copy(), ast_cli_args::fd, and ast_cli_entry::usage.
00135 { 00136 struct channel_usage copy; 00137 00138 switch (cmd) { 00139 case CLI_INIT: 00140 e->command = "transcoder show"; 00141 e->usage = 00142 "Usage: transcoder show\n" 00143 " Displays channel utilization of DAHDI transcoder(s).\n"; 00144 return NULL; 00145 case CLI_GENERATE: 00146 return NULL; 00147 } 00148 00149 if (a->argc != 2) 00150 return CLI_SHOWUSAGE; 00151 00152 copy = channels; 00153 00154 if (copy.total == 0) 00155 ast_cli(a->fd, "No DAHDI transcoders found.\n"); 00156 else 00157 ast_cli(a->fd, "%d/%d encoders/decoders of %d channels are in use.\n", copy.encoders, copy.decoders, copy.total); 00158 00159 return CLI_SUCCESS; 00160 }
static int is_encoder | ( | struct translator * | zt | ) | [static] |
Definition at line 488 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().
00489 { 00490 if (zt->t.srcfmt&(AST_FORMAT_ULAW|AST_FORMAT_ALAW|AST_FORMAT_SLINEAR)) { 00491 return 1; 00492 } else { 00493 return 0; 00494 } 00495 }
static int lintoulaw | ( | struct ast_trans_pvt * | pvt, | |
struct ast_frame * | f | |||
) | [static] |
Definition at line 114 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.
00115 { 00116 struct codec_dahdi_pvt *dahdip = pvt->pvt; 00117 int i = f->samples; 00118 uint8_t *dst = &dahdip->ulaw_buffer[dahdip->samples_in_buffer]; 00119 int16_t *src = f->data.ptr; 00120 00121 if (dahdip->samples_in_buffer + i > sizeof(dahdip->ulaw_buffer)) { 00122 ast_log(LOG_ERROR, "Out of buffer space!\n"); 00123 return -i; 00124 } 00125 00126 while (i--) { 00127 *dst++ = AST_LIN2MU(*src++); 00128 } 00129 00130 dahdip->samples_in_buffer += f->samples; 00131 return 0; 00132 }
static int load_module | ( | void | ) | [static] |
Definition at line 658 of file codec_dahdi.c.
References ARRAY_LEN, ast_cli_register_multiple(), AST_MODULE_LOAD_SUCCESS, ast_ulaw_init(), cli, and find_transcoders().
00659 { 00660 ast_ulaw_init(); 00661 find_transcoders(); 00662 ast_cli_register_multiple(cli, ARRAY_LEN(cli)); 00663 return AST_MODULE_LOAD_SUCCESS; 00664 }
static int register_translator | ( | int | dst, | |
int | src | |||
) | [static] |
Definition at line 497 of file codec_dahdi.c.
References ast_calloc, 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(), global_format_map, is_encoder(), and format_map::map.
Referenced by build_translators().
00498 { 00499 struct translator *zt; 00500 int res; 00501 00502 if (!(zt = ast_calloc(1, sizeof(*zt)))) { 00503 return -1; 00504 } 00505 00506 snprintf((char *) (zt->t.name), sizeof(zt->t.name), "zap%sto%s", 00507 ast_getformatname((1 << src)), ast_getformatname((1 << dst))); 00508 zt->t.srcfmt = (1 << src); 00509 zt->t.dstfmt = (1 << dst); 00510 zt->t.buf_size = BUFFER_SIZE; 00511 if (is_encoder(zt)) { 00512 zt->t.framein = dahdi_encoder_framein; 00513 zt->t.frameout = dahdi_encoder_frameout; 00514 } else { 00515 zt->t.framein = dahdi_decoder_framein; 00516 zt->t.frameout = dahdi_decoder_frameout; 00517 } 00518 zt->t.destroy = dahdi_destroy; 00519 zt->t.buffer_samples = 0; 00520 zt->t.newpvt = dahdi_new; 00521 zt->t.sample = fakesrc_sample; 00522 zt->t.native_plc = 0; 00523 00524 zt->t.desc_size = sizeof(struct codec_dahdi_pvt); 00525 if ((res = ast_register_translator(&zt->t))) { 00526 ast_free(zt); 00527 return -1; 00528 } 00529 00530 AST_LIST_LOCK(&translators); 00531 AST_LIST_INSERT_HEAD(&translators, zt, entry); 00532 AST_LIST_UNLOCK(&translators); 00533 00534 global_format_map.map[dst][src] = 1; 00535 00536 return res; 00537 }
static int reload | ( | void | ) | [static] |
Definition at line 645 of file codec_dahdi.c.
References AST_MODULE_LOAD_SUCCESS.
00646 { 00647 return AST_MODULE_LOAD_SUCCESS; 00648 }
static int ulawtolin | ( | struct ast_trans_pvt * | pvt, | |
int | samples | |||
) | [static] |
Definition at line 98 of file codec_dahdi.c.
References AST_MULAW, ast_trans_pvt::datalen, ast_trans_pvt::i16, ast_trans_pvt::outbuf, ast_trans_pvt::pvt, and codec_dahdi_pvt::ulaw_buffer.
00099 { 00100 struct codec_dahdi_pvt *dahdip = pvt->pvt; 00101 int i = samples; 00102 uint8_t *src = &dahdip->ulaw_buffer[0]; 00103 int16_t *dst = pvt->outbuf.i16 + pvt->datalen; 00104 00105 /* convert and copy in outbuf */ 00106 while (i--) { 00107 *dst++ = AST_MULAW(*src++); 00108 } 00109 00110 return 0; 00111 }
static int unload_module | ( | void | ) | [static] |
Definition at line 650 of file codec_dahdi.c.
References ARRAY_LEN, ast_cli_unregister_multiple(), cli, and unregister_translators().
00651 { 00652 ast_cli_unregister_multiple(cli, ARRAY_LEN(cli)); 00653 unregister_translators(); 00654 00655 return 0; 00656 }
static void unregister_translators | ( | void | ) | [static] |
Definition at line 561 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().
00562 { 00563 struct translator *cur; 00564 00565 AST_LIST_LOCK(&translators); 00566 while ((cur = AST_LIST_REMOVE_HEAD(&translators, entry))) { 00567 ast_unregister_translator(&cur->t); 00568 ast_free(cur); 00569 } 00570 AST_LIST_UNLOCK(&translators); 00571 }
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 = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .reload = reload, } [static] |
Definition at line 670 of file codec_dahdi.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 670 of file codec_dahdi.c.
struct channel_usage channels [static] |
Referenced by __ast_channel_alloc_ap(), action_dahdishowchannels(), action_status(), ast_active_channels(), ast_begin_shutdown(), ast_change_name(), ast_channel_callback(), ast_channel_get_full(), ast_channel_iterator_all_new(), ast_channel_release(), ast_channels_init(), ast_do_masquerade(), ast_hangup(), channel_iterator_search(), check_header(), dahdi_destroy(), dahdi_translate(), and handle_cli_transcoder_show().
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().