Remove pthread.h from source. We should be using asterisk/lock.h everywhere instead...
[asterisk/asterisk.git] / codecs / codec_g723_1.c
index b71e28c..48b85e8 100755 (executable)
  * the GNU General Public License
  */
 
-#define TYPE_SILENCE    0x2
 #define TYPE_HIGH       0x0
 #define TYPE_LOW        0x1
+#define TYPE_SILENCE    0x2
+#define TYPE_DONTSEND   0x3
 #define TYPE_MASK       0x3
 
+#include <sys/types.h>
+#include <asterisk/lock.h>
 #include <asterisk/translate.h>
 #include <asterisk/module.h>
 #include <asterisk/logger.h>
-#include <pthread.h>
+#include <asterisk/channel.h>
 #include <fcntl.h>
 #include <stdlib.h>
 #include <unistd.h>
@@ -53,7 +56,7 @@
 #include "slin_g723_ex.h"
 #include "g723_slin_ex.h"
 
-static pthread_mutex_t localuser_lock = PTHREAD_MUTEX_INITIALIZER;
+AST_MUTEX_DEFINE_STATIC(localuser_lock);
 static int localusecnt=0;
 
 #ifdef ANNEX_B
@@ -75,7 +78,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;
@@ -91,7 +94,7 @@ struct g723_decoder_pvt {
        int tail;
 };
 
-static struct ast_translator_pvt *g723tolin_new()
+static struct ast_translator_pvt *g723tolin_new(void)
 {
        struct g723_decoder_pvt *tmp;
        tmp = malloc(sizeof(struct g723_decoder_pvt));
@@ -105,14 +108,14 @@ static struct ast_translator_pvt *g723tolin_new()
        return (struct ast_translator_pvt *)tmp;
 }
 
-static struct ast_frame *lintog723_sample()
+static struct ast_frame *lintog723_sample(void)
 {
        static struct ast_frame f;
        f.frametype = AST_FRAME_VOICE;
        f.subclass = AST_FORMAT_SLINEAR;
        f.datalen = sizeof(slin_g723_ex);
        /* Assume 8000 Hz */
-       f.timelen = sizeof(slin_g723_ex)/16;
+       f.samples = sizeof(slin_g723_ex)/2;
        f.mallocd = 0;
        f.offset = 0;
        f.src = __PRETTY_FUNCTION__;
@@ -120,14 +123,14 @@ static struct ast_frame *lintog723_sample()
        return &f;
 }
 
-static struct ast_frame *g723tolin_sample()
+static struct ast_frame *g723tolin_sample(void)
 {
        static struct ast_frame f;
        f.frametype = AST_FRAME_VOICE;
        f.subclass = AST_FORMAT_G723_1;
        f.datalen = sizeof(g723_slin_ex);
        /* All frames are 30 ms long */
-       f.timelen = 30;
+       f.samples = 240;
        f.mallocd = 0;
        f.offset = 0;
        f.src = __PRETTY_FUNCTION__;
@@ -135,7 +138,7 @@ static struct ast_frame *g723tolin_sample()
        return &f;
 }
 
-static struct ast_translator_pvt *lintog723_new()
+static struct ast_translator_pvt *lintog723_new(void)
 {
        struct g723_encoder_pvt *tmp;
        tmp = malloc(sizeof(struct g723_encoder_pvt));
@@ -164,7 +167,7 @@ static struct ast_frame *g723tolin_frameout(struct ast_translator_pvt *pvt)
        tmp->f.subclass = AST_FORMAT_SLINEAR;
        tmp->f.datalen = tmp->tail * 2;
        /* Assume 8000 Hz */
-       tmp->f.timelen = tmp->tail / 8;
+       tmp->f.samples = tmp->tail;
        tmp->f.mallocd = 0;
        tmp->f.offset = AST_FRIENDLY_OFFSET;
        tmp->f.src = __PRETTY_FUNCTION__;
@@ -173,41 +176,74 @@ static struct ast_frame *g723tolin_frameout(struct ast_translator_pvt *pvt)
        tmp->tail = 0;
 
 #if 0
-       /* Save a sample frame */
-       { static int samplefr = 0;
-       if (samplefr == 80) {
-               int fd;
-               fd = open("g723.example", O_WRONLY | O_CREAT | O_TRUNC, 0644);
-               write(fd, tmp->f.data, tmp->f.datalen);
-               close(fd);
+       /* Save the frames */
+       { 
+               static int fd2 = -1;
+               if (fd2 == -1) {
+                       fd2 = open("g723.example", O_WRONLY | O_CREAT | O_TRUNC, 0644);
+               }
+               write(fd2, tmp->f.data, tmp->f.datalen);
        }               
-       samplefr++;
-       }
 #endif
        return &tmp->f; 
 }
 
+static int g723_len(unsigned char buf)
+{
+       switch(buf & TYPE_MASK) {
+       case TYPE_DONTSEND:
+               return 0;
+               break;
+       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;
 }
@@ -236,43 +272,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.samples = 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.samples += 240;
+               cnt += g723_len(tmp->outbuf[cnt]);
+               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... */
        { 
@@ -330,13 +362,13 @@ static struct ast_translator lintog723 =
 int unload_module(void)
 {
        int res;
-       pthread_mutex_lock(&localuser_lock);
+       ast_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_mutex_unlock(&localuser_lock);
        return res;
 }
 
@@ -362,3 +394,8 @@ int usecount(void)
        STANDARD_USECOUNT(res);
        return res;
 }
+
+char *key(void)
+{
+       return ASTERISK_GPL_KEY;
+}