Home | History | Annotate | Download | only in src
      1 /* Copyright (c) 2011 Xiph.Org Foundation
      2    Written by Jean-Marc Valin */
      3 /*
      4    Redistribution and use in source and binary forms, with or without
      5    modification, are permitted provided that the following conditions
      6    are met:
      7 
      8    - Redistributions of source code must retain the above copyright
      9    notice, this list of conditions and the following disclaimer.
     10 
     11    - Redistributions in binary form must reproduce the above copyright
     12    notice, this list of conditions and the following disclaimer in the
     13    documentation and/or other materials provided with the distribution.
     14 
     15    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     16    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     17    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     18    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
     19    OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     20    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     21    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     22    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
     23    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
     24    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     25    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26 */
     27 
     28 #ifdef HAVE_CONFIG_H
     29 #include "config.h"
     30 #endif
     31 
     32 #include "opus_multistream.h"
     33 #include "opus.h"
     34 #include "opus_private.h"
     35 #include "stack_alloc.h"
     36 #include <stdarg.h>
     37 #include "float_cast.h"
     38 #include "os_support.h"
     39 
     40 struct OpusMSDecoder {
     41    ChannelLayout layout;
     42    /* Decoder states go here */
     43 };
     44 
     45 
     46 
     47 
     48 /* DECODER */
     49 
     50 opus_int32 opus_multistream_decoder_get_size(int nb_streams, int nb_coupled_streams)
     51 {
     52    int coupled_size;
     53    int mono_size;
     54 
     55    if(nb_streams<1||nb_coupled_streams>nb_streams||nb_coupled_streams<0)return 0;
     56    coupled_size = opus_decoder_get_size(2);
     57    mono_size = opus_decoder_get_size(1);
     58    return align(sizeof(OpusMSDecoder))
     59          + nb_coupled_streams * align(coupled_size)
     60          + (nb_streams-nb_coupled_streams) * align(mono_size);
     61 }
     62 
     63 int opus_multistream_decoder_init(
     64       OpusMSDecoder *st,
     65       opus_int32 Fs,
     66       int channels,
     67       int streams,
     68       int coupled_streams,
     69       const unsigned char *mapping
     70 )
     71 {
     72    int coupled_size;
     73    int mono_size;
     74    int i, ret;
     75    char *ptr;
     76 
     77    if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
     78        (coupled_streams+streams>255) || (streams<1) || (coupled_streams<0))
     79       return OPUS_BAD_ARG;
     80 
     81    st->layout.nb_channels = channels;
     82    st->layout.nb_streams = streams;
     83    st->layout.nb_coupled_streams = coupled_streams;
     84 
     85    for (i=0;i<st->layout.nb_channels;i++)
     86       st->layout.mapping[i] = mapping[i];
     87    if (!validate_layout(&st->layout))
     88       return OPUS_BAD_ARG;
     89 
     90    ptr = (char*)st + align(sizeof(OpusMSDecoder));
     91    coupled_size = opus_decoder_get_size(2);
     92    mono_size = opus_decoder_get_size(1);
     93 
     94    for (i=0;i<st->layout.nb_coupled_streams;i++)
     95    {
     96       ret=opus_decoder_init((OpusDecoder*)ptr, Fs, 2);
     97       if(ret!=OPUS_OK)return ret;
     98       ptr += align(coupled_size);
     99    }
    100    for (;i<st->layout.nb_streams;i++)
    101    {
    102       ret=opus_decoder_init((OpusDecoder*)ptr, Fs, 1);
    103       if(ret!=OPUS_OK)return ret;
    104       ptr += align(mono_size);
    105    }
    106    return OPUS_OK;
    107 }
    108 
    109 
    110 OpusMSDecoder *opus_multistream_decoder_create(
    111       opus_int32 Fs,
    112       int channels,
    113       int streams,
    114       int coupled_streams,
    115       const unsigned char *mapping,
    116       int *error
    117 )
    118 {
    119    int ret;
    120    OpusMSDecoder *st;
    121    if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
    122        (coupled_streams+streams>255) || (streams<1) || (coupled_streams<0))
    123    {
    124       if (error)
    125          *error = OPUS_BAD_ARG;
    126       return NULL;
    127    }
    128    st = (OpusMSDecoder *)opus_alloc(opus_multistream_decoder_get_size(streams, coupled_streams));
    129    if (st==NULL)
    130    {
    131       if (error)
    132          *error = OPUS_ALLOC_FAIL;
    133       return NULL;
    134    }
    135    ret = opus_multistream_decoder_init(st, Fs, channels, streams, coupled_streams, mapping);
    136    if (error)
    137       *error = ret;
    138    if (ret != OPUS_OK)
    139    {
    140       opus_free(st);
    141       st = NULL;
    142    }
    143    return st;
    144 }
    145 
    146 typedef void (*opus_copy_channel_out_func)(
    147   void *dst,
    148   int dst_stride,
    149   int dst_channel,
    150   const opus_val16 *src,
    151   int src_stride,
    152   int frame_size
    153 );
    154 
    155 static int opus_multistream_decode_native(
    156       OpusMSDecoder *st,
    157       const unsigned char *data,
    158       opus_int32 len,
    159       void *pcm,
    160       opus_copy_channel_out_func copy_channel_out,
    161       int frame_size,
    162       int decode_fec,
    163       int soft_clip
    164 )
    165 {
    166    opus_int32 Fs;
    167    int coupled_size;
    168    int mono_size;
    169    int s, c;
    170    char *ptr;
    171    int do_plc=0;
    172    VARDECL(opus_val16, buf);
    173    ALLOC_STACK;
    174 
    175    /* Limit frame_size to avoid excessive stack allocations. */
    176    opus_multistream_decoder_ctl(st, OPUS_GET_SAMPLE_RATE(&Fs));
    177    frame_size = IMIN(frame_size, Fs/25*3);
    178    ALLOC(buf, 2*frame_size, opus_val16);
    179    ptr = (char*)st + align(sizeof(OpusMSDecoder));
    180    coupled_size = opus_decoder_get_size(2);
    181    mono_size = opus_decoder_get_size(1);
    182 
    183    if (len==0)
    184       do_plc = 1;
    185    if (len < 0)
    186       return OPUS_BAD_ARG;
    187    if (!do_plc && len < 2*st->layout.nb_streams-1)
    188       return OPUS_INVALID_PACKET;
    189    for (s=0;s<st->layout.nb_streams;s++)
    190    {
    191       OpusDecoder *dec;
    192       int packet_offset, ret;
    193 
    194       dec = (OpusDecoder*)ptr;
    195       ptr += (s < st->layout.nb_coupled_streams) ? align(coupled_size) : align(mono_size);
    196 
    197       if (!do_plc && len<=0)
    198       {
    199          RESTORE_STACK;
    200          return OPUS_INVALID_PACKET;
    201       }
    202       packet_offset = 0;
    203       ret = opus_decode_native(dec, data, len, buf, frame_size, decode_fec, s!=st->layout.nb_streams-1, &packet_offset, soft_clip);
    204       data += packet_offset;
    205       len -= packet_offset;
    206       if (ret > frame_size)
    207       {
    208          RESTORE_STACK;
    209          return OPUS_BUFFER_TOO_SMALL;
    210       }
    211       if (s>0 && ret != frame_size)
    212       {
    213          RESTORE_STACK;
    214          return OPUS_INVALID_PACKET;
    215       }
    216       if (ret <= 0)
    217       {
    218          RESTORE_STACK;
    219          return ret;
    220       }
    221       frame_size = ret;
    222       if (s < st->layout.nb_coupled_streams)
    223       {
    224          int chan, prev;
    225          prev = -1;
    226          /* Copy "left" audio to the channel(s) where it belongs */
    227          while ( (chan = get_left_channel(&st->layout, s, prev)) != -1)
    228          {
    229             (*copy_channel_out)(pcm, st->layout.nb_channels, chan,
    230                buf, 2, frame_size);
    231             prev = chan;
    232          }
    233          prev = -1;
    234          /* Copy "right" audio to the channel(s) where it belongs */
    235          while ( (chan = get_right_channel(&st->layout, s, prev)) != -1)
    236          {
    237             (*copy_channel_out)(pcm, st->layout.nb_channels, chan,
    238                buf+1, 2, frame_size);
    239             prev = chan;
    240          }
    241       } else {
    242          int chan, prev;
    243          prev = -1;
    244          /* Copy audio to the channel(s) where it belongs */
    245          while ( (chan = get_mono_channel(&st->layout, s, prev)) != -1)
    246          {
    247             (*copy_channel_out)(pcm, st->layout.nb_channels, chan,
    248                buf, 1, frame_size);
    249             prev = chan;
    250          }
    251       }
    252    }
    253    /* Handle muted channels */
    254    for (c=0;c<st->layout.nb_channels;c++)
    255    {
    256       if (st->layout.mapping[c] == 255)
    257       {
    258          (*copy_channel_out)(pcm, st->layout.nb_channels, c,
    259             NULL, 0, frame_size);
    260       }
    261    }
    262    RESTORE_STACK;
    263    return frame_size;
    264 }
    265 
    266 #if !defined(DISABLE_FLOAT_API)
    267 static void opus_copy_channel_out_float(
    268   void *dst,
    269   int dst_stride,
    270   int dst_channel,
    271   const opus_val16 *src,
    272   int src_stride,
    273   int frame_size
    274 )
    275 {
    276    float *float_dst;
    277    opus_int32 i;
    278    float_dst = (float*)dst;
    279    if (src != NULL)
    280    {
    281       for (i=0;i<frame_size;i++)
    282 #if defined(FIXED_POINT)
    283          float_dst[i*dst_stride+dst_channel] = (1/32768.f)*src[i*src_stride];
    284 #else
    285          float_dst[i*dst_stride+dst_channel] = src[i*src_stride];
    286 #endif
    287    }
    288    else
    289    {
    290       for (i=0;i<frame_size;i++)
    291          float_dst[i*dst_stride+dst_channel] = 0;
    292    }
    293 }
    294 #endif
    295 
    296 static void opus_copy_channel_out_short(
    297   void *dst,
    298   int dst_stride,
    299   int dst_channel,
    300   const opus_val16 *src,
    301   int src_stride,
    302   int frame_size
    303 )
    304 {
    305    opus_int16 *short_dst;
    306    opus_int32 i;
    307    short_dst = (opus_int16*)dst;
    308    if (src != NULL)
    309    {
    310       for (i=0;i<frame_size;i++)
    311 #if defined(FIXED_POINT)
    312          short_dst[i*dst_stride+dst_channel] = src[i*src_stride];
    313 #else
    314          short_dst[i*dst_stride+dst_channel] = FLOAT2INT16(src[i*src_stride]);
    315 #endif
    316    }
    317    else
    318    {
    319       for (i=0;i<frame_size;i++)
    320          short_dst[i*dst_stride+dst_channel] = 0;
    321    }
    322 }
    323 
    324 
    325 
    326 #ifdef FIXED_POINT
    327 int opus_multistream_decode(
    328       OpusMSDecoder *st,
    329       const unsigned char *data,
    330       opus_int32 len,
    331       opus_int16 *pcm,
    332       int frame_size,
    333       int decode_fec
    334 )
    335 {
    336    return opus_multistream_decode_native(st, data, len,
    337        pcm, opus_copy_channel_out_short, frame_size, decode_fec, 0);
    338 }
    339 
    340 #ifndef DISABLE_FLOAT_API
    341 int opus_multistream_decode_float(OpusMSDecoder *st, const unsigned char *data,
    342       opus_int32 len, float *pcm, int frame_size, int decode_fec)
    343 {
    344    return opus_multistream_decode_native(st, data, len,
    345        pcm, opus_copy_channel_out_float, frame_size, decode_fec, 0);
    346 }
    347 #endif
    348 
    349 #else
    350 
    351 int opus_multistream_decode(OpusMSDecoder *st, const unsigned char *data,
    352       opus_int32 len, opus_int16 *pcm, int frame_size, int decode_fec)
    353 {
    354    return opus_multistream_decode_native(st, data, len,
    355        pcm, opus_copy_channel_out_short, frame_size, decode_fec, 1);
    356 }
    357 
    358 int opus_multistream_decode_float(
    359       OpusMSDecoder *st,
    360       const unsigned char *data,
    361       opus_int32 len,
    362       float *pcm,
    363       int frame_size,
    364       int decode_fec
    365 )
    366 {
    367    return opus_multistream_decode_native(st, data, len,
    368        pcm, opus_copy_channel_out_float, frame_size, decode_fec, 0);
    369 }
    370 #endif
    371 
    372 int opus_multistream_decoder_ctl(OpusMSDecoder *st, int request, ...)
    373 {
    374    va_list ap;
    375    int coupled_size, mono_size;
    376    char *ptr;
    377    int ret = OPUS_OK;
    378 
    379    va_start(ap, request);
    380 
    381    coupled_size = opus_decoder_get_size(2);
    382    mono_size = opus_decoder_get_size(1);
    383    ptr = (char*)st + align(sizeof(OpusMSDecoder));
    384    switch (request)
    385    {
    386        case OPUS_GET_BANDWIDTH_REQUEST:
    387        case OPUS_GET_SAMPLE_RATE_REQUEST:
    388        case OPUS_GET_GAIN_REQUEST:
    389        case OPUS_GET_LAST_PACKET_DURATION_REQUEST:
    390        {
    391           OpusDecoder *dec;
    392           /* For int32* GET params, just query the first stream */
    393           opus_int32 *value = va_arg(ap, opus_int32*);
    394           dec = (OpusDecoder*)ptr;
    395           ret = opus_decoder_ctl(dec, request, value);
    396        }
    397        break;
    398        case OPUS_GET_FINAL_RANGE_REQUEST:
    399        {
    400           int s;
    401           opus_uint32 *value = va_arg(ap, opus_uint32*);
    402           opus_uint32 tmp;
    403           if (!value)
    404           {
    405              goto bad_arg;
    406           }
    407           *value = 0;
    408           for (s=0;s<st->layout.nb_streams;s++)
    409           {
    410              OpusDecoder *dec;
    411              dec = (OpusDecoder*)ptr;
    412              if (s < st->layout.nb_coupled_streams)
    413                 ptr += align(coupled_size);
    414              else
    415                 ptr += align(mono_size);
    416              ret = opus_decoder_ctl(dec, request, &tmp);
    417              if (ret != OPUS_OK) break;
    418              *value ^= tmp;
    419           }
    420        }
    421        break;
    422        case OPUS_RESET_STATE:
    423        {
    424           int s;
    425           for (s=0;s<st->layout.nb_streams;s++)
    426           {
    427              OpusDecoder *dec;
    428 
    429              dec = (OpusDecoder*)ptr;
    430              if (s < st->layout.nb_coupled_streams)
    431                 ptr += align(coupled_size);
    432              else
    433                 ptr += align(mono_size);
    434              ret = opus_decoder_ctl(dec, OPUS_RESET_STATE);
    435              if (ret != OPUS_OK)
    436                 break;
    437           }
    438        }
    439        break;
    440        case OPUS_MULTISTREAM_GET_DECODER_STATE_REQUEST:
    441        {
    442           int s;
    443           opus_int32 stream_id;
    444           OpusDecoder **value;
    445           stream_id = va_arg(ap, opus_int32);
    446           if (stream_id<0 || stream_id >= st->layout.nb_streams)
    447              ret = OPUS_BAD_ARG;
    448           value = va_arg(ap, OpusDecoder**);
    449           if (!value)
    450           {
    451              goto bad_arg;
    452           }
    453           for (s=0;s<stream_id;s++)
    454           {
    455              if (s < st->layout.nb_coupled_streams)
    456                 ptr += align(coupled_size);
    457              else
    458                 ptr += align(mono_size);
    459           }
    460           *value = (OpusDecoder*)ptr;
    461        }
    462        break;
    463        case OPUS_SET_GAIN_REQUEST:
    464        {
    465           int s;
    466           /* This works for int32 params */
    467           opus_int32 value = va_arg(ap, opus_int32);
    468           for (s=0;s<st->layout.nb_streams;s++)
    469           {
    470              OpusDecoder *dec;
    471 
    472              dec = (OpusDecoder*)ptr;
    473              if (s < st->layout.nb_coupled_streams)
    474                 ptr += align(coupled_size);
    475              else
    476                 ptr += align(mono_size);
    477              ret = opus_decoder_ctl(dec, request, value);
    478              if (ret != OPUS_OK)
    479                 break;
    480           }
    481        }
    482        break;
    483        default:
    484           ret = OPUS_UNIMPLEMENTED;
    485        break;
    486    }
    487 
    488    va_end(ap);
    489    return ret;
    490 bad_arg:
    491    va_end(ap);
    492    return OPUS_BAD_ARG;
    493 }
    494 
    495 
    496 void opus_multistream_decoder_destroy(OpusMSDecoder *st)
    497 {
    498     opus_free(st);
    499 }
    500