Wed Oct 28 15:47:53 2009

Asterisk developer's documentation


codec_g723_1.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * The G.723.1 code is not included in the Asterisk distribution because
00005  * it is covered with patents, and in spite of statements to the contrary,
00006  * the "technology" is extremely expensive to license.
00007  * 
00008  * Copyright (C) 1999 - 2005, Digium, Inc.
00009  *
00010  * Mark Spencer <markster@digium.com>
00011  *
00012  * See http://www.asterisk.org for more information about
00013  * the Asterisk project. Please do not directly contact
00014  * any of the maintainers of this project for assistance;
00015  * the project provides a web site, mailing lists and IRC
00016  * channels for your use.
00017  *
00018  * This program is free software, distributed under the terms of
00019  * the GNU General Public License Version 2. See the LICENSE file
00020  * at the top of the source tree.
00021  */
00022 
00023 /*! \file
00024  *
00025  * \brief Translate between signed linear and G.723.1
00026  *
00027  * \ingroup codecs
00028  */
00029 
00030 #define TYPE_HIGH  0x0
00031 #define TYPE_LOW   0x1
00032 #define TYPE_SILENCE  0x2
00033 #define TYPE_DONTSEND    0x3
00034 #define TYPE_MASK  0x3
00035 
00036 #include <sys/types.h>
00037 #include <fcntl.h>
00038 #include <stdlib.h>
00039 #include <unistd.h>
00040 #include <netinet/in.h>
00041 #include <string.h>
00042 #include <stdio.h>
00043 
00044 #include "asterisk.h"
00045 
00046 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 7221 $")
00047 
00048 #include "asterisk/lock.h"
00049 #include "asterisk/translate.h"
00050 #include "asterisk/module.h"
00051 #include "asterisk/logger.h"
00052 #include "asterisk/channel.h"
00053 
00054 #ifdef ANNEX_B
00055 #include "g723.1b/typedef2.h"
00056 #include "g723.1b/cst2.h"
00057 #include "g723.1b/coder2.h"
00058 #include "g723.1b/decod2.h"
00059 #include "g723.1b/deccng2.h"
00060 #include "g723.1b/codcng2.h"
00061 #include "g723.1b/vad2.h"
00062 #else
00063 #include "g723.1/typedef.h"
00064 #include "g723.1/cst_lbc.h"
00065 #include "g723.1/coder.h"
00066 #include "g723.1/decod.h"
00067 #include "g723.1/dec_cng.h"
00068 #include "g723.1/cod_cng.h"
00069 #include "g723.1/vad.h"
00070 #endif
00071 
00072 /* Sample frame data */
00073 #include "slin_g723_ex.h"
00074 #include "g723_slin_ex.h"
00075 
00076 AST_MUTEX_DEFINE_STATIC(localuser_lock);
00077 static int localusecnt=0;
00078 
00079 #ifdef ANNEX_B
00080 static char *tdesc = "Annex B (floating point) G.723.1/PCM16 Codec Translator";
00081 #else
00082 static char *tdesc = "Annex A (fixed point) G.723.1/PCM16 Codec Translator";
00083 #endif
00084 
00085 /* Globals */
00086 Flag UsePf = True;
00087 Flag UseHp = True;
00088 Flag UseVx = True;
00089 
00090 enum Crate WrkRate = Rate63;
00091 
00092 struct g723_encoder_pvt {
00093    struct cod_state cod;
00094    struct ast_frame f;
00095    /* Space to build offset */
00096    char offset[AST_FRIENDLY_OFFSET];
00097    /* Buffer for our outgoing frame */
00098    char outbuf[8000];
00099    /* Enough to store a full second */
00100    short buf[8000];
00101    int tail;
00102 };
00103 
00104 struct g723_decoder_pvt {
00105    struct dec_state dec;
00106    struct ast_frame f;
00107    /* Space to build offset */
00108    char offset[AST_FRIENDLY_OFFSET];
00109    /* Enough to store a full second */
00110    short buf[8000];
00111    int tail;
00112 };
00113 
00114 static struct ast_translator_pvt *g723tolin_new(void)
00115 {
00116    struct g723_decoder_pvt *tmp;
00117    tmp = malloc(sizeof(struct g723_decoder_pvt));
00118    if (tmp) {
00119       Init_Decod(&tmp->dec);
00120        Init_Dec_Cng(&tmp->dec);
00121       tmp->tail = 0;
00122       localusecnt++;
00123       ast_update_use_count();
00124    }
00125    return (struct ast_translator_pvt *)tmp;
00126 }
00127 
00128 static struct ast_frame *lintog723_sample(void)
00129 {
00130    static struct ast_frame f;
00131    f.frametype = AST_FRAME_VOICE;
00132    f.subclass = AST_FORMAT_SLINEAR;
00133    f.datalen = sizeof(slin_g723_ex);
00134    /* Assume 8000 Hz */
00135    f.samples = sizeof(slin_g723_ex)/2;
00136    f.mallocd = 0;
00137    f.offset = 0;
00138    f.src = __PRETTY_FUNCTION__;
00139    f.data = slin_g723_ex;
00140    return &f;
00141 }
00142 
00143 static struct ast_frame *g723tolin_sample(void)
00144 {
00145    static struct ast_frame f;
00146    f.frametype = AST_FRAME_VOICE;
00147    f.subclass = AST_FORMAT_G723_1;
00148    f.datalen = sizeof(g723_slin_ex);
00149    /* All frames are 30 ms long */
00150    f.samples = 240;
00151    f.mallocd = 0;
00152    f.offset = 0;
00153    f.src = __PRETTY_FUNCTION__;
00154    f.data = g723_slin_ex;
00155    return &f;
00156 }
00157 
00158 static struct ast_translator_pvt *lintog723_new(void)
00159 {
00160    struct g723_encoder_pvt *tmp;
00161    tmp = malloc(sizeof(struct g723_encoder_pvt));
00162    if (tmp) {
00163       Init_Coder(&tmp->cod);
00164        /* Init Comfort Noise Functions */
00165           if( UseVx ) {
00166                Init_Vad(&tmp->cod);
00167          Init_Cod_Cng(&tmp->cod);
00168        }
00169       localusecnt++;
00170       ast_update_use_count();
00171       tmp->tail = 0;
00172    }
00173    return (struct ast_translator_pvt *)tmp;
00174 }
00175 
00176 static struct ast_frame *g723tolin_frameout(struct ast_translator_pvt *pvt)
00177 {
00178    struct g723_decoder_pvt *tmp = (struct g723_decoder_pvt *)pvt;
00179    if (!tmp->tail)
00180       return NULL;
00181    /* Signed linear is no particular frame size, so just send whatever
00182       we have in the buffer in one lump sum */
00183    tmp->f.frametype = AST_FRAME_VOICE;
00184    tmp->f.subclass = AST_FORMAT_SLINEAR;
00185    tmp->f.datalen = tmp->tail * 2;
00186    /* Assume 8000 Hz */
00187    tmp->f.samples = tmp->tail;
00188    tmp->f.mallocd = 0;
00189    tmp->f.offset = AST_FRIENDLY_OFFSET;
00190    tmp->f.src = __PRETTY_FUNCTION__;
00191    tmp->f.data = tmp->buf;
00192    /* Reset tail pointer */
00193    tmp->tail = 0;
00194 
00195 #if 0
00196    /* Save the frames */
00197    { 
00198       static int fd2 = -1;
00199       if (fd2 == -1) {
00200          fd2 = open("g723.example", O_WRONLY | O_CREAT | O_TRUNC, 0644);
00201       }
00202       write(fd2, tmp->f.data, tmp->f.datalen);
00203    }     
00204 #endif
00205    return &tmp->f;   
00206 }
00207 
00208 static int g723_len(unsigned char buf)
00209 {
00210    switch(buf & TYPE_MASK) {
00211    case TYPE_DONTSEND:
00212       return 0;
00213       break;
00214    case TYPE_SILENCE:
00215       return 4;
00216       break;
00217    case TYPE_HIGH:
00218       return 24;
00219       break;
00220    case TYPE_LOW:
00221       return 20;
00222       break;
00223    default:
00224       ast_log(LOG_WARNING, "Badly encoded frame (%d)\n", buf & TYPE_MASK);
00225    }
00226    return -1;
00227 }
00228 
00229 static int g723tolin_framein(struct ast_translator_pvt *pvt, struct ast_frame *f)
00230 {
00231    struct g723_decoder_pvt *tmp = (struct g723_decoder_pvt *)pvt;
00232    int len = 0;
00233    int res;
00234 #ifdef  ANNEX_B
00235    FLOAT tmpdata[Frame];
00236    int x;
00237 #endif
00238    while(len < f->datalen) {
00239       /* Assuming there's space left, decode into the current buffer at
00240          the tail location */
00241       res = g723_len(((unsigned char *)f->data + len)[0]);
00242       if (res < 0) {
00243          ast_log(LOG_WARNING, "Invalid data\n");
00244          return -1;
00245       }
00246       if (res + len > f->datalen) {
00247          ast_log(LOG_WARNING, "Measured length exceeds frame length\n");
00248          return -1;
00249       }
00250       if (tmp->tail + Frame < sizeof(tmp->buf)/2) {   
00251 #ifdef ANNEX_B
00252          Decod(&tmp->dec, tmpdata, f->data + len, 0);
00253          for (x=0;x<Frame;x++)
00254             (tmp->buf + tmp->tail)[x] = (short)(tmpdata[x]); 
00255 #else
00256          Decod(&tmp->dec, tmp->buf + tmp->tail, f->data + len, 0);
00257 #endif
00258          tmp->tail+=Frame;
00259       } else {
00260          ast_log(LOG_WARNING, "Out of buffer space\n");
00261          return -1;
00262       }
00263       len += res;
00264    }
00265    return 0;
00266 }
00267 
00268 static int lintog723_framein(struct ast_translator_pvt *pvt, struct ast_frame *f)
00269 {
00270    /* Just add the frames to our stream */
00271    /* XXX We should look at how old the rest of our stream is, and if it
00272       is too old, then we should overwrite it entirely, otherwise we can
00273       get artifacts of earlier talk that do not belong */
00274    struct g723_encoder_pvt *tmp = (struct g723_encoder_pvt *)pvt;
00275    if (tmp->tail + f->datalen/2 < sizeof(tmp->buf) / 2) {
00276       memcpy(&tmp->buf[tmp->tail], f->data, f->datalen);
00277       tmp->tail += f->datalen/2;
00278    } else {
00279       ast_log(LOG_WARNING, "Out of buffer space\n");
00280       return -1;
00281    }
00282    return 0;
00283 }
00284 
00285 static struct ast_frame *lintog723_frameout(struct ast_translator_pvt *pvt)
00286 {
00287    struct g723_encoder_pvt *tmp = (struct g723_encoder_pvt *)pvt;
00288 #ifdef ANNEX_B
00289    int x;
00290    FLOAT tmpdata[Frame];
00291 #endif
00292    int cnt=0;
00293    /* We can't work on anything less than a frame in size */
00294    if (tmp->tail < Frame)
00295       return NULL;
00296    tmp->f.frametype = AST_FRAME_VOICE;
00297    tmp->f.subclass = AST_FORMAT_G723_1;
00298    tmp->f.offset = AST_FRIENDLY_OFFSET;
00299    tmp->f.src = __PRETTY_FUNCTION__;
00300    tmp->f.samples = 0;
00301    tmp->f.mallocd = 0;
00302    while(tmp->tail >= Frame) {
00303       /* Encode a frame of data */
00304       if (cnt + 24 >= sizeof(tmp->outbuf)) {
00305          ast_log(LOG_WARNING, "Out of buffer space\n");
00306          return NULL;
00307       }
00308 #ifdef ANNEX_B
00309       for (x=0;x<Frame;x++)
00310          tmpdata[x] = tmp->buf[x];
00311       Coder(&tmp->cod, tmpdata, tmp->outbuf + cnt);
00312 #else
00313       Coder(&tmp->cod, tmp->buf, tmp->outbuf + cnt);
00314 #endif
00315       /* Assume 8000 Hz */
00316       tmp->f.samples += 240;
00317       cnt += g723_len(tmp->outbuf[cnt]);
00318       tmp->tail -= Frame;
00319       /* Move the data at the end of the buffer to the front */
00320       if (tmp->tail)
00321          memmove(tmp->buf, tmp->buf + Frame, tmp->tail * 2);
00322    }
00323    tmp->f.datalen = cnt;
00324    tmp->f.data = tmp->outbuf;
00325 #if 0
00326    /* Save to a g723 sample output file... */
00327    { 
00328       static int fd = -1;
00329       int delay = htonl(30);
00330       short size;
00331       if (fd < 0)
00332          fd = open("trans.g723", O_WRONLY | O_CREAT | O_TRUNC, 0644);
00333       if (fd < 0)
00334          ast_log(LOG_WARNING, "Unable to create demo\n");
00335       write(fd, &delay, 4);
00336       size = htons(tmp->f.datalen);
00337       write(fd, &size, 2);
00338       write(fd, tmp->f.data, tmp->f.datalen);
00339    }
00340 #endif
00341    return &tmp->f;   
00342 }
00343 
00344 static void g723_destroy(struct ast_translator_pvt *pvt)
00345 {
00346    free(pvt);
00347    localusecnt--;
00348    ast_update_use_count();
00349 }
00350 
00351 static struct ast_translator g723tolin =
00352 #ifdef ANNEX_B
00353    { "g723tolinb", 
00354 #else
00355    { "g723tolin", 
00356 #endif
00357       AST_FORMAT_G723_1, AST_FORMAT_SLINEAR,
00358       g723tolin_new,
00359       g723tolin_framein,
00360       g723tolin_frameout,
00361       g723_destroy,
00362       g723tolin_sample
00363       };
00364 
00365 static struct ast_translator lintog723 =
00366 #ifdef ANNEX_B
00367    { "lintog723b", 
00368 #else
00369    { "lintog723", 
00370 #endif
00371       AST_FORMAT_SLINEAR, AST_FORMAT_G723_1,
00372       lintog723_new,
00373       lintog723_framein,
00374       lintog723_frameout,
00375       g723_destroy,
00376       lintog723_sample
00377       };
00378 
00379 int unload_module(void)
00380 {
00381    int res;
00382    ast_mutex_lock(&localuser_lock);
00383    res = ast_unregister_translator(&lintog723);
00384    if (!res)
00385       res = ast_unregister_translator(&g723tolin);
00386    if (localusecnt)
00387       res = -1;
00388    ast_mutex_unlock(&localuser_lock);
00389    return res;
00390 }
00391 
00392 int load_module(void)
00393 {
00394    int res;
00395    res=ast_register_translator(&g723tolin);
00396    if (!res) 
00397       res=ast_register_translator(&lintog723);
00398    else
00399       ast_unregister_translator(&g723tolin);
00400    return res;
00401 }
00402 
00403 char *description(void)
00404 {
00405    return tdesc;
00406 }
00407 
00408 int usecount(void)
00409 {
00410    int res;
00411    STANDARD_USECOUNT(res);
00412    return res;
00413 }
00414 
00415 char *key(void)
00416 {
00417    return ASTERISK_GPL_KEY;
00418 }

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