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 /* DECODER */
41
42 #if defined(ENABLE_HARDENING) || defined(ENABLE_ASSERTIONS)
validate_ms_decoder(OpusMSDecoder * st)43 static void validate_ms_decoder(OpusMSDecoder *st)
44 {
45 validate_layout(&st->layout);
46 }
47 #define VALIDATE_MS_DECODER(st) validate_ms_decoder(st)
48 #else
49 #define VALIDATE_MS_DECODER(st)
50 #endif
51
52
opus_multistream_decoder_get_size(int nb_streams,int nb_coupled_streams)53 opus_int32 opus_multistream_decoder_get_size(int nb_streams, int nb_coupled_streams)
54 {
55 int coupled_size;
56 int mono_size;
57
58 if(nb_streams<1||nb_coupled_streams>nb_streams||nb_coupled_streams<0)return 0;
59 coupled_size = opus_decoder_get_size(2);
60 mono_size = opus_decoder_get_size(1);
61 return align(sizeof(OpusMSDecoder))
62 + nb_coupled_streams * align(coupled_size)
63 + (nb_streams-nb_coupled_streams) * align(mono_size);
64 }
65
opus_multistream_decoder_init(OpusMSDecoder * st,opus_int32 Fs,int channels,int streams,int coupled_streams,const unsigned char * mapping)66 int opus_multistream_decoder_init(
67 OpusMSDecoder *st,
68 opus_int32 Fs,
69 int channels,
70 int streams,
71 int coupled_streams,
72 const unsigned char *mapping
73 )
74 {
75 int coupled_size;
76 int mono_size;
77 int i, ret;
78 char *ptr;
79
80 if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
81 (streams<1) || (coupled_streams<0) || (streams>255-coupled_streams))
82 return OPUS_BAD_ARG;
83
84 st->layout.nb_channels = channels;
85 st->layout.nb_streams = streams;
86 st->layout.nb_coupled_streams = coupled_streams;
87
88 for (i=0;i<st->layout.nb_channels;i++)
89 st->layout.mapping[i] = mapping[i];
90 if (!validate_layout(&st->layout))
91 return OPUS_BAD_ARG;
92
93 ptr = (char*)st + align(sizeof(OpusMSDecoder));
94 coupled_size = opus_decoder_get_size(2);
95 mono_size = opus_decoder_get_size(1);
96
97 for (i=0;i<st->layout.nb_coupled_streams;i++)
98 {
99 ret=opus_decoder_init((OpusDecoder*)ptr, Fs, 2);
100 if(ret!=OPUS_OK)return ret;
101 ptr += align(coupled_size);
102 }
103 for (;i<st->layout.nb_streams;i++)
104 {
105 ret=opus_decoder_init((OpusDecoder*)ptr, Fs, 1);
106 if(ret!=OPUS_OK)return ret;
107 ptr += align(mono_size);
108 }
109 return OPUS_OK;
110 }
111
112
opus_multistream_decoder_create(opus_int32 Fs,int channels,int streams,int coupled_streams,const unsigned char * mapping,int * error)113 OpusMSDecoder *opus_multistream_decoder_create(
114 opus_int32 Fs,
115 int channels,
116 int streams,
117 int coupled_streams,
118 const unsigned char *mapping,
119 int *error
120 )
121 {
122 int ret;
123 OpusMSDecoder *st;
124 if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
125 (streams<1) || (coupled_streams<0) || (streams>255-coupled_streams))
126 {
127 if (error)
128 *error = OPUS_BAD_ARG;
129 return NULL;
130 }
131 st = (OpusMSDecoder *)opus_alloc(opus_multistream_decoder_get_size(streams, coupled_streams));
132 if (st==NULL)
133 {
134 if (error)
135 *error = OPUS_ALLOC_FAIL;
136 return NULL;
137 }
138 ret = opus_multistream_decoder_init(st, Fs, channels, streams, coupled_streams, mapping);
139 if (error)
140 *error = ret;
141 if (ret != OPUS_OK)
142 {
143 opus_free(st);
144 st = NULL;
145 }
146 return st;
147 }
148
opus_multistream_packet_validate(const unsigned char * data,opus_int32 len,int nb_streams,opus_int32 Fs)149 static int opus_multistream_packet_validate(const unsigned char *data,
150 opus_int32 len, int nb_streams, opus_int32 Fs)
151 {
152 int s;
153 int count;
154 unsigned char toc;
155 opus_int16 size[48];
156 int samples=0;
157 opus_int32 packet_offset;
158
159 for (s=0;s<nb_streams;s++)
160 {
161 int tmp_samples;
162 if (len<=0)
163 return OPUS_INVALID_PACKET;
164 count = opus_packet_parse_impl(data, len, s!=nb_streams-1, &toc, NULL,
165 size, NULL, &packet_offset);
166 if (count<0)
167 return count;
168 tmp_samples = opus_packet_get_nb_samples(data, packet_offset, Fs);
169 if (s!=0 && samples != tmp_samples)
170 return OPUS_INVALID_PACKET;
171 samples = tmp_samples;
172 data += packet_offset;
173 len -= packet_offset;
174 }
175 return samples;
176 }
177
opus_multistream_decode_native(OpusMSDecoder * st,const unsigned char * data,opus_int32 len,void * pcm,opus_copy_channel_out_func copy_channel_out,int frame_size,int decode_fec,int soft_clip,void * user_data)178 int opus_multistream_decode_native(
179 OpusMSDecoder *st,
180 const unsigned char *data,
181 opus_int32 len,
182 void *pcm,
183 opus_copy_channel_out_func copy_channel_out,
184 int frame_size,
185 int decode_fec,
186 int soft_clip,
187 void *user_data
188 )
189 {
190 opus_int32 Fs;
191 int coupled_size;
192 int mono_size;
193 int s, c;
194 char *ptr;
195 int do_plc=0;
196 VARDECL(opus_val16, buf);
197 ALLOC_STACK;
198
199 VALIDATE_MS_DECODER(st);
200 if (frame_size <= 0)
201 {
202 RESTORE_STACK;
203 return OPUS_BAD_ARG;
204 }
205 /* Limit frame_size to avoid excessive stack allocations. */
206 MUST_SUCCEED(opus_multistream_decoder_ctl(st, OPUS_GET_SAMPLE_RATE(&Fs)));
207 frame_size = IMIN(frame_size, Fs/25*3);
208 ALLOC(buf, 2*frame_size, opus_val16);
209 ptr = (char*)st + align(sizeof(OpusMSDecoder));
210 coupled_size = opus_decoder_get_size(2);
211 mono_size = opus_decoder_get_size(1);
212
213 if (len==0)
214 do_plc = 1;
215 if (len < 0)
216 {
217 RESTORE_STACK;
218 return OPUS_BAD_ARG;
219 }
220 if (!do_plc && len < 2*st->layout.nb_streams-1)
221 {
222 RESTORE_STACK;
223 return OPUS_INVALID_PACKET;
224 }
225 if (!do_plc)
226 {
227 int ret = opus_multistream_packet_validate(data, len, st->layout.nb_streams, Fs);
228 if (ret < 0)
229 {
230 RESTORE_STACK;
231 return ret;
232 } else if (ret > frame_size)
233 {
234 RESTORE_STACK;
235 return OPUS_BUFFER_TOO_SMALL;
236 }
237 }
238 for (s=0;s<st->layout.nb_streams;s++)
239 {
240 OpusDecoder *dec;
241 opus_int32 packet_offset;
242 int ret;
243
244 dec = (OpusDecoder*)ptr;
245 ptr += (s < st->layout.nb_coupled_streams) ? align(coupled_size) : align(mono_size);
246
247 if (!do_plc && len<=0)
248 {
249 RESTORE_STACK;
250 return OPUS_INTERNAL_ERROR;
251 }
252 packet_offset = 0;
253 ret = opus_decode_native(dec, data, len, buf, frame_size, decode_fec, s!=st->layout.nb_streams-1, &packet_offset, soft_clip);
254 if (!do_plc)
255 {
256 data += packet_offset;
257 len -= packet_offset;
258 }
259 if (ret <= 0)
260 {
261 RESTORE_STACK;
262 return ret;
263 }
264 frame_size = ret;
265 if (s < st->layout.nb_coupled_streams)
266 {
267 int chan, prev;
268 prev = -1;
269 /* Copy "left" audio to the channel(s) where it belongs */
270 while ( (chan = get_left_channel(&st->layout, s, prev)) != -1)
271 {
272 (*copy_channel_out)(pcm, st->layout.nb_channels, chan,
273 buf, 2, frame_size, user_data);
274 prev = chan;
275 }
276 prev = -1;
277 /* Copy "right" audio to the channel(s) where it belongs */
278 while ( (chan = get_right_channel(&st->layout, s, prev)) != -1)
279 {
280 (*copy_channel_out)(pcm, st->layout.nb_channels, chan,
281 buf+1, 2, frame_size, user_data);
282 prev = chan;
283 }
284 } else {
285 int chan, prev;
286 prev = -1;
287 /* Copy audio to the channel(s) where it belongs */
288 while ( (chan = get_mono_channel(&st->layout, s, prev)) != -1)
289 {
290 (*copy_channel_out)(pcm, st->layout.nb_channels, chan,
291 buf, 1, frame_size, user_data);
292 prev = chan;
293 }
294 }
295 }
296 /* Handle muted channels */
297 for (c=0;c<st->layout.nb_channels;c++)
298 {
299 if (st->layout.mapping[c] == 255)
300 {
301 (*copy_channel_out)(pcm, st->layout.nb_channels, c,
302 NULL, 0, frame_size, user_data);
303 }
304 }
305 RESTORE_STACK;
306 return frame_size;
307 }
308
309 #if !defined(DISABLE_FLOAT_API)
opus_copy_channel_out_float(void * dst,int dst_stride,int dst_channel,const opus_val16 * src,int src_stride,int frame_size,void * user_data)310 static void opus_copy_channel_out_float(
311 void *dst,
312 int dst_stride,
313 int dst_channel,
314 const opus_val16 *src,
315 int src_stride,
316 int frame_size,
317 void *user_data
318 )
319 {
320 float *float_dst;
321 opus_int32 i;
322 (void)user_data;
323 float_dst = (float*)dst;
324 if (src != NULL)
325 {
326 for (i=0;i<frame_size;i++)
327 #if defined(FIXED_POINT)
328 float_dst[i*dst_stride+dst_channel] = (1/32768.f)*src[i*src_stride];
329 #else
330 float_dst[i*dst_stride+dst_channel] = src[i*src_stride];
331 #endif
332 }
333 else
334 {
335 for (i=0;i<frame_size;i++)
336 float_dst[i*dst_stride+dst_channel] = 0;
337 }
338 }
339 #endif
340
opus_copy_channel_out_short(void * dst,int dst_stride,int dst_channel,const opus_val16 * src,int src_stride,int frame_size,void * user_data)341 static void opus_copy_channel_out_short(
342 void *dst,
343 int dst_stride,
344 int dst_channel,
345 const opus_val16 *src,
346 int src_stride,
347 int frame_size,
348 void *user_data
349 )
350 {
351 opus_int16 *short_dst;
352 opus_int32 i;
353 (void)user_data;
354 short_dst = (opus_int16*)dst;
355 if (src != NULL)
356 {
357 for (i=0;i<frame_size;i++)
358 #if defined(FIXED_POINT)
359 short_dst[i*dst_stride+dst_channel] = src[i*src_stride];
360 #else
361 short_dst[i*dst_stride+dst_channel] = FLOAT2INT16(src[i*src_stride]);
362 #endif
363 }
364 else
365 {
366 for (i=0;i<frame_size;i++)
367 short_dst[i*dst_stride+dst_channel] = 0;
368 }
369 }
370
371
372
373 #ifdef FIXED_POINT
opus_multistream_decode(OpusMSDecoder * st,const unsigned char * data,opus_int32 len,opus_int16 * pcm,int frame_size,int decode_fec)374 int opus_multistream_decode(
375 OpusMSDecoder *st,
376 const unsigned char *data,
377 opus_int32 len,
378 opus_int16 *pcm,
379 int frame_size,
380 int decode_fec
381 )
382 {
383 return opus_multistream_decode_native(st, data, len,
384 pcm, opus_copy_channel_out_short, frame_size, decode_fec, 0, NULL);
385 }
386
387 #ifndef DISABLE_FLOAT_API
opus_multistream_decode_float(OpusMSDecoder * st,const unsigned char * data,opus_int32 len,float * pcm,int frame_size,int decode_fec)388 int opus_multistream_decode_float(OpusMSDecoder *st, const unsigned char *data,
389 opus_int32 len, float *pcm, int frame_size, int decode_fec)
390 {
391 return opus_multistream_decode_native(st, data, len,
392 pcm, opus_copy_channel_out_float, frame_size, decode_fec, 0, NULL);
393 }
394 #endif
395
396 #else
397
opus_multistream_decode(OpusMSDecoder * st,const unsigned char * data,opus_int32 len,opus_int16 * pcm,int frame_size,int decode_fec)398 int opus_multistream_decode(OpusMSDecoder *st, const unsigned char *data,
399 opus_int32 len, opus_int16 *pcm, int frame_size, int decode_fec)
400 {
401 return opus_multistream_decode_native(st, data, len,
402 pcm, opus_copy_channel_out_short, frame_size, decode_fec, 1, NULL);
403 }
404
opus_multistream_decode_float(OpusMSDecoder * st,const unsigned char * data,opus_int32 len,opus_val16 * pcm,int frame_size,int decode_fec)405 int opus_multistream_decode_float(
406 OpusMSDecoder *st,
407 const unsigned char *data,
408 opus_int32 len,
409 opus_val16 *pcm,
410 int frame_size,
411 int decode_fec
412 )
413 {
414 return opus_multistream_decode_native(st, data, len,
415 pcm, opus_copy_channel_out_float, frame_size, decode_fec, 0, NULL);
416 }
417 #endif
418
opus_multistream_decoder_ctl_va_list(OpusMSDecoder * st,int request,va_list ap)419 int opus_multistream_decoder_ctl_va_list(OpusMSDecoder *st, int request,
420 va_list ap)
421 {
422 int coupled_size, mono_size;
423 char *ptr;
424 int ret = OPUS_OK;
425
426 coupled_size = opus_decoder_get_size(2);
427 mono_size = opus_decoder_get_size(1);
428 ptr = (char*)st + align(sizeof(OpusMSDecoder));
429 switch (request)
430 {
431 case OPUS_GET_BANDWIDTH_REQUEST:
432 case OPUS_GET_SAMPLE_RATE_REQUEST:
433 case OPUS_GET_GAIN_REQUEST:
434 case OPUS_GET_LAST_PACKET_DURATION_REQUEST:
435 case OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST:
436 {
437 OpusDecoder *dec;
438 /* For int32* GET params, just query the first stream */
439 opus_int32 *value = va_arg(ap, opus_int32*);
440 dec = (OpusDecoder*)ptr;
441 ret = opus_decoder_ctl(dec, request, value);
442 }
443 break;
444 case OPUS_GET_FINAL_RANGE_REQUEST:
445 {
446 int s;
447 opus_uint32 *value = va_arg(ap, opus_uint32*);
448 opus_uint32 tmp;
449 if (!value)
450 {
451 goto bad_arg;
452 }
453 *value = 0;
454 for (s=0;s<st->layout.nb_streams;s++)
455 {
456 OpusDecoder *dec;
457 dec = (OpusDecoder*)ptr;
458 if (s < st->layout.nb_coupled_streams)
459 ptr += align(coupled_size);
460 else
461 ptr += align(mono_size);
462 ret = opus_decoder_ctl(dec, request, &tmp);
463 if (ret != OPUS_OK) break;
464 *value ^= tmp;
465 }
466 }
467 break;
468 case OPUS_RESET_STATE:
469 {
470 int s;
471 for (s=0;s<st->layout.nb_streams;s++)
472 {
473 OpusDecoder *dec;
474
475 dec = (OpusDecoder*)ptr;
476 if (s < st->layout.nb_coupled_streams)
477 ptr += align(coupled_size);
478 else
479 ptr += align(mono_size);
480 ret = opus_decoder_ctl(dec, OPUS_RESET_STATE);
481 if (ret != OPUS_OK)
482 break;
483 }
484 }
485 break;
486 case OPUS_MULTISTREAM_GET_DECODER_STATE_REQUEST:
487 {
488 int s;
489 opus_int32 stream_id;
490 OpusDecoder **value;
491 stream_id = va_arg(ap, opus_int32);
492 if (stream_id<0 || stream_id >= st->layout.nb_streams)
493 goto bad_arg;
494 value = va_arg(ap, OpusDecoder**);
495 if (!value)
496 {
497 goto bad_arg;
498 }
499 for (s=0;s<stream_id;s++)
500 {
501 if (s < st->layout.nb_coupled_streams)
502 ptr += align(coupled_size);
503 else
504 ptr += align(mono_size);
505 }
506 *value = (OpusDecoder*)ptr;
507 }
508 break;
509 case OPUS_SET_GAIN_REQUEST:
510 case OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST:
511 {
512 int s;
513 /* This works for int32 params */
514 opus_int32 value = va_arg(ap, opus_int32);
515 for (s=0;s<st->layout.nb_streams;s++)
516 {
517 OpusDecoder *dec;
518
519 dec = (OpusDecoder*)ptr;
520 if (s < st->layout.nb_coupled_streams)
521 ptr += align(coupled_size);
522 else
523 ptr += align(mono_size);
524 ret = opus_decoder_ctl(dec, request, value);
525 if (ret != OPUS_OK)
526 break;
527 }
528 }
529 break;
530 default:
531 ret = OPUS_UNIMPLEMENTED;
532 break;
533 }
534 return ret;
535 bad_arg:
536 return OPUS_BAD_ARG;
537 }
538
opus_multistream_decoder_ctl(OpusMSDecoder * st,int request,...)539 int opus_multistream_decoder_ctl(OpusMSDecoder *st, int request, ...)
540 {
541 int ret;
542 va_list ap;
543 va_start(ap, request);
544 ret = opus_multistream_decoder_ctl_va_list(st, request, ap);
545 va_end(ap);
546 return ret;
547 }
548
opus_multistream_decoder_destroy(OpusMSDecoder * st)549 void opus_multistream_decoder_destroy(OpusMSDecoder *st)
550 {
551 opus_free(st);
552 }
553