• 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 struct OpusMSDecoder {
41    ChannelLayout layout;
42    /* Decoder states go here */
43 };
44 
45 
46 
47 
48 /* DECODER */
49 
opus_multistream_decoder_get_size(int nb_streams,int nb_coupled_streams)50 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    if(nb_streams<1||nb_coupled_streams>nb_streams||nb_coupled_streams<0)return 0;
56    coupled_size = opus_decoder_get_size(2);
57    mono_size = opus_decoder_get_size(1);
58    return align(sizeof(OpusMSDecoder))
59          + nb_coupled_streams * align(coupled_size)
60          + (nb_streams-nb_coupled_streams) * align(mono_size);
61 }
62 
opus_multistream_decoder_init(OpusMSDecoder * st,opus_int32 Fs,int channels,int streams,int coupled_streams,const unsigned char * mapping)63 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    if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
78        (streams<1) || (coupled_streams<0) || (streams>255-coupled_streams))
79       return OPUS_BAD_ARG;
80 
81    st->layout.nb_channels = channels;
82    st->layout.nb_streams = streams;
83    st->layout.nb_coupled_streams = coupled_streams;
84 
85    for (i=0;i<st->layout.nb_channels;i++)
86       st->layout.mapping[i] = mapping[i];
87    if (!validate_layout(&st->layout))
88       return OPUS_BAD_ARG;
89 
90    ptr = (char*)st + align(sizeof(OpusMSDecoder));
91    coupled_size = opus_decoder_get_size(2);
92    mono_size = opus_decoder_get_size(1);
93 
94    for (i=0;i<st->layout.nb_coupled_streams;i++)
95    {
96       ret=opus_decoder_init((OpusDecoder*)ptr, Fs, 2);
97       if(ret!=OPUS_OK)return ret;
98       ptr += align(coupled_size);
99    }
100    for (;i<st->layout.nb_streams;i++)
101    {
102       ret=opus_decoder_init((OpusDecoder*)ptr, Fs, 1);
103       if(ret!=OPUS_OK)return ret;
104       ptr += align(mono_size);
105    }
106    return OPUS_OK;
107 }
108 
109 
opus_multistream_decoder_create(opus_int32 Fs,int channels,int streams,int coupled_streams,const unsigned char * mapping,int * error)110 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    if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
122        (streams<1) || (coupled_streams<0) || (streams>255-coupled_streams))
123    {
124       if (error)
125          *error = OPUS_BAD_ARG;
126       return NULL;
127    }
128    st = (OpusMSDecoder *)opus_alloc(opus_multistream_decoder_get_size(streams, coupled_streams));
129    if (st==NULL)
130    {
131       if (error)
132          *error = OPUS_ALLOC_FAIL;
133       return NULL;
134    }
135    ret = opus_multistream_decoder_init(st, Fs, channels, streams, coupled_streams, mapping);
136    if (error)
137       *error = ret;
138    if (ret != OPUS_OK)
139    {
140       opus_free(st);
141       st = NULL;
142    }
143    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 
opus_multistream_packet_validate(const unsigned char * data,opus_int32 len,int nb_streams,opus_int32 Fs)155 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    int samples=0;
163    opus_int32 packet_offset;
164 
165    for (s=0;s<nb_streams;s++)
166    {
167       int tmp_samples;
168       if (len<=0)
169          return OPUS_INVALID_PACKET;
170       count = opus_packet_parse_impl(data, len, s!=nb_streams-1, &toc, NULL,
171                                      size, NULL, &packet_offset);
172       if (count<0)
173          return count;
174       tmp_samples = opus_packet_get_nb_samples(data, packet_offset, Fs);
175       if (s!=0 && samples != tmp_samples)
176          return OPUS_INVALID_PACKET;
177       samples = tmp_samples;
178       data += packet_offset;
179       len -= packet_offset;
180    }
181    return samples;
182 }
183 
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)184 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    int do_plc=0;
201    VARDECL(opus_val16, buf);
202    ALLOC_STACK;
203 
204    /* Limit frame_size to avoid excessive stack allocations. */
205    opus_multistream_decoder_ctl(st, OPUS_GET_SAMPLE_RATE(&Fs));
206    frame_size = IMIN(frame_size, Fs/25*3);
207    ALLOC(buf, 2*frame_size, opus_val16);
208    ptr = (char*)st + align(sizeof(OpusMSDecoder));
209    coupled_size = opus_decoder_get_size(2);
210    mono_size = opus_decoder_get_size(1);
211 
212    if (len==0)
213       do_plc = 1;
214    if (len < 0)
215    {
216       RESTORE_STACK;
217       return OPUS_BAD_ARG;
218    }
219    if (!do_plc && len < 2*st->layout.nb_streams-1)
220    {
221       RESTORE_STACK;
222       return OPUS_INVALID_PACKET;
223    }
224    if (!do_plc)
225    {
226       int ret = opus_multistream_packet_validate(data, len, st->layout.nb_streams, Fs);
227       if (ret < 0)
228       {
229          RESTORE_STACK;
230          return ret;
231       } else if (ret > frame_size)
232       {
233          RESTORE_STACK;
234          return OPUS_BUFFER_TOO_SMALL;
235       }
236    }
237    for (s=0;s<st->layout.nb_streams;s++)
238    {
239       OpusDecoder *dec;
240       opus_int32 packet_offset;
241       int ret;
242 
243       dec = (OpusDecoder*)ptr;
244       ptr += (s < st->layout.nb_coupled_streams) ? align(coupled_size) : align(mono_size);
245 
246       if (!do_plc && len<=0)
247       {
248          RESTORE_STACK;
249          return OPUS_INTERNAL_ERROR;
250       }
251       packet_offset = 0;
252       ret = opus_decode_native(dec, data, len, buf, frame_size, decode_fec, s!=st->layout.nb_streams-1, &packet_offset, soft_clip);
253       data += packet_offset;
254       len -= packet_offset;
255       if (ret <= 0)
256       {
257          RESTORE_STACK;
258          return ret;
259       }
260       frame_size = ret;
261       if (s < st->layout.nb_coupled_streams)
262       {
263          int chan, prev;
264          prev = -1;
265          /* Copy "left" audio to the channel(s) where it belongs */
266          while ( (chan = get_left_channel(&st->layout, s, prev)) != -1)
267          {
268             (*copy_channel_out)(pcm, st->layout.nb_channels, chan,
269                buf, 2, frame_size);
270             prev = chan;
271          }
272          prev = -1;
273          /* Copy "right" audio to the channel(s) where it belongs */
274          while ( (chan = get_right_channel(&st->layout, s, prev)) != -1)
275          {
276             (*copy_channel_out)(pcm, st->layout.nb_channels, chan,
277                buf+1, 2, frame_size);
278             prev = chan;
279          }
280       } else {
281          int chan, prev;
282          prev = -1;
283          /* Copy audio to the channel(s) where it belongs */
284          while ( (chan = get_mono_channel(&st->layout, s, prev)) != -1)
285          {
286             (*copy_channel_out)(pcm, st->layout.nb_channels, chan,
287                buf, 1, frame_size);
288             prev = chan;
289          }
290       }
291    }
292    /* Handle muted channels */
293    for (c=0;c<st->layout.nb_channels;c++)
294    {
295       if (st->layout.mapping[c] == 255)
296       {
297          (*copy_channel_out)(pcm, st->layout.nb_channels, c,
298             NULL, 0, frame_size);
299       }
300    }
301    RESTORE_STACK;
302    return frame_size;
303 }
304 
305 #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)306 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    float_dst = (float*)dst;
318    if (src != NULL)
319    {
320       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          float_dst[i*dst_stride+dst_channel] = src[i*src_stride];
325 #endif
326    }
327    else
328    {
329       for (i=0;i<frame_size;i++)
330          float_dst[i*dst_stride+dst_channel] = 0;
331    }
332 }
333 #endif
334 
opus_copy_channel_out_short(void * dst,int dst_stride,int dst_channel,const opus_val16 * src,int src_stride,int frame_size)335 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    short_dst = (opus_int16*)dst;
347    if (src != NULL)
348    {
349       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          short_dst[i*dst_stride+dst_channel] = FLOAT2INT16(src[i*src_stride]);
354 #endif
355    }
356    else
357    {
358       for (i=0;i<frame_size;i++)
359          short_dst[i*dst_stride+dst_channel] = 0;
360    }
361 }
362 
363 
364 
365 #ifdef FIXED_POINT
opus_multistream_decode(OpusMSDecoder * st,const unsigned char * data,opus_int32 len,opus_int16 * pcm,int frame_size,int decode_fec)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
opus_multistream_decode_float(OpusMSDecoder * st,const unsigned char * data,opus_int32 len,float * pcm,int frame_size,int decode_fec)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 
opus_multistream_decode(OpusMSDecoder * st,const unsigned char * data,opus_int32 len,opus_int16 * pcm,int frame_size,int decode_fec)390 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    return opus_multistream_decode_native(st, data, len,
394        pcm, opus_copy_channel_out_short, frame_size, decode_fec, 1);
395 }
396 
opus_multistream_decode_float(OpusMSDecoder * st,const unsigned char * data,opus_int32 len,float * pcm,int frame_size,int decode_fec)397 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    return opus_multistream_decode_native(st, data, len,
407        pcm, opus_copy_channel_out_float, frame_size, decode_fec, 0);
408 }
409 #endif
410 
opus_multistream_decoder_ctl(OpusMSDecoder * st,int request,...)411 int opus_multistream_decoder_ctl(OpusMSDecoder *st, int request, ...)
412 {
413    va_list ap;
414    int coupled_size, mono_size;
415    char *ptr;
416    int ret = OPUS_OK;
417 
418    va_start(ap, request);
419 
420    coupled_size = opus_decoder_get_size(2);
421    mono_size = opus_decoder_get_size(1);
422    ptr = (char*)st + align(sizeof(OpusMSDecoder));
423    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           opus_int32 *value = va_arg(ap, opus_int32*);
434           dec = (OpusDecoder*)ptr;
435           ret = opus_decoder_ctl(dec, request, value);
436        }
437        break;
438        case OPUS_GET_FINAL_RANGE_REQUEST:
439        {
440           int s;
441           opus_uint32 *value = va_arg(ap, opus_uint32*);
442           opus_uint32 tmp;
443           if (!value)
444           {
445              goto bad_arg;
446           }
447           *value = 0;
448           for (s=0;s<st->layout.nb_streams;s++)
449           {
450              OpusDecoder *dec;
451              dec = (OpusDecoder*)ptr;
452              if (s < st->layout.nb_coupled_streams)
453                 ptr += align(coupled_size);
454              else
455                 ptr += align(mono_size);
456              ret = opus_decoder_ctl(dec, request, &tmp);
457              if (ret != OPUS_OK) break;
458              *value ^= tmp;
459           }
460        }
461        break;
462        case OPUS_RESET_STATE:
463        {
464           int s;
465           for (s=0;s<st->layout.nb_streams;s++)
466           {
467              OpusDecoder *dec;
468 
469              dec = (OpusDecoder*)ptr;
470              if (s < st->layout.nb_coupled_streams)
471                 ptr += align(coupled_size);
472              else
473                 ptr += align(mono_size);
474              ret = opus_decoder_ctl(dec, OPUS_RESET_STATE);
475              if (ret != OPUS_OK)
476                 break;
477           }
478        }
479        break;
480        case OPUS_MULTISTREAM_GET_DECODER_STATE_REQUEST:
481        {
482           int s;
483           opus_int32 stream_id;
484           OpusDecoder **value;
485           stream_id = va_arg(ap, opus_int32);
486           if (stream_id<0 || stream_id >= st->layout.nb_streams)
487              ret = OPUS_BAD_ARG;
488           value = va_arg(ap, OpusDecoder**);
489           if (!value)
490           {
491              goto bad_arg;
492           }
493           for (s=0;s<stream_id;s++)
494           {
495              if (s < st->layout.nb_coupled_streams)
496                 ptr += align(coupled_size);
497              else
498                 ptr += align(mono_size);
499           }
500           *value = (OpusDecoder*)ptr;
501        }
502        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           opus_int32 value = va_arg(ap, opus_int32);
509           for (s=0;s<st->layout.nb_streams;s++)
510           {
511              OpusDecoder *dec;
512 
513              dec = (OpusDecoder*)ptr;
514              if (s < st->layout.nb_coupled_streams)
515                 ptr += align(coupled_size);
516              else
517                 ptr += align(mono_size);
518              ret = opus_decoder_ctl(dec, request, value);
519              if (ret != OPUS_OK)
520                 break;
521           }
522        }
523        break;
524        default:
525           ret = OPUS_UNIMPLEMENTED;
526        break;
527    }
528 
529    va_end(ap);
530    return ret;
531 bad_arg:
532    va_end(ap);
533    return OPUS_BAD_ARG;
534 }
535 
536 
opus_multistream_decoder_destroy(OpusMSDecoder * st)537 void opus_multistream_decoder_destroy(OpusMSDecoder *st)
538 {
539     opus_free(st);
540 }
541