Wed Feb 11 12:00:20 2009

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 <stdlib.h>
#include <unistd.h>
#include <netinet/in.h>
#include <string.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <sys/mman.h>
#include "asterisk/lock.h"
#include "asterisk/translate.h"
#include "asterisk/config.h"
#include "asterisk/options.h"
#include "asterisk/module.h"
#include "asterisk/cli.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/utils.h"
#include "asterisk/linkedlists.h"
#include "asterisk/dahdi_compat.h"

Go to the source code of this file.

Data Structures

struct  channel_usage
struct  format_map
struct  pvt
struct  translator
struct  translators
 the list of translators More...

Defines

#define BUFFER_SAMPLES   8000

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 void drop_translator (int dst, int src)
static struct ast_framefakesrc_sample (void)
static int find_transcoders (void)
static int load_module (void)
static void parse_config (void)
static int register_translator (int dst, int src)
static int reload (void)
static int transcoder_show (int fd, int argc, char **argv)
static int unload_module (void)
static void unregister_translators (void)
static void zap_destroy (struct ast_trans_pvt *pvt)
static int zap_framein (struct ast_trans_pvt *pvt, struct ast_frame *f)
static struct ast_framezap_frameout (struct ast_trans_pvt *pvt)
static int zap_new (struct ast_trans_pvt *pvt)
static int zap_translate (struct ast_trans_pvt *pvt, int dest, int source)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .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 = "f450f61f60e761b3aa089ebed76ca8a5" , .load = load_module, .unload = unload_module, .reload = reload, }
static const struct ast_module_infoast_module_info = &__mod_info
static struct channel_usage channels
static struct ast_cli_entry cli []
static struct ast_cli_entry cli_deprecated []
static struct format_map global_format_map = { { { 0 } } }
static unsigned int global_useplc = 0
static char show_transcoder_usage []
static char transcoder_show_usage []


Detailed Description

Translate between various formats natively through DAHDI transcoding.

Definition in file codec_dahdi.c.


Define Documentation

#define BUFFER_SAMPLES   8000

Definition at line 60 of file codec_dahdi.c.


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 480 of file codec_dahdi.c.

static void __unreg_module ( void   )  [static]

Definition at line 480 of file codec_dahdi.c.

static void build_translators ( struct format_map map,
unsigned int  dstfmts,
unsigned int  srcfmts 
) [static]

Definition at line 390 of file codec_dahdi.c.

References global_format_map, map, format_map::map, and register_translator().

Referenced by find_transcoders().

00391 {
00392    unsigned int src, dst;
00393 
00394    for (src = 0; src < 32; src++) {
00395       for (dst = 0; dst < 32; dst++) {
00396          if (!(srcfmts & (1 << src)))
00397             continue;
00398 
00399          if (!(dstfmts & (1 << dst)))
00400             continue;
00401 
00402          if (global_format_map.map[dst][src])
00403             continue;
00404 
00405          if (!register_translator(dst, src))
00406             map->map[dst][src] = 1;
00407       }
00408    }
00409 }

static void drop_translator ( int  dst,
int  src 
) [static]

Definition at line 336 of file codec_dahdi.c.

References 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, free, global_format_map, format_map::map, ast_translator::srcfmt, and translator::t.

Referenced by find_transcoders().

00337 {
00338    struct translator *cur;
00339 
00340    AST_LIST_LOCK(&translators);
00341    AST_LIST_TRAVERSE_SAFE_BEGIN(&translators, cur, entry) {
00342       if (cur->t.srcfmt != src)
00343          continue;
00344 
00345       if (cur->t.dstfmt != dst)
00346          continue;
00347 
00348       AST_LIST_REMOVE_CURRENT(&translators, entry);
00349       ast_unregister_translator(&cur->t);
00350       free(cur);
00351       global_format_map.map[dst][src] = 0;
00352       break;
00353    }
00354    AST_LIST_TRAVERSE_SAFE_END;
00355    AST_LIST_UNLOCK(&translators);
00356 }

static struct ast_frame* fakesrc_sample ( void   )  [static]

Definition at line 290 of file codec_dahdi.c.

References AST_FRAME_VOICE, and f.

Referenced by register_translator().

00291 {
00292    /* Don't bother really trying to test hardware ones. */
00293    static struct ast_frame f = {
00294       .frametype = AST_FRAME_VOICE,
00295       .samples = 160,
00296       .src = __PRETTY_FUNCTION__
00297    };
00298 
00299    return &f;
00300 }

static int find_transcoders ( void   )  [static]

Definition at line 411 of file codec_dahdi.c.

References ast_atomic_fetchadd_int(), ast_log(), ast_verbose(), build_translators(), DAHDI_FILE_TRANSCODE, drop_translator(), errno, global_format_map, LOG_ERROR, format_map::map, map, option_verbose, and VERBOSE_PREFIX_2.

Referenced by load_module().

00412 {
00413    struct dahdi_transcoder_info info = { 0, };
00414    struct format_map map = { { { 0 } } };
00415    int fd, res;
00416    unsigned int x, y;
00417 
00418    if ((fd = open(DAHDI_FILE_TRANSCODE, O_RDWR)) < 0) {
00419       ast_log(LOG_ERROR, "Failed to open " DAHDI_FILE_TRANSCODE ": %s\n", strerror(errno));
00420       return 0;
00421    }
00422 
00423    for (info.tcnum = 0; !(res = ioctl(fd, DAHDI_TC_GETINFO, &info)); info.tcnum++) {
00424       if (option_verbose > 1)
00425          ast_verbose(VERBOSE_PREFIX_2 "Found transcoder '%s'.\n", info.name);
00426       build_translators(&map, info.dstfmts, info.srcfmts);
00427       ast_atomic_fetchadd_int(&channels.total, info.numchannels / 2);
00428    }
00429 
00430    close(fd);
00431 
00432    if (!info.tcnum && (option_verbose > 1))
00433       ast_verbose(VERBOSE_PREFIX_2 "No hardware transcoders found.\n");
00434 
00435    for (x = 0; x < 32; x++) {
00436       for (y = 0; y < 32; y++) {
00437          if (!map.map[x][y] && global_format_map.map[x][y])
00438             drop_translator(x, y);
00439       }
00440    }
00441 
00442    return 0;
00443 }

static int load_module ( void   )  [static]

Definition at line 467 of file codec_dahdi.c.

References ast_cli_register_multiple(), cli, find_transcoders(), and parse_config().

00468 {
00469    parse_config();
00470    find_transcoders();
00471    ast_cli_register_multiple(cli, sizeof(cli) / sizeof(cli[0]));
00472 
00473    return 0;
00474 }

static void parse_config ( void   )  [static]

Definition at line 370 of file codec_dahdi.c.

References ast_config_load(), ast_true(), ast_variable_browse(), ast_verbose(), option_verbose, var, and VERBOSE_PREFIX_3.

00371 {
00372    struct ast_variable *var;
00373    struct ast_config *cfg = ast_config_load("codecs.conf");
00374 
00375    if (!cfg)
00376       return;
00377 
00378    for (var = ast_variable_browse(cfg, "plc"); var; var = var->next) {
00379           if (!strcasecmp(var->name, "genericplc")) {
00380              global_useplc = ast_true(var->value);
00381              if (option_verbose > 2)
00382                 ast_verbose(VERBOSE_PREFIX_3 "codec_zap: %susing generic PLC\n",
00383                   global_useplc ? "" : "not ");
00384           }
00385    }
00386 
00387    ast_config_destroy(cfg);
00388 }

static int register_translator ( int  dst,
int  src 
) [static]

Definition at line 302 of file codec_dahdi.c.

References ast_calloc, ast_getformatname(), AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_register_translator, BUFFER_SAMPLES, translator::entry, fakesrc_sample(), free, global_format_map, format_map::map, zap_destroy(), zap_framein(), zap_frameout(), and zap_new().

Referenced by build_translators().

00303 {
00304    struct translator *zt;
00305    int res;
00306 
00307    if (!(zt = ast_calloc(1, sizeof(*zt))))
00308       return -1;
00309 
00310    snprintf((char *) (zt->t.name), sizeof(zt->t.name), "zap%sto%s", 
00311        ast_getformatname((1 << src)), ast_getformatname((1 << dst)));
00312    zt->t.srcfmt = (1 << src);
00313    zt->t.dstfmt = (1 << dst);
00314    zt->t.newpvt = zap_new;
00315    zt->t.framein = zap_framein;
00316    zt->t.frameout = zap_frameout;
00317    zt->t.destroy = zap_destroy;
00318    zt->t.sample = fakesrc_sample;
00319    zt->t.useplc = global_useplc;
00320    zt->t.buf_size = BUFFER_SAMPLES * 2;
00321    zt->t.desc_size = sizeof(struct pvt);
00322    if ((res = ast_register_translator(&zt->t))) {
00323       free(zt);
00324       return -1;
00325    }
00326 
00327    AST_LIST_LOCK(&translators);
00328    AST_LIST_INSERT_HEAD(&translators, zt, entry);
00329    AST_LIST_UNLOCK(&translators);
00330 
00331    global_format_map.map[dst][src] = 1;
00332 
00333    return res;
00334 }

static int reload ( void   )  [static]

Definition at line 445 of file codec_dahdi.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, translator::entry, parse_config(), translator::t, and ast_translator::useplc.

00446 {
00447    struct translator *cur;
00448 
00449    parse_config();
00450 
00451    AST_LIST_LOCK(&translators);
00452    AST_LIST_TRAVERSE(&translators, cur, entry)
00453       cur->t.useplc = global_useplc;
00454    AST_LIST_UNLOCK(&translators);
00455 
00456    return 0;
00457 }

static int transcoder_show ( int  fd,
int  argc,
char **  argv 
) [static]

Definition at line 115 of file codec_dahdi.c.

References ast_cli(), copy(), and RESULT_SUCCESS.

00116 {
00117    struct channel_usage copy;
00118 
00119    copy = channels;
00120 
00121    if (copy.total == 0)
00122       ast_cli(fd, "No DAHDI transcoders found.\n");
00123    else
00124       ast_cli(fd, "%d/%d encoders/decoders of %d channels are in use.\n", copy.encoders, copy.decoders, copy.total);
00125 
00126    return RESULT_SUCCESS;
00127 }

static int unload_module ( void   )  [static]

Definition at line 459 of file codec_dahdi.c.

References ast_cli_unregister_multiple(), cli, and unregister_translators().

00460 {
00461    ast_cli_unregister_multiple(cli, sizeof(cli) / sizeof(cli[0]));
00462    unregister_translators();
00463 
00464    return 0;
00465 }

static void unregister_translators ( void   )  [static]

Definition at line 358 of file codec_dahdi.c.

References AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, ast_unregister_translator(), translator::entry, free, and translator::t.

Referenced by unload_module().

00359 {
00360    struct translator *cur;
00361 
00362    AST_LIST_LOCK(&translators);
00363    while ((cur = AST_LIST_REMOVE_HEAD(&translators, entry))) {
00364       ast_unregister_translator(&cur->t);
00365       free(cur);
00366    }
00367    AST_LIST_UNLOCK(&translators);
00368 }

static void zap_destroy ( struct ast_trans_pvt pvt  )  [static]

Definition at line 209 of file codec_dahdi.c.

References ast_atomic_fetchadd_int(), AST_FORMAT_G723_1, AST_FORMAT_G729A, pvt::fd, pvt::fmts, and ast_trans_pvt::pvt.

Referenced by register_translator().

00210 {
00211    struct pvt *ztp = pvt->pvt;
00212 
00213    switch (ztp->fmts.dstfmt) {
00214    case AST_FORMAT_G729A:
00215    case AST_FORMAT_G723_1:
00216       ast_atomic_fetchadd_int(&channels.encoders, -1);
00217       break;
00218    default:
00219       ast_atomic_fetchadd_int(&channels.decoders, -1);
00220       break;
00221    }
00222 
00223    close(ztp->fd);
00224 }

static int zap_framein ( struct ast_trans_pvt pvt,
struct ast_frame f 
) [static]

Definition at line 129 of file codec_dahdi.c.

References ast_log(), errno, f, pvt::fake, pvt::fd, LOG_ERROR, ast_trans_pvt::pvt, and ast_trans_pvt::samples.

Referenced by register_translator().

00130 {
00131    int res;
00132    struct pvt *ztp = pvt->pvt;
00133 
00134    if (f->subclass) {
00135       /* Give the frame to the hardware transcoder... */
00136       res = write(ztp->fd, f->data, f->datalen); 
00137       if (-1 == res) {
00138          ast_log(LOG_ERROR, "Failed to write to transcoder: %s\n", strerror(errno));
00139       }
00140       if (f->datalen != res) {
00141          ast_log(LOG_ERROR, "Requested write of %d bytes, but only wrote %d bytes.\n", f->datalen, res);
00142       }
00143       res = -1;
00144       pvt->samples += f->samples;
00145    } else {
00146       /* Fake a return frame for calculation purposes */
00147       ztp->fake = 2;
00148       pvt->samples = f->samples;
00149       res = 0;
00150    }
00151    return res;
00152 }

static struct ast_frame* zap_frameout ( struct ast_trans_pvt pvt  )  [static]

Definition at line 154 of file codec_dahdi.c.

References AST_FRAME_VOICE, AST_FRFLAG_FROM_TRANSLATOR, AST_FRIENDLY_OFFSET, ast_log(), ast_set_flag, ast_translator::buf_size, ast_frame::data, ast_frame::datalen, ast_trans_pvt::datalen, ast_translator::dstfmt, errno, ast_trans_pvt::f, pvt::fake, pvt::fd, ast_frame::frametype, LOG_ERROR, ast_frame::mallocd, ast_translator::name, ast_frame::offset, ast_trans_pvt::outbuf, ast_trans_pvt::pvt, ast_trans_pvt::samples, pvt::samples, ast_frame::samples, ast_frame::src, ast_frame::subclass, and ast_trans_pvt::t.

Referenced by register_translator().

00155 {
00156    struct pvt *ztp = pvt->pvt;
00157 
00158    if (0 == ztp->fake) {
00159       int res;
00160       /* Let's check to see if there is a new frame for us.... */
00161       res = read(ztp->fd, pvt->outbuf + pvt->datalen, pvt->t->buf_size - pvt->datalen);
00162       if (-1 == res) {
00163          if (EWOULDBLOCK == errno) {
00164             /* Nothing waiting... */
00165             return NULL;
00166          } else {
00167             ast_log(LOG_ERROR, "Failed to read from transcoder: %s\n", strerror(errno));
00168             return NULL;
00169          }
00170       } else {
00171          pvt->f.samples = ztp->samples;
00172          pvt->f.datalen = res;
00173          pvt->datalen = 0;
00174          pvt->f.frametype = AST_FRAME_VOICE;
00175          pvt->f.subclass = 1 <<  (pvt->t->dstfmt);
00176          pvt->f.mallocd = 0;
00177          pvt->f.offset = AST_FRIENDLY_OFFSET;
00178          pvt->f.src = pvt->t->name;
00179          pvt->f.data = pvt->outbuf;
00180          ast_set_flag(&pvt->f, AST_FRFLAG_FROM_TRANSLATOR);
00181 
00182          return &pvt->f;
00183       }
00184 
00185    } else if (2 == ztp->fake) {
00186 
00187       ztp->fake = 1;
00188       pvt->f.frametype = AST_FRAME_VOICE;
00189       pvt->f.subclass = 0;
00190       pvt->f.samples = 160;
00191       pvt->f.data = NULL;
00192       pvt->f.offset = 0;
00193       pvt->f.datalen = 0;
00194       pvt->f.mallocd = 0;
00195       ast_set_flag(&pvt->f, AST_FRFLAG_FROM_TRANSLATOR);
00196       pvt->samples = 0;
00197 
00198       return &pvt->f;
00199 
00200    } else if (1 == ztp->fake) {
00201 
00202       return NULL;
00203 
00204    }
00205    /* Shouldn't get here... */
00206    return NULL;
00207 }

static int zap_new ( struct ast_trans_pvt pvt  )  [static]

Definition at line 285 of file codec_dahdi.c.

References ast_translator::dstfmt, ast_translator::srcfmt, ast_trans_pvt::t, and zap_translate().

Referenced by register_translator().

00286 {
00287    return zap_translate(pvt, pvt->t->dstfmt, pvt->t->srcfmt);
00288 }

static int zap_translate ( struct ast_trans_pvt pvt,
int  dest,
int  source 
) [static]

Definition at line 226 of file codec_dahdi.c.

References ast_atomic_fetchadd_int(), AST_FORMAT_G723_1, AST_FORMAT_G729A, ast_log(), DAHDI_FILE_TRANSCODE, errno, pvt::fd, pvt::fmts, LOG_ERROR, LOG_VERBOSE, LOG_WARNING, ast_trans_pvt::pvt, and pvt::samples.

Referenced by zap_new().

00227 {
00228    /* Request translation through zap if possible */
00229    int fd;
00230    struct pvt *ztp = pvt->pvt;
00231    int flags;
00232    
00233    if ((fd = open(DAHDI_FILE_TRANSCODE, O_RDWR)) < 0) {
00234       ast_log(LOG_ERROR, "Failed to open " DAHDI_FILE_TRANSCODE ": %s\n", strerror(errno));
00235       return -1;
00236    }
00237    
00238    ztp->fmts.srcfmt = (1 << source);
00239    ztp->fmts.dstfmt = (1 << dest);
00240 
00241    ast_log(LOG_VERBOSE, "Opening transcoder channel from %d to %d.\n", source, dest);
00242 
00243    if (ioctl(fd, DAHDI_TC_ALLOCATE, &ztp->fmts)) {
00244       ast_log(LOG_ERROR, "Unable to attach to transcoder: %s\n", strerror(errno));
00245       close(fd);
00246 
00247       return -1;
00248    }
00249 
00250    flags = fcntl(fd, F_GETFL);
00251    if (flags > - 1) {
00252       if (fcntl(fd, F_SETFL, flags | O_NONBLOCK))
00253          ast_log(LOG_WARNING, "Could not set non-block mode!\n");
00254    }
00255 
00256    ztp->fd = fd;
00257 
00258    switch (ztp->fmts.dstfmt) {
00259    case AST_FORMAT_G729A:
00260       ztp->samples = 160;
00261       break;
00262    case AST_FORMAT_G723_1:
00263       ztp->samples = 240;
00264       break;
00265    default:
00266       ztp->samples = 160;
00267       break;
00268    };
00269 
00270    switch (ztp->fmts.dstfmt) {
00271    case AST_FORMAT_G729A:
00272       ast_atomic_fetchadd_int(&channels.encoders, +1);
00273       break;
00274    case AST_FORMAT_G723_1:
00275       ast_atomic_fetchadd_int(&channels.encoders, +1);
00276       break;
00277    default:
00278       ast_atomic_fetchadd_int(&channels.decoders, +1);
00279       break;
00280    }
00281 
00282    return 0;
00283 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .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 = "f450f61f60e761b3aa089ebed76ca8a5" , .load = load_module, .unload = unload_module, .reload = reload, } [static]

Definition at line 480 of file codec_dahdi.c.

const struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 480 of file codec_dahdi.c.

struct channel_usage channels [static]

struct ast_cli_entry cli[] [static]

Definition at line 87 of file codec_dahdi.c.

Referenced by load_module(), and unload_module().

struct ast_cli_entry cli_deprecated[] [static]

Definition at line 80 of file codec_dahdi.c.

struct format_map global_format_map = { { { 0 } } } [static]

Definition at line 99 of file codec_dahdi.c.

Referenced by build_translators(), drop_translator(), find_transcoders(), and register_translator().

unsigned int global_useplc = 0 [static]

Definition at line 62 of file codec_dahdi.c.

char show_transcoder_usage[] [static]

Initial value:

"Usage: show transcoder\n"
"       Displays channel utilization of DAHDI transcoder(s).\n"

Definition at line 70 of file codec_dahdi.c.

char transcoder_show_usage[] [static]

Initial value:

"Usage: transcoder show\n"
"       Displays channel utilization of DAHDI transcoder(s).\n"

Definition at line 74 of file codec_dahdi.c.


Generated on Wed Feb 11 12:00:20 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7