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 }

Generated on Wed Oct 28 15:47:53 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.6