Sat Feb 11 06:35:01 2012

Asterisk developer's documentation


codec_dahdi.c File Reference

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"

Include dependency graph for codec_dahdi.c:

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_framedahdi_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_framedahdi_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_framefakesrc_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_infoast_module_info = &__mod_info
static struct channel_usage channels
static struct ast_cli_entry cli []
static struct format_map global_format_map = { { { 0 } } }


Detailed Description

Translate between various formats natively through DAHDI transcoding.

Definition in file codec_dahdi.c.


Define Documentation

#define BUFFER_SIZE   8000

Definition at line 54 of file codec_dahdi.c.

Referenced by register_translator().

#define DAHDI_FORMAT_ADPCM   (1 << 5)

Definition at line 65 of file codec_dahdi.c.

#define DAHDI_FORMAT_ALAW   (1 << 3)

Definition at line 63 of file codec_dahdi.c.

Referenced by find_transcoders().

#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)

Definition at line 66 of file codec_dahdi.c.

Referenced by find_transcoders().

#define DAHDI_FORMAT_SPEEX   (1 << 9)

Definition at line 69 of file codec_dahdi.c.

#define DAHDI_FORMAT_ULAW   (1 << 2)

Definition at line 62 of file codec_dahdi.c.

Referenced by find_transcoders().

#define G723_SAMPLES   240

Definition at line 56 of file codec_dahdi.c.

Referenced by dahdi_translate().

#define G729_SAMPLES   160

Definition at line 57 of file codec_dahdi.c.

Referenced by dahdi_translate().


Function Documentation

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]

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]

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 }


Variable Documentation

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.

Definition at line 669 of file codec_dahdi.c.

struct channel_usage channels [static]

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.


Generated on Sat Feb 11 06:35:02 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6