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