Translate between various formats natively through DAHDI transcoding. More...
#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 |
Defines | |
#define | BUFFER_SIZE 8000 |
#define | G723_SAMPLES 240 |
#define | G729_SAMPLES 160 |
#define | ULAW_SAMPLES 160 |
Functions | |
static | AST_LIST_HEAD_STATIC (translators, translator) |
AST_MODULE_INFO (ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT,"Generic DAHDI Transcoder Codec Translator",.load=load_module,.unload=unload_module,.reload=reload,) | |
static void | build_translators (struct format_map *map, unsigned int dstfmts, unsigned int srcfmts) |
static 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 channel_usage | channels |
static struct ast_cli_entry | cli [] |
static struct format_map | global_format_map = { { { 0 } } } |
Translate between various formats natively through DAHDI transcoding.
Definition in file codec_dahdi.c.
#define BUFFER_SIZE 8000 |
Definition at line 55 of file codec_dahdi.c.
Referenced by register_translator().
#define G723_SAMPLES 240 |
Definition at line 57 of file codec_dahdi.c.
Referenced by dahdi_translate().
#define G729_SAMPLES 160 |
Definition at line 58 of file codec_dahdi.c.
Referenced by dahdi_translate().
#define ULAW_SAMPLES 160 |
Definition at line 59 of file codec_dahdi.c.
Referenced by dahdi_decoder_frameout().
static AST_LIST_HEAD_STATIC | ( | translators | , | |
translator | ||||
) | [static] |
AST_MODULE_INFO | ( | ASTERISK_GPL_KEY | , | |
AST_MODFLAG_DEFAULT | , | |||
"Generic DAHDI Transcoder Codec Translator" | , | |||
. | load = load_module , |
|||
. | unload = unload_module , |
|||
. | reload = reload | |||
) |
static void build_translators | ( | struct format_map * | map, | |
unsigned int | dstfmts, | |||
unsigned int | srcfmts | |||
) | [static] |
Definition at line 573 of file codec_dahdi.c.
References format_map::map, and register_translator().
Referenced by find_transcoders().
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(), ast_frame_subclass::codec, dahdi_write_frame(), ast_frame::data, ast_trans_pvt::datalen, ast_frame::datalen, codec_dahdi_pvt::fake, LOG_ERROR, ast_frame::ptr, ast_trans_pvt::pvt, codec_dahdi_pvt::required_samples, ast_frame::samples, ast_trans_pvt::samples, codec_dahdi_pvt::samples_written_to_hardware, and ast_frame::subclass.
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, read] |
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(), ast_frame_subclass::codec, dahdi_write_frame(), ast_frame::data, ast_trans_pvt::datalen, codec_dahdi_pvt::fake, lintoulaw(), LOG_ERROR, ast_frame::ptr, ast_trans_pvt::pvt, codec_dahdi_pvt::required_samples, ast_frame::samples, ast_trans_pvt::samples, codec_dahdi_pvt::samples_in_buffer, codec_dahdi_pvt::samples_written_to_hardware, codec_dahdi_pvt::softslin, ast_frame::subclass, 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, read] |
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.
Referenced by register_translator().
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().
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, format_map::map, ast_translator::srcfmt, and translator::t.
Referenced by find_transcoders().
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, read] |
Definition at line 476 of file codec_dahdi.c.
References AST_FRAME_VOICE, and ast_frame::frametype.
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_atomic_fetchadd_int(), AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, AST_FORMAT_ULAW, ast_log(), ast_verbose, build_translators(), channels, drop_translator(), errno, LOG_ERROR, format_map::map, option_verbose, channel_usage::total, 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, channel_usage::decoders, channel_usage::encoders, ast_cli_args::fd, channel_usage::total, 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(), ast_frame::data, LOG_ERROR, ast_frame::ptr, ast_trans_pvt::pvt, ast_frame::samples, codec_dahdi_pvt::samples_in_buffer, and codec_dahdi_pvt::ulaw_buffer.
Referenced by dahdi_encoder_framein().
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(), 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, ast_translator::buf_size, ast_translator::buffer_samples, BUFFER_SIZE, dahdi_decoder_framein(), dahdi_decoder_frameout(), dahdi_destroy(), dahdi_encoder_framein(), dahdi_encoder_frameout(), dahdi_new(), ast_translator::desc_size, ast_translator::destroy, ast_translator::dstfmt, fakesrc_sample(), ast_translator::framein, ast_translator::frameout, is_encoder(), format_map::map, ast_translator::name, ast_translator::native_plc, ast_translator::newpvt, ast_translator::sample, ast_translator::srcfmt, and translator::t.
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.
Referenced by dahdi_decoder_frameout().
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(), 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(), 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 channel_usage channels [static] |
Referenced by action_status(), check_header(), dahdi_destroy(), dahdi_translate(), find_transcoders(), and handle_cli_transcoder_show().
struct ast_cli_entry cli[] [static] |
{ }
Definition at line 69 of file codec_dahdi.c.
struct format_map global_format_map = { { { 0 } } } [static] |
Definition at line 77 of file codec_dahdi.c.