• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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       data += packet_offset;
255       len -= packet_offset;
256       if (ret <= 0)
257       {
258          RESTORE_STACK;
259          return ret;
260       }
261       frame_size = ret;
262       if (s < st->layout.nb_coupled_streams)
263       {
264          int chan, prev;
265          prev = -1;
266          /* Copy "left" audio to the channel(s) where it belongs */
267          while ( (chan = get_left_channel(&st->layout, s, prev)) != -1)
268          {
269             (*copy_channel_out)(pcm, st->layout.nb_channels, chan,
270                buf, 2, frame_size, user_data);
271             prev = chan;
272          }
273          prev = -1;
274          /* Copy "right" audio to the channel(s) where it belongs */
275          while ( (chan = get_right_channel(&st->layout, s, prev)) != -1)
276          {
277             (*copy_channel_out)(pcm, st->layout.nb_channels, chan,
278                buf+1, 2, frame_size, user_data);
279             prev = chan;
280          }
281       } else {
282          int chan, prev;
283          prev = -1;
284          /* Copy audio to the channel(s) where it belongs */
285          while ( (chan = get_mono_channel(&st->layout, s, prev)) != -1)
286          {
287             (*copy_channel_out)(pcm, st->layout.nb_channels, chan,
288                buf, 1, frame_size, user_data);
289             prev = chan;
290          }
291       }
292    }
293    /* Handle muted channels */
294    for (c=0;c<st->layout.nb_channels;c++)
295    {
296       if (st->layout.mapping[c] == 255)
297       {
298          (*copy_channel_out)(pcm, st->layout.nb_channels, c,
299             NULL, 0, frame_size, user_data);
300       }
301    }
302    RESTORE_STACK;
303    return frame_size;
304 }
305 
306 #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)307 static void opus_copy_channel_out_float(
308   void *dst,
309   int dst_stride,
310   int dst_channel,
311   const opus_val16 *src,
312   int src_stride,
313   int frame_size,
314   void *user_data
315 )
316 {
317    float *float_dst;
318    opus_int32 i;
319    (void)user_data;
320    float_dst = (float*)dst;
321    if (src != NULL)
322    {
323       for (i=0;i<frame_size;i++)
324 #if defined(FIXED_POINT)
325          float_dst[i*dst_stride+dst_channel] = (1/32768.f)*src[i*src_stride];
326 #else
327          float_dst[i*dst_stride+dst_channel] = src[i*src_stride];
328 #endif
329    }
330    else
331    {
332       for (i=0;i<frame_size;i++)
333          float_dst[i*dst_stride+dst_channel] = 0;
334    }
335 }
336 #endif
337 
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)338 static void opus_copy_channel_out_short(
339   void *dst,
340   int dst_stride,
341   int dst_channel,
342   const opus_val16 *src,
343   int src_stride,
344   int frame_size,
345   void *user_data
346 )
347 {
348    opus_int16 *short_dst;
349    opus_int32 i;
350    (void)user_data;
351    short_dst = (opus_int16*)dst;
352    if (src != NULL)
353    {
354       for (i=0;i<frame_size;i++)
355 #if defined(FIXED_POINT)
356          short_dst[i*dst_stride+dst_channel] = src[i*src_stride];
357 #else
358          short_dst[i*dst_stride+dst_channel] = FLOAT2INT16(src[i*src_stride]);
359 #endif
360    }
361    else
362    {
363       for (i=0;i<frame_size;i++)
364          short_dst[i*dst_stride+dst_channel] = 0;
365    }
366 }
367 
368 
369 
370 #ifdef FIXED_POINT
opus_multistream_decode(OpusMSDecoder * st,const unsigned char * data,opus_int32 len,opus_int16 * pcm,int frame_size,int decode_fec)371 int opus_multistream_decode(
372       OpusMSDecoder *st,
373       const unsigned char *data,
374       opus_int32 len,
375       opus_int16 *pcm,
376       int frame_size,
377       int decode_fec
378 )
379 {
380    return opus_multistream_decode_native(st, data, len,
381        pcm, opus_copy_channel_out_short, frame_size, decode_fec, 0, NULL);
382 }
383 
384 #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)385 int opus_multistream_decode_float(OpusMSDecoder *st, const unsigned char *data,
386       opus_int32 len, float *pcm, int frame_size, int decode_fec)
387 {
388    return opus_multistream_decode_native(st, data, len,
389        pcm, opus_copy_channel_out_float, frame_size, decode_fec, 0, NULL);
390 }
391 #endif
392 
393 #else
394 
opus_multistream_decode(OpusMSDecoder * st,const unsigned char * data,opus_int32 len,opus_int16 * pcm,int frame_size,int decode_fec)395 int opus_multistream_decode(OpusMSDecoder *st, const unsigned char *data,
396       opus_int32 len, opus_int16 *pcm, int frame_size, int decode_fec)
397 {
398    return opus_multistream_decode_native(st, data, len,
399        pcm, opus_copy_channel_out_short, frame_size, decode_fec, 1, NULL);
400 }
401 
opus_multistream_decode_float(OpusMSDecoder * st,const unsigned char * data,opus_int32 len,opus_val16 * pcm,int frame_size,int decode_fec)402 int opus_multistream_decode_float(
403       OpusMSDecoder *st,
404       const unsigned char *data,
405       opus_int32 len,
406       opus_val16 *pcm,
407       int frame_size,
408       int decode_fec
409 )
410 {
411    return opus_multistream_decode_native(st, data, len,
412        pcm, opus_copy_channel_out_float, frame_size, decode_fec, 0, NULL);
413 }
414 #endif
415 
opus_multistream_decoder_ctl_va_list(OpusMSDecoder * st,int request,va_list ap)416 int opus_multistream_decoder_ctl_va_list(OpusMSDecoder *st, int request,
417                                          va_list ap)
418 {
419    int coupled_size, mono_size;
420    char *ptr;
421    int ret = OPUS_OK;
422 
423    coupled_size = opus_decoder_get_size(2);
424    mono_size = opus_decoder_get_size(1);
425    ptr = (char*)st + align(sizeof(OpusMSDecoder));
426    switch (request)
427    {
428        case OPUS_GET_BANDWIDTH_REQUEST:
429        case OPUS_GET_SAMPLE_RATE_REQUEST:
430        case OPUS_GET_GAIN_REQUEST:
431        case OPUS_GET_LAST_PACKET_DURATION_REQUEST:
432        case OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST:
433        {
434           OpusDecoder *dec;
435           /* For int32* GET params, just query the first stream */
436           opus_int32 *value = va_arg(ap, opus_int32*);
437           dec = (OpusDecoder*)ptr;
438           ret = opus_decoder_ctl(dec, request, value);
439        }
440        break;
441        case OPUS_GET_FINAL_RANGE_REQUEST:
442        {
443           int s;
444           opus_uint32 *value = va_arg(ap, opus_uint32*);
445           opus_uint32 tmp;
446           if (!value)
447           {
448              goto bad_arg;
449           }
450           *value = 0;
451           for (s=0;s<st->layout.nb_streams;s++)
452           {
453              OpusDecoder *dec;
454              dec = (OpusDecoder*)ptr;
455              if (s < st->layout.nb_coupled_streams)
456                 ptr += align(coupled_size);
457              else
458                 ptr += align(mono_size);
459              ret = opus_decoder_ctl(dec, request, &tmp);
460              if (ret != OPUS_OK) break;
461              *value ^= tmp;
462           }
463        }
464        break;
465        case OPUS_RESET_STATE:
466        {
467           int s;
468           for (s=0;s<st->layout.nb_streams;s++)
469           {
470              OpusDecoder *dec;
471 
472              dec = (OpusDecoder*)ptr;
473              if (s < st->layout.nb_coupled_streams)
474                 ptr += align(coupled_size);
475              else
476                 ptr += align(mono_size);
477              ret = opus_decoder_ctl(dec, OPUS_RESET_STATE);
478              if (ret != OPUS_OK)
479                 break;
480           }
481        }
482        break;
483        case OPUS_MULTISTREAM_GET_DECODER_STATE_REQUEST:
484        {
485           int s;
486           opus_int32 stream_id;
487           OpusDecoder **value;
488           stream_id = va_arg(ap, opus_int32);
489           if (stream_id<0 || stream_id >= st->layout.nb_streams)
490              ret = OPUS_BAD_ARG;
491           value = va_arg(ap, OpusDecoder**);
492           if (!value)
493           {
494              goto bad_arg;
495           }
496           for (s=0;s<stream_id;s++)
497           {
498              if (s < st->layout.nb_coupled_streams)
499                 ptr += align(coupled_size);
500              else
501                 ptr += align(mono_size);
502           }
503           *value = (OpusDecoder*)ptr;
504        }
505        break;
506        case OPUS_SET_GAIN_REQUEST:
507        case OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST:
508        {
509           int s;
510           /* This works for int32 params */
511           opus_int32 value = va_arg(ap, opus_int32);
512           for (s=0;s<st->layout.nb_streams;s++)
513           {
514              OpusDecoder *dec;
515 
516              dec = (OpusDecoder*)ptr;
517              if (s < st->layout.nb_coupled_streams)
518                 ptr += align(coupled_size);
519              else
520                 ptr += align(mono_size);
521              ret = opus_decoder_ctl(dec, request, value);
522              if (ret != OPUS_OK)
523                 break;
524           }
525        }
526        break;
527        default:
528           ret = OPUS_UNIMPLEMENTED;
529        break;
530    }
531    return ret;
532 bad_arg:
533    return OPUS_BAD_ARG;
534 }
535 
opus_multistream_decoder_ctl(OpusMSDecoder * st,int request,...)536 int opus_multistream_decoder_ctl(OpusMSDecoder *st, int request, ...)
537 {
538    int ret;
539    va_list ap;
540    va_start(ap, request);
541    ret = opus_multistream_decoder_ctl_va_list(st, request, ap);
542    va_end(ap);
543    return ret;
544 }
545 
opus_multistream_decoder_destroy(OpusMSDecoder * st)546 void opus_multistream_decoder_destroy(OpusMSDecoder *st)
547 {
548     opus_free(st);
549 }
550