• 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        (coupled_streams+streams>255) || (streams<1) || (coupled_streams<0))
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        (coupled_streams+streams>255) || (streams<1) || (coupled_streams<0))
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_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)155 static int opus_multistream_decode_native(
156       OpusMSDecoder *st,
157       const unsigned char *data,
158       opus_int32 len,
159       void *pcm,
160       opus_copy_channel_out_func copy_channel_out,
161       int frame_size,
162       int decode_fec,
163       int soft_clip
164 )
165 {
166    opus_int32 Fs;
167    int coupled_size;
168    int mono_size;
169    int s, c;
170    char *ptr;
171    int do_plc=0;
172    VARDECL(opus_val16, buf);
173    ALLOC_STACK;
174 
175    /* Limit frame_size to avoid excessive stack allocations. */
176    opus_multistream_decoder_ctl(st, OPUS_GET_SAMPLE_RATE(&Fs));
177    frame_size = IMIN(frame_size, Fs/25*3);
178    ALLOC(buf, 2*frame_size, opus_val16);
179    ptr = (char*)st + align(sizeof(OpusMSDecoder));
180    coupled_size = opus_decoder_get_size(2);
181    mono_size = opus_decoder_get_size(1);
182 
183    if (len==0)
184       do_plc = 1;
185    if (len < 0)
186       return OPUS_BAD_ARG;
187    if (!do_plc && len < 2*st->layout.nb_streams-1)
188       return OPUS_INVALID_PACKET;
189    for (s=0;s<st->layout.nb_streams;s++)
190    {
191       OpusDecoder *dec;
192       int packet_offset, ret;
193 
194       dec = (OpusDecoder*)ptr;
195       ptr += (s < st->layout.nb_coupled_streams) ? align(coupled_size) : align(mono_size);
196 
197       if (!do_plc && len<=0)
198       {
199          RESTORE_STACK;
200          return OPUS_INVALID_PACKET;
201       }
202       packet_offset = 0;
203       ret = opus_decode_native(dec, data, len, buf, frame_size, decode_fec, s!=st->layout.nb_streams-1, &packet_offset, soft_clip);
204       data += packet_offset;
205       len -= packet_offset;
206       if (ret > frame_size)
207       {
208          RESTORE_STACK;
209          return OPUS_BUFFER_TOO_SMALL;
210       }
211       if (s>0 && ret != frame_size)
212       {
213          RESTORE_STACK;
214          return OPUS_INVALID_PACKET;
215       }
216       if (ret <= 0)
217       {
218          RESTORE_STACK;
219          return ret;
220       }
221       frame_size = ret;
222       if (s < st->layout.nb_coupled_streams)
223       {
224          int chan, prev;
225          prev = -1;
226          /* Copy "left" audio to the channel(s) where it belongs */
227          while ( (chan = get_left_channel(&st->layout, s, prev)) != -1)
228          {
229             (*copy_channel_out)(pcm, st->layout.nb_channels, chan,
230                buf, 2, frame_size);
231             prev = chan;
232          }
233          prev = -1;
234          /* Copy "right" audio to the channel(s) where it belongs */
235          while ( (chan = get_right_channel(&st->layout, s, prev)) != -1)
236          {
237             (*copy_channel_out)(pcm, st->layout.nb_channels, chan,
238                buf+1, 2, frame_size);
239             prev = chan;
240          }
241       } else {
242          int chan, prev;
243          prev = -1;
244          /* Copy audio to the channel(s) where it belongs */
245          while ( (chan = get_mono_channel(&st->layout, s, prev)) != -1)
246          {
247             (*copy_channel_out)(pcm, st->layout.nb_channels, chan,
248                buf, 1, frame_size);
249             prev = chan;
250          }
251       }
252    }
253    /* Handle muted channels */
254    for (c=0;c<st->layout.nb_channels;c++)
255    {
256       if (st->layout.mapping[c] == 255)
257       {
258          (*copy_channel_out)(pcm, st->layout.nb_channels, c,
259             NULL, 0, frame_size);
260       }
261    }
262    RESTORE_STACK;
263    return frame_size;
264 }
265 
266 #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)267 static void opus_copy_channel_out_float(
268   void *dst,
269   int dst_stride,
270   int dst_channel,
271   const opus_val16 *src,
272   int src_stride,
273   int frame_size
274 )
275 {
276    float *float_dst;
277    opus_int32 i;
278    float_dst = (float*)dst;
279    if (src != NULL)
280    {
281       for (i=0;i<frame_size;i++)
282 #if defined(FIXED_POINT)
283          float_dst[i*dst_stride+dst_channel] = (1/32768.f)*src[i*src_stride];
284 #else
285          float_dst[i*dst_stride+dst_channel] = src[i*src_stride];
286 #endif
287    }
288    else
289    {
290       for (i=0;i<frame_size;i++)
291          float_dst[i*dst_stride+dst_channel] = 0;
292    }
293 }
294 #endif
295 
opus_copy_channel_out_short(void * dst,int dst_stride,int dst_channel,const opus_val16 * src,int src_stride,int frame_size)296 static void opus_copy_channel_out_short(
297   void *dst,
298   int dst_stride,
299   int dst_channel,
300   const opus_val16 *src,
301   int src_stride,
302   int frame_size
303 )
304 {
305    opus_int16 *short_dst;
306    opus_int32 i;
307    short_dst = (opus_int16*)dst;
308    if (src != NULL)
309    {
310       for (i=0;i<frame_size;i++)
311 #if defined(FIXED_POINT)
312          short_dst[i*dst_stride+dst_channel] = src[i*src_stride];
313 #else
314          short_dst[i*dst_stride+dst_channel] = FLOAT2INT16(src[i*src_stride]);
315 #endif
316    }
317    else
318    {
319       for (i=0;i<frame_size;i++)
320          short_dst[i*dst_stride+dst_channel] = 0;
321    }
322 }
323 
324 
325 
326 #ifdef FIXED_POINT
opus_multistream_decode(OpusMSDecoder * st,const unsigned char * data,opus_int32 len,opus_int16 * pcm,int frame_size,int decode_fec)327 int opus_multistream_decode(
328       OpusMSDecoder *st,
329       const unsigned char *data,
330       opus_int32 len,
331       opus_int16 *pcm,
332       int frame_size,
333       int decode_fec
334 )
335 {
336    return opus_multistream_decode_native(st, data, len,
337        pcm, opus_copy_channel_out_short, frame_size, decode_fec, 0);
338 }
339 
340 #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)341 int opus_multistream_decode_float(OpusMSDecoder *st, const unsigned char *data,
342       opus_int32 len, float *pcm, int frame_size, int decode_fec)
343 {
344    return opus_multistream_decode_native(st, data, len,
345        pcm, opus_copy_channel_out_float, frame_size, decode_fec, 0);
346 }
347 #endif
348 
349 #else
350 
opus_multistream_decode(OpusMSDecoder * st,const unsigned char * data,opus_int32 len,opus_int16 * pcm,int frame_size,int decode_fec)351 int opus_multistream_decode(OpusMSDecoder *st, const unsigned char *data,
352       opus_int32 len, opus_int16 *pcm, int frame_size, int decode_fec)
353 {
354    return opus_multistream_decode_native(st, data, len,
355        pcm, opus_copy_channel_out_short, frame_size, decode_fec, 1);
356 }
357 
opus_multistream_decode_float(OpusMSDecoder * st,const unsigned char * data,opus_int32 len,float * pcm,int frame_size,int decode_fec)358 int opus_multistream_decode_float(
359       OpusMSDecoder *st,
360       const unsigned char *data,
361       opus_int32 len,
362       float *pcm,
363       int frame_size,
364       int decode_fec
365 )
366 {
367    return opus_multistream_decode_native(st, data, len,
368        pcm, opus_copy_channel_out_float, frame_size, decode_fec, 0);
369 }
370 #endif
371 
opus_multistream_decoder_ctl(OpusMSDecoder * st,int request,...)372 int opus_multistream_decoder_ctl(OpusMSDecoder *st, int request, ...)
373 {
374    va_list ap;
375    int coupled_size, mono_size;
376    char *ptr;
377    int ret = OPUS_OK;
378 
379    va_start(ap, request);
380 
381    coupled_size = opus_decoder_get_size(2);
382    mono_size = opus_decoder_get_size(1);
383    ptr = (char*)st + align(sizeof(OpusMSDecoder));
384    switch (request)
385    {
386        case OPUS_GET_BANDWIDTH_REQUEST:
387        case OPUS_GET_SAMPLE_RATE_REQUEST:
388        case OPUS_GET_GAIN_REQUEST:
389        case OPUS_GET_LAST_PACKET_DURATION_REQUEST:
390        {
391           OpusDecoder *dec;
392           /* For int32* GET params, just query the first stream */
393           opus_int32 *value = va_arg(ap, opus_int32*);
394           dec = (OpusDecoder*)ptr;
395           ret = opus_decoder_ctl(dec, request, value);
396        }
397        break;
398        case OPUS_GET_FINAL_RANGE_REQUEST:
399        {
400           int s;
401           opus_uint32 *value = va_arg(ap, opus_uint32*);
402           opus_uint32 tmp;
403           if (!value)
404           {
405              goto bad_arg;
406           }
407           *value = 0;
408           for (s=0;s<st->layout.nb_streams;s++)
409           {
410              OpusDecoder *dec;
411              dec = (OpusDecoder*)ptr;
412              if (s < st->layout.nb_coupled_streams)
413                 ptr += align(coupled_size);
414              else
415                 ptr += align(mono_size);
416              ret = opus_decoder_ctl(dec, request, &tmp);
417              if (ret != OPUS_OK) break;
418              *value ^= tmp;
419           }
420        }
421        break;
422        case OPUS_RESET_STATE:
423        {
424           int s;
425           for (s=0;s<st->layout.nb_streams;s++)
426           {
427              OpusDecoder *dec;
428 
429              dec = (OpusDecoder*)ptr;
430              if (s < st->layout.nb_coupled_streams)
431                 ptr += align(coupled_size);
432              else
433                 ptr += align(mono_size);
434              ret = opus_decoder_ctl(dec, OPUS_RESET_STATE);
435              if (ret != OPUS_OK)
436                 break;
437           }
438        }
439        break;
440        case OPUS_MULTISTREAM_GET_DECODER_STATE_REQUEST:
441        {
442           int s;
443           opus_int32 stream_id;
444           OpusDecoder **value;
445           stream_id = va_arg(ap, opus_int32);
446           if (stream_id<0 || stream_id >= st->layout.nb_streams)
447              ret = OPUS_BAD_ARG;
448           value = va_arg(ap, OpusDecoder**);
449           if (!value)
450           {
451              goto bad_arg;
452           }
453           for (s=0;s<stream_id;s++)
454           {
455              if (s < st->layout.nb_coupled_streams)
456                 ptr += align(coupled_size);
457              else
458                 ptr += align(mono_size);
459           }
460           *value = (OpusDecoder*)ptr;
461        }
462        break;
463        case OPUS_SET_GAIN_REQUEST:
464        {
465           int s;
466           /* This works for int32 params */
467           opus_int32 value = va_arg(ap, opus_int32);
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, request, value);
478              if (ret != OPUS_OK)
479                 break;
480           }
481        }
482        break;
483        default:
484           ret = OPUS_UNIMPLEMENTED;
485        break;
486    }
487 
488    va_end(ap);
489    return ret;
490 bad_arg:
491    va_end(ap);
492    return OPUS_BAD_ARG;
493 }
494 
495 
opus_multistream_decoder_destroy(OpusMSDecoder * st)496 void opus_multistream_decoder_destroy(OpusMSDecoder *st)
497 {
498     opus_free(st);
499 }
500