Mon Oct 8 12:39:20 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"

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_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, 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_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 = "ac1f6a56484a8820659555499174e588" , .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 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().


Function Documentation

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 }


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 = "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().


Generated on Mon Oct 8 12:39:20 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7