Asterisk.org: Developer Documentation (28 Oct 2009)

Wed Oct 28 15:47:53 2009

## Asterisk developer's documentation

# codec_zap.c

Go to the documentation of this file.

    00001 /*
    00002  * Asterisk -- An open source telephony toolkit.
    00003  *
    00004  * Zaptel native transcoding support
    00005  *
    00006  * Copyright (C) 1999 - 2006, Digium, Inc.
    00007  *
    00008  * Mark Spencer <markster@digium.com>
    00009  * Kevin P. Fleming <kpfleming@digium.com>
    00010  *
    00011  * See http://www.asterisk.org for more information about
    00012  * the Asterisk project. Please do not directly contact
    00013  * any of the maintainers of this project for assistance;
    00014  * the project provides a web site, mailing lists and IRC
    00015  * channels for your use.
    00016  *
    00017  * This program is free software, distributed under the terms of
    00018  * the GNU General Public License Version 2. See the LICENSE file
    00019  * at the top of the source tree.
    00020  */
    00021
    00022 /*! \file
    00023  *
    00024  * \brief Translate between various formats natively through Zaptel transcoding
    00025  *
    00026  * \ingroup codecs
    00027  */
    00028
    00029 #include "asterisk.h"
    00030
    00031 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 62173 $")
    00032
    00033 #include <fcntl.h>
    00034 #include <stdlib.h>
    00035 #include <unistd.h>
    00036 #include <netinet/in.h>
    00037 #include <string.h>
    00038 #include <stdio.h>
    00039 #include <sys/ioctl.h>
    00040 #include <errno.h>
    00041 #include <sys/mman.h>
    00042 #include <linux/zaptel.h>
    00043
    00044 #include "asterisk/lock.h"
    00045 #include "asterisk/translate.h"
    00046 #include "asterisk/config.h"
    00047 #include "asterisk/options.h"
    00048 #include "asterisk/module.h"
    00049 #include "asterisk/cli.h"
    00050 #include "asterisk/logger.h"
    00051 #include "asterisk/channel.h"
    00052 #include "asterisk/utils.h"
    00053 #include "asterisk/linkedlists.h"
    00054
    00055 #define BUFFER_SAMPLES  8000
    00056
    00057 static unsigned int global_useplc = 0;
    00058
    00059 static int totalchannels = 0;
    00060 static int complexinuse = 0;
    00061 static int simpleinuse = 0;
    00062 static int localusecnt = 0;
    00063 AST_MUTEX_DEFINE_STATIC(channelcount);
    00064
    00065 static char *tdesc = "Generic Zaptel Transcoder Codec Translator";
    00066
    00067 static char show_transcoder_usage[] =
    00068 "Usage: show transcoder\n"
    00069 "       Displays transcoder utilization.\n";
    00070
    00071 static int show_transcoder(int fd, int argc, char **argv);
    00072
    00073 static struct ast_cli_entry transcoder_cli[] = {
    00074    { { "show", "transcoder", NULL},
    00075    show_transcoder, "Displays transcoder utilization.",
    00076    show_transcoder_usage}
    00077 };
    00078
    00079 struct format_map {
    00080    unsigned int map[32][32];
    00081 };
    00082
    00083 static struct format_map global_format_map = { { { 0 } } };
    00084
    00085 struct translator {
    00086    struct ast_translator t;
    00087    AST_LIST_ENTRY(translator) entry;
    00088 };
    00089
    00090 static AST_LIST_HEAD_STATIC(zap_translators, translator);
    00091
    00092 struct ast_translator_pvt {
    00093    int fd;
    00094    int fake;
    00095    int inuse;
    00096    int samples;
    00097    int dstfmt;
    00098    int srcfmt;
    00099 #ifdef DEBUG_TRANSCODE
    00100    int totalms;
    00101    int lasttotalms;
    00102 #endif
    00103    struct zt_transcode_header *hdr;
    00104    struct ast_frame f;
    00105 };
    00106
    00107
    00108 static int show_transcoder(int fd, int argc, char **argv)
    00109 {
    00110    ast_mutex_lock(&channelcount);
    00111
    00112    if (!totalchannels) {
    00113       ast_cli(fd, "No transcoder card registered\n");
    00114       ast_mutex_unlock(&channelcount);
    00115       return RESULT_SUCCESS;
    00116    }
    00117
    00118    ast_cli(fd, "%d/%d encoders/decoders of %d channels are in use.\n", complexinuse, simpleinuse, totalchannels);
    00119
    00120    ast_mutex_unlock(&channelcount);
    00121    return RESULT_SUCCESS;
    00122 }
    00123
    00124 static int zap_framein(struct ast_translator_pvt *ztp, struct ast_frame *f)
    00125 {
    00126    struct zt_transcode_header *hdr = ztp->hdr;
    00127    if (!f->subclass) {
    00128       /* Fake a return frame for calculation purposes */
    00129       ztp->fake = 2;
    00130       ztp->samples = f->samples;
    00131       return 0;
    00132    }
    00133    if(!ztp->inuse) {
    00134       ast_mutex_lock(&channelcount);
    00135       localusecnt++;
    00136       if(ztp->dstfmt == 8 || ztp->dstfmt == 0 )
    00137          complexinuse++;
    00138       else
    00139          simpleinuse++;
    00140       ast_mutex_unlock(&channelcount);
    00141       ztp->inuse = 1;
    00142    }
    00143    if (!hdr->srclen)
    00144       /* Copy at front of buffer */
    00145       hdr->srcoffset = 0;
    00146
    00147    if (hdr->srclen + f->datalen > sizeof(hdr->srcdata)) {
    00148       ast_log(LOG_WARNING, "Out of space for codec translation!\n");
    00149       return -1;
    00150    }
    00151
    00152    if (hdr->srclen + f->datalen + hdr->srcoffset > sizeof(hdr->srcdata)) {
    00153       /* Very unlikely */
    00154       memmove(hdr->srcdata, hdr->srcdata + hdr->srcoffset, hdr->srclen);
    00155       hdr->srcoffset = 0;
    00156    }
    00157
    00158    memcpy(hdr->srcdata + hdr->srcoffset + hdr->srclen, f->data, f->datalen);
    00159    hdr->srclen += f->datalen;
    00160    ztp->samples += f->samples;
    00161
    00162    return -1;
    00163 }
    00164
    00165 static struct ast_frame *zap_frameout(struct ast_translator_pvt *ztp)
    00166 {
    00167    struct zt_transcode_header *hdr = ztp->hdr;
    00168    unsigned int x;
    00169
    00170    if (ztp->fake == 2) {
    00171       ztp->fake = 1;
    00172       ztp->f.frametype = AST_FRAME_VOICE;
    00173       ztp->f.subclass = 0;
    00174       ztp->f.samples = 240;
    00175       ztp->f.data = NULL;
    00176       ztp->f.offset = 0;
    00177       ztp->f.datalen = 0;
    00178       ztp->f.mallocd = 0;
    00179       ztp->samples = 0;
    00180    } else if (ztp->fake == 1) {
    00181       return NULL;
    00182    } else {
    00183       if (hdr->dstlen) {
    00184 #ifdef DEBUG_TRANSCODE
    00185          ztp->totalms += hdr->dstsamples;
    00186          if ((ztp->totalms - ztp->lasttotalms) > 8000) {
    00187             ast_verbose("Whee %p, %d (%d to %d)\n", ztp, hdr->dstlen, ztp->lasttotalms, ztp->totalms);
    00188             ztp->lasttotalms = ztp->totalms;
    00189          }
    00190 #endif
    00191          ztp->f.frametype = AST_FRAME_VOICE;
    00192          ztp->f.subclass = hdr->dstfmt;
    00193          ztp->f.samples = hdr->dstsamples;
    00194          ztp->f.data = hdr->dstdata + hdr->dstoffset;
    00195          ztp->f.offset = hdr->dstoffset;
    00196          ztp->f.datalen = hdr->dstlen;
    00197          ztp->f.mallocd = 0;
    00198          ztp->samples -= ztp->f.samples;
    00199          hdr->dstlen = 0;
    00200
    00201       } else {
    00202          if (hdr->srclen) {
    00203             hdr->dstoffset = AST_FRIENDLY_OFFSET;
    00204             x = ZT_TCOP_TRANSCODE;
    00205             if (ioctl(ztp->fd, ZT_TRANSCODE_OP, &x))
    00206                ast_log(LOG_WARNING, "Failed to transcode: %s\n", strerror(errno));
    00207          }
    00208          return NULL;
    00209       }
    00210    }
    00211
    00212    return &ztp->f;
    00213 }
    00214
    00215 static void zap_destroy(struct ast_translator_pvt *ztp)
    00216 {
    00217    unsigned int x;
    00218
    00219    x = ZT_TCOP_RELEASE;
    00220    if (ioctl(ztp->fd, ZT_TRANSCODE_OP, &x))
    00221       ast_log(LOG_WARNING, "Failed to release transcoder channel: %s\n", strerror(errno));
    00222
    00223    munmap(ztp->hdr, sizeof(*ztp->hdr));
    00224    if(ztp->inuse) {
    00225       ast_mutex_lock(&channelcount);
    00226       localusecnt--;
    00227       if(ztp->dstfmt == 8 || ztp->dstfmt == 0)
    00228          complexinuse--;
    00229       else
    00230          simpleinuse--;
    00231       ast_mutex_unlock(&channelcount);
    00232    }
    00233    close(ztp->fd);
    00234 }
    00235
    00236 static struct ast_translator_pvt *zap_new_alawtog723(void)
    00237 {
    00238    /* Request translation through zap if possible */
    00239    int fd;
    00240    unsigned int x = ZT_TCOP_ALLOCATE;
    00241    struct ast_translator_pvt *ztp;
    00242    struct zt_transcode_header *hdr;
    00243    int flags;
    00244
    00245    ztp = calloc(1,sizeof(struct ast_translator_pvt));
    00246    if(!ztp) {
    00247       ast_log(LOG_ERROR, "Could not allocate ztp structure.\n");
    00248       return NULL;
    00249    }
    00250    ztp->dstfmt = 0;
    00251    ztp->srcfmt = 3;
    00252
    00253    if ((fd = open("/dev/zap/transcode", O_RDWR)) < 0)
    00254       return NULL;
    00255    flags = fcntl(fd, F_GETFL);
    00256    if (flags > - 1) {
    00257       if (fcntl(fd, F_SETFL, flags | O_NONBLOCK))
    00258          ast_log(LOG_WARNING, "Could not set non-block mode!\n");
    00259    }
    00260
    00261
    00262    if ((hdr = mmap(NULL, sizeof(*hdr), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED) {
    00263       ast_log(LOG_ERROR, "Memory Map failed for transcoding (%s)\n", strerror(errno));
    00264       close(fd);
    00265
    00266       return NULL;
    00267    }
    00268
    00269    if (hdr->magic != ZT_TRANSCODE_MAGIC) {
    00270       ast_log(LOG_ERROR, "Transcoder header (%08x) wasn't magic.  Abandoning\n", hdr->magic);
    00271       munmap(hdr, sizeof(*hdr));
    00272       close(fd);
    00273
    00274       return NULL;
    00275    }
    00276
    00277    hdr->srcfmt = (1 << ztp->srcfmt);
    00278    hdr->dstfmt = (1 << ztp->dstfmt);
    00279    if (ioctl(fd, ZT_TRANSCODE_OP, &x)) {
    00280       ast_log(LOG_ERROR, "Unable to attach transcoder: %s\n", strerror(errno));
    00281       munmap(hdr, sizeof(*hdr));
    00282       close(fd);
    00283
    00284       return NULL;
    00285    }
    00286
    00287    ztp->fd = fd;
    00288    ztp->hdr = hdr;
    00289
    00290    return (struct ast_translator_pvt *) ztp;
    00291 }
    00292
    00293 static struct ast_translator_pvt *zap_new_ulawtog723(void)
    00294 {
    00295    /* Request translation through zap if possible */
    00296    int fd;
    00297    unsigned int x = ZT_TCOP_ALLOCATE;
    00298    struct ast_translator_pvt *ztp;
    00299    struct zt_transcode_header *hdr;
    00300    int flags;
    00301
    00302    ztp = calloc(1,sizeof(struct ast_translator_pvt));
    00303    if(!ztp) {
    00304       ast_log(LOG_ERROR, "Could not allocate ztp structure.\n");
    00305       return NULL;
    00306    }
    00307    ztp->dstfmt = 0;
    00308    ztp->srcfmt = 2;
    00309
    00310    if ((fd = open("/dev/zap/transcode", O_RDWR)) < 0)
    00311       return NULL;
    00312    flags = fcntl(fd, F_GETFL);
    00313    if (flags > - 1) {
    00314       if (fcntl(fd, F_SETFL, flags | O_NONBLOCK))
    00315          ast_log(LOG_WARNING, "Could not set non-block mode!\n");
    00316    }
    00317
    00318
    00319    if ((hdr = mmap(NULL, sizeof(*hdr), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED) {
    00320       ast_log(LOG_ERROR, "Memory Map failed for transcoding (%s)\n", strerror(errno));
    00321       close(fd);
    00322
    00323       return NULL;
    00324    }
    00325
    00326    if (hdr->magic != ZT_TRANSCODE_MAGIC) {
    00327       ast_log(LOG_ERROR, "Transcoder header (%08x) wasn't magic.  Abandoning\n", hdr->magic);
    00328       munmap(hdr, sizeof(*hdr));
    00329       close(fd);
    00330
    00331       return NULL;
    00332    }
    00333
    00334    hdr->srcfmt = (1 << ztp->srcfmt);
    00335    hdr->dstfmt = (1 << ztp->dstfmt);
    00336    if (ioctl(fd, ZT_TRANSCODE_OP, &x)) {
    00337       ast_log(LOG_ERROR, "Unable to attach transcoder: %s\n", strerror(errno));
    00338       munmap(hdr, sizeof(*hdr));
    00339       close(fd);
    00340
    00341       return NULL;
    00342    }
    00343
    00344    ztp->fd = fd;
    00345    ztp->hdr = hdr;
    00346
    00347    return (struct ast_translator_pvt *) ztp;
    00348 }
    00349
    00350 static struct ast_translator_pvt *zap_new_g723toalaw(void)
    00351 {
    00352    /* Request translation through zap if possible */
    00353    int fd;
    00354    unsigned int x = ZT_TCOP_ALLOCATE;
    00355    struct ast_translator_pvt *ztp;
    00356    struct zt_transcode_header *hdr;
    00357    int flags;
    00358
    00359    ztp = calloc(1,sizeof(struct ast_translator_pvt));
    00360    if(!ztp) {
    00361       ast_log(LOG_ERROR, "Could not allocate ztp structure.\n");
    00362       return NULL;
    00363    }
    00364    ztp->dstfmt = 3;
    00365    ztp->srcfmt = 0;
    00366
    00367    if ((fd = open("/dev/zap/transcode", O_RDWR)) < 0)
    00368       return NULL;
    00369    flags = fcntl(fd, F_GETFL);
    00370    if (flags > - 1) {
    00371       if (fcntl(fd, F_SETFL, flags | O_NONBLOCK))
    00372          ast_log(LOG_WARNING, "Could not set non-block mode!\n");
    00373    }
    00374
    00375
    00376    if ((hdr = mmap(NULL, sizeof(*hdr), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED) {
    00377       ast_log(LOG_ERROR, "Memory Map failed for transcoding (%s)\n", strerror(errno));
    00378       close(fd);
    00379
    00380       return NULL;
    00381    }
    00382
    00383    if (hdr->magic != ZT_TRANSCODE_MAGIC) {
    00384       ast_log(LOG_ERROR, "Transcoder header (%08x) wasn't magic.  Abandoning\n", hdr->magic);
    00385       munmap(hdr, sizeof(*hdr));
    00386       close(fd);
    00387
    00388       return NULL;
    00389    }
    00390
    00391    hdr->srcfmt = (1 << ztp->srcfmt);
    00392    hdr->dstfmt = (1 << ztp->dstfmt);
    00393    if (ioctl(fd, ZT_TRANSCODE_OP, &x)) {
    00394       ast_log(LOG_ERROR, "Unable to attach transcoder: %s\n", strerror(errno));
    00395       munmap(hdr, sizeof(*hdr));
    00396       close(fd);
    00397
    00398       return NULL;
    00399    }
    00400
    00401    ztp->fd = fd;
    00402    ztp->hdr = hdr;
    00403
    00404    return (struct ast_translator_pvt *) ztp;
    00405 }
    00406
    00407 static struct ast_translator_pvt *zap_new_g723toulaw(void)
    00408 {
    00409    /* Request translation through zap if possible */
    00410    int fd;
    00411    unsigned int x = ZT_TCOP_ALLOCATE;
    00412    struct ast_translator_pvt *ztp;
    00413    struct zt_transcode_header *hdr;
    00414    int flags;
    00415
    00416    ztp = calloc(1,sizeof(struct ast_translator_pvt));
    00417    if(!ztp) {
    00418       ast_log(LOG_ERROR, "Could not allocate ztp structure.\n");
    00419       return NULL;
    00420    }
    00421    ztp->dstfmt = 2;
    00422    ztp->srcfmt = 0;
    00423
    00424    if ((fd = open("/dev/zap/transcode", O_RDWR)) < 0)
    00425       return NULL;
    00426    flags = fcntl(fd, F_GETFL);
    00427    if (flags > - 1) {
    00428       if (fcntl(fd, F_SETFL, flags | O_NONBLOCK))
    00429          ast_log(LOG_WARNING, "Could not set non-block mode!\n");
    00430    }
    00431
    00432
    00433    if ((hdr = mmap(NULL, sizeof(*hdr), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED) {
    00434       ast_log(LOG_ERROR, "Memory Map failed for transcoding (%s)\n", strerror(errno));
    00435       close(fd);
    00436
    00437       return NULL;
    00438    }
    00439
    00440    if (hdr->magic != ZT_TRANSCODE_MAGIC) {
    00441       ast_log(LOG_ERROR, "Transcoder header (%08x) wasn't magic.  Abandoning\n", hdr->magic);
    00442       munmap(hdr, sizeof(*hdr));
    00443       close(fd);
    00444
    00445       return NULL;
    00446    }
    00447
    00448    hdr->srcfmt = (1 << ztp->srcfmt);
    00449    hdr->dstfmt = (1 << ztp->dstfmt);
    00450    if (ioctl(fd, ZT_TRANSCODE_OP, &x)) {
    00451       ast_log(LOG_ERROR, "Unable to attach transcoder: %s\n", strerror(errno));
    00452       munmap(hdr, sizeof(*hdr));
    00453       close(fd);
    00454
    00455       return NULL;
    00456    }
    00457
    00458    ztp->fd = fd;
    00459    ztp->hdr = hdr;
    00460
    00461    return (struct ast_translator_pvt *) ztp;
    00462 }
    00463
    00464 static struct ast_translator_pvt *zap_new_alawtog729(void)
    00465 {
    00466    /* Request translation through zap if possible */
    00467    int fd;
    00468    unsigned int x = ZT_TCOP_ALLOCATE;
    00469    struct ast_translator_pvt *ztp;
    00470    struct zt_transcode_header *hdr;
    00471    int flags;
    00472
    00473    ztp = calloc(1,sizeof(struct ast_translator_pvt));
    00474    if(!ztp) {
    00475       ast_log(LOG_ERROR, "Could not allocate ztp structure.\n");
    00476       return NULL;
    00477    }
    00478    ztp->dstfmt = 8;
    00479    ztp->srcfmt = 3;
    00480
    00481    if ((fd = open("/dev/zap/transcode", O_RDWR)) < 0)
    00482       return NULL;
    00483    flags = fcntl(fd, F_GETFL);
    00484    if (flags > - 1) {
    00485       if (fcntl(fd, F_SETFL, flags | O_NONBLOCK))
    00486          ast_log(LOG_WARNING, "Could not set non-block mode!\n");
    00487    }
    00488
    00489
    00490    if ((hdr = mmap(NULL, sizeof(*hdr), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED) {
    00491       ast_log(LOG_ERROR, "Memory Map failed for transcoding (%s)\n", strerror(errno));
    00492       close(fd);
    00493
    00494       return NULL;
    00495    }
    00496
    00497    if (hdr->magic != ZT_TRANSCODE_MAGIC) {
    00498       ast_log(LOG_ERROR, "Transcoder header (%08x) wasn't magic.  Abandoning\n", hdr->magic);
    00499       munmap(hdr, sizeof(*hdr));
    00500       close(fd);
    00501
    00502       return NULL;
    00503    }
    00504
    00505    hdr->srcfmt = (1 << ztp->srcfmt);
    00506    hdr->dstfmt = (1 << ztp->dstfmt);
    00507    if (ioctl(fd, ZT_TRANSCODE_OP, &x)) {
    00508       ast_log(LOG_ERROR, "Unable to attach transcoder: %s\n", strerror(errno));
    00509       munmap(hdr, sizeof(*hdr));
    00510       close(fd);
    00511
    00512       return NULL;
    00513    }
    00514
    00515    ztp->fd = fd;
    00516    ztp->hdr = hdr;
    00517
    00518    return (struct ast_translator_pvt *) ztp;
    00519 }
    00520
    00521 static struct ast_translator_pvt *zap_new_ulawtog729(void)
    00522 {
    00523    /* Request translation through zap if possible */
    00524    int fd;
    00525    unsigned int x = ZT_TCOP_ALLOCATE;
    00526    struct ast_translator_pvt *ztp;
    00527    struct zt_transcode_header *hdr;
    00528    int flags;
    00529
    00530    ztp = calloc(1,sizeof(struct ast_translator_pvt));
    00531    if(!ztp) {
    00532       ast_log(LOG_ERROR, "Could not allocate ztp structure.\n");
    00533       return NULL;
    00534    }
    00535    ztp->dstfmt = 8;
    00536    ztp->srcfmt = 2;
    00537
    00538    if ((fd = open("/dev/zap/transcode", O_RDWR)) < 0)
    00539       return NULL;
    00540    flags = fcntl(fd, F_GETFL);
    00541    if (flags > - 1) {
    00542       if (fcntl(fd, F_SETFL, flags | O_NONBLOCK))
    00543          ast_log(LOG_WARNING, "Could not set non-block mode!\n");
    00544    }
    00545
    00546
    00547    if ((hdr = mmap(NULL, sizeof(*hdr), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED) {
    00548       ast_log(LOG_ERROR, "Memory Map failed for transcoding (%s)\n", strerror(errno));
    00549       close(fd);
    00550
    00551       return NULL;
    00552    }
    00553
    00554    if (hdr->magic != ZT_TRANSCODE_MAGIC) {
    00555       ast_log(LOG_ERROR, "Transcoder header (%08x) wasn't magic.  Abandoning\n", hdr->magic);
    00556       munmap(hdr, sizeof(*hdr));
    00557       close(fd);
    00558
    00559       return NULL;
    00560    }
    00561
    00562    hdr->srcfmt = (1 << ztp->srcfmt);
    00563    hdr->dstfmt = (1 << ztp->dstfmt);
    00564    if (ioctl(fd, ZT_TRANSCODE_OP, &x)) {
    00565       ast_log(LOG_ERROR, "Unable to attach transcoder: %s\n", strerror(errno));
    00566       munmap(hdr, sizeof(*hdr));
    00567       close(fd);
    00568
    00569       return NULL;
    00570    }
    00571
    00572    ztp->fd = fd;
    00573    ztp->hdr = hdr;
    00574
    00575    return (struct ast_translator_pvt *) ztp;
    00576 }
    00577
    00578 static struct ast_translator_pvt *zap_new_g729toalaw(void)
    00579 {
    00580    /* Request translation through zap if possible */
    00581    int fd;
    00582    unsigned int x = ZT_TCOP_ALLOCATE;
    00583    struct ast_translator_pvt *ztp;
    00584    struct zt_transcode_header *hdr;
    00585    int flags;
    00586
    00587    ztp = calloc(1,sizeof(struct ast_translator_pvt));
    00588    if(!ztp) {
    00589       ast_log(LOG_ERROR, "Could not allocate ztp structure.\n");
    00590       return NULL;
    00591    }
    00592    ztp->dstfmt = 3;
    00593    ztp->srcfmt = 8;
    00594
    00595    if ((fd = open("/dev/zap/transcode", O_RDWR)) < 0)
    00596       return NULL;
    00597    flags = fcntl(fd, F_GETFL);
    00598    if (flags > - 1) {
    00599       if (fcntl(fd, F_SETFL, flags | O_NONBLOCK))
    00600          ast_log(LOG_WARNING, "Could not set non-block mode!\n");
    00601    }
    00602
    00603
    00604    if ((hdr = mmap(NULL, sizeof(*hdr), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED) {
    00605       ast_log(LOG_ERROR, "Memory Map failed for transcoding (%s)\n", strerror(errno));
    00606       close(fd);
    00607
    00608       return NULL;
    00609    }
    00610
    00611    if (hdr->magic != ZT_TRANSCODE_MAGIC) {
    00612       ast_log(LOG_ERROR, "Transcoder header (%08x) wasn't magic.  Abandoning\n", hdr->magic);
    00613       munmap(hdr, sizeof(*hdr));
    00614       close(fd);
    00615
    00616       return NULL;
    00617    }
    00618
    00619    hdr->srcfmt = (1 << ztp->srcfmt);
    00620    hdr->dstfmt = (1 << ztp->dstfmt);
    00621    if (ioctl(fd, ZT_TRANSCODE_OP, &x)) {
    00622       ast_log(LOG_ERROR, "Unable to attach transcoder: %s\n", strerror(errno));
    00623       munmap(hdr, sizeof(*hdr));
    00624       close(fd);
    00625
    00626       return NULL;
    00627    }
    00628
    00629    ztp->fd = fd;
    00630    ztp->hdr = hdr;
    00631
    00632    return (struct ast_translator_pvt *) ztp;
    00633 }
    00634
    00635 static struct ast_translator_pvt *zap_new_g729toulaw(void)
    00636 {
    00637    /* Request translation through zap if possible */
    00638    int fd;
    00639    unsigned int x = ZT_TCOP_ALLOCATE;
    00640    struct ast_translator_pvt *ztp;
    00641    struct zt_transcode_header *hdr;
    00642    int flags;
    00643
    00644    ztp = calloc(1,sizeof(struct ast_translator_pvt));
    00645    if(!ztp) {
    00646       ast_log(LOG_ERROR, "Could not allocate ztp structure.\n");
    00647       return NULL;
    00648    }
    00649    ztp->dstfmt = 2;
    00650    ztp->srcfmt = 8;
    00651
    00652    if ((fd = open("/dev/zap/transcode", O_RDWR)) < 0)
    00653       return NULL;
    00654    flags = fcntl(fd, F_GETFL);
    00655    if (flags > - 1) {
    00656       if (fcntl(fd, F_SETFL, flags | O_NONBLOCK))
    00657          ast_log(LOG_WARNING, "Could not set non-block mode!\n");
    00658    }
    00659
    00660
    00661    if ((hdr = mmap(NULL, sizeof(*hdr), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED) {
    00662       ast_log(LOG_ERROR, "Memory Map failed for transcoding (%s)\n", strerror(errno));
    00663       close(fd);
    00664
    00665       return NULL;
    00666    }
    00667
    00668    if (hdr->magic != ZT_TRANSCODE_MAGIC) {
    00669       ast_log(LOG_ERROR, "Transcoder header (%08x) wasn't magic.  Abandoning\n", hdr->magic);
    00670       munmap(hdr, sizeof(*hdr));
    00671       close(fd);
    00672
    00673       return NULL;
    00674    }
    00675
    00676    hdr->srcfmt = (1 << ztp->srcfmt);
    00677    hdr->dstfmt = (1 << ztp->dstfmt);
    00678    if (ioctl(fd, ZT_TRANSCODE_OP, &x)) {
    00679       ast_log(LOG_ERROR, "Unable to attach transcoder: %s\n", strerror(errno));
    00680       munmap(hdr, sizeof(*hdr));
    00681       close(fd);
    00682
    00683       return NULL;
    00684    }
    00685
    00686    ztp->fd = fd;
    00687    ztp->hdr = hdr;
    00688
    00689    return (struct ast_translator_pvt *) ztp;
    00690 }
    00691
    00692 static struct ast_frame *fakesrc_sample(void)
    00693 {
    00694    /* Don't bother really trying to test hardware ones. */
    00695    static struct ast_frame f = {
    00696       .frametype = AST_FRAME_VOICE,
    00697       .samples = 240,
    00698       .src = __PRETTY_FUNCTION__
    00699    };
    00700
    00701    return &f;
    00702 }
    00703
    00704 static int register_translator(int dst, int src)
    00705 {
    00706    struct translator *zt;
    00707    int res;
    00708
    00709    if (!(zt = calloc(1, sizeof(*zt)))) {
    00710       ast_log(LOG_ERROR, "Could not allocate translator\n");
    00711       return -1;
    00712    }
    00713
    00714    snprintf((char *) (zt->t.name), sizeof(zt->t.name), "zap%sto%s",
    00715        ast_getformatname((1 << src)), ast_getformatname((1 << dst)));
    00716
    00717    if(src == 8 && dst == 2) /* G.729 to Ulaw */
    00718       zt->t.newpvt = zap_new_g729toulaw;
    00719    else if(src == 8 && dst == 3) /* G.729 to Alaw */
    00720       zt->t.newpvt = zap_new_g729toalaw;
    00721    else if(src == 2 && dst == 8) /* Ulaw to G.729 */
    00722       zt->t.newpvt = zap_new_ulawtog729;
    00723    else if(src == 3 && dst == 8) /* Alaw to G.729 */
    00724       zt->t.newpvt = zap_new_alawtog729;
    00725    else if(src == 0 && dst == 2) /* G.723 to Ulaw */
    00726       zt->t.newpvt = zap_new_g723toulaw;
    00727    else if(src == 0 && dst == 3) /* G.723 to Alaw */
    00728       zt->t.newpvt = zap_new_g723toalaw;
    00729    else if(src == 2 && dst == 0) /* Ulaw to G.723 */
    00730       zt->t.newpvt = zap_new_ulawtog723;
    00731    else if(src == 3 && dst == 0) /* Alaw to G.723 */
    00732       zt->t.newpvt = zap_new_alawtog723;
    00733
    00734    zt->t.frameout = zap_frameout;
    00735    zt->t.destroy = zap_destroy;
    00736    zt->t.sample = fakesrc_sample;
    00737    zt->t.framein = zap_framein;
    00738    zt->t.srcfmt = (1 << src);
    00739    zt->t.dstfmt = (1 << dst);
    00740    if ((res = ast_register_translator(&zt->t))) {
    00741       free(zt);
    00742       return -1;
    00743    }
    00744
    00745    AST_LIST_LOCK(&zap_translators);
    00746    AST_LIST_INSERT_HEAD(&zap_translators, zt, entry);
    00747    AST_LIST_UNLOCK(&zap_translators);
    00748
    00749    global_format_map.map[dst][src] = 1;
    00750
    00751    return res;
    00752 }
    00753
    00754 static void drop_translator(int dst, int src)
    00755 {
    00756    struct translator *cur;
    00757
    00758    AST_LIST_LOCK(&zap_translators);
    00759    AST_LIST_TRAVERSE_SAFE_BEGIN(&zap_translators, cur, entry) {
    00760       if (cur->t.srcfmt != src)
    00761          continue;
    00762
    00763       if (cur->t.dstfmt != dst)
    00764          continue;
    00765
    00766       AST_LIST_REMOVE_CURRENT(&zap_translators, entry);
    00767       ast_unregister_translator(&cur->t);
    00768       free(cur);
    00769       global_format_map.map[dst][src] = 0;
    00770       break;
    00771    }
    00772    AST_LIST_TRAVERSE_SAFE_END;
    00773    AST_LIST_UNLOCK(&zap_translators);
    00774 }
    00775
    00776 static void unregister_translators(void)
    00777 {
    00778    struct translator *cur;
    00779
    00780    AST_LIST_LOCK(&zap_translators);
    00781    while ((cur = AST_LIST_REMOVE_HEAD(&zap_translators, entry))) {
    00782       ast_unregister_translator(&cur->t);
    00783       free(cur);
    00784    }
    00785    AST_LIST_UNLOCK(&zap_translators);
    00786 }
    00787
    00788 static void parse_config(void)
    00789 {
    00790    struct ast_variable *var;
    00791    struct ast_config *cfg = ast_config_load("codecs.conf");
    00792
    00793    if (!cfg)
    00794       return;
    00795
    00796    for (var = ast_variable_browse(cfg, "plc"); var; var = var->next) {
    00797       if (!strcasecmp(var->name, "genericplc")) {
    00798          global_useplc = ast_true(var->value);
    00799          if (option_verbose > 2)
    00800             ast_verbose(VERBOSE_PREFIX_3 "codec_zap: %susing generic PLC\n", global_useplc ? "" : "not ");
    00801       }
    00802    }
    00803
    00804    ast_config_destroy(cfg);
    00805 }
    00806
    00807 static int build_translators(struct format_map *map, unsigned int dstfmts, unsigned int srcfmts)
    00808 {
    00809    unsigned int src, dst;
    00810
    00811    for (src = 0; src < 32; src++) {
    00812       for (dst = 0; dst < 32; dst++) {
    00813          if (!(srcfmts & (1<< src)))
    00814             continue;
    00815
    00816          if (!(dstfmts & (1 << dst)))
    00817             continue;
    00818
    00819          if (global_format_map.map[dst][src])
    00820             continue;
    00821
    00822          if (!register_translator(dst, src))
    00823             map->map[dst][src] = 1;
    00824          else
    00825             return 0;
    00826       }
    00827    }
    00828    return 1;
    00829 }
    00830
    00831 static int find_transcoders(void)
    00832 {
    00833    struct zt_transcode_info info = { 0, };
    00834    struct format_map map = { { { 0 } } };
    00835    int fd, res;
    00836    unsigned int x, y;
    00837
    00838    info.op = ZT_TCOP_GETINFO;
    00839    if ((fd = open("/dev/zap/transcode", O_RDWR)) < 0) {
    00840       ast_log(LOG_DEBUG, "No Zaptel transcoder support!\n");
    00841       return 0;
    00842    }
    00843
    00844    ast_mutex_lock(&channelcount);
    00845    totalchannels = 0;
    00846    ast_mutex_unlock(&channelcount);
    00847
    00848    for (info.tcnum = 0; !(res = ioctl(fd, ZT_TRANSCODE_OP, &info)); info.tcnum++) {
    00849       if (option_verbose > 1)
    00850          ast_verbose(VERBOSE_PREFIX_2 "Found transcoder '%s'.\n", info.name);
    00851
    00852       if(build_translators(&map, info.dstfmts, info.srcfmts)) {
    00853          ast_mutex_lock(&channelcount);
    00854          totalchannels += info.numchannels;
    00855          ast_mutex_unlock(&channelcount);
    00856       }
    00857    }
    00858    close(fd);
    00859
    00860    if (!info.tcnum && (option_verbose > 1))
    00861       ast_verbose(VERBOSE_PREFIX_2 "No hardware transcoders found.\n");
    00862
    00863    for (x = 0; x < 32; x++) {
    00864       for (y = 0; y < 32; y++) {
    00865          if (!map.map[x][y] && global_format_map.map[x][y])
    00866             drop_translator(x, y);
    00867       }
    00868    }
    00869    ast_mutex_lock(&channelcount);
    00870    totalchannels = totalchannels/2;
    00871    ast_mutex_unlock(&channelcount);
    00872    return 0;
    00873 }
    00874
    00875 int reload(void)
    00876 {
    00877    parse_config();
    00878
    00879    return 0;
    00880 }
    00881
    00882 int unload_module(void)
    00883 {
    00884    if(!localusecnt)
    00885       return -1;
    00886    unregister_translators();
    00887    ast_cli_unregister_multiple(transcoder_cli, sizeof(transcoder_cli) / sizeof(struct ast_cli_entry));
    00888    return 0;
    00889 }
    00890
    00891 int load_module(void)
    00892 {
    00893    ast_mutex_init(&channelcount);
    00894    parse_config();
    00895
    00896    find_transcoders();
    00897    ast_cli_register_multiple(transcoder_cli, sizeof(transcoder_cli) / sizeof(struct ast_cli_entry));
    00898    return 0;
    00899 }
    00900
    00901 char *description(void)
    00902 {
    00903    return tdesc;
    00904 }
    00905
    00906 int usecount(void)
    00907 {
    00908    int res;
    00909    STANDARD_USECOUNT(res);
    00910    return res;
    00911 }
    00912
    00913 char *key()
    00914 {
    00915    return ASTERISK_GPL_KEY;
    00916 }