Coverage Report

Created: 2025-12-31 07:57

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
316k
{
45
316k
   validate_layout(&st->layout);
46
316k
}
47
316k
#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.67k
{
55
6.67k
   int coupled_size;
56
6.67k
   int mono_size;
57
58
6.67k
   if(nb_streams<1||nb_coupled_streams>nb_streams||nb_coupled_streams<0)return 0;
59
6.67k
   coupled_size = opus_decoder_get_size(2);
60
6.67k
   mono_size = opus_decoder_get_size(1);
61
6.67k
   return align(sizeof(OpusMSDecoder))
62
6.67k
         + nb_coupled_streams * align(coupled_size)
63
6.67k
         + (nb_streams-nb_coupled_streams) * align(mono_size);
64
6.67k
}
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.67k
{
75
6.67k
   int coupled_size;
76
6.67k
   int mono_size;
77
6.67k
   int i, ret;
78
6.67k
   char *ptr;
79
80
6.67k
   if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
81
6.67k
       (streams<1) || (coupled_streams<0) || (streams>255-coupled_streams))
82
0
      return OPUS_BAD_ARG;
83
84
6.67k
   st->layout.nb_channels = channels;
85
6.67k
   st->layout.nb_streams = streams;
86
6.67k
   st->layout.nb_coupled_streams = coupled_streams;
87
88
41.7k
   for (i=0;i<st->layout.nb_channels;i++)
89
35.0k
      st->layout.mapping[i] = mapping[i];
90
6.67k
   if (!validate_layout(&st->layout))
91
6
      return OPUS_BAD_ARG;
92
93
6.67k
   ptr = (char*)st + align(sizeof(OpusMSDecoder));
94
6.67k
   coupled_size = opus_decoder_get_size(2);
95
6.67k
   mono_size = opus_decoder_get_size(1);
96
97
20.7k
   for (i=0;i<st->layout.nb_coupled_streams;i++)
98
14.0k
   {
99
14.0k
      ret=opus_decoder_init((OpusDecoder*)ptr, Fs, 2);
100
14.0k
      if(ret!=OPUS_OK)return ret;
101
14.0k
      ptr += align(coupled_size);
102
14.0k
   }
103
53.4k
   for (;i<st->layout.nb_streams;i++)
104
46.7k
   {
105
46.7k
      ret=opus_decoder_init((OpusDecoder*)ptr, Fs, 1);
106
46.7k
      if(ret!=OPUS_OK)return ret;
107
46.7k
      ptr += align(mono_size);
108
46.7k
   }
109
6.67k
   return OPUS_OK;
110
6.67k
}
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.70k
{
122
6.70k
   int ret;
123
6.70k
   OpusMSDecoder *st;
124
6.70k
   if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
125
6.70k
       (streams<1) || (coupled_streams<0) || (streams>255-coupled_streams))
126
28
   {
127
28
      if (error)
128
28
         *error = OPUS_BAD_ARG;
129
28
      return NULL;
130
28
   }
131
6.67k
   st = (OpusMSDecoder *)opus_alloc(opus_multistream_decoder_get_size(streams, coupled_streams));
132
6.67k
   if (st==NULL)
133
0
   {
134
0
      if (error)
135
0
         *error = OPUS_ALLOC_FAIL;
136
0
      return NULL;
137
0
   }
138
6.67k
   ret = opus_multistream_decoder_init(st, Fs, channels, streams, coupled_streams, mapping);
139
6.67k
   if (error)
140
6.67k
      *error = ret;
141
6.67k
   if (ret != OPUS_OK)
142
6
   {
143
6
      opus_free(st);
144
6
      st = NULL;
145
6
   }
146
6.67k
   return st;
147
6.67k
}
148
149
static int opus_multistream_packet_validate(const unsigned char *data,
150
      opus_int32 len, int nb_streams, opus_int32 Fs)
151
270k
{
152
270k
   int s;
153
270k
   int count;
154
270k
   unsigned char toc;
155
270k
   opus_int16 size[48];
156
270k
   int samples=0;
157
270k
   opus_int32 packet_offset;
158
159
523k
   for (s=0;s<nb_streams;s++)
160
285k
   {
161
285k
      int tmp_samples;
162
285k
      if (len<=0)
163
238
         return OPUS_INVALID_PACKET;
164
285k
      count = opus_packet_parse_impl(data, len, s!=nb_streams-1, &toc, NULL,
165
285k
                                     size, NULL, &packet_offset, NULL, NULL);
166
285k
      if (count<0)
167
31.5k
         return count;
168
254k
      tmp_samples = opus_packet_get_nb_samples(data, packet_offset, Fs);
169
254k
      if (s!=0 && samples != tmp_samples)
170
1.31k
         return OPUS_INVALID_PACKET;
171
252k
      samples = tmp_samples;
172
252k
      data += packet_offset;
173
252k
      len -= packet_offset;
174
252k
   }
175
237k
   return samples;
176
270k
}
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
316k
{
190
316k
   opus_int32 Fs;
191
316k
   int coupled_size;
192
316k
   int mono_size;
193
316k
   int s, c;
194
316k
   char *ptr;
195
316k
   int do_plc=0;
196
316k
   VARDECL(opus_res, buf);
197
316k
   ALLOC_STACK;
198
199
316k
   VALIDATE_MS_DECODER(st);
200
316k
   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
316k
   MUST_SUCCEED(opus_multistream_decoder_ctl(st, OPUS_GET_SAMPLE_RATE(&Fs)));
207
316k
   frame_size = IMIN(frame_size, Fs/25*3);
208
316k
   ALLOC(buf, 2*frame_size, opus_res);
209
316k
   ptr = (char*)st + align(sizeof(OpusMSDecoder));
210
316k
   coupled_size = opus_decoder_get_size(2);
211
316k
   mono_size = opus_decoder_get_size(1);
212
213
316k
   if (len==0)
214
0
      do_plc = 1;
215
316k
   if (len < 0)
216
0
   {
217
0
      RESTORE_STACK;
218
0
      return OPUS_BAD_ARG;
219
0
   }
220
316k
   if (!do_plc && len < 2*st->layout.nb_streams-1)
221
45.5k
   {
222
45.5k
      RESTORE_STACK;
223
45.5k
      return OPUS_INVALID_PACKET;
224
45.5k
   }
225
270k
   if (!do_plc)
226
270k
   {
227
270k
      int ret = opus_multistream_packet_validate(data, len, st->layout.nb_streams, Fs);
228
270k
      if (ret < 0)
229
33.1k
      {
230
33.1k
         RESTORE_STACK;
231
33.1k
         return ret;
232
237k
      } else if (ret > frame_size)
233
0
      {
234
0
         RESTORE_STACK;
235
0
         return OPUS_BUFFER_TOO_SMALL;
236
0
      }
237
270k
   }
238
478k
   for (s=0;s<st->layout.nb_streams;s++)
239
241k
   {
240
241k
      OpusDecoder *dec;
241
241k
      opus_int32 packet_offset;
242
241k
      int ret;
243
244
241k
      dec = (OpusDecoder*)ptr;
245
241k
      ptr += (s < st->layout.nb_coupled_streams) ? align(coupled_size) : align(mono_size);
246
247
241k
      if (!do_plc && len<=0)
248
0
      {
249
0
         RESTORE_STACK;
250
0
         return OPUS_INTERNAL_ERROR;
251
0
      }
252
241k
      packet_offset = 0;
253
241k
      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
241k
      if (!do_plc)
255
241k
      {
256
241k
        data += packet_offset;
257
241k
        len -= packet_offset;
258
241k
      }
259
241k
      if (ret <= 0)
260
0
      {
261
0
         RESTORE_STACK;
262
0
         return ret;
263
0
      }
264
241k
      frame_size = ret;
265
241k
      if (s < st->layout.nb_coupled_streams)
266
220k
      {
267
220k
         int chan, prev;
268
220k
         prev = -1;
269
         /* Copy "left" audio to the channel(s) where it belongs */
270
435k
         while ( (chan = get_left_channel(&st->layout, s, prev)) != -1)
271
215k
         {
272
215k
            (*copy_channel_out)(pcm, st->layout.nb_channels, chan,
273
215k
               buf, 2, frame_size, user_data);
274
215k
            prev = chan;
275
215k
         }
276
220k
         prev = -1;
277
         /* Copy "right" audio to the channel(s) where it belongs */
278
446k
         while ( (chan = get_right_channel(&st->layout, s, prev)) != -1)
279
225k
         {
280
225k
            (*copy_channel_out)(pcm, st->layout.nb_channels, chan,
281
225k
               buf+1, 2, frame_size, user_data);
282
225k
            prev = chan;
283
225k
         }
284
220k
      } else {
285
20.3k
         int chan, prev;
286
20.3k
         prev = -1;
287
         /* Copy audio to the channel(s) where it belongs */
288
39.7k
         while ( (chan = get_mono_channel(&st->layout, s, prev)) != -1)
289
19.3k
         {
290
19.3k
            (*copy_channel_out)(pcm, st->layout.nb_channels, chan,
291
19.3k
               buf, 1, frame_size, user_data);
292
19.3k
            prev = chan;
293
19.3k
         }
294
20.3k
      }
295
241k
   }
296
   /* Handle muted channels */
297
699k
   for (c=0;c<st->layout.nb_channels;c++)
298
461k
   {
299
461k
      if (st->layout.mapping[c] == 255)
300
1.73k
      {
301
1.73k
         (*copy_channel_out)(pcm, st->layout.nb_channels, c,
302
1.73k
            NULL, 0, frame_size, user_data);
303
1.73k
      }
304
461k
   }
305
237k
   RESTORE_STACK;
306
237k
   return frame_size;
307
237k
}
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
461k
{
347
461k
   opus_int16 *short_dst;
348
461k
   opus_int32 i;
349
461k
   (void)user_data;
350
461k
   short_dst = (opus_int16*)dst;
351
461k
   if (src != NULL)
352
460k
   {
353
553M
      for (i=0;i<frame_size;i++)
354
552M
         short_dst[i*dst_stride+dst_channel] = RES2INT16(src[i*src_stride]);
355
460k
   }
356
1.73k
   else
357
1.73k
   {
358
1.72M
      for (i=0;i<frame_size;i++)
359
1.72M
         short_dst[i*dst_stride+dst_channel] = 0;
360
1.73k
   }
361
461k
}
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
316k
#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
316k
{
404
316k
   return opus_multistream_decode_native(st, data, len,
405
316k
       pcm, opus_copy_channel_out_short, frame_size, decode_fec, OPTIONAL_CLIP, NULL);
406
316k
}
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
470k
{
433
470k
   int coupled_size, mono_size;
434
470k
   char *ptr;
435
470k
   int ret = OPUS_OK;
436
437
470k
   coupled_size = opus_decoder_get_size(2);
438
470k
   mono_size = opus_decoder_get_size(1);
439
470k
   ptr = (char*)st + align(sizeof(OpusMSDecoder));
440
470k
   switch (request)
441
470k
   {
442
0
       case OPUS_GET_BANDWIDTH_REQUEST:
443
316k
       case OPUS_GET_SAMPLE_RATE_REQUEST:
444
316k
       case OPUS_GET_GAIN_REQUEST:
445
316k
       case OPUS_GET_LAST_PACKET_DURATION_REQUEST:
446
316k
       case OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST:
447
316k
       case OPUS_GET_COMPLEXITY_REQUEST:
448
316k
       {
449
316k
          OpusDecoder *dec;
450
          /* For int32* GET params, just query the first stream */
451
316k
          opus_int32 *value = va_arg(ap, opus_int32*);
452
316k
          dec = (OpusDecoder*)ptr;
453
316k
          ret = opus_decoder_ctl(dec, request, value);
454
316k
       }
455
316k
       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
140k
       case OPUS_RESET_STATE:
481
140k
       {
482
140k
          int s;
483
2.54M
          for (s=0;s<st->layout.nb_streams;s++)
484
2.40M
          {
485
2.40M
             OpusDecoder *dec;
486
487
2.40M
             dec = (OpusDecoder*)ptr;
488
2.40M
             if (s < st->layout.nb_coupled_streams)
489
928k
                ptr += align(coupled_size);
490
1.47M
             else
491
1.47M
                ptr += align(mono_size);
492
2.40M
             ret = opus_decoder_ctl(dec, OPUS_RESET_STATE);
493
2.40M
             if (ret != OPUS_OK)
494
0
                break;
495
2.40M
          }
496
140k
       }
497
140k
       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.67k
       case OPUS_SET_GAIN_REQUEST:
522
6.67k
       case OPUS_SET_COMPLEXITY_REQUEST:
523
13.3k
       case OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST:
524
13.3k
       {
525
13.3k
          int s;
526
          /* This works for int32 params */
527
13.3k
          opus_int32 value = va_arg(ap, opus_int32);
528
135k
          for (s=0;s<st->layout.nb_streams;s++)
529
121k
          {
530
121k
             OpusDecoder *dec;
531
532
121k
             dec = (OpusDecoder*)ptr;
533
121k
             if (s < st->layout.nb_coupled_streams)
534
28.0k
                ptr += align(coupled_size);
535
93.5k
             else
536
93.5k
                ptr += align(mono_size);
537
121k
             ret = opus_decoder_ctl(dec, request, value);
538
121k
             if (ret != OPUS_OK)
539
0
                break;
540
121k
          }
541
13.3k
       }
542
13.3k
       break;
543
0
       default:
544
0
          ret = OPUS_UNIMPLEMENTED;
545
0
       break;
546
470k
   }
547
470k
   return ret;
548
0
bad_arg:
549
0
   return OPUS_BAD_ARG;
550
470k
}
551
552
int opus_multistream_decoder_ctl(OpusMSDecoder *st, int request, ...)
553
470k
{
554
470k
   int ret;
555
470k
   va_list ap;
556
470k
   va_start(ap, request);
557
470k
   ret = opus_multistream_decoder_ctl_va_list(st, request, ap);
558
470k
   va_end(ap);
559
470k
   return ret;
560
470k
}
561
562
void opus_multistream_decoder_destroy(OpusMSDecoder *st)
563
6.67k
{
564
6.67k
    opus_free(st);
565
6.67k
}