Fix 40/60ms zero-length frame decode failure
authorMark Harris <mark.hsj@gmail.com>
Tue, 8 Oct 2013 01:50:59 +0000 (18:50 -0700)
committerJean-Marc Valin <jmvalin@jmvalin.ca>
Sat, 12 Oct 2013 03:43:21 +0000 (23:43 -0400)
Decoding failed with OPUS_BAD_ARG on a packet containing a 40ms or
60ms zero-length frame when it followed a hybrid or MDCT frame.
It now invokes the PLC for the duration of the packet as expected.

Signed-off-by: Jean-Marc Valin <jmvalin@jmvalin.ca>
src/opus_decoder.c

index ee0c9f5..5e39bd4 100644 (file)
@@ -257,23 +257,33 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
       ec_dec_init(&dec,(unsigned char*)data,len);
    } else {
       audiosize = frame_size;
+      mode = st->prev_mode;
 
-      if (st->prev_mode == 0)
+      if (mode == 0)
       {
          /* If we haven't got any packet yet, all we can do is return zeros */
          for (i=0;i<audiosize*st->channels;i++)
             pcm[i] = 0;
          RESTORE_STACK;
          return audiosize;
-      } else {
-         mode = st->prev_mode;
       }
-   }
 
-   /* For CELT/hybrid PLC of more than 20 ms, opus_decode_native() will do
-      multiple calls */
-   if (data==NULL  && mode != MODE_SILK_ONLY)
-      frame_size = IMIN(frame_size, F20);
+      if (mode != MODE_SILK_ONLY && audiosize > F20)
+      {
+         do {
+            int ret = opus_decode_frame(st, NULL, 0, pcm, IMIN(audiosize, F20), 0);
+            if (ret<0)
+            {
+               RESTORE_STACK;
+               return ret;
+            }
+            pcm += ret*st->channels;
+            audiosize -= ret;
+         } while (audiosize > 0);
+         RESTORE_STACK;
+         return frame_size;
+      }
+   }
 
    pcm_transition_silk_size = 0;
    pcm_transition_celt_size = 0;