Adding multistream decoder validation
[opus.git] / src / opus_multistream_decoder.c
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)
43 static void validate_ms_decoder(OpusMSDecoder *st)
44 {
45    validate_layout(&st->layout);
46 #ifdef OPUS_ARCHMASK
47    celt_assert(st->arch >= 0);
48    celt_assert(st->arch <= OPUS_ARCHMASK);
49 #endif
50 }
51 #define VALIDATE_MS_DECODER(st) validate_ms_decoder(st)
52 #else
53 #define VALIDATE_MS_DECODER(st)
54 #endif
55
56
57 opus_int32 opus_multistream_decoder_get_size(int nb_streams, int nb_coupled_streams)
58 {
59    int coupled_size;
60    int mono_size;
61
62    if(nb_streams<1||nb_coupled_streams>nb_streams||nb_coupled_streams<0)return 0;
63    coupled_size = opus_decoder_get_size(2);
64    mono_size = opus_decoder_get_size(1);
65    return align(sizeof(OpusMSDecoder))
66          + nb_coupled_streams * align(coupled_size)
67          + (nb_streams-nb_coupled_streams) * align(mono_size);
68 }
69
70 int opus_multistream_decoder_init(
71       OpusMSDecoder *st,
72       opus_int32 Fs,
73       int channels,
74       int streams,
75       int coupled_streams,
76       const unsigned char *mapping
77 )
78 {
79    int coupled_size;
80    int mono_size;
81    int i, ret;
82    char *ptr;
83
84    if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
85        (streams<1) || (coupled_streams<0) || (streams>255-coupled_streams))
86       return OPUS_BAD_ARG;
87
88    st->layout.nb_channels = channels;
89    st->layout.nb_streams = streams;
90    st->layout.nb_coupled_streams = coupled_streams;
91
92    for (i=0;i<st->layout.nb_channels;i++)
93       st->layout.mapping[i] = mapping[i];
94    if (!validate_layout(&st->layout))
95       return OPUS_BAD_ARG;
96
97    ptr = (char*)st + align(sizeof(OpusMSDecoder));
98    coupled_size = opus_decoder_get_size(2);
99    mono_size = opus_decoder_get_size(1);
100
101    for (i=0;i<st->layout.nb_coupled_streams;i++)
102    {
103       ret=opus_decoder_init((OpusDecoder*)ptr, Fs, 2);
104       if(ret!=OPUS_OK)return ret;
105       ptr += align(coupled_size);
106    }
107    for (;i<st->layout.nb_streams;i++)
108    {
109       ret=opus_decoder_init((OpusDecoder*)ptr, Fs, 1);
110       if(ret!=OPUS_OK)return ret;
111       ptr += align(mono_size);
112    }
113    return OPUS_OK;
114 }
115
116
117 OpusMSDecoder *opus_multistream_decoder_create(
118       opus_int32 Fs,
119       int channels,
120       int streams,
121       int coupled_streams,
122       const unsigned char *mapping,
123       int *error
124 )
125 {
126    int ret;
127    OpusMSDecoder *st;
128    if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
129        (streams<1) || (coupled_streams<0) || (streams>255-coupled_streams))
130    {
131       if (error)
132          *error = OPUS_BAD_ARG;
133       return NULL;
134    }
135    st = (OpusMSDecoder *)opus_alloc(opus_multistream_decoder_get_size(streams, coupled_streams));
136    if (st==NULL)
137    {
138       if (error)
139          *error = OPUS_ALLOC_FAIL;
140       return NULL;
141    }
142    ret = opus_multistream_decoder_init(st, Fs, channels, streams, coupled_streams, mapping);
143    if (error)
144       *error = ret;
145    if (ret != OPUS_OK)
146    {
147       opus_free(st);
148       st = NULL;
149    }
150    return st;
151 }
152
153 static int opus_multistream_packet_validate(const unsigned char *data,
154       opus_int32 len, int nb_streams, opus_int32 Fs)
155 {
156    int s;
157    int count;
158    unsigned char toc;
159    opus_int16 size[48];
160    int samples=0;
161    opus_int32 packet_offset;
162
163    for (s=0;s<nb_streams;s++)
164    {
165       int tmp_samples;
166       if (len<=0)
167          return OPUS_INVALID_PACKET;
168       count = opus_packet_parse_impl(data, len, s!=nb_streams-1, &toc, NULL,
169                                      size, NULL, &packet_offset);
170       if (count<0)
171          return count;
172       tmp_samples = opus_packet_get_nb_samples(data, packet_offset, Fs);
173       if (s!=0 && samples != tmp_samples)
174          return OPUS_INVALID_PACKET;
175       samples = tmp_samples;
176       data += packet_offset;
177       len -= packet_offset;
178    }
179    return samples;
180 }
181
182 int opus_multistream_decode_native(
183       OpusMSDecoder *st,
184       const unsigned char *data,
185       opus_int32 len,
186       void *pcm,
187       opus_copy_channel_out_func copy_channel_out,
188       int frame_size,
189       int decode_fec,
190       int soft_clip,
191       void *user_data
192 )
193 {
194    opus_int32 Fs;
195    int coupled_size;
196    int mono_size;
197    int s, c;
198    char *ptr;
199    int do_plc=0;
200    VARDECL(opus_val16, buf);
201    ALLOC_STACK;
202
203    VALIDATE_MS_DECODER(st);
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, user_data);
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, user_data);
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, user_data);
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, user_data);
299       }
300    }
301    RESTORE_STACK;
302    return frame_size;
303 }
304
305 #if !defined(DISABLE_FLOAT_API)
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   void *user_data
314 )
315 {
316    float *float_dst;
317    opus_int32 i;
318    (void)user_data;
319    float_dst = (float*)dst;
320    if (src != NULL)
321    {
322       for (i=0;i<frame_size;i++)
323 #if defined(FIXED_POINT)
324          float_dst[i*dst_stride+dst_channel] = (1/32768.f)*src[i*src_stride];
325 #else
326          float_dst[i*dst_stride+dst_channel] = src[i*src_stride];
327 #endif
328    }
329    else
330    {
331       for (i=0;i<frame_size;i++)
332          float_dst[i*dst_stride+dst_channel] = 0;
333    }
334 }
335 #endif
336
337 static void opus_copy_channel_out_short(
338   void *dst,
339   int dst_stride,
340   int dst_channel,
341   const opus_val16 *src,
342   int src_stride,
343   int frame_size,
344   void *user_data
345 )
346 {
347    opus_int16 *short_dst;
348    opus_int32 i;
349    (void)user_data;
350    short_dst = (opus_int16*)dst;
351    if (src != NULL)
352    {
353       for (i=0;i<frame_size;i++)
354 #if defined(FIXED_POINT)
355          short_dst[i*dst_stride+dst_channel] = src[i*src_stride];
356 #else
357          short_dst[i*dst_stride+dst_channel] = FLOAT2INT16(src[i*src_stride]);
358 #endif
359    }
360    else
361    {
362       for (i=0;i<frame_size;i++)
363          short_dst[i*dst_stride+dst_channel] = 0;
364    }
365 }
366
367
368
369 #ifdef FIXED_POINT
370 int opus_multistream_decode(
371       OpusMSDecoder *st,
372       const unsigned char *data,
373       opus_int32 len,
374       opus_int16 *pcm,
375       int frame_size,
376       int decode_fec
377 )
378 {
379    return opus_multistream_decode_native(st, data, len,
380        pcm, opus_copy_channel_out_short, frame_size, decode_fec, 0, NULL);
381 }
382
383 #ifndef DISABLE_FLOAT_API
384 int opus_multistream_decode_float(OpusMSDecoder *st, const unsigned char *data,
385       opus_int32 len, float *pcm, int frame_size, int decode_fec)
386 {
387    return opus_multistream_decode_native(st, data, len,
388        pcm, opus_copy_channel_out_float, frame_size, decode_fec, 0, NULL);
389 }
390 #endif
391
392 #else
393
394 int opus_multistream_decode(OpusMSDecoder *st, const unsigned char *data,
395       opus_int32 len, opus_int16 *pcm, int frame_size, int decode_fec)
396 {
397    return opus_multistream_decode_native(st, data, len,
398        pcm, opus_copy_channel_out_short, frame_size, decode_fec, 1, NULL);
399 }
400
401 int opus_multistream_decode_float(
402       OpusMSDecoder *st,
403       const unsigned char *data,
404       opus_int32 len,
405       opus_val16 *pcm,
406       int frame_size,
407       int decode_fec
408 )
409 {
410    return opus_multistream_decode_native(st, data, len,
411        pcm, opus_copy_channel_out_float, frame_size, decode_fec, 0, NULL);
412 }
413 #endif
414
415 int opus_multistream_decoder_ctl_va_list(OpusMSDecoder *st, int request,
416                                          va_list ap)
417 {
418    int coupled_size, mono_size;
419    char *ptr;
420    int ret = OPUS_OK;
421
422    coupled_size = opus_decoder_get_size(2);
423    mono_size = opus_decoder_get_size(1);
424    ptr = (char*)st + align(sizeof(OpusMSDecoder));
425    switch (request)
426    {
427        case OPUS_GET_BANDWIDTH_REQUEST:
428        case OPUS_GET_SAMPLE_RATE_REQUEST:
429        case OPUS_GET_GAIN_REQUEST:
430        case OPUS_GET_LAST_PACKET_DURATION_REQUEST:
431        case OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST:
432        {
433           OpusDecoder *dec;
434           /* For int32* GET params, just query the first stream */
435           opus_int32 *value = va_arg(ap, opus_int32*);
436           dec = (OpusDecoder*)ptr;
437           ret = opus_decoder_ctl(dec, request, value);
438        }
439        break;
440        case OPUS_GET_FINAL_RANGE_REQUEST:
441        {
442           int s;
443           opus_uint32 *value = va_arg(ap, opus_uint32*);
444           opus_uint32 tmp;
445           if (!value)
446           {
447              goto bad_arg;
448           }
449           *value = 0;
450           for (s=0;s<st->layout.nb_streams;s++)
451           {
452              OpusDecoder *dec;
453              dec = (OpusDecoder*)ptr;
454              if (s < st->layout.nb_coupled_streams)
455                 ptr += align(coupled_size);
456              else
457                 ptr += align(mono_size);
458              ret = opus_decoder_ctl(dec, request, &tmp);
459              if (ret != OPUS_OK) break;
460              *value ^= tmp;
461           }
462        }
463        break;
464        case OPUS_RESET_STATE:
465        {
466           int s;
467           for (s=0;s<st->layout.nb_streams;s++)
468           {
469              OpusDecoder *dec;
470
471              dec = (OpusDecoder*)ptr;
472              if (s < st->layout.nb_coupled_streams)
473                 ptr += align(coupled_size);
474              else
475                 ptr += align(mono_size);
476              ret = opus_decoder_ctl(dec, OPUS_RESET_STATE);
477              if (ret != OPUS_OK)
478                 break;
479           }
480        }
481        break;
482        case OPUS_MULTISTREAM_GET_DECODER_STATE_REQUEST:
483        {
484           int s;
485           opus_int32 stream_id;
486           OpusDecoder **value;
487           stream_id = va_arg(ap, opus_int32);
488           if (stream_id<0 || stream_id >= st->layout.nb_streams)
489              ret = OPUS_BAD_ARG;
490           value = va_arg(ap, OpusDecoder**);
491           if (!value)
492           {
493              goto bad_arg;
494           }
495           for (s=0;s<stream_id;s++)
496           {
497              if (s < st->layout.nb_coupled_streams)
498                 ptr += align(coupled_size);
499              else
500                 ptr += align(mono_size);
501           }
502           *value = (OpusDecoder*)ptr;
503        }
504        break;
505        case OPUS_SET_GAIN_REQUEST:
506        case OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST:
507        {
508           int s;
509           /* This works for int32 params */
510           opus_int32 value = va_arg(ap, opus_int32);
511           for (s=0;s<st->layout.nb_streams;s++)
512           {
513              OpusDecoder *dec;
514
515              dec = (OpusDecoder*)ptr;
516              if (s < st->layout.nb_coupled_streams)
517                 ptr += align(coupled_size);
518              else
519                 ptr += align(mono_size);
520              ret = opus_decoder_ctl(dec, request, value);
521              if (ret != OPUS_OK)
522                 break;
523           }
524        }
525        break;
526        default:
527           ret = OPUS_UNIMPLEMENTED;
528        break;
529    }
530    return ret;
531 bad_arg:
532    return OPUS_BAD_ARG;
533 }
534
535 int opus_multistream_decoder_ctl(OpusMSDecoder *st, int request, ...)
536 {
537    int ret;
538    va_list ap;
539    va_start(ap, request);
540    ret = opus_multistream_decoder_ctl_va_list(st, request, ap);
541    va_end(ap);
542    return ret;
543 }
544
545 void opus_multistream_decoder_destroy(OpusMSDecoder *st)
546 {
547     opus_free(st);
548 }