Remove useless code in alloc_trim_analysis()
[opus.git] / src / opus_multistream_decoder.c
index ed7cb55..a05fa1e 100644 (file)
@@ -152,6 +152,35 @@ typedef void (*opus_copy_channel_out_func)(
   int frame_size
 );
 
+static int opus_multistream_packet_validate(const unsigned char *data,
+      opus_int32 len, int nb_streams, opus_int32 Fs)
+{
+   int s;
+   int count;
+   unsigned char toc;
+   opus_int16 size[48];
+   int samples=0;
+   opus_int32 packet_offset;
+
+   for (s=0;s<nb_streams;s++)
+   {
+      int tmp_samples;
+      if (len<=0)
+         return OPUS_INVALID_PACKET;
+      count = opus_packet_parse_impl(data, len, s!=nb_streams-1, &toc, NULL,
+                                     size, NULL, &packet_offset);
+      if (count<0)
+         return count;
+      tmp_samples = opus_packet_get_nb_samples(data, packet_offset, Fs);
+      if (s!=0 && samples != tmp_samples)
+         return OPUS_INVALID_PACKET;
+      samples = tmp_samples;
+      data += packet_offset;
+      len -= packet_offset;
+   }
+   return samples;
+}
+
 static int opus_multistream_decode_native(
       OpusMSDecoder *st,
       const unsigned char *data,
@@ -159,7 +188,8 @@ static int opus_multistream_decode_native(
       void *pcm,
       opus_copy_channel_out_func copy_channel_out,
       int frame_size,
-      int decode_fec
+      int decode_fec,
+      int soft_clip
 )
 {
    opus_int32 Fs;
@@ -182,9 +212,28 @@ static int opus_multistream_decode_native(
    if (len==0)
       do_plc = 1;
    if (len < 0)
+   {
+      RESTORE_STACK;
       return OPUS_BAD_ARG;
+   }
    if (!do_plc && len < 2*st->layout.nb_streams-1)
+   {
+      RESTORE_STACK;
       return OPUS_INVALID_PACKET;
+   }
+   if (!do_plc)
+   {
+      int ret = opus_multistream_packet_validate(data, len, st->layout.nb_streams, Fs);
+      if (ret < 0)
+      {
+         RESTORE_STACK;
+         return ret;
+      } else if (ret > frame_size)
+      {
+         RESTORE_STACK;
+         return OPUS_BUFFER_TOO_SMALL;
+      }
+   }
    for (s=0;s<st->layout.nb_streams;s++)
    {
       OpusDecoder *dec;
@@ -196,22 +245,12 @@ static int opus_multistream_decode_native(
       if (!do_plc && len<=0)
       {
          RESTORE_STACK;
-         return OPUS_INVALID_PACKET;
+         return OPUS_INTERNAL_ERROR;
       }
       packet_offset = 0;
-      ret = opus_decode_native(dec, data, len, buf, frame_size, decode_fec, s!=st->layout.nb_streams-1, &packet_offset);
+      ret = opus_decode_native(dec, data, len, buf, frame_size, decode_fec, s!=st->layout.nb_streams-1, &packet_offset, soft_clip);
       data += packet_offset;
       len -= packet_offset;
-      if (ret > frame_size)
-      {
-         RESTORE_STACK;
-         return OPUS_BUFFER_TOO_SMALL;
-      }
-      if (s>0 && ret != frame_size)
-      {
-         RESTORE_STACK;
-         return OPUS_INVALID_PACKET;
-      }
       if (ret <= 0)
       {
          RESTORE_STACK;
@@ -273,7 +312,7 @@ static void opus_copy_channel_out_float(
 )
 {
    float *float_dst;
-   int i;
+   opus_int32 i;
    float_dst = (float*)dst;
    if (src != NULL)
    {
@@ -302,7 +341,7 @@ static void opus_copy_channel_out_short(
 )
 {
    opus_int16 *short_dst;
-   int i;
+   opus_int32 i;
    short_dst = (opus_int16*)dst;
    if (src != NULL)
    {
@@ -333,7 +372,7 @@ int opus_multistream_decode(
 )
 {
    return opus_multistream_decode_native(st, data, len,
-       pcm, opus_copy_channel_out_short, frame_size, decode_fec);
+       pcm, opus_copy_channel_out_short, frame_size, decode_fec, 0);
 }
 
 #ifndef DISABLE_FLOAT_API
@@ -341,7 +380,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);
+       pcm, opus_copy_channel_out_float, frame_size, decode_fec, 0);
 }
 #endif
 
@@ -351,7 +390,7 @@ 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);
+       pcm, opus_copy_channel_out_short, frame_size, decode_fec, 1);
 }
 
 int opus_multistream_decode_float(
@@ -364,7 +403,7 @@ int opus_multistream_decode_float(
 )
 {
    return opus_multistream_decode_native(st, data, len,
-       pcm, opus_copy_channel_out_float, frame_size, decode_fec);
+       pcm, opus_copy_channel_out_float, frame_size, decode_fec, 0);
 }
 #endif
 
@@ -384,6 +423,8 @@ int opus_multistream_decoder_ctl(OpusMSDecoder *st, int request, ...)
    {
        case OPUS_GET_BANDWIDTH_REQUEST:
        case OPUS_GET_SAMPLE_RATE_REQUEST:
+       case OPUS_GET_GAIN_REQUEST:
+       case OPUS_GET_LAST_PACKET_DURATION_REQUEST:
        {
           OpusDecoder *dec;
           /* For int32* GET params, just query the first stream */
@@ -397,6 +438,10 @@ int opus_multistream_decoder_ctl(OpusMSDecoder *st, int request, ...)
           int s;
           opus_uint32 *value = va_arg(ap, opus_uint32*);
           opus_uint32 tmp;
+          if (!value)
+          {
+             goto bad_arg;
+          }
           *value = 0;
           for (s=0;s<st->layout.nb_streams;s++)
           {
@@ -439,6 +484,10 @@ int opus_multistream_decoder_ctl(OpusMSDecoder *st, int request, ...)
           if (stream_id<0 || stream_id >= st->layout.nb_streams)
              ret = OPUS_BAD_ARG;
           value = va_arg(ap, OpusDecoder**);
+          if (!value)
+          {
+             goto bad_arg;
+          }
           for (s=0;s<stream_id;s++)
           {
              if (s < st->layout.nb_coupled_streams)
@@ -476,6 +525,9 @@ int opus_multistream_decoder_ctl(OpusMSDecoder *st, int request, ...)
 
    va_end(ap);
    return ret;
+bad_arg:
+   va_end(ap);
+   return OPUS_BAD_ARG;
 }