Asterisk.org: Developer Documentation (28 Oct 2009)

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 }