Some missing checks
[opus.git] / src / opus_multistream_decoder.c
index e421726..f767ea0 100644 (file)
 #include "float_cast.h"
 #include "os_support.h"
 
-struct OpusMSDecoder {
-   ChannelLayout layout;
-   /* Decoder states go here */
-};
-
+/* DECODER */
 
+#if defined(ENABLE_HARDENING) || defined(ENABLE_ASSERTIONS)
+static void validate_ms_decoder(OpusMSDecoder *st)
+{
+   validate_layout(&st->layout);
+#ifdef OPUS_ARCHMASK
+   celt_assert(st->arch >= 0);
+   celt_assert(st->arch <= OPUS_ARCHMASK);
+#endif
+}
+#define VALIDATE_MS_DECODER(st) validate_ms_decoder(st)
+#else
+#define VALIDATE_MS_DECODER(st)
+#endif
 
 
-/* DECODER */
-
 opus_int32 opus_multistream_decoder_get_size(int nb_streams, int nb_coupled_streams)
 {
    int coupled_size;
@@ -143,15 +150,6 @@ OpusMSDecoder *opus_multistream_decoder_create(
    return st;
 }
 
-typedef void (*opus_copy_channel_out_func)(
-  void *dst,
-  int dst_stride,
-  int dst_channel,
-  const opus_val16 *src,
-  int src_stride,
-  int frame_size
-);
-
 static int opus_multistream_packet_validate(const unsigned char *data,
       opus_int32 len, int nb_streams, opus_int32 Fs)
 {
@@ -181,7 +179,7 @@ static int opus_multistream_packet_validate(const unsigned char *data,
    return samples;
 }
 
-static int opus_multistream_decode_native(
+int opus_multistream_decode_native(
       OpusMSDecoder *st,
       const unsigned char *data,
       opus_int32 len,
@@ -189,7 +187,8 @@ static int opus_multistream_decode_native(
       opus_copy_channel_out_func copy_channel_out,
       int frame_size,
       int decode_fec,
-      int soft_clip
+      int soft_clip,
+      void *user_data
 )
 {
    opus_int32 Fs;
@@ -201,8 +200,9 @@ static int opus_multistream_decode_native(
    VARDECL(opus_val16, buf);
    ALLOC_STACK;
 
+   VALIDATE_MS_DECODER(st);
    /* Limit frame_size to avoid excessive stack allocations. */
-   opus_multistream_decoder_ctl(st, OPUS_GET_SAMPLE_RATE(&Fs));
+   MUST_SUCCEED(opus_multistream_decoder_ctl(st, OPUS_GET_SAMPLE_RATE(&Fs)));
    frame_size = IMIN(frame_size, Fs/25*3);
    ALLOC(buf, 2*frame_size, opus_val16);
    ptr = (char*)st + align(sizeof(OpusMSDecoder));
@@ -266,7 +266,7 @@ static int opus_multistream_decode_native(
          while ( (chan = get_left_channel(&st->layout, s, prev)) != -1)
          {
             (*copy_channel_out)(pcm, st->layout.nb_channels, chan,
-               buf, 2, frame_size);
+               buf, 2, frame_size, user_data);
             prev = chan;
          }
          prev = -1;
@@ -274,7 +274,7 @@ static int opus_multistream_decode_native(
          while ( (chan = get_right_channel(&st->layout, s, prev)) != -1)
          {
             (*copy_channel_out)(pcm, st->layout.nb_channels, chan,
-               buf+1, 2, frame_size);
+               buf+1, 2, frame_size, user_data);
             prev = chan;
          }
       } else {
@@ -284,7 +284,7 @@ static int opus_multistream_decode_native(
          while ( (chan = get_mono_channel(&st->layout, s, prev)) != -1)
          {
             (*copy_channel_out)(pcm, st->layout.nb_channels, chan,
-               buf, 1, frame_size);
+               buf, 1, frame_size, user_data);
             prev = chan;
          }
       }
@@ -295,7 +295,7 @@ static int opus_multistream_decode_native(
       if (st->layout.mapping[c] == 255)
       {
          (*copy_channel_out)(pcm, st->layout.nb_channels, c,
-            NULL, 0, frame_size);
+            NULL, 0, frame_size, user_data);
       }
    }
    RESTORE_STACK;
@@ -309,11 +309,13 @@ static void opus_copy_channel_out_float(
   int dst_channel,
   const opus_val16 *src,
   int src_stride,
-  int frame_size
+  int frame_size,
+  void *user_data
 )
 {
    float *float_dst;
    opus_int32 i;
+   (void)user_data;
    float_dst = (float*)dst;
    if (src != NULL)
    {
@@ -338,11 +340,13 @@ static void opus_copy_channel_out_short(
   int dst_channel,
   const opus_val16 *src,
   int src_stride,
-  int frame_size
+  int frame_size,
+  void *user_data
 )
 {
    opus_int16 *short_dst;
    opus_int32 i;
+   (void)user_data;
    short_dst = (opus_int16*)dst;
    if (src != NULL)
    {
@@ -373,7 +377,7 @@ int opus_multistream_decode(
 )
 {
    return opus_multistream_decode_native(st, data, len,
-       pcm, opus_copy_channel_out_short, frame_size, decode_fec, 0);
+       pcm, opus_copy_channel_out_short, frame_size, decode_fec, 0, NULL);
 }
 
 #ifndef DISABLE_FLOAT_API
@@ -381,7 +385,7 @@ int opus_multistream_decode_float(OpusMSDecoder *st, const unsigned char *data,
       opus_int32 len, float *pcm, int frame_size, int decode_fec)
 {
    return opus_multistream_decode_native(st, data, len,
-       pcm, opus_copy_channel_out_float, frame_size, decode_fec, 0);
+       pcm, opus_copy_channel_out_float, frame_size, decode_fec, 0, NULL);
 }
 #endif
 
@@ -391,32 +395,30 @@ int opus_multistream_decode(OpusMSDecoder *st, const unsigned char *data,
       opus_int32 len, opus_int16 *pcm, int frame_size, int decode_fec)
 {
    return opus_multistream_decode_native(st, data, len,
-       pcm, opus_copy_channel_out_short, frame_size, decode_fec, 1);
+       pcm, opus_copy_channel_out_short, frame_size, decode_fec, 1, NULL);
 }
 
 int opus_multistream_decode_float(
       OpusMSDecoder *st,
       const unsigned char *data,
       opus_int32 len,
-      float *pcm,
+      opus_val16 *pcm,
       int frame_size,
       int decode_fec
 )
 {
    return opus_multistream_decode_native(st, data, len,
-       pcm, opus_copy_channel_out_float, frame_size, decode_fec, 0);
+       pcm, opus_copy_channel_out_float, frame_size, decode_fec, 0, NULL);
 }
 #endif
 
-int opus_multistream_decoder_ctl(OpusMSDecoder *st, int request, ...)
+int opus_multistream_decoder_ctl_va_list(OpusMSDecoder *st, int request,
+                                         va_list ap)
 {
-   va_list ap;
    int coupled_size, mono_size;
    char *ptr;
    int ret = OPUS_OK;
 
-   va_start(ap, request);
-
    coupled_size = opus_decoder_get_size(2);
    mono_size = opus_decoder_get_size(1);
    ptr = (char*)st + align(sizeof(OpusMSDecoder));
@@ -525,14 +527,20 @@ int opus_multistream_decoder_ctl(OpusMSDecoder *st, int request, ...)
           ret = OPUS_UNIMPLEMENTED;
        break;
    }
-
-   va_end(ap);
    return ret;
 bad_arg:
-   va_end(ap);
    return OPUS_BAD_ARG;
 }
 
+int opus_multistream_decoder_ctl(OpusMSDecoder *st, int request, ...)
+{
+   int ret;
+   va_list ap;
+   va_start(ap, request);
+   ret = opus_multistream_decoder_ctl_va_list(st, request, ap);
+   va_end(ap);
+   return ret;
+}
 
 void opus_multistream_decoder_destroy(OpusMSDecoder *st)
 {