Moves opus_compare to the same base64 tar.gz as the rest of the code
[opus.git] / src / opus_multistream.c
index da498dd..b5f7bba 100644 (file)
@@ -33,9 +33,6 @@
 #include "opus.h"
 #include "opus_private.h"
 #include "stack_alloc.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
 #include <stdarg.h>
 #include "float_cast.h"
 #include "os_support.h"
@@ -151,13 +148,13 @@ int opus_multistream_encoder_get_size(int nb_streams, int nb_coupled_streams)
 
 
 int opus_multistream_encoder_init(
-      OpusMSEncoder *st,            /* Encoder state */
-      int Fs,                     /* Sampling rate of input signal (Hz) */
-      int channels,               /* Number of channels (1/2) in input signal */
+      OpusMSEncoder *st,
+      opus_int32 Fs,
+      int channels,
       int streams,
       int coupled_streams,
       unsigned char *mapping,
-      int application             /* Coding mode (OPUS_APPLICATION_VOIP/OPUS_APPLICATION_AUDIO) */
+      int application
 )
 {
    int coupled_size;
@@ -191,17 +188,17 @@ int opus_multistream_encoder_init(
 }
 
 OpusMSEncoder *opus_multistream_encoder_create(
-      int Fs,                     /* Sampling rate of input signal (Hz) */
-      int channels,               /* Number of channels (1/2) in input signal */
+      opus_int32 Fs,
+      int channels,
       int streams,
       int coupled_streams,
       unsigned char *mapping,
-      int application,            /* Coding mode (OPUS_APPLICATION_VOIP/OPUS_APPLICATION_AUDIO) */
-      int *error                  /* Error code */
+      int application,
+      int *error
 )
 {
    int ret;
-   OpusMSEncoder *st = opus_alloc(opus_multistream_encoder_get_size(streams, coupled_streams));
+   OpusMSEncoder *st = (OpusMSEncoder *)opus_alloc(opus_multistream_encoder_get_size(streams, coupled_streams));
    if (st==NULL)
    {
       if (error)
@@ -225,11 +222,11 @@ int opus_multistream_encode(
 #else
 int opus_multistream_encode_float(
 #endif
-    OpusMSEncoder *st,            /* Encoder state */
-    const opus_val16 *pcm,      /* Input signal (interleaved if 2 channels). length is frame_size*channels */
-    int frame_size,             /* Number of samples per frame of input signal */
-    unsigned char *data,        /* Output payload (no more than max_data_bytes long) */
-    int max_data_bytes          /* Allocated memory for payload; don't use for controlling bitrate */
+    OpusMSEncoder *st,
+    const opus_val16 *pcm,
+    int frame_size,
+    unsigned char *data,
+    int max_data_bytes
 )
 {
    int coupled_size;
@@ -238,10 +235,15 @@ int opus_multistream_encode_float(
    char *ptr;
    int tot_size;
    VARDECL(opus_val16, buf);
-   unsigned char tmp_data[1276];
+   /* Max size in case the encoder decides to return three frames */
+   unsigned char tmp_data[3*1275+7];
+   VARDECL(unsigned char, rp_);
+   OpusRepacketizer *rp;
    ALLOC_STACK;
 
    ALLOC(buf, 2*frame_size, opus_val16);
+   ALLOC(rp_, opus_repacketizer_get_size(), unsigned char);
+   rp = (OpusRepacketizer*)rp_;
    ptr = (char*)st + align(sizeof(OpusMSEncoder));
    coupled_size = opus_encoder_get_size(2);
    mono_size = opus_encoder_get_size(1);
@@ -259,6 +261,7 @@ int opus_multistream_encode_float(
       int len;
       int curr_max;
 
+      opus_repacketizer_init(rp);
       enc = (OpusEncoder*)ptr;
       if (s < st->layout.nb_coupled_streams)
       {
@@ -287,17 +290,13 @@ int opus_multistream_encode_float(
          RESTORE_STACK;
          return len;
       }
-      /* ToC first */
-      *data++ = tmp_data[0];
-      if (s != st->layout.nb_streams-1)
-      {
-         int tmp = encode_size(len-1, data);
-         data += tmp;
-         tot_size += tmp;
-      }
-      /* IMPORTANT: Here we assume that the encoder only returned one frame */
+      /* We need to use the repacketizer to add the self-delimiting lengths
+         while taking into account the fact that the encoder can now return
+         more than one frame at a time (e.g. 60 ms CELT-only) */
+      opus_repacketizer_cat(rp, tmp_data, len);
+      len = opus_repacketizer_out_range_impl(rp, 0, opus_repacketizer_get_nb_frames(rp), data, max_data_bytes-tot_size, s != st->layout.nb_streams-1);
+      data += len;
       tot_size += len;
-      memcpy(data, &tmp_data[1], len-1);
    }
    RESTORE_STACK;
    return tot_size;
@@ -308,11 +307,11 @@ int opus_multistream_encode_float(
 
 #ifndef DISABLE_FLOAT_API
 int opus_multistream_encode_float(
-    OpusMSEncoder *st,          /* Encoder state */
-    const float *pcm,           /* Input signal (interleaved if 2 channels). length is frame_size*channels */
-    int frame_size,             /* Number of samples per frame of input signal */
-    unsigned char *data,        /* Output payload (no more than max_data_bytes long) */
-    int max_data_bytes          /* Allocated memory for payload; don't use for controlling bitrate */
+    OpusMSEncoder *st,
+    const float *pcm,
+    int frame_size,
+    unsigned char *data,
+    int max_data_bytes
 )
 {
    int i, ret;
@@ -332,11 +331,11 @@ int opus_multistream_encode_float(
 #else
 
 int opus_multistream_encode(
-    OpusMSEncoder *st,          /* Encoder state */
-    const opus_int16 *pcm,      /* Input signal (interleaved if 2 channels). length is frame_size*channels */
-    int frame_size,             /* Number of samples per frame of input signal */
-    unsigned char *data,        /* Output payload (no more than max_data_bytes long) */
-    int max_data_bytes          /* Allocated memory for payload; don't use for controlling bitrate */
+    OpusMSEncoder *st,
+    const opus_int16 *pcm,
+    int frame_size,
+    unsigned char *data,
+    int max_data_bytes
 )
 {
    int i, ret;
@@ -371,7 +370,7 @@ int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...)
    case OPUS_SET_BITRATE_REQUEST:
    {
       int chan, s;
-      opus_uint32 value = va_arg(ap, opus_uint32);
+      opus_int32 value = va_arg(ap, opus_int32);
       chan = st->layout.nb_streams + st->layout.nb_coupled_streams;
       value /= chan;
       for (s=0;s<st->layout.nb_streams;s++)
@@ -382,8 +381,21 @@ int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...)
       }
    }
    break;
-   /* FIXME: Add missing ones */
    case OPUS_GET_BITRATE_REQUEST:
+   {
+      int s;
+      opus_int32 *value = va_arg(ap, opus_int32*);
+      *value = 0;
+      for (s=0;s<st->layout.nb_streams;s++)
+      {
+         opus_int32 rate;
+         OpusEncoder *enc;
+         enc = (OpusEncoder*)ptr;
+         opus_encoder_ctl(enc, request, &rate);
+         *value += rate;
+      }
+   }
+   break;
    case OPUS_GET_VBR_REQUEST:
    case OPUS_GET_APPLICATION_REQUEST:
    case OPUS_GET_BANDWIDTH_REQUEST:
@@ -394,10 +406,28 @@ int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...)
    case OPUS_GET_VBR_CONSTRAINT_REQUEST:
    case OPUS_GET_SIGNAL_REQUEST:
    case OPUS_GET_LOOKAHEAD_REQUEST:
+   case OPUS_GET_INBAND_FEC_REQUEST:
+   {
+      OpusEncoder *enc;
+      /* For int32* GET params, just query the first stream */
+      opus_int32 *value = va_arg(ap, opus_int32*);
+      enc = (OpusEncoder*)ptr;
+      ret = opus_encoder_ctl(enc, request, value);
+   }
+   break;
+   case OPUS_SET_COMPLEXITY_REQUEST:
+   case OPUS_SET_VBR_REQUEST:
+   case OPUS_SET_VBR_CONSTRAINT_REQUEST:
+   case OPUS_SET_BANDWIDTH_REQUEST:
+   case OPUS_SET_SIGNAL_REQUEST:
+   case OPUS_SET_APPLICATION_REQUEST:
+   case OPUS_SET_INBAND_FEC_REQUEST:
+   case OPUS_SET_PACKET_LOSS_PERC_REQUEST:
+   case OPUS_SET_DTX_REQUEST:
    {
       int s;
-      /* This works for int32* params */
-      opus_uint32 *value = va_arg(ap, opus_uint32*);
+      /* This works for int32 params */
+      opus_int32 value = va_arg(ap, opus_int32);
       for (s=0;s<st->layout.nb_streams;s++)
       {
          OpusEncoder *enc;
@@ -413,26 +443,28 @@ int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...)
       }
    }
    break;
-   default:
+   case OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST:
    {
       int s;
-      /* This works for int32 params */
-      opus_uint32 value = va_arg(ap, opus_uint32);
-      for (s=0;s<st->layout.nb_streams;s++)
+      opus_int32 stream_id;
+      OpusEncoder **value;
+      stream_id = va_arg(ap, opus_int32);
+      if (stream_id<0 || stream_id >= st->layout.nb_streams)
+         ret = OPUS_BAD_ARG;
+      value = va_arg(ap, OpusEncoder**);
+      for (s=0;s<stream_id;s++)
       {
-         OpusEncoder *enc;
-
-         enc = (OpusEncoder*)ptr;
          if (s < st->layout.nb_coupled_streams)
             ptr += align(coupled_size);
          else
             ptr += align(mono_size);
-         ret = opus_encoder_ctl(enc, request, value);
-         if (ret < 0)
-            break;
       }
+      *value = (OpusEncoder*)ptr;
    }
-   break;
+      break;
+   default:
+      ret = OPUS_UNIMPLEMENTED;
+      break;
    }
 
    va_end(ap);
@@ -460,9 +492,9 @@ int opus_multistream_decoder_get_size(int nb_streams, int nb_coupled_streams)
 }
 
 int opus_multistream_decoder_init(
-      OpusMSDecoder *st,            /* Encoder state */
-      int Fs,                     /* Sampling rate of input signal (Hz) */
-      int channels,               /* Number of channels (1/2) in input signal */
+      OpusMSDecoder *st,
+      opus_int32 Fs,
+      int channels,
       int streams,
       int coupled_streams,
       unsigned char *mapping
@@ -501,16 +533,16 @@ int opus_multistream_decoder_init(
 
 
 OpusMSDecoder *opus_multistream_decoder_create(
-      int Fs,                     /* Sampling rate of input signal (Hz) */
-      int channels,               /* Number of channels (1/2) in input signal */
+      opus_int32 Fs,
+      int channels,
       int streams,
       int coupled_streams,
       unsigned char *mapping,
-      int *error                  /* Error code */
+      int *error
 )
 {
    int ret;
-   OpusMSDecoder *st = opus_alloc(opus_multistream_decoder_get_size(streams, coupled_streams));
+   OpusMSDecoder *st = (OpusMSDecoder *)opus_alloc(opus_multistream_decoder_get_size(streams, coupled_streams));
    if (st==NULL)
    {
       if (error)
@@ -531,7 +563,7 @@ OpusMSDecoder *opus_multistream_decoder_create(
 }
 
 static int opus_multistream_decode_native(
-      OpusMSDecoder *st,            /* Encoder state */
+      OpusMSDecoder *st,
       const unsigned char *data,
       int len,
       opus_val16 *pcm,
@@ -564,9 +596,9 @@ static int opus_multistream_decode_native(
       if (len<=0)
       {
          RESTORE_STACK;
-         return OPUS_CORRUPTED_DATA;
+         return OPUS_INVALID_PACKET;
       }
-      ret = opus_decode_native(dec, data, len, buf, frame_size, decode_fec, 1, &packet_offset);
+      ret = opus_decode_native(dec, data, len, buf, frame_size, decode_fec, s!=st->layout.nb_streams-1, &packet_offset);
       data += packet_offset;
       len -= packet_offset;
       if (ret > frame_size)
@@ -577,7 +609,7 @@ static int opus_multistream_decode_native(
       if (s>0 && ret != frame_size)
       {
          RESTORE_STACK;
-         return OPUS_CORRUPTED_DATA;
+         return OPUS_INVALID_PACKET;
       }
       if (ret <= 0)
       {
@@ -631,7 +663,7 @@ static int opus_multistream_decode_native(
 
 #ifdef FIXED_POINT
 int opus_multistream_decode(
-      OpusMSDecoder *st,            /* Encoder state */
+      OpusMSDecoder *st,
       const unsigned char *data,
       int len,
       opus_int16 *pcm,
@@ -685,7 +717,7 @@ int opus_multistream_decode(OpusMSDecoder *st, const unsigned char *data,
 }
 
 int opus_multistream_decode_float(
-      OpusMSDecoder *st,            /* Encoder state */
+      OpusMSDecoder *st,
       const unsigned char *data,
       int len,
       float *pcm,
@@ -711,26 +743,66 @@ int opus_multistream_decoder_ctl(OpusMSDecoder *st, int request, ...)
    ptr = (char*)st + align(sizeof(OpusMSDecoder));
    switch (request)
    {
-       default:
+       case OPUS_GET_BANDWIDTH_REQUEST:
+       case OPUS_GET_FINAL_RANGE_REQUEST:
        {
           int s;
-          /* This only works for int32* params, but that's all we have right now */
           opus_uint32 *value = va_arg(ap, opus_uint32*);
           for (s=0;s<st->layout.nb_streams;s++)
           {
-             OpusDecoder *enc;
+             OpusDecoder *dec;
 
-             enc = (OpusDecoder*)ptr;
+             dec = (OpusDecoder*)ptr;
              if (s < st->layout.nb_coupled_streams)
                 ptr += align(coupled_size);
              else
                 ptr += align(mono_size);
-             ret = opus_decoder_ctl(enc, request, value);
+             ret = opus_decoder_ctl(dec, request, value);
              if (ret < 0)
                 break;
           }
        }
        break;
+       case OPUS_RESET_STATE:
+       {
+          int s;
+          for (s=0;s<st->layout.nb_streams;s++)
+          {
+             OpusDecoder *dec;
+
+             dec = (OpusDecoder*)ptr;
+             if (s < st->layout.nb_coupled_streams)
+                ptr += align(coupled_size);
+             else
+                ptr += align(mono_size);
+             ret = opus_decoder_ctl(dec, OPUS_RESET_STATE);
+             if (ret < 0)
+                break;
+          }
+       }
+       break;
+       case OPUS_MULTISTREAM_GET_DECODER_STATE_REQUEST:
+       {
+          int s;
+          opus_int32 stream_id;
+          OpusDecoder **value;
+          stream_id = va_arg(ap, opus_int32);
+          if (stream_id<0 || stream_id >= st->layout.nb_streams)
+             ret = OPUS_BAD_ARG;
+          value = va_arg(ap, OpusDecoder**);
+          for (s=0;s<stream_id;s++)
+          {
+             if (s < st->layout.nb_coupled_streams)
+                ptr += align(coupled_size);
+             else
+                ptr += align(mono_size);
+          }
+          *value = (OpusDecoder*)ptr;
+       }
+          break;
+       default:
+          ret = OPUS_UNIMPLEMENTED;
+       break;
    }
 
    va_end(ap);