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