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