1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/media/libopus/src/opus_multistream_decoder.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,537 @@ 1.4 +/* Copyright (c) 2011 Xiph.Org Foundation 1.5 + Written by Jean-Marc Valin */ 1.6 +/* 1.7 + Redistribution and use in source and binary forms, with or without 1.8 + modification, are permitted provided that the following conditions 1.9 + are met: 1.10 + 1.11 + - Redistributions of source code must retain the above copyright 1.12 + notice, this list of conditions and the following disclaimer. 1.13 + 1.14 + - Redistributions in binary form must reproduce the above copyright 1.15 + notice, this list of conditions and the following disclaimer in the 1.16 + documentation and/or other materials provided with the distribution. 1.17 + 1.18 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1.19 + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1.20 + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1.21 + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 1.22 + OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 1.23 + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 1.24 + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 1.25 + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 1.26 + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 1.27 + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 1.28 + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.29 +*/ 1.30 + 1.31 +#ifdef HAVE_CONFIG_H 1.32 +#include "config.h" 1.33 +#endif 1.34 + 1.35 +#include "opus_multistream.h" 1.36 +#include "opus.h" 1.37 +#include "opus_private.h" 1.38 +#include "stack_alloc.h" 1.39 +#include <stdarg.h> 1.40 +#include "float_cast.h" 1.41 +#include "os_support.h" 1.42 + 1.43 +struct OpusMSDecoder { 1.44 + ChannelLayout layout; 1.45 + /* Decoder states go here */ 1.46 +}; 1.47 + 1.48 + 1.49 + 1.50 + 1.51 +/* DECODER */ 1.52 + 1.53 +opus_int32 opus_multistream_decoder_get_size(int nb_streams, int nb_coupled_streams) 1.54 +{ 1.55 + int coupled_size; 1.56 + int mono_size; 1.57 + 1.58 + if(nb_streams<1||nb_coupled_streams>nb_streams||nb_coupled_streams<0)return 0; 1.59 + coupled_size = opus_decoder_get_size(2); 1.60 + mono_size = opus_decoder_get_size(1); 1.61 + return align(sizeof(OpusMSDecoder)) 1.62 + + nb_coupled_streams * align(coupled_size) 1.63 + + (nb_streams-nb_coupled_streams) * align(mono_size); 1.64 +} 1.65 + 1.66 +int opus_multistream_decoder_init( 1.67 + OpusMSDecoder *st, 1.68 + opus_int32 Fs, 1.69 + int channels, 1.70 + int streams, 1.71 + int coupled_streams, 1.72 + const unsigned char *mapping 1.73 +) 1.74 +{ 1.75 + int coupled_size; 1.76 + int mono_size; 1.77 + int i, ret; 1.78 + char *ptr; 1.79 + 1.80 + if ((channels>255) || (channels<1) || (coupled_streams>streams) || 1.81 + (coupled_streams+streams>255) || (streams<1) || (coupled_streams<0)) 1.82 + return OPUS_BAD_ARG; 1.83 + 1.84 + st->layout.nb_channels = channels; 1.85 + st->layout.nb_streams = streams; 1.86 + st->layout.nb_coupled_streams = coupled_streams; 1.87 + 1.88 + for (i=0;i<st->layout.nb_channels;i++) 1.89 + st->layout.mapping[i] = mapping[i]; 1.90 + if (!validate_layout(&st->layout)) 1.91 + return OPUS_BAD_ARG; 1.92 + 1.93 + ptr = (char*)st + align(sizeof(OpusMSDecoder)); 1.94 + coupled_size = opus_decoder_get_size(2); 1.95 + mono_size = opus_decoder_get_size(1); 1.96 + 1.97 + for (i=0;i<st->layout.nb_coupled_streams;i++) 1.98 + { 1.99 + ret=opus_decoder_init((OpusDecoder*)ptr, Fs, 2); 1.100 + if(ret!=OPUS_OK)return ret; 1.101 + ptr += align(coupled_size); 1.102 + } 1.103 + for (;i<st->layout.nb_streams;i++) 1.104 + { 1.105 + ret=opus_decoder_init((OpusDecoder*)ptr, Fs, 1); 1.106 + if(ret!=OPUS_OK)return ret; 1.107 + ptr += align(mono_size); 1.108 + } 1.109 + return OPUS_OK; 1.110 +} 1.111 + 1.112 + 1.113 +OpusMSDecoder *opus_multistream_decoder_create( 1.114 + opus_int32 Fs, 1.115 + int channels, 1.116 + int streams, 1.117 + int coupled_streams, 1.118 + const unsigned char *mapping, 1.119 + int *error 1.120 +) 1.121 +{ 1.122 + int ret; 1.123 + OpusMSDecoder *st; 1.124 + if ((channels>255) || (channels<1) || (coupled_streams>streams) || 1.125 + (coupled_streams+streams>255) || (streams<1) || (coupled_streams<0)) 1.126 + { 1.127 + if (error) 1.128 + *error = OPUS_BAD_ARG; 1.129 + return NULL; 1.130 + } 1.131 + st = (OpusMSDecoder *)opus_alloc(opus_multistream_decoder_get_size(streams, coupled_streams)); 1.132 + if (st==NULL) 1.133 + { 1.134 + if (error) 1.135 + *error = OPUS_ALLOC_FAIL; 1.136 + return NULL; 1.137 + } 1.138 + ret = opus_multistream_decoder_init(st, Fs, channels, streams, coupled_streams, mapping); 1.139 + if (error) 1.140 + *error = ret; 1.141 + if (ret != OPUS_OK) 1.142 + { 1.143 + opus_free(st); 1.144 + st = NULL; 1.145 + } 1.146 + return st; 1.147 +} 1.148 + 1.149 +typedef void (*opus_copy_channel_out_func)( 1.150 + void *dst, 1.151 + int dst_stride, 1.152 + int dst_channel, 1.153 + const opus_val16 *src, 1.154 + int src_stride, 1.155 + int frame_size 1.156 +); 1.157 + 1.158 +static int opus_multistream_packet_validate(const unsigned char *data, 1.159 + opus_int32 len, int nb_streams, opus_int32 Fs) 1.160 +{ 1.161 + int s; 1.162 + int count; 1.163 + unsigned char toc; 1.164 + opus_int16 size[48]; 1.165 + int samples=0; 1.166 + opus_int32 packet_offset; 1.167 + 1.168 + for (s=0;s<nb_streams;s++) 1.169 + { 1.170 + int tmp_samples; 1.171 + if (len<=0) 1.172 + return OPUS_INVALID_PACKET; 1.173 + count = opus_packet_parse_impl(data, len, s!=nb_streams-1, &toc, NULL, 1.174 + size, NULL, &packet_offset); 1.175 + if (count<0) 1.176 + return count; 1.177 + tmp_samples = opus_packet_get_nb_samples(data, packet_offset, Fs); 1.178 + if (s!=0 && samples != tmp_samples) 1.179 + return OPUS_INVALID_PACKET; 1.180 + samples = tmp_samples; 1.181 + data += packet_offset; 1.182 + len -= packet_offset; 1.183 + } 1.184 + return samples; 1.185 +} 1.186 + 1.187 +static int opus_multistream_decode_native( 1.188 + OpusMSDecoder *st, 1.189 + const unsigned char *data, 1.190 + opus_int32 len, 1.191 + void *pcm, 1.192 + opus_copy_channel_out_func copy_channel_out, 1.193 + int frame_size, 1.194 + int decode_fec, 1.195 + int soft_clip 1.196 +) 1.197 +{ 1.198 + opus_int32 Fs; 1.199 + int coupled_size; 1.200 + int mono_size; 1.201 + int s, c; 1.202 + char *ptr; 1.203 + int do_plc=0; 1.204 + VARDECL(opus_val16, buf); 1.205 + ALLOC_STACK; 1.206 + 1.207 + /* Limit frame_size to avoid excessive stack allocations. */ 1.208 + opus_multistream_decoder_ctl(st, OPUS_GET_SAMPLE_RATE(&Fs)); 1.209 + frame_size = IMIN(frame_size, Fs/25*3); 1.210 + ALLOC(buf, 2*frame_size, opus_val16); 1.211 + ptr = (char*)st + align(sizeof(OpusMSDecoder)); 1.212 + coupled_size = opus_decoder_get_size(2); 1.213 + mono_size = opus_decoder_get_size(1); 1.214 + 1.215 + if (len==0) 1.216 + do_plc = 1; 1.217 + if (len < 0) 1.218 + { 1.219 + RESTORE_STACK; 1.220 + return OPUS_BAD_ARG; 1.221 + } 1.222 + if (!do_plc && len < 2*st->layout.nb_streams-1) 1.223 + { 1.224 + RESTORE_STACK; 1.225 + return OPUS_INVALID_PACKET; 1.226 + } 1.227 + if (!do_plc) 1.228 + { 1.229 + int ret = opus_multistream_packet_validate(data, len, st->layout.nb_streams, Fs); 1.230 + if (ret < 0) 1.231 + { 1.232 + RESTORE_STACK; 1.233 + return ret; 1.234 + } else if (ret > frame_size) 1.235 + { 1.236 + RESTORE_STACK; 1.237 + return OPUS_BUFFER_TOO_SMALL; 1.238 + } 1.239 + } 1.240 + for (s=0;s<st->layout.nb_streams;s++) 1.241 + { 1.242 + OpusDecoder *dec; 1.243 + int packet_offset, ret; 1.244 + 1.245 + dec = (OpusDecoder*)ptr; 1.246 + ptr += (s < st->layout.nb_coupled_streams) ? align(coupled_size) : align(mono_size); 1.247 + 1.248 + if (!do_plc && len<=0) 1.249 + { 1.250 + RESTORE_STACK; 1.251 + return OPUS_INTERNAL_ERROR; 1.252 + } 1.253 + packet_offset = 0; 1.254 + ret = opus_decode_native(dec, data, len, buf, frame_size, decode_fec, s!=st->layout.nb_streams-1, &packet_offset, soft_clip); 1.255 + data += packet_offset; 1.256 + len -= packet_offset; 1.257 + if (ret <= 0) 1.258 + { 1.259 + RESTORE_STACK; 1.260 + return ret; 1.261 + } 1.262 + frame_size = ret; 1.263 + if (s < st->layout.nb_coupled_streams) 1.264 + { 1.265 + int chan, prev; 1.266 + prev = -1; 1.267 + /* Copy "left" audio to the channel(s) where it belongs */ 1.268 + while ( (chan = get_left_channel(&st->layout, s, prev)) != -1) 1.269 + { 1.270 + (*copy_channel_out)(pcm, st->layout.nb_channels, chan, 1.271 + buf, 2, frame_size); 1.272 + prev = chan; 1.273 + } 1.274 + prev = -1; 1.275 + /* Copy "right" audio to the channel(s) where it belongs */ 1.276 + while ( (chan = get_right_channel(&st->layout, s, prev)) != -1) 1.277 + { 1.278 + (*copy_channel_out)(pcm, st->layout.nb_channels, chan, 1.279 + buf+1, 2, frame_size); 1.280 + prev = chan; 1.281 + } 1.282 + } else { 1.283 + int chan, prev; 1.284 + prev = -1; 1.285 + /* Copy audio to the channel(s) where it belongs */ 1.286 + while ( (chan = get_mono_channel(&st->layout, s, prev)) != -1) 1.287 + { 1.288 + (*copy_channel_out)(pcm, st->layout.nb_channels, chan, 1.289 + buf, 1, frame_size); 1.290 + prev = chan; 1.291 + } 1.292 + } 1.293 + } 1.294 + /* Handle muted channels */ 1.295 + for (c=0;c<st->layout.nb_channels;c++) 1.296 + { 1.297 + if (st->layout.mapping[c] == 255) 1.298 + { 1.299 + (*copy_channel_out)(pcm, st->layout.nb_channels, c, 1.300 + NULL, 0, frame_size); 1.301 + } 1.302 + } 1.303 + RESTORE_STACK; 1.304 + return frame_size; 1.305 +} 1.306 + 1.307 +#if !defined(DISABLE_FLOAT_API) 1.308 +static void opus_copy_channel_out_float( 1.309 + void *dst, 1.310 + int dst_stride, 1.311 + int dst_channel, 1.312 + const opus_val16 *src, 1.313 + int src_stride, 1.314 + int frame_size 1.315 +) 1.316 +{ 1.317 + float *float_dst; 1.318 + opus_int32 i; 1.319 + float_dst = (float*)dst; 1.320 + if (src != NULL) 1.321 + { 1.322 + for (i=0;i<frame_size;i++) 1.323 +#if defined(FIXED_POINT) 1.324 + float_dst[i*dst_stride+dst_channel] = (1/32768.f)*src[i*src_stride]; 1.325 +#else 1.326 + float_dst[i*dst_stride+dst_channel] = src[i*src_stride]; 1.327 +#endif 1.328 + } 1.329 + else 1.330 + { 1.331 + for (i=0;i<frame_size;i++) 1.332 + float_dst[i*dst_stride+dst_channel] = 0; 1.333 + } 1.334 +} 1.335 +#endif 1.336 + 1.337 +static void opus_copy_channel_out_short( 1.338 + void *dst, 1.339 + int dst_stride, 1.340 + int dst_channel, 1.341 + const opus_val16 *src, 1.342 + int src_stride, 1.343 + int frame_size 1.344 +) 1.345 +{ 1.346 + opus_int16 *short_dst; 1.347 + opus_int32 i; 1.348 + short_dst = (opus_int16*)dst; 1.349 + if (src != NULL) 1.350 + { 1.351 + for (i=0;i<frame_size;i++) 1.352 +#if defined(FIXED_POINT) 1.353 + short_dst[i*dst_stride+dst_channel] = src[i*src_stride]; 1.354 +#else 1.355 + short_dst[i*dst_stride+dst_channel] = FLOAT2INT16(src[i*src_stride]); 1.356 +#endif 1.357 + } 1.358 + else 1.359 + { 1.360 + for (i=0;i<frame_size;i++) 1.361 + short_dst[i*dst_stride+dst_channel] = 0; 1.362 + } 1.363 +} 1.364 + 1.365 + 1.366 + 1.367 +#ifdef FIXED_POINT 1.368 +int opus_multistream_decode( 1.369 + OpusMSDecoder *st, 1.370 + const unsigned char *data, 1.371 + opus_int32 len, 1.372 + opus_int16 *pcm, 1.373 + int frame_size, 1.374 + int decode_fec 1.375 +) 1.376 +{ 1.377 + return opus_multistream_decode_native(st, data, len, 1.378 + pcm, opus_copy_channel_out_short, frame_size, decode_fec, 0); 1.379 +} 1.380 + 1.381 +#ifndef DISABLE_FLOAT_API 1.382 +int opus_multistream_decode_float(OpusMSDecoder *st, const unsigned char *data, 1.383 + opus_int32 len, float *pcm, int frame_size, int decode_fec) 1.384 +{ 1.385 + return opus_multistream_decode_native(st, data, len, 1.386 + pcm, opus_copy_channel_out_float, frame_size, decode_fec, 0); 1.387 +} 1.388 +#endif 1.389 + 1.390 +#else 1.391 + 1.392 +int opus_multistream_decode(OpusMSDecoder *st, const unsigned char *data, 1.393 + opus_int32 len, opus_int16 *pcm, int frame_size, int decode_fec) 1.394 +{ 1.395 + return opus_multistream_decode_native(st, data, len, 1.396 + pcm, opus_copy_channel_out_short, frame_size, decode_fec, 1); 1.397 +} 1.398 + 1.399 +int opus_multistream_decode_float( 1.400 + OpusMSDecoder *st, 1.401 + const unsigned char *data, 1.402 + opus_int32 len, 1.403 + float *pcm, 1.404 + int frame_size, 1.405 + int decode_fec 1.406 +) 1.407 +{ 1.408 + return opus_multistream_decode_native(st, data, len, 1.409 + pcm, opus_copy_channel_out_float, frame_size, decode_fec, 0); 1.410 +} 1.411 +#endif 1.412 + 1.413 +int opus_multistream_decoder_ctl(OpusMSDecoder *st, int request, ...) 1.414 +{ 1.415 + va_list ap; 1.416 + int coupled_size, mono_size; 1.417 + char *ptr; 1.418 + int ret = OPUS_OK; 1.419 + 1.420 + va_start(ap, request); 1.421 + 1.422 + coupled_size = opus_decoder_get_size(2); 1.423 + mono_size = opus_decoder_get_size(1); 1.424 + ptr = (char*)st + align(sizeof(OpusMSDecoder)); 1.425 + switch (request) 1.426 + { 1.427 + case OPUS_GET_BANDWIDTH_REQUEST: 1.428 + case OPUS_GET_SAMPLE_RATE_REQUEST: 1.429 + case OPUS_GET_GAIN_REQUEST: 1.430 + case OPUS_GET_LAST_PACKET_DURATION_REQUEST: 1.431 + { 1.432 + OpusDecoder *dec; 1.433 + /* For int32* GET params, just query the first stream */ 1.434 + opus_int32 *value = va_arg(ap, opus_int32*); 1.435 + dec = (OpusDecoder*)ptr; 1.436 + ret = opus_decoder_ctl(dec, request, value); 1.437 + } 1.438 + break; 1.439 + case OPUS_GET_FINAL_RANGE_REQUEST: 1.440 + { 1.441 + int s; 1.442 + opus_uint32 *value = va_arg(ap, opus_uint32*); 1.443 + opus_uint32 tmp; 1.444 + if (!value) 1.445 + { 1.446 + goto bad_arg; 1.447 + } 1.448 + *value = 0; 1.449 + for (s=0;s<st->layout.nb_streams;s++) 1.450 + { 1.451 + OpusDecoder *dec; 1.452 + dec = (OpusDecoder*)ptr; 1.453 + if (s < st->layout.nb_coupled_streams) 1.454 + ptr += align(coupled_size); 1.455 + else 1.456 + ptr += align(mono_size); 1.457 + ret = opus_decoder_ctl(dec, request, &tmp); 1.458 + if (ret != OPUS_OK) break; 1.459 + *value ^= tmp; 1.460 + } 1.461 + } 1.462 + break; 1.463 + case OPUS_RESET_STATE: 1.464 + { 1.465 + int s; 1.466 + for (s=0;s<st->layout.nb_streams;s++) 1.467 + { 1.468 + OpusDecoder *dec; 1.469 + 1.470 + dec = (OpusDecoder*)ptr; 1.471 + if (s < st->layout.nb_coupled_streams) 1.472 + ptr += align(coupled_size); 1.473 + else 1.474 + ptr += align(mono_size); 1.475 + ret = opus_decoder_ctl(dec, OPUS_RESET_STATE); 1.476 + if (ret != OPUS_OK) 1.477 + break; 1.478 + } 1.479 + } 1.480 + break; 1.481 + case OPUS_MULTISTREAM_GET_DECODER_STATE_REQUEST: 1.482 + { 1.483 + int s; 1.484 + opus_int32 stream_id; 1.485 + OpusDecoder **value; 1.486 + stream_id = va_arg(ap, opus_int32); 1.487 + if (stream_id<0 || stream_id >= st->layout.nb_streams) 1.488 + ret = OPUS_BAD_ARG; 1.489 + value = va_arg(ap, OpusDecoder**); 1.490 + if (!value) 1.491 + { 1.492 + goto bad_arg; 1.493 + } 1.494 + for (s=0;s<stream_id;s++) 1.495 + { 1.496 + if (s < st->layout.nb_coupled_streams) 1.497 + ptr += align(coupled_size); 1.498 + else 1.499 + ptr += align(mono_size); 1.500 + } 1.501 + *value = (OpusDecoder*)ptr; 1.502 + } 1.503 + break; 1.504 + case OPUS_SET_GAIN_REQUEST: 1.505 + { 1.506 + int s; 1.507 + /* This works for int32 params */ 1.508 + opus_int32 value = va_arg(ap, opus_int32); 1.509 + for (s=0;s<st->layout.nb_streams;s++) 1.510 + { 1.511 + OpusDecoder *dec; 1.512 + 1.513 + dec = (OpusDecoder*)ptr; 1.514 + if (s < st->layout.nb_coupled_streams) 1.515 + ptr += align(coupled_size); 1.516 + else 1.517 + ptr += align(mono_size); 1.518 + ret = opus_decoder_ctl(dec, request, value); 1.519 + if (ret != OPUS_OK) 1.520 + break; 1.521 + } 1.522 + } 1.523 + break; 1.524 + default: 1.525 + ret = OPUS_UNIMPLEMENTED; 1.526 + break; 1.527 + } 1.528 + 1.529 + va_end(ap); 1.530 + return ret; 1.531 +bad_arg: 1.532 + va_end(ap); 1.533 + return OPUS_BAD_ARG; 1.534 +} 1.535 + 1.536 + 1.537 +void opus_multistream_decoder_destroy(OpusMSDecoder *st) 1.538 +{ 1.539 + opus_free(st); 1.540 +}