Version 0.3.0 from FTP
[asterisk/asterisk.git] / codecs / codec_g723_1.c
index d33ba87..cbc2e63 100755 (executable)
@@ -7,7 +7,7 @@
  * it is covered with patents, and in spite of statements to the contrary,
  * the "technology" is extremely expensive to license.
  * 
  * it is covered with patents, and in spite of statements to the contrary,
  * the "technology" is extremely expensive to license.
  * 
- * Copyright (C) 1999, Adtran Inc. and Linux Support Services, LLC
+ * Copyright (C) 1999, Mark Spencer
  *
  * Mark Spencer <markster@linux-support.net>
  *
  *
  * Mark Spencer <markster@linux-support.net>
  *
@@ -75,7 +75,7 @@ struct g723_encoder_pvt {
        /* Space to build offset */
        char offset[AST_FRIENDLY_OFFSET];
        /* Buffer for our outgoing frame */
        /* 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;
        /* Enough to store a full second */
        short buf[8000];
        int tail;
@@ -99,6 +99,8 @@ static struct ast_translator_pvt *g723tolin_new()
                Init_Decod(&tmp->dec);
            Init_Dec_Cng(&tmp->dec);
                tmp->tail = 0;
                Init_Decod(&tmp->dec);
            Init_Dec_Cng(&tmp->dec);
                tmp->tail = 0;
+               localusecnt++;
+               ast_update_use_count();
        }
        return (struct ast_translator_pvt *)tmp;
 }
        }
        return (struct ast_translator_pvt *)tmp;
 }
@@ -144,6 +146,8 @@ static struct ast_translator_pvt *lintog723_new()
                        Init_Vad(&tmp->cod);
                Init_Cod_Cng(&tmp->cod);
         }
                        Init_Vad(&tmp->cod);
                Init_Cod_Cng(&tmp->cod);
         }
+               localusecnt++;
+               ast_update_use_count();
                tmp->tail = 0;
        }
        return (struct ast_translator_pvt *)tmp;
                tmp->tail = 0;
        }
        return (struct ast_translator_pvt *)tmp;
@@ -169,41 +173,72 @@ static struct ast_frame *g723tolin_frameout(struct ast_translator_pvt *pvt)
        tmp->tail = 0;
 
 #if 0
        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; 
 }
 
 #endif
        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;
 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
 #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
 #ifdef ANNEX_B
-               Decod(&tmp->dec, tmpdata, f->data, 0);
-               for (x=0;x<Frame;x++)
-                       (tmp->buf + tmp->tail)[x] = 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
 #else
-               Decod(&tmp->dec, tmp->buf + tmp->tail, f->data, 0);
+                       Decod(&tmp->dec, tmp->buf + tmp->tail, f->data + len, 0);
 #endif
 #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;
 }
        }
        return 0;
 }
@@ -232,43 +267,39 @@ static struct ast_frame *lintog723_frameout(struct ast_translator_pvt *pvt)
        int x;
        FLOAT tmpdata[Frame];
 #endif
        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;
        /* 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;
        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.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... */
        { 
 #if 0
        /* Save to a g723 sample output file... */
        { 
@@ -291,6 +322,8 @@ static struct ast_frame *lintog723_frameout(struct ast_translator_pvt *pvt)
 static void g723_destroy(struct ast_translator_pvt *pvt)
 {
        free(pvt);
 static void g723_destroy(struct ast_translator_pvt *pvt)
 {
        free(pvt);
+       localusecnt--;
+       ast_update_use_count();
 }
 
 static struct ast_translator g723tolin =
 }
 
 static struct ast_translator g723tolin =
@@ -356,3 +389,8 @@ int usecount(void)
        STANDARD_USECOUNT(res);
        return res;
 }
        STANDARD_USECOUNT(res);
        return res;
 }
+
+char *key()
+{
+       return ASTERISK_GPL_KEY;
+}