Version 0.1.12 from FTP
[asterisk/asterisk.git] / codecs / codec_g723_1.c
index 72dcd90..1d65555 100755 (executable)
@@ -23,6 +23,7 @@
 #include <asterisk/translate.h>
 #include <asterisk/module.h>
 #include <asterisk/logger.h>
+#include <asterisk/channel.h>
 #include <pthread.h>
 #include <fcntl.h>
 #include <stdlib.h>
@@ -53,7 +54,7 @@
 #include "slin_g723_ex.h"
 #include "g723_slin_ex.h"
 
-static pthread_mutex_t localuser_lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t localuser_lock = AST_MUTEX_INITIALIZER;
 static int localusecnt=0;
 
 #ifdef ANNEX_B
@@ -75,7 +76,7 @@ struct g723_encoder_pvt {
        /* Space to build offset */
        char offset[AST_FRIENDLY_OFFSET];
        /* Buffer for our outgoing frame */
-       char outbuf[24];
+       char outbuf[8000];
        /* Enough to store a full second */
        short buf[8000];
        int tail;
@@ -185,27 +186,60 @@ static struct ast_frame *g723tolin_frameout(struct ast_translator_pvt *pvt)
        return &tmp->f; 
 }
 
+static int g723_len(unsigned char buf)
+{
+       switch(buf & TYPE_MASK) {
+       case TYPE_MASK:
+       case TYPE_SILENCE:
+               return 4;
+               break;
+       case TYPE_HIGH:
+               return 24;
+               break;
+       case TYPE_LOW:
+               return 20;
+               break;
+       default:
+               ast_log(LOG_WARNING, "Badly encoded frame (%d)\n", buf & TYPE_MASK);
+       }
+       return -1;
+}
+
 static int g723tolin_framein(struct ast_translator_pvt *pvt, struct ast_frame *f)
 {
        struct g723_decoder_pvt *tmp = (struct g723_decoder_pvt *)pvt;
+       int len = 0;
+       int res;
 #ifdef  ANNEX_B
        FLOAT tmpdata[Frame];
        int x;
 #endif
-       /* Assuming there's space left, decode into the current buffer at
-          the tail location */
-       if (tmp->tail + Frame < sizeof(tmp->buf)/2) {   
+       while(len < f->datalen) {
+               /* Assuming there's space left, decode into the current buffer at
+                  the tail location */
+               res = g723_len(((unsigned char *)f->data + len)[0]);
+               if (res < 0) {
+                       ast_log(LOG_WARNING, "Invalid data\n");
+                       return -1;
+               }
+               if (res + len > f->datalen) {
+                       ast_log(LOG_WARNING, "Measured length exceeds frame length\n");
+                       return -1;
+               }
+               if (tmp->tail + Frame < sizeof(tmp->buf)/2) {   
 #ifdef ANNEX_B
-               Decod(&tmp->dec, tmpdata, f->data, 0);
-               for (x=0;x<Frame;x++)
-                       (tmp->buf + tmp->tail)[x] = (short)(tmpdata[x]); 
+                       Decod(&tmp->dec, tmpdata, f->data + len, 0);
+                       for (x=0;x<Frame;x++)
+                               (tmp->buf + tmp->tail)[x] = (short)(tmpdata[x]); 
 #else
-               Decod(&tmp->dec, tmp->buf + tmp->tail, f->data, 0);
+                       Decod(&tmp->dec, tmp->buf + tmp->tail, f->data + len, 0);
 #endif
-               tmp->tail+=Frame;
-       } else {
-               ast_log(LOG_WARNING, "Out of buffer space\n");
-               return -1;
+                       tmp->tail+=Frame;
+               } else {
+                       ast_log(LOG_WARNING, "Out of buffer space\n");
+                       return -1;
+               }
+               len += res;
        }
        return 0;
 }
@@ -234,43 +268,39 @@ static struct ast_frame *lintog723_frameout(struct ast_translator_pvt *pvt)
        int x;
        FLOAT tmpdata[Frame];
 #endif
+       int cnt=0;
        /* We can't work on anything less than a frame in size */
        if (tmp->tail < Frame)
                return NULL;
-       /* Encode a frame of data */
-#ifdef ANNEX_B
-       for (x=0;x<Frame;x++)
-               tmpdata[x] = tmp->buf[x];
-       Coder(&tmp->cod, tmpdata, tmp->outbuf);
-#else
-       Coder(&tmp->cod, tmp->buf, tmp->outbuf);
-#endif
        tmp->f.frametype = AST_FRAME_VOICE;
        tmp->f.subclass = AST_FORMAT_G723_1;
-       /* Assume 8000 Hz */
-       tmp->f.timelen = 30;
-       tmp->f.mallocd = 0;
        tmp->f.offset = AST_FRIENDLY_OFFSET;
        tmp->f.src = __PRETTY_FUNCTION__;
-       tmp->f.data = tmp->outbuf;
-       switch(tmp->outbuf[0] & TYPE_MASK) {
-       case TYPE_MASK:
-       case TYPE_SILENCE:
-               tmp->f.datalen = 4;
-               break;
-       case TYPE_HIGH:
-               tmp->f.datalen = 24;
-               break;
-       case TYPE_LOW:
-               tmp->f.datalen = 20;
-               break;
-       default:
-               ast_log(LOG_WARNING, "Badly encoded frame (%d)\n", tmp->outbuf[0] & TYPE_MASK);
+       tmp->f.timelen = 0;
+       tmp->f.mallocd = 0;
+       while(tmp->tail >= Frame) {
+               /* Encode a frame of data */
+               if (cnt + 24 >= sizeof(tmp->outbuf)) {
+                       ast_log(LOG_WARNING, "Out of buffer space\n");
+                       return NULL;
+               }
+#ifdef ANNEX_B
+               for (x=0;x<Frame;x++)
+                       tmpdata[x] = tmp->buf[x];
+               Coder(&tmp->cod, tmpdata, tmp->outbuf + cnt);
+#else
+               Coder(&tmp->cod, tmp->buf, tmp->outbuf + cnt);
+#endif
+               /* Assume 8000 Hz */
+               tmp->f.timelen += 30;
+               cnt += g723_len(tmp->outbuf[0]);
+               tmp->tail -= Frame;
+               /* Move the data at the end of the buffer to the front */
+               if (tmp->tail)
+                       memmove(tmp->buf, tmp->buf + Frame, tmp->tail * 2);
        }
-       tmp->tail -= Frame;
-       /* Move the data at the end of the buffer to the front */
-       if (tmp->tail)
-               memmove(tmp->buf, tmp->buf + Frame, tmp->tail * 2);
+       tmp->f.datalen = cnt;
+       tmp->f.data = tmp->outbuf;
 #if 0
        /* Save to a g723 sample output file... */
        { 
@@ -328,13 +358,13 @@ static struct ast_translator lintog723 =
 int unload_module(void)
 {
        int res;
-       pthread_mutex_lock(&localuser_lock);
+       ast_pthread_mutex_lock(&localuser_lock);
        res = ast_unregister_translator(&lintog723);
        if (!res)
                res = ast_unregister_translator(&g723tolin);
        if (localusecnt)
                res = -1;
-       pthread_mutex_unlock(&localuser_lock);
+       ast_pthread_mutex_unlock(&localuser_lock);
        return res;
 }
 
@@ -360,3 +390,8 @@ int usecount(void)
        STANDARD_USECOUNT(res);
        return res;
 }
+
+char *key()
+{
+       return ASTERISK_GPL_KEY;
+}