opus_packet_parse() now returns the payload offset rather than the pointer
[opus.git] / src / opus_decoder.c
index 48b637d..7138854 100644 (file)
 #include "entdec.h"
 #include "modes.h"
 #include "silk_API.h"
+#include "stack_alloc.h"
+#include "float_cast.h"
 
-#define MAX_PACKET (1275)
+#ifdef FIXED_POINT
+#define celt_decode_native celt_decode
+#else
+#define celt_decode_native celt_decode_float
+#endif
 
 /* Make sure everything's aligned to 4 bytes (this may need to be increased
    on really weird architectures) */
@@ -97,6 +103,7 @@ OpusDecoder *opus_decoder_init(OpusDecoder *st, int Fs, int channels)
     celt_decoder_ctl(celt_dec, CELT_SET_SIGNALLING(0));
 
        st->prev_mode = 0;
+       st->frame_size = Fs/400;
        return st;
 failure:
     free(st);
@@ -111,8 +118,8 @@ OpusDecoder *opus_decoder_create(int Fs, int channels)
     return opus_decoder_init((OpusDecoder*)raw_state, Fs, channels);
 }
 
-static void smooth_fade(const short *in1, const short *in2, short *out,
-        int overlap, int channels, const celt_word16 *window, int Fs)
+static void smooth_fade(const opus_val16 *in1, const opus_val16 *in2, opus_val16 *out,
+        int overlap, int channels, const opus_val16 *window, int Fs)
 {
        int i, c;
        int inc = 48000/Fs;
@@ -120,7 +127,7 @@ static void smooth_fade(const short *in1, const short *in2, short *out,
        {
                for (i=0;i<overlap;i++)
                {
-                   celt_word16 w = MULT16_16_Q15(window[i*inc], window[i*inc]);
+                   opus_val16 w = MULT16_16_Q15(window[i*inc], window[i*inc]);
                    out[i*channels+c] = SHR32(MAC16_16(MULT16_16(w,in2[i*channels+c]),
                            Q15ONE-w, in1[i*channels+c]), 15);
                }
@@ -144,16 +151,16 @@ static int opus_packet_get_mode(const unsigned char *data)
 }
 
 static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
-               int len, short *pcm, int frame_size, int decode_fec)
+               int len, opus_val16 *pcm, int frame_size, int decode_fec)
 {
        void *silk_dec;
        CELTDecoder *celt_dec;
        int i, silk_ret=0, celt_ret=0;
        ec_dec dec;
     silk_DecControlStruct DecControl;
-    SKP_int32 silk_frame_size;
-    short pcm_celt[960*2];
-    short pcm_transition[480*2];
+    opus_int32 silk_frame_size;
+    VARDECL(opus_int16, pcm_silk);
+    VARDECL(opus_val16, pcm_transition);
 
     int audiosize;
     int mode;
@@ -162,10 +169,10 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
     int redundancy=0;
     int redundancy_bytes = 0;
     int celt_to_silk=0;
-    short redundant_audio[240*2];
     int c;
     int F2_5, F5, F10, F20;
-    const celt_word16 *window;
+    const opus_val16 *window;
+    ALLOC_STACK;
 
     silk_dec = (char*)st+st->silk_dec_offset;
     celt_dec = (CELTDecoder*)((char*)st+st->celt_dec_offset);
@@ -173,11 +180,14 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
     F10 = F20>>1;
     F5 = F10>>1;
     F2_5 = F5>>1;
+    if (frame_size < F2_5)
+       return OPUS_BUFFER_TOO_SMALL;
     /* Payloads of 1 (2 including ToC) or 0 trigger the PLC/DTX */
     if (len<=1)
     {
        data = NULL;
        /* In that case, don't conceal more than what the ToC says */
+       /* FIXME: What if st->frame_size has never been set? */
        frame_size = IMIN(frame_size, st->frame_size);
     }
     if (data != NULL)
@@ -187,38 +197,46 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
         ec_dec_init(&dec,(unsigned char*)data,len);
     } else {
        audiosize = frame_size;
+
        if (st->prev_mode == 0)
        {
                /* If we haven't got any packet yet, all we can do is return zeros */
-               for (i=0;i<audiosize;i++)
+               for (i=0;i<audiosize*st->channels;i++)
                        pcm[i] = 0;
+               RESTORE_STACK;
                return audiosize;
        } else {
                mode = st->prev_mode;
        }
     }
 
+    ALLOC(pcm_transition, F5*st->channels, opus_val16);
+
     if (data!=NULL && !st->prev_redundancy && mode != st->prev_mode && st->prev_mode > 0
                && !(mode == MODE_SILK_ONLY && st->prev_mode == MODE_HYBRID)
                && !(mode == MODE_HYBRID && st->prev_mode == MODE_SILK_ONLY))
     {
        transition = 1;
        if (mode == MODE_CELT_ONLY)
-           opus_decode_frame(st, NULL, 0, pcm_transition, IMIN(F10, audiosize), 0);
+           opus_decode_frame(st, NULL, 0, pcm_transition, IMIN(F5, audiosize), 0);
     }
     if (audiosize > frame_size)
     {
         fprintf(stderr, "PCM buffer too small: %d vs %d (mode = %d)\n", audiosize, frame_size, mode);
+        RESTORE_STACK;
         return OPUS_BAD_ARG;
     } else {
         frame_size = audiosize;
     }
 
+    ALLOC(pcm_silk, frame_size*st->channels, opus_int16);
+    ALLOC(redundant_audio, F5*st->channels, opus_val16);
+
     /* SILK processing */
     if (mode != MODE_CELT_ONLY)
     {
         int lost_flag, decoded_samples;
-        SKP_int16 *pcm_ptr = pcm;
+        opus_int16 *pcm_ptr = pcm_silk;
 
         if (st->prev_mode==MODE_CELT_ONLY)
                silk_InitDecoder( silk_dec );
@@ -248,7 +266,7 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
         do {
             /* Call SILK decoder */
             int first_frame = decoded_samples == 0;
-            silk_ret = silk_Decode( silk_dec, &DecControl, 
+            silk_ret = silk_Decode( silk_dec, &DecControl,
                 lost_flag, first_frame, &dec, pcm_ptr, &silk_frame_size );
             if( silk_ret ) {
                if (lost_flag) {
@@ -256,15 +274,14 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
                        silk_frame_size = frame_size;
                        for (i=0;i<frame_size*st->channels;i++)
                                pcm_ptr[i] = 0;
-               } else
-                    return OPUS_CORRUPTED_DATA;
+               } else {
+                  RESTORE_STACK;
+                  return OPUS_CORRUPTED_DATA;
+               }
             }
             pcm_ptr += silk_frame_size * st->channels;
             decoded_samples += silk_frame_size;
         } while( decoded_samples < frame_size );
-    } else {
-        for (i=0;i<frame_size*st->channels;i++)
-            pcm[i] = 0;
     }
 
     start_band = 0;
@@ -287,8 +304,10 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
                }
             }
             len -= redundancy_bytes;
-            if (len<0)
-                return OPUS_CORRUPTED_DATA;
+            if (len<0) {
+               RESTORE_STACK;
+               return OPUS_CORRUPTED_DATA;
+            }
             /* Shrink decoder because of raw bits */
             dec.storage -= redundancy_bytes;
         }
@@ -323,13 +342,13 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
         transition = 0;
 
     if (transition && mode != MODE_CELT_ONLY)
-        opus_decode_frame(st, NULL, 0, pcm_transition, IMIN(F10, audiosize), 0);
+        opus_decode_frame(st, NULL, 0, pcm_transition, IMIN(F5, audiosize), 0);
 
     /* 5 ms redundant frame for CELT->SILK*/
     if (redundancy && celt_to_silk)
     {
         celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(0));
-        celt_decode(celt_dec, data+len, redundancy_bytes, redundant_audio, F5);
+        celt_decode_native(celt_dec, data+len, redundancy_bytes, redundant_audio, F5);
         celt_decoder_ctl(celt_dec, CELT_RESET_STATE);
     }
 
@@ -343,9 +362,21 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
     {
        int celt_frame_size = IMIN(F20, frame_size);
         /* Decode CELT */
-        celt_ret = celt_decode_with_ec(celt_dec, decode_fec?NULL:data, len, pcm_celt, celt_frame_size, &dec);
-        for (i=0;i<celt_frame_size*st->channels;i++)
-            pcm[i] = SAT16(pcm[i] + (int)pcm_celt[i]);
+        celt_ret = celt_decode_with_ec(celt_dec, decode_fec?NULL:data, len, pcm, celt_frame_size, &dec);
+    } else {
+       for (i=0;i<frame_size*st->channels;i++)
+          pcm[i] = 0;
+    }
+
+    if (mode != MODE_CELT_ONLY)
+    {
+#ifdef FIXED_POINT
+        for (i=0;i<frame_size*st->channels;i++)
+            pcm[i] = SAT16(pcm[i] + pcm_silk[i]);
+#else
+        for (i=0;i<frame_size*st->channels;i++)
+            pcm[i] = pcm[i] + (1./32768.)*pcm_silk[i];
+#endif
     }
 
     {
@@ -360,7 +391,7 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
         celt_decoder_ctl(celt_dec, CELT_RESET_STATE);
         celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(0));
 
-        celt_decode(celt_dec, data+len, redundancy_bytes, redundant_audio, F5);
+        celt_decode_native(celt_dec, data+len, redundancy_bytes, redundant_audio, F5);
         smooth_fade(pcm+st->channels*(frame_size-F2_5), redundant_audio+st->channels*F2_5,
                        pcm+st->channels*(frame_size-F2_5), F2_5, st->channels, window, st->Fs);
     }
@@ -383,12 +414,12 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
                    pcm+st->channels*F2_5, F2_5,
                    st->channels, window, st->Fs);
     }
-#if OPUS_TEST_RANGE_CODER_STATE
+
     st->rangeFinal = dec.rng;
-#endif
 
     st->prev_mode = mode;
     st->prev_redundancy = redundancy;
+    RESTORE_STACK;
        return celt_ret<0 ? celt_ret : audiosize;
 
 }
@@ -413,12 +444,136 @@ static int parse_size(const unsigned char *data, int len, short *size)
        }
 }
 
+int opus_packet_parse(const unsigned char *data, int len,
+      unsigned char *out_toc, const unsigned char *frames[48],
+      short size[48], int *payload_offset)
+{
+   int i, bytes;
+   int count;
+   unsigned char ch, toc;
+   int framesize;
+   const unsigned char *data0 = data;
+
+   if (size==NULL)
+      return OPUS_BAD_ARG;
+
+   framesize = opus_packet_get_samples_per_frame(data, 48000);
+
+   toc = *data++;
+   len--;
+   switch (toc&0x3)
+   {
+   /* One frame */
+   case 0:
+      count=1;
+      size[0] = len;
+      break;
+      /* Two CBR frames */
+   case 1:
+      count=2;
+      if (len&0x1)
+         return OPUS_CORRUPTED_DATA;
+      size[0] = size[1] = len/2;
+      break;
+      /* Two VBR frames */
+   case 2:
+      count = 2;
+      bytes = parse_size(data, len, size);
+      len -= bytes;
+      if (size[0]<0 || size[0] > len)
+         return OPUS_CORRUPTED_DATA;
+      data += bytes;
+      size[1] = len-size[0];
+      break;
+      /* Multiple CBR/VBR frames (from 0 to 120 ms) */
+   case 3:
+      if (len<1)
+         return OPUS_CORRUPTED_DATA;
+      /* Number of frames encoded in bits 0 to 5 */
+      ch = *data++;
+      count = ch&0x3F;
+      if (count <= 0 || framesize*count > 5760)
+          return OPUS_CORRUPTED_DATA;
+      len--;
+      /* Padding flag is bit 6 */
+      if (ch&0x40)
+      {
+         int padding=0;
+         int p;
+         do {
+            if (len<=0)
+               return OPUS_CORRUPTED_DATA;
+            p = *data++;
+            len--;
+            padding += p==255 ? 254: p;
+         } while (p==255);
+         len -= padding;
+      }
+      if (len<0)
+         return OPUS_CORRUPTED_DATA;
+      /* VBR flag is bit 7 */
+      if (ch&0x80)
+      {
+         /* VBR case */
+         int last_size=len;
+         for (i=0;i<count-1;i++)
+         {
+            bytes = parse_size(data, len, size+i);
+            len -= bytes;
+            if (size[i]<0 || size[i] > len)
+               return OPUS_CORRUPTED_DATA;
+            data += bytes;
+            last_size -= bytes+size[i];
+         }
+         if (last_size<0)
+            return OPUS_CORRUPTED_DATA;
+         size[count-1]=last_size;
+      } else {
+         /* CBR case */
+         int sz = len/count;
+         if (sz*count!=len)
+            return OPUS_CORRUPTED_DATA;
+         for (i=0;i<count;i++)
+            size[i] = sz;
+      }
+      break;
+   }
+   /* Because it's not encoded explicitly, it's possible the size of the
+       last packet (or all the packets, for the CBR case) is larger than
+       1275.
+      Reject them here.*/
+   if (size[count-1] > 1275)
+      return OPUS_CORRUPTED_DATA;
+
+   if (frames)
+   {
+      for (i=0;i<count;i++)
+      {
+         frames[i] = data;
+         data += size[i];
+      }
+   }
+
+   if (out_toc)
+      *out_toc = toc;
+
+   if (payload_offset)
+      *payload_offset = data-data0;
+
+   return count;
+}
+
+#ifdef FIXED_POINT
 int opus_decode(OpusDecoder *st, const unsigned char *data,
-               int len, short *pcm, int frame_size, int decode_fec)
+      int len, opus_val16 *pcm, int frame_size, int decode_fec)
+#else
+int opus_decode_float(OpusDecoder *st, const unsigned char *data,
+               int len, opus_val16 *pcm, int frame_size, int decode_fec)
+#endif
 {
-       int i, bytes, nb_samples;
-       int count;
-       unsigned char ch, toc;
+       int i, nb_samples;
+       int count, offset;
+       unsigned char toc;
        /* 48 x 2.5 ms = 120 ms */
        short size[48];
        if (len==0 || data==NULL)
@@ -429,91 +584,12 @@ int opus_decode(OpusDecoder *st, const unsigned char *data,
        st->bandwidth = opus_packet_get_bandwidth(data);
        st->frame_size = opus_packet_get_samples_per_frame(data, st->Fs);
        st->stream_channels = opus_packet_get_nb_channels(data);
-       toc = *data++;
-       len--;
-       switch (toc&0x3)
-       {
-       /* One frame */
-       case 0:
-               count=1;
-               size[0] = len;
-               break;
-               /* Two CBR frames */
-       case 1:
-               count=2;
-               if (len&0x1)
-                       return OPUS_CORRUPTED_DATA;
-               size[0] = size[1] = len/2;
-               break;
-               /* Two VBR frames */
-       case 2:
-               count = 2;
-               bytes = parse_size(data, len, size);
-               len -= bytes;
-               if (size[0]<0 || size[0] > len)
-                       return OPUS_CORRUPTED_DATA;
-               data += bytes;
-               size[1] = len-size[0];
-               break;
-               /* Multiple CBR/VBR frames (from 0 to 120 ms) */
-       case 3:
-               if (len<1)
-                       return OPUS_CORRUPTED_DATA;
-               /* Number of frames encoded in bits 0 to 5 */
-               ch = *data++;
-               count = ch&0x3F;
-               if (count <= 0 || st->frame_size*count*25 > 3*st->Fs)
-                   return OPUS_CORRUPTED_DATA;
-               len--;
-               /* Padding flag is bit 6 */
-               if (ch&0x40)
-               {
-                       int padding=0;
-                       int p;
-                       do {
-                               if (len<=0)
-                                       return OPUS_CORRUPTED_DATA;
-                               p = *data++;
-                               len--;
-                               padding += p==255 ? 254: p;
-                       } while (p==255);
-                       len -= padding;
-               }
-               if (len<0)
-                       return OPUS_CORRUPTED_DATA;
-               /* VBR flag is bit 7 */
-               if (ch&0x80)
-               {
-                       /* VBR case */
-                       int last_size=len;
-                       for (i=0;i<count-1;i++)
-                       {
-                               bytes = parse_size(data, len, size+i);
-                               len -= bytes;
-                               if (size[i]<0 || size[i] > len)
-                                       return OPUS_CORRUPTED_DATA;
-                               data += bytes;
-                               last_size -= bytes+size[i];
-                       }
-                       if (last_size<0)
-                               return OPUS_CORRUPTED_DATA;
-                       size[count-1]=last_size;
-               } else {
-                       /* CBR case */
-                       int sz = len/count;
-                       if (sz*count!=len)
-                               return OPUS_CORRUPTED_DATA;
-                       for (i=0;i<count;i++)
-                               size[i] = sz;
-               }
-               break;
-       }
-       /* Because it's not encoded explicitly, it's possible the size of the
-           last packet (or all the packets, for the CBR case) is larger than
-           1275.
-          Reject them here.*/
-       if (size[count-1] > MAX_PACKET)
-               return OPUS_CORRUPTED_DATA;
+
+       count = opus_packet_parse(data, len, &toc, NULL, size, &offset);
+       if (count < 0)
+          return count;
+
+       data += offset;
        if (count*st->frame_size > frame_size)
                return OPUS_BAD_ARG;
        nb_samples=0;
@@ -529,6 +605,51 @@ int opus_decode(OpusDecoder *st, const unsigned char *data,
        }
        return nb_samples;
 }
+
+#ifdef FIXED_POINT
+
+#ifndef DISABLE_FLOAT_API
+int opus_decode_float(OpusDecoder *st, const unsigned char *data,
+      int len, float *pcm, int frame_size, int decode_fec)
+{
+   VARDECL(opus_int16, out);
+   int ret, i;
+   ALLOC_STACK;
+
+   ALLOC(out, frame_size*st->channels, opus_int16);
+
+   ret = opus_decode(st, data, len, out, frame_size, decode_fec);
+   if (ret > 0)
+   {
+      for (i=0;i<ret*st->channels;i++)
+         pcm[i] = (1./32768.)*(out[i]);
+   }
+   RESTORE_STACK;
+   return ret;
+}
+#endif
+
+#else
+int opus_decode(OpusDecoder *st, const unsigned char *data,
+      int len, opus_int16 *pcm, int frame_size, int decode_fec)
+{
+   VARDECL(float, out);
+   int ret, i;
+   ALLOC_STACK;
+
+   ALLOC(out, frame_size*st->channels, float);
+
+   ret = opus_decode_float(st, data, len, out, frame_size, decode_fec);
+   if (ret > 0)
+   {
+      for (i=0;i<ret*st->channels;i++)
+         pcm[i] = FLOAT2INT16(out[i]);
+   }
+   RESTORE_STACK;
+   return ret;
+}
+#endif
+
 int opus_decoder_ctl(OpusDecoder *st, int request, ...)
 {
     va_list ap;
@@ -569,13 +690,10 @@ void opus_decoder_destroy(OpusDecoder *st)
        free(st);
 }
 
-#if OPUS_TEST_RANGE_CODER_STATE
 int opus_decoder_get_final_range(OpusDecoder *st)
 {
     return st->rangeFinal;
 }
-#endif
-
 
 int opus_packet_get_bandwidth(const unsigned char *data)
 {