codec_dahdi.c File Reference

Translate between various formats natively through DAHDI transcoding. More...

#include "asterisk.h"
#include <stdbool.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 "asterisk/format_compatibility.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  translator
struct  translators
 the list of translators More...

Defines

#define BUFFER_SIZE   8000
#define container_of(ptr, type, member)   ((type *)((char *)(ptr) - offsetof(type, member)))
#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
#define ULAW_SAMPLES   160

Functions

static void __reg_module (void)
static void __unreg_module (void)
static void build_translators (uint32_t dstfmts, uint32_t 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 struct ast_formatdahdi_format_to_cached (int format)
static int dahdi_new (struct ast_trans_pvt *pvt)
static int dahdi_translate (struct ast_trans_pvt *pvt, uint32_t dst_dahdi_fmt, uint32_t src_dahdi_fmt)
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 struct ast_framefakesrc_sample (void)
static int find_transcoders (void)
static struct ast_codecget_dahdi_codec (uint32_t dahdi_fmt)
static char * handle_cli_transcoder_show (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static bool is_already_registered (uint32_t dstfmt, uint32_t srcfmt)
static bool is_encoder (uint32_t src_dahdi_fmt)
static int lintoulaw (struct ast_trans_pvt *pvt, struct ast_frame *f)
static int load_module (void)
static int register_translator (uint32_t dst_dahdi_fmt, uint32_t src_dahdi_fmt)
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, .support_level = AST_MODULE_SUPPORT_CORE, .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 []


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 57 of file codec_dahdi.c.

Referenced by register_translator().

#define container_of ( ptr,
type,
member   )     ((type *)((char *)(ptr) - offsetof(type, member)))

Definition at line 279 of file codec_dahdi.c.

Referenced by dahdi_new().

#define DAHDI_FORMAT_ADPCM   (1 << 5)

ADPCM (IMA)

Definition at line 76 of file codec_dahdi.c.

Referenced by dahdi_format_to_cached(), and get_dahdi_codec().

#define DAHDI_FORMAT_ALAW   (1 << 3)

Raw A-law data (G.711)

Definition at line 72 of file codec_dahdi.c.

Referenced by dahdi_format_to_cached(), find_transcoders(), get_dahdi_codec(), and is_encoder().

#define DAHDI_FORMAT_G723_1   (1 << 0)

G.723.1 compression

Definition at line 66 of file codec_dahdi.c.

Referenced by dahdi_destroy(), dahdi_format_to_cached(), dahdi_translate(), and get_dahdi_codec().

#define DAHDI_FORMAT_G726   (1 << 4)

ADPCM (G.726, 32kbps)

Definition at line 74 of file codec_dahdi.c.

Referenced by dahdi_format_to_cached(), and get_dahdi_codec().

#define DAHDI_FORMAT_G729A   (1 << 8)

G.729A audio

Definition at line 82 of file codec_dahdi.c.

Referenced by dahdi_destroy(), dahdi_format_to_cached(), dahdi_translate(), and get_dahdi_codec().

#define DAHDI_FORMAT_GSM   (1 << 1)

GSM compression

Definition at line 68 of file codec_dahdi.c.

Referenced by dahdi_format_to_cached(), and get_dahdi_codec().

#define DAHDI_FORMAT_ILBC   (1 << 10)

iLBC Free Compression

Definition at line 86 of file codec_dahdi.c.

Referenced by dahdi_format_to_cached(), and get_dahdi_codec().

#define DAHDI_FORMAT_LPC10   (1 << 7)

LPC10, 180 samples/frame

Definition at line 80 of file codec_dahdi.c.

Referenced by dahdi_format_to_cached(), and get_dahdi_codec().

#define DAHDI_FORMAT_SLINEAR   (1 << 6)

Raw 16-bit Signed Linear (8000 Hz) PCM

Definition at line 78 of file codec_dahdi.c.

Referenced by dahdi_format_to_cached(), dahdi_translate(), find_transcoders(), get_dahdi_codec(), and is_encoder().

#define DAHDI_FORMAT_SPEEX   (1 << 9)

SpeeX Free Compression

Definition at line 84 of file codec_dahdi.c.

Referenced by dahdi_format_to_cached(), and get_dahdi_codec().

#define DAHDI_FORMAT_ULAW   (1 << 2)

Raw mu-law data (G.711)

Definition at line 70 of file codec_dahdi.c.

Referenced by dahdi_format_to_cached(), dahdi_translate(), find_transcoders(), get_dahdi_codec(), and is_encoder().

#define G723_SAMPLES   240

Definition at line 59 of file codec_dahdi.c.

Referenced by dahdi_translate().

#define G729_SAMPLES   160

Definition at line 60 of file codec_dahdi.c.

Referenced by dahdi_translate().

#define ULAW_SAMPLES   160

Definition at line 61 of file codec_dahdi.c.

Referenced by dahdi_decoder_frameout().


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 880 of file codec_dahdi.c.

static void __unreg_module ( void   )  [static]

Definition at line 880 of file codec_dahdi.c.

static void build_translators ( uint32_t  dstfmts,
uint32_t  srcfmts 
) [static]

Definition at line 792 of file codec_dahdi.c.

References AST_LIST_LOCK, AST_LIST_UNLOCK, is_already_registered(), and register_translator().

Referenced by find_transcoders().

00793 {
00794    uint32_t srcfmt;
00795    uint32_t dstfmt;
00796 
00797    AST_LIST_LOCK(&translators);
00798 
00799    for (srcfmt = 1; srcfmt != 0; srcfmt <<= 1) {
00800       for (dstfmt = 1; dstfmt != 0; dstfmt <<= 1) {
00801          if (!(dstfmts & dstfmt) || !(srcfmts & srcfmt)) {
00802             continue;
00803          }
00804          if (is_already_registered(dstfmt, srcfmt)) {
00805             continue;
00806          }
00807          register_translator(dstfmt, srcfmt);
00808       }
00809    }
00810 
00811    AST_LIST_UNLOCK(&translators);
00812 }

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

Definition at line 478 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, LOG_ERROR, ast_frame::ptr, ast_trans_pvt::pvt, codec_dahdi_pvt::required_samples, ast_frame::samples, ast_trans_pvt::samples, codec_dahdi_pvt::samples_written_to_hardware, and ast_frame::subclass.

Referenced by register_translator().

00479 {
00480    struct codec_dahdi_pvt *dahdip = pvt->pvt;
00481 
00482    if (!f->subclass.format) {
00483       /* We're just faking a return for calculation purposes. */
00484       dahdip->fake = 2;
00485       pvt->samples = f->samples;
00486       return 0;
00487    }
00488 
00489    if (!f->datalen) {
00490       if (f->samples != dahdip->required_samples) {
00491          ast_log(LOG_ERROR, "%d != %d %d\n", f->samples, dahdip->required_samples, f->datalen);
00492       }
00493    }
00494    dahdi_write_frame(dahdip, f->data.ptr, f->datalen);
00495    dahdip->samples_written_to_hardware += f->samples;
00496    pvt->samples += f->samples;
00497    pvt->datalen = 0;
00498    return -1;
00499 }

static struct ast_frame* dahdi_decoder_frameout ( struct ast_trans_pvt pvt  )  [static, read]

Definition at line 501 of file codec_dahdi.c.

References AST_FRAME_VOICE, ast_frisolate(), ast_log, ast_translator::buf_size, ast_trans_pvt::c, dahdi_wait_for_packet(), ast_frame::datalen, ast_trans_pvt::datalen, errno, ast_trans_pvt::f, codec_dahdi_pvt::fake, codec_dahdi_pvt::fd, ast_frame::frametype, LOG_ERROR, ast_translator::name, NULL, ast_trans_pvt::outbuf, ast_trans_pvt::pvt, codec_dahdi_pvt::required_samples, ast_frame::samples, ast_trans_pvt::samples, codec_dahdi_pvt::samples_written_to_hardware, codec_dahdi_pvt::softslin, ast_trans_pvt::t, codec_dahdi_pvt::ulaw_buffer, ULAW_SAMPLES, and ulawtolin.

Referenced by register_translator().

00502 {
00503    int res;
00504    struct codec_dahdi_pvt *dahdip = pvt->pvt;
00505 
00506    if (2 == dahdip->fake) {
00507       struct ast_frame frm = {
00508          .frametype = AST_FRAME_VOICE,
00509          .samples = dahdip->required_samples,
00510          .src = pvt->t->name,
00511       };
00512 
00513       dahdip->fake = 1;
00514       pvt->samples = 0;
00515 
00516       return ast_frisolate(&frm);
00517    } else if (1 == dahdip->fake) {
00518       pvt->samples = 0;
00519       dahdip->fake = 0;
00520       return NULL;
00521    }
00522 
00523    if (dahdip->samples_written_to_hardware >= ULAW_SAMPLES) {
00524       dahdi_wait_for_packet(dahdip->fd);
00525    }
00526 
00527    /* Let's check to see if there is a new frame for us.... */
00528    if (dahdip->softslin) {
00529       res = read(dahdip->fd, dahdip->ulaw_buffer, sizeof(dahdip->ulaw_buffer));
00530    } else {
00531       res = read(dahdip->fd, pvt->outbuf.c + pvt->datalen, pvt->t->buf_size - pvt->datalen);
00532    }
00533 
00534    if (-1 == res) {
00535       if (EWOULDBLOCK == errno) {
00536          /* Nothing waiting... */
00537          return NULL;
00538       } else {
00539          ast_log(LOG_ERROR, "Failed to read from transcoder: %s\n", strerror(errno));
00540          return NULL;
00541       }
00542    } else {
00543       if (dahdip->softslin) {
00544          ulawtolin(pvt, res);
00545          pvt->f.datalen = res * 2;
00546       } else {
00547          pvt->f.datalen = res;
00548       }
00549       pvt->datalen = 0;
00550       pvt->f.samples = res;
00551       pvt->samples = 0;
00552       dahdip->samples_written_to_hardware =
00553          (dahdip->samples_written_to_hardware >= res) ?
00554                  dahdip->samples_written_to_hardware - res : 0;
00555 
00556       return ast_frisolate(&pvt->f);
00557    }
00558 
00559    /* Shouldn't get here... */
00560    return NULL;
00561 }

static void dahdi_destroy ( struct ast_trans_pvt pvt  )  [static]

Definition at line 564 of file codec_dahdi.c.

References ast_atomic_fetchadd_int(), channels, DAHDI_FORMAT_G723_1, DAHDI_FORMAT_G729A, channel_usage::decoders, channel_usage::encoders, codec_dahdi_pvt::fd, codec_dahdi_pvt::fmts, and ast_trans_pvt::pvt.

Referenced by register_translator().

00565 {
00566    struct codec_dahdi_pvt *dahdip = pvt->pvt;
00567 
00568    switch (dahdip->fmts.dstfmt) {
00569    case DAHDI_FORMAT_G729A:
00570    case DAHDI_FORMAT_G723_1:
00571       ast_atomic_fetchadd_int(&channels.encoders, -1);
00572       break;
00573    default:
00574       ast_atomic_fetchadd_int(&channels.decoders, -1);
00575       break;
00576    }
00577 
00578    close(dahdip->fd);
00579 }

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

Definition at line 374 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, lintoulaw, LOG_ERROR, ast_frame::ptr, ast_trans_pvt::pvt, codec_dahdi_pvt::required_samples, ast_frame::samples, ast_trans_pvt::samples, codec_dahdi_pvt::samples_in_buffer, codec_dahdi_pvt::samples_written_to_hardware, codec_dahdi_pvt::softslin, ast_frame::subclass, and codec_dahdi_pvt::ulaw_buffer.

Referenced by register_translator().

00375 {
00376    struct codec_dahdi_pvt *dahdip = pvt->pvt;
00377 
00378    if (!f->subclass.format) {
00379       /* We're just faking a return for calculation purposes. */
00380       dahdip->fake = 2;
00381       pvt->samples = f->samples;
00382       return 0;
00383    }
00384 
00385    /* Buffer up the packets and send them to the hardware if we
00386     * have enough samples set up. */
00387    if (dahdip->softslin) {
00388       if (lintoulaw(pvt, f)) {
00389           return -1;
00390       }
00391    } else {
00392       /* NOTE:  If softslin support is not needed, and the sample
00393        * size is equal to the required sample size, we wouldn't
00394        * need this copy operation.  But at the time this was
00395        * written, only softslin is supported. */
00396       if (dahdip->samples_in_buffer + f->samples > sizeof(dahdip->ulaw_buffer)) {
00397          ast_log(LOG_ERROR, "Out of buffer space.\n");
00398          return -1;
00399       }
00400       memcpy(&dahdip->ulaw_buffer[dahdip->samples_in_buffer], f->data.ptr, f->samples);
00401       dahdip->samples_in_buffer += f->samples;
00402    }
00403 
00404    while (dahdip->samples_in_buffer >= dahdip->required_samples) {
00405       dahdi_write_frame(dahdip, dahdip->ulaw_buffer, dahdip->required_samples);
00406       dahdip->samples_written_to_hardware += dahdip->required_samples;
00407       dahdip->samples_in_buffer -= dahdip->required_samples;
00408       if (dahdip->samples_in_buffer) {
00409          /* Shift any remaining bytes down. */
00410          memmove(dahdip->ulaw_buffer, &dahdip->ulaw_buffer[dahdip->required_samples],
00411             dahdip->samples_in_buffer);
00412       }
00413    }
00414    pvt->samples += f->samples;
00415    pvt->datalen = 0;
00416    return -1;
00417 }

static struct ast_frame* dahdi_encoder_frameout ( struct ast_trans_pvt pvt  )  [static, read]

Definition at line 427 of file codec_dahdi.c.

References ast_codec_samples_count(), AST_FRAME_VOICE, ast_frisolate(), ast_log, ast_translator::buf_size, ast_trans_pvt::c, dahdi_wait_for_packet(), ast_frame::datalen, ast_trans_pvt::datalen, errno, ast_trans_pvt::f, codec_dahdi_pvt::fake, codec_dahdi_pvt::fd, ast_frame::frametype, LOG_ERROR, ast_translator::name, NULL, ast_trans_pvt::outbuf, ast_trans_pvt::pvt, codec_dahdi_pvt::required_samples, ast_frame::samples, ast_trans_pvt::samples, codec_dahdi_pvt::samples_written_to_hardware, and ast_trans_pvt::t.

Referenced by register_translator().

00428 {
00429    struct codec_dahdi_pvt *dahdip = pvt->pvt;
00430    int res;
00431 
00432    if (2 == dahdip->fake) {
00433       struct ast_frame frm = {
00434          .frametype = AST_FRAME_VOICE,
00435          .samples = dahdip->required_samples,
00436          .src = pvt->t->name,
00437       };
00438 
00439       dahdip->fake = 1;
00440       pvt->samples = 0;
00441 
00442       return ast_frisolate(&frm);
00443    } else if (1 == dahdip->fake) {
00444       dahdip->fake = 0;
00445       return NULL;
00446    }
00447 
00448    if (dahdip->samples_written_to_hardware >= dahdip->required_samples) {
00449       dahdi_wait_for_packet(dahdip->fd);
00450    }
00451 
00452    res = read(dahdip->fd, pvt->outbuf.c + pvt->datalen, pvt->t->buf_size - pvt->datalen);
00453    if (-1 == res) {
00454       if (EWOULDBLOCK == errno) {
00455          /* Nothing waiting... */
00456          return NULL;
00457       } else {
00458          ast_log(LOG_ERROR, "Failed to read from transcoder: %s\n", strerror(errno));
00459          return NULL;
00460       }
00461    } else {
00462       pvt->f.datalen = res;
00463       pvt->f.samples = ast_codec_samples_count(&pvt->f);
00464 
00465       dahdip->samples_written_to_hardware =
00466         (dahdip->samples_written_to_hardware >= pvt->f.samples) ?
00467            dahdip->samples_written_to_hardware - pvt->f.samples : 0;
00468 
00469       pvt->samples = 0;
00470       pvt->datalen = 0;
00471       return ast_frisolate(&pvt->f);
00472    }
00473 
00474    /* Shouldn't get here... */
00475    return NULL;
00476 }

static struct ast_format* dahdi_format_to_cached ( int  format  )  [static, read]

Definition at line 581 of file codec_dahdi.c.

References ast_assert, ast_format_adpcm, ast_format_alaw, ast_format_g723, ast_format_g726, ast_format_g729, ast_format_gsm, ast_format_ilbc, ast_format_lpc10, ast_format_slin, ast_format_speex, ast_format_ulaw, DAHDI_FORMAT_ADPCM, DAHDI_FORMAT_ALAW, DAHDI_FORMAT_G723_1, DAHDI_FORMAT_G726, DAHDI_FORMAT_G729A, DAHDI_FORMAT_GSM, DAHDI_FORMAT_ILBC, DAHDI_FORMAT_LPC10, DAHDI_FORMAT_SLINEAR, DAHDI_FORMAT_SPEEX, DAHDI_FORMAT_ULAW, and NULL.

Referenced by dahdi_translate().

00582 {
00583    switch (format) {
00584    case DAHDI_FORMAT_G723_1:
00585       return ast_format_g723;
00586    case DAHDI_FORMAT_GSM:
00587       return ast_format_gsm;
00588    case DAHDI_FORMAT_ULAW:
00589       return ast_format_ulaw;
00590    case DAHDI_FORMAT_ALAW:
00591       return ast_format_alaw;
00592    case DAHDI_FORMAT_G726:
00593       return ast_format_g726;
00594    case DAHDI_FORMAT_ADPCM:
00595       return ast_format_adpcm;
00596    case DAHDI_FORMAT_SLINEAR:
00597       return ast_format_slin;
00598    case DAHDI_FORMAT_LPC10:
00599       return ast_format_lpc10;
00600    case DAHDI_FORMAT_G729A:
00601       return ast_format_g729;
00602    case DAHDI_FORMAT_SPEEX:
00603       return ast_format_speex;
00604    case DAHDI_FORMAT_ILBC:
00605       return ast_format_ilbc;
00606    }
00607 
00608    /* This will never be reached */
00609    ast_assert(0);
00610    return NULL;
00611 }

static int dahdi_new ( struct ast_trans_pvt pvt  )  [static]

Definition at line 689 of file codec_dahdi.c.

References container_of, dahdi_translate(), translator::dst_dahdi_fmt, translator::src_dahdi_fmt, translator::t, and ast_trans_pvt::t.

00690 {
00691    struct translator *zt = container_of(pvt->t, struct translator, t);
00692 
00693    return dahdi_translate(pvt, zt->dst_dahdi_fmt, zt->src_dahdi_fmt);
00694 }

static int dahdi_translate ( struct ast_trans_pvt pvt,
uint32_t  dst_dahdi_fmt,
uint32_t  src_dahdi_fmt 
) [static]

Definition at line 613 of file codec_dahdi.c.

References ao2_bump, ast_assert, ast_atomic_fetchadd_int(), ast_debug, ast_log, channels, DAHDI_FORMAT_G723_1, DAHDI_FORMAT_G729A, DAHDI_FORMAT_SLINEAR, dahdi_format_to_cached(), DAHDI_FORMAT_ULAW, channel_usage::decoders, ast_translator::dst_codec, channel_usage::encoders, errno, ast_trans_pvt::f, codec_dahdi_pvt::fd, codec_dahdi_pvt::fmts, ast_frame_subclass::format, G723_SAMPLES, G729_SAMPLES, LOG_ERROR, LOG_WARNING, ast_codec::name, NULL, ast_trans_pvt::pvt, codec_dahdi_pvt::required_samples, codec_dahdi_pvt::softslin, ast_translator::src_codec, ast_frame::subclass, and ast_trans_pvt::t.

Referenced by dahdi_new().

00614 {
00615    /* Request translation through zap if possible */
00616    int fd;
00617    struct codec_dahdi_pvt *dahdip = pvt->pvt;
00618    int flags;
00619    int tried_once = 0;
00620    const char *dev_filename = "/dev/dahdi/transcode";
00621 
00622    if ((fd = open(dev_filename, O_RDWR)) < 0) {
00623       ast_log(LOG_ERROR, "Failed to open %s: %s\n", dev_filename, strerror(errno));
00624       return -1;
00625    }
00626 
00627    dahdip->fmts.srcfmt = src_dahdi_fmt;
00628    dahdip->fmts.dstfmt = dst_dahdi_fmt;
00629 
00630    ast_assert(pvt->f.subclass.format == NULL);
00631    pvt->f.subclass.format = ao2_bump(dahdi_format_to_cached(dahdip->fmts.dstfmt));
00632 
00633    ast_debug(1, "Opening transcoder channel from %s to %s.\n", pvt->t->src_codec.name, pvt->t->dst_codec.name);
00634 
00635 retry:
00636    if (ioctl(fd, DAHDI_TC_ALLOCATE, &dahdip->fmts)) {
00637       if ((ENODEV == errno) && !tried_once) {
00638          /* We requested to translate to/from an unsupported
00639           * format.  Most likely this is because signed linear
00640           * was not supported by any hardware devices even
00641           * though this module always registers signed linear
00642           * support. In this case we'll retry, requesting
00643           * support for ULAW instead of signed linear and then
00644           * we'll just convert from ulaw to signed linear in
00645           * software. */
00646          if (dahdip->fmts.srcfmt == DAHDI_FORMAT_SLINEAR) {
00647             ast_debug(1, "Using soft_slin support on source\n");
00648             dahdip->softslin = 1;
00649             dahdip->fmts.srcfmt = DAHDI_FORMAT_ULAW;
00650          } else if (dahdip->fmts.dstfmt == DAHDI_FORMAT_SLINEAR) {
00651             ast_debug(1, "Using soft_slin support on destination\n");
00652             dahdip->softslin = 1;
00653             dahdip->fmts.dstfmt = DAHDI_FORMAT_ULAW;
00654          }
00655          tried_once = 1;
00656          goto retry;
00657       }
00658       ast_log(LOG_ERROR, "Unable to attach to transcoder: %s\n", strerror(errno));
00659       close(fd);
00660 
00661       return -1;
00662    }
00663 
00664    flags = fcntl(fd, F_GETFL);
00665    if (flags > - 1) {
00666       if (fcntl(fd, F_SETFL, flags | O_NONBLOCK))
00667          ast_log(LOG_WARNING, "Could not set non-block mode!\n");
00668    }
00669 
00670    dahdip->fd = fd;
00671 
00672    dahdip->required_samples = ((dahdip->fmts.dstfmt|dahdip->fmts.srcfmt) & (DAHDI_FORMAT_G723_1)) ? G723_SAMPLES : G729_SAMPLES;
00673 
00674    switch (dahdip->fmts.dstfmt) {
00675    case DAHDI_FORMAT_G729A:
00676       ast_atomic_fetchadd_int(&channels.encoders, +1);
00677       break;
00678    case DAHDI_FORMAT_G723_1:
00679       ast_atomic_fetchadd_int(&channels.encoders, +1);
00680       break;
00681    default:
00682       ast_atomic_fetchadd_int(&channels.decoders, +1);
00683       break;
00684    }
00685 
00686    return 0;
00687 }

static void dahdi_wait_for_packet ( int  fd  )  [static]

Definition at line 419 of file codec_dahdi.c.

Referenced by dahdi_decoder_frameout(), and dahdi_encoder_frameout().

00420 {
00421    struct pollfd p = {0};
00422    p.fd = fd;
00423    p.events = POLLIN;
00424    poll(&p, 1, 10);
00425 }

static void dahdi_write_frame ( struct codec_dahdi_pvt dahdip,
const uint8_t *  buffer,
const ssize_t  count 
) [static]

Definition at line 361 of file codec_dahdi.c.

References ast_log, errno, codec_dahdi_pvt::fd, and LOG_ERROR.

Referenced by dahdi_decoder_framein(), and dahdi_encoder_framein().

00362 {
00363    int res;
00364    if (!count) return;
00365    res = write(dahdip->fd, buffer, count);
00366    if (-1 == res) {
00367       ast_log(LOG_ERROR, "Failed to write to transcoder: %s\n", strerror(errno));
00368    }
00369    if (count != res) {
00370       ast_log(LOG_ERROR, "Requested write of %zd bytes, but only wrote %d bytes.\n", count, res);
00371    }
00372 }

static struct ast_frame* fakesrc_sample ( void   )  [static, read]

Definition at line 696 of file codec_dahdi.c.

References AST_FRAME_VOICE, and ast_frame::frametype.

Referenced by register_translator().

00697 {
00698    /* Don't bother really trying to test hardware ones. */
00699    static struct ast_frame f = {
00700       .frametype = AST_FRAME_VOICE,
00701       .samples = 160,
00702       .src = __PRETTY_FUNCTION__
00703    };
00704 
00705    return &f;
00706 }

static int find_transcoders ( void   )  [static]

Definition at line 814 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, errno, LOG_ERROR, and channel_usage::total.

Referenced by load_module().

00815 {
00816    struct dahdi_transcoder_info info = { 0, };
00817    int fd;
00818 
00819    if ((fd = open("/dev/dahdi/transcode", O_RDWR)) < 0) {
00820       ast_log(LOG_ERROR, "Failed to open /dev/dahdi/transcode: %s\n", strerror(errno));
00821       return 0;
00822    }
00823 
00824    for (info.tcnum = 0; !ioctl(fd, DAHDI_TC_GETINFO, &info); info.tcnum++) {
00825       ast_verb(2, "Found transcoder '%s'.\n", info.name);
00826 
00827       /* Complex codecs need to support signed linear.  If the
00828        * hardware transcoder does not natively support signed linear
00829        * format, we will emulate it in software directly in this
00830        * module. Also, do not allow direct ulaw/alaw to complex
00831        * codec translation, since that will prevent the generic PLC
00832        * functions from working. */
00833       if (info.dstfmts & (DAHDI_FORMAT_ULAW | DAHDI_FORMAT_ALAW)) {
00834          info.dstfmts |= DAHDI_FORMAT_SLINEAR;
00835          info.dstfmts &= ~(DAHDI_FORMAT_ULAW | DAHDI_FORMAT_ALAW);
00836       }
00837       if (info.srcfmts & (DAHDI_FORMAT_ULAW | DAHDI_FORMAT_ALAW)) {
00838          info.srcfmts |= DAHDI_FORMAT_SLINEAR;
00839          info.srcfmts &= ~(DAHDI_FORMAT_ULAW | DAHDI_FORMAT_ALAW);
00840       }
00841 
00842       build_translators(info.dstfmts, info.srcfmts);
00843       ast_atomic_fetchadd_int(&channels.total, info.numchannels / 2);
00844    }
00845 
00846    close(fd);
00847 
00848    if (!info.tcnum) {
00849       ast_verb(2, "No hardware transcoders found.\n");
00850    }
00851 
00852    return 0;
00853 }

static struct ast_codec* get_dahdi_codec ( uint32_t  dahdi_fmt  )  [static, read]

Definition at line 163 of file codec_dahdi.c.

References AST_MEDIA_TYPE_AUDIO, DAHDI_FORMAT_ADPCM, DAHDI_FORMAT_ALAW, DAHDI_FORMAT_G723_1, DAHDI_FORMAT_G726, DAHDI_FORMAT_G729A, DAHDI_FORMAT_GSM, DAHDI_FORMAT_ILBC, DAHDI_FORMAT_LPC10, DAHDI_FORMAT_SLINEAR, DAHDI_FORMAT_SPEEX, DAHDI_FORMAT_ULAW, ast_codec::name, and NULL.

Referenced by register_translator().

00164 {
00165    const struct ast_codec *codec;
00166 
00167    static const struct ast_codec dahdi_g723_1 = {
00168       .name = "g723",
00169       .type = AST_MEDIA_TYPE_AUDIO,
00170       .sample_rate = 8000,
00171    };
00172    static const struct ast_codec dahdi_gsm = {
00173       .name = "gsm",
00174       .type = AST_MEDIA_TYPE_AUDIO,
00175       .sample_rate = 8000,
00176    };
00177    static const struct ast_codec dahdi_ulaw = {
00178       .name = "ulaw",
00179       .type = AST_MEDIA_TYPE_AUDIO,
00180       .sample_rate = 8000,
00181    };
00182    static const struct ast_codec dahdi_alaw = {
00183       .name = "alaw",
00184       .type = AST_MEDIA_TYPE_AUDIO,
00185       .sample_rate = 8000,
00186    };
00187    static const struct ast_codec dahdi_g726 = {
00188       .name = "g726",
00189       .type = AST_MEDIA_TYPE_AUDIO,
00190       .sample_rate = 8000,
00191    };
00192    static const struct ast_codec dahdi_adpcm = {
00193       .name = "adpcm",
00194       .type = AST_MEDIA_TYPE_AUDIO,
00195       .sample_rate = 8000,
00196    };
00197    static const struct ast_codec dahdi_slinear = {
00198       .name = "slin",
00199       .type = AST_MEDIA_TYPE_AUDIO,
00200       .sample_rate = 8000,
00201    };
00202    static const struct ast_codec dahdi_lpc10 = {
00203       .name = "lpc10",
00204       .type = AST_MEDIA_TYPE_AUDIO,
00205       .sample_rate = 8000,
00206    };
00207    static const struct ast_codec dahdi_g729a = {
00208       .name = "g729",
00209       .type = AST_MEDIA_TYPE_AUDIO,
00210       .sample_rate = 8000,
00211    };
00212    static const struct ast_codec dahdi_speex = {
00213       .name = "speex",
00214       .type = AST_MEDIA_TYPE_AUDIO,
00215       .sample_rate = 8000,
00216    };
00217    static const struct ast_codec dahdi_ilbc = {
00218       .name = "ilbc",
00219       .type = AST_MEDIA_TYPE_AUDIO,
00220       .sample_rate = 8000,
00221    };
00222 
00223    switch (dahdi_fmt) {
00224    case DAHDI_FORMAT_G723_1:
00225       codec = &dahdi_g723_1;
00226       break;
00227    case DAHDI_FORMAT_GSM:
00228       codec = &dahdi_gsm;
00229       break;
00230    case DAHDI_FORMAT_ULAW:
00231       codec = &dahdi_ulaw;
00232       break;
00233    case DAHDI_FORMAT_ALAW:
00234       codec = &dahdi_alaw;
00235       break;
00236    case DAHDI_FORMAT_G726:
00237       codec = &dahdi_g726;
00238       break;
00239    case DAHDI_FORMAT_ADPCM:
00240       codec = &dahdi_adpcm;
00241       break;
00242    case DAHDI_FORMAT_SLINEAR:
00243       codec = &dahdi_slinear;
00244       break;
00245    case DAHDI_FORMAT_LPC10:
00246       codec = &dahdi_lpc10;
00247       break;
00248    case DAHDI_FORMAT_G729A:
00249       codec = &dahdi_g729a;
00250       break;
00251    case DAHDI_FORMAT_SPEEX:
00252       codec = &dahdi_speex;
00253       break;
00254    case DAHDI_FORMAT_ILBC:
00255       codec = &dahdi_ilbc;
00256       break;
00257    default:
00258       codec = NULL;
00259       break;
00260    }
00261 
00262    return codec;
00263 }

static char * handle_cli_transcoder_show ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 333 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, NULL, channel_usage::total, and ast_cli_entry::usage.

00334 {
00335    struct channel_usage copy;
00336 
00337    switch (cmd) {
00338    case CLI_INIT:
00339       e->command = "transcoder show";
00340       e->usage =
00341          "Usage: transcoder show\n"
00342          "       Displays channel utilization of DAHDI transcoder(s).\n";
00343       return NULL;
00344    case CLI_GENERATE:
00345       return NULL;
00346    }
00347 
00348    if (a->argc != 2)
00349       return CLI_SHOWUSAGE;
00350 
00351    copy = channels;
00352 
00353    if (copy.total == 0)
00354       ast_cli(a->fd, "No DAHDI transcoders found.\n");
00355    else
00356       ast_cli(a->fd, "%d/%d encoders/decoders of %d channels are in use.\n", copy.encoders, copy.decoders, copy.total);
00357 
00358    return CLI_SUCCESS;
00359 }

static bool is_already_registered ( uint32_t  dstfmt,
uint32_t  srcfmt 
) [static]

Definition at line 777 of file codec_dahdi.c.

References AST_LIST_TRAVERSE, translator::dst_dahdi_fmt, and translator::src_dahdi_fmt.

Referenced by build_translators().

00778 {
00779    bool res = false;
00780    const struct translator *zt;
00781 
00782    AST_LIST_TRAVERSE(&translators, zt, entry) {
00783       if ((zt->src_dahdi_fmt == srcfmt) && (zt->dst_dahdi_fmt == dstfmt)) {
00784          res = true;
00785          break;
00786       }
00787    }
00788 
00789    return res;
00790 }

static bool is_encoder ( uint32_t  src_dahdi_fmt  )  [static]

Definition at line 708 of file codec_dahdi.c.

References DAHDI_FORMAT_ALAW, DAHDI_FORMAT_SLINEAR, and DAHDI_FORMAT_ULAW.

Referenced by register_translator().

00709 {
00710    return ((src_dahdi_fmt & (DAHDI_FORMAT_ULAW | DAHDI_FORMAT_ALAW | DAHDI_FORMAT_SLINEAR)) > 0);
00711 }

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

Definition at line 313 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.

00314 {
00315    struct codec_dahdi_pvt *dahdip = pvt->pvt;
00316    int i = f->samples;
00317    uint8_t *dst = &dahdip->ulaw_buffer[dahdip->samples_in_buffer];
00318    int16_t *src = f->data.ptr;
00319 
00320    if (dahdip->samples_in_buffer + i > sizeof(dahdip->ulaw_buffer)) {
00321       ast_log(LOG_ERROR, "Out of buffer space!\n");
00322       return -i;
00323    }
00324 
00325    while (i--) {
00326       *dst++ = AST_LIN2MU(*src++);
00327    }
00328 
00329    dahdip->samples_in_buffer += f->samples;
00330    return 0;
00331 }

static int load_module ( void   )  [static]

static int register_translator ( uint32_t  dst_dahdi_fmt,
uint32_t  src_dahdi_fmt 
) [static]

Definition at line 714 of file codec_dahdi.c.

References ast_calloc, ast_free, AST_LIST_INSERT_HEAD, 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_codec, translator::dst_dahdi_fmt, fakesrc_sample(), ast_translator::framein, ast_translator::frameout, get_dahdi_codec(), is_encoder(), ast_codec::name, ast_translator::name, ast_translator::native_plc, ast_translator::newpvt, ast_translator::sample, ast_translator::src_codec, translator::src_dahdi_fmt, and translator::t.

Referenced by build_translators().

00715 {
00716    const struct ast_codec *dst_codec;
00717    const struct ast_codec *src_codec;
00718    struct translator *zt;
00719    int res;
00720 
00721    dst_codec = get_dahdi_codec(dst_dahdi_fmt);
00722    src_codec = get_dahdi_codec(src_dahdi_fmt);
00723    if (!dst_codec || !src_codec) {
00724       return -1;
00725    }
00726 
00727    if (!(zt = ast_calloc(1, sizeof(*zt)))) {
00728       return -1;
00729    }
00730 
00731    zt->src_dahdi_fmt = src_dahdi_fmt;
00732    zt->dst_dahdi_fmt = dst_dahdi_fmt;
00733 
00734    snprintf(zt->t.name, sizeof(zt->t.name), "dahdi_%s_to_%s",
00735       src_codec->name, dst_codec->name);
00736 
00737    memcpy(&zt->t.src_codec, src_codec, sizeof(*src_codec));
00738    memcpy(&zt->t.dst_codec, dst_codec, sizeof(*dst_codec));
00739    zt->t.buf_size = BUFFER_SIZE;
00740    if (is_encoder(src_dahdi_fmt)) {
00741       zt->t.framein = dahdi_encoder_framein;
00742       zt->t.frameout = dahdi_encoder_frameout;
00743    } else {
00744       zt->t.framein = dahdi_decoder_framein;
00745       zt->t.frameout = dahdi_decoder_frameout;
00746    }
00747    zt->t.destroy = dahdi_destroy;
00748    zt->t.buffer_samples = 0;
00749    zt->t.newpvt = dahdi_new;
00750    zt->t.sample = fakesrc_sample;
00751    zt->t.native_plc = 0;
00752 
00753    zt->t.desc_size = sizeof(struct codec_dahdi_pvt);
00754    if ((res = ast_register_translator(&zt->t))) {
00755       ast_free(zt);
00756       return -1;
00757    }
00758 
00759    AST_LIST_INSERT_HEAD(&translators, zt, entry);
00760 
00761    return res;
00762 }

static int reload ( void   )  [static]

Definition at line 855 of file codec_dahdi.c.

References AST_MODULE_LOAD_SUCCESS.

00856 {
00857    return AST_MODULE_LOAD_SUCCESS;
00858 }

static int ulawtolin ( struct ast_trans_pvt pvt,
int  samples 
) [static]

Definition at line 297 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.

00298 {
00299    struct codec_dahdi_pvt *dahdip = pvt->pvt;
00300    int i = samples;
00301    uint8_t *src = &dahdip->ulaw_buffer[0];
00302    int16_t *dst = pvt->outbuf.i16 + pvt->datalen;
00303 
00304    /* convert and copy in outbuf */
00305    while (i--) {
00306       *dst++ = AST_MULAW(*src++);
00307    }
00308 
00309    return 0;
00310 }

static int unload_module ( void   )  [static]

Definition at line 860 of file codec_dahdi.c.

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

00861 {
00862    ast_cli_unregister_multiple(cli, ARRAY_LEN(cli));
00863    unregister_translators();
00864 
00865    return 0;
00866 }

static void unregister_translators ( void   )  [static]

Definition at line 764 of file codec_dahdi.c.

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

Referenced by unload_module().

00765 {
00766    struct translator *cur;
00767 
00768    AST_LIST_LOCK(&translators);
00769    while ((cur = AST_LIST_REMOVE_HEAD(&translators, entry))) {
00770       ast_unregister_translator(&cur->t);
00771       ast_free(cur);
00772    }
00773    AST_LIST_UNLOCK(&translators);
00774 }


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, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload, } [static]

Definition at line 880 of file codec_dahdi.c.

Definition at line 880 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 267 of file codec_dahdi.c.


Generated on Thu Apr 16 06:30:15 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6