Coverage Report

Created: 2026-09-14 08:00

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