Coverage Report

Created: 2025-03-11 07:31

/src/opus/src/repacketizer.c
Line
Count
Source (jump to first uncovered line)
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.h"
33
#include "opus_private.h"
34
#include "os_support.h"
35
#include "stack_alloc.h"
36
37
38
int opus_repacketizer_get_size(void)
39
2.98k
{
40
2.98k
   return sizeof(OpusRepacketizer);
41
2.98k
}
42
43
OpusRepacketizer *opus_repacketizer_init(OpusRepacketizer *rp)
44
321k
{
45
321k
   rp->nb_frames = 0;
46
321k
   return rp;
47
321k
}
48
49
OpusRepacketizer *opus_repacketizer_create(void)
50
2.98k
{
51
2.98k
   OpusRepacketizer *rp;
52
2.98k
   rp=(OpusRepacketizer *)opus_alloc(opus_repacketizer_get_size());
53
2.98k
   if(rp==NULL)return NULL;
54
2.98k
   return opus_repacketizer_init(rp);
55
2.98k
}
56
57
void opus_repacketizer_destroy(OpusRepacketizer *rp)
58
2.98k
{
59
2.98k
   opus_free(rp);
60
2.98k
}
61
62
static int opus_repacketizer_cat_impl(OpusRepacketizer *rp, const unsigned char *data, opus_int32 len, int self_delimited)
63
413k
{
64
413k
   unsigned char tmp_toc;
65
413k
   int curr_nb_frames,ret;
66
   /* Set of check ToC */
67
413k
   if (len<1) return OPUS_INVALID_PACKET;
68
412k
   if (rp->nb_frames == 0)
69
321k
   {
70
321k
      rp->toc = data[0];
71
321k
      rp->framesize = opus_packet_get_samples_per_frame(data, 8000);
72
321k
   } else if ((rp->toc&0xFC) != (data[0]&0xFC))
73
164
   {
74
      /*fprintf(stderr, "toc mismatch: 0x%x vs 0x%x\n", rp->toc, data[0]);*/
75
164
      return OPUS_INVALID_PACKET;
76
164
   }
77
412k
   curr_nb_frames = opus_packet_get_nb_frames(data, len);
78
412k
   if(curr_nb_frames<1) return OPUS_INVALID_PACKET;
79
80
   /* Check the 120 ms maximum packet size */
81
411k
   if ((curr_nb_frames+rp->nb_frames)*rp->framesize > 960)
82
186
   {
83
186
      return OPUS_INVALID_PACKET;
84
186
   }
85
86
411k
   ret=opus_packet_parse_impl(data, len, self_delimited, &tmp_toc, &rp->frames[rp->nb_frames], &rp->len[rp->nb_frames],
87
411k
       NULL, NULL, &rp->paddings[rp->nb_frames], &rp->padding_len[rp->nb_frames]);
88
411k
   if(ret<1)return ret;
89
408k
   rp->padding_nb_frames[rp->nb_frames]=ret;
90
91
   /* set padding length to zero for all but the first frame */
92
572k
   while (curr_nb_frames > 1)
93
163k
   {
94
163k
      rp->nb_frames++;
95
163k
      rp->padding_len[rp->nb_frames] = 0;
96
163k
      rp->padding_nb_frames[rp->nb_frames] = 0;
97
163k
      rp->paddings[rp->nb_frames] = NULL;
98
163k
      curr_nb_frames--;
99
163k
   }
100
408k
   rp->nb_frames++;
101
408k
   return OPUS_OK;
102
411k
}
103
104
int opus_repacketizer_cat(OpusRepacketizer *rp, const unsigned char *data, opus_int32 len)
105
413k
{
106
413k
   return opus_repacketizer_cat_impl(rp, data, len, 0);
107
413k
}
108
109
int opus_repacketizer_get_nb_frames(OpusRepacketizer *rp)
110
220k
{
111
220k
   return rp->nb_frames;
112
220k
}
113
114
opus_int32 opus_repacketizer_out_range_impl(OpusRepacketizer *rp, int begin, int end,
115
      unsigned char *data, opus_int32 maxlen, int self_delimited, int pad, const opus_extension_data *extensions, int nb_extensions)
116
318k
{
117
318k
   int i, count;
118
318k
   opus_int32 tot_size;
119
318k
   opus_int16 *len;
120
318k
   const unsigned char **frames;
121
318k
   unsigned char * ptr;
122
318k
   int ones_begin=0, ones_end=0;
123
318k
   int ext_begin=0, ext_len=0;
124
318k
   int ext_count, total_ext_count;
125
318k
   VARDECL(opus_extension_data, all_extensions);
126
318k
   SAVE_STACK;
127
128
318k
   if (begin<0 || begin>=end || end>rp->nb_frames)
129
731
   {
130
      /*fprintf(stderr, "%d %d %d\n", begin, end, rp->nb_frames);*/
131
731
      RESTORE_STACK;
132
731
      return OPUS_BAD_ARG;
133
731
   }
134
318k
   count = end-begin;
135
136
318k
   len = rp->len+begin;
137
318k
   frames = rp->frames+begin;
138
318k
   if (self_delimited)
139
187k
      tot_size = 1 + (len[count-1]>=252);
140
130k
   else
141
130k
      tot_size = 0;
142
143
   /* figure out total number of extensions */
144
318k
   total_ext_count = nb_extensions;
145
890k
   for (i=begin;i<end;i++)
146
572k
   {
147
572k
      int n = opus_packet_extensions_count(rp->paddings[i], rp->padding_len[i],
148
572k
       rp->padding_nb_frames[i]);
149
572k
      if (n > 0) total_ext_count += n;
150
572k
   }
151
318k
   ALLOC(all_extensions, total_ext_count ? total_ext_count : ALLOC_NONE, opus_extension_data);
152
   /* copy over any extensions that were passed in */
153
318k
   for (ext_count=0;ext_count<nb_extensions;ext_count++)
154
0
   {
155
0
      all_extensions[ext_count] = extensions[ext_count];
156
0
   }
157
158
   /* incorporate any extensions from the repacketizer padding */
159
884k
   for (i=begin;i<end;i++)
160
566k
   {
161
566k
      int j, ret;
162
566k
      opus_int32 frame_ext_count;
163
566k
      frame_ext_count = total_ext_count - ext_count;
164
566k
      ret = opus_packet_extensions_parse(rp->paddings[i], rp->padding_len[i],
165
566k
         &all_extensions[ext_count], &frame_ext_count, rp->padding_nb_frames[i]);
166
566k
      if (ret<0)
167
438
      {
168
438
         RESTORE_STACK;
169
438
         return OPUS_INTERNAL_ERROR;
170
438
      }
171
      /* renumber the extension frame numbers */
172
6.63M
      for (j=0;j<frame_ext_count;j++)
173
6.07M
      {
174
6.07M
         all_extensions[ext_count+j].frame += i-begin;
175
6.07M
      }
176
566k
      ext_count += frame_ext_count;
177
566k
   }
178
179
317k
   ptr = data;
180
317k
   if (count==1)
181
233k
   {
182
      /* Code 0 */
183
233k
      tot_size += len[0]+1;
184
233k
      if (tot_size > maxlen)
185
0
      {
186
0
         RESTORE_STACK;
187
0
         return OPUS_BUFFER_TOO_SMALL;
188
0
      }
189
233k
      *ptr++ = rp->toc&0xFC;
190
233k
   } else if (count==2)
191
34.1k
   {
192
34.1k
      if (len[1] == len[0])
193
13.6k
      {
194
         /* Code 1 */
195
13.6k
         tot_size += 2*len[0]+1;
196
13.6k
         if (tot_size > maxlen)
197
0
         {
198
0
            RESTORE_STACK;
199
0
            return OPUS_BUFFER_TOO_SMALL;
200
0
         }
201
13.6k
         *ptr++ = (rp->toc&0xFC) | 0x1;
202
20.4k
      } else {
203
         /* Code 2 */
204
20.4k
         tot_size += len[0]+len[1]+2+(len[0]>=252);
205
20.4k
         if (tot_size > maxlen)
206
0
         {
207
0
            RESTORE_STACK;
208
0
            return OPUS_BUFFER_TOO_SMALL;
209
0
         }
210
20.4k
         *ptr++ = (rp->toc&0xFC) | 0x2;
211
20.4k
         ptr += encode_size(len[0], ptr);
212
20.4k
      }
213
34.1k
   }
214
317k
   if (count > 2 || (pad && tot_size < maxlen) || ext_count > 0)
215
125k
   {
216
      /* Code 3 */
217
125k
      int vbr;
218
125k
      int pad_amount=0;
219
220
      /* Restart the process for the padding case */
221
125k
      ptr = data;
222
125k
      if (self_delimited)
223
21.8k
         tot_size = 1 + (len[count-1]>=252);
224
103k
      else
225
103k
         tot_size = 0;
226
125k
      vbr = 0;
227
241k
      for (i=1;i<count;i++)
228
149k
      {
229
149k
         if (len[i] != len[0])
230
33.6k
         {
231
33.6k
            vbr=1;
232
33.6k
            break;
233
33.6k
         }
234
149k
      }
235
125k
      if (vbr)
236
33.6k
      {
237
33.6k
         tot_size += 2;
238
153k
         for (i=0;i<count-1;i++)
239
119k
            tot_size += 1 + (len[i]>=252) + len[i];
240
33.6k
         tot_size += len[count-1];
241
242
33.6k
         if (tot_size > maxlen)
243
31
         {
244
31
            RESTORE_STACK;
245
31
            return OPUS_BUFFER_TOO_SMALL;
246
31
         }
247
33.5k
         *ptr++ = (rp->toc&0xFC) | 0x3;
248
33.5k
         *ptr++ = count | 0x80;
249
91.8k
      } else {
250
91.8k
         tot_size += count*len[0]+2;
251
91.8k
         if (tot_size > maxlen)
252
12
         {
253
12
            RESTORE_STACK;
254
12
            return OPUS_BUFFER_TOO_SMALL;
255
12
         }
256
91.8k
         *ptr++ = (rp->toc&0xFC) | 0x3;
257
91.8k
         *ptr++ = count;
258
91.8k
      }
259
125k
      pad_amount = pad ? (maxlen-tot_size) : 0;
260
125k
      if (ext_count>0)
261
1.09k
      {
262
         /* figure out how much space we need for the extensions */
263
1.09k
         ext_len = opus_packet_extensions_generate(NULL, maxlen-tot_size,
264
1.09k
          all_extensions, ext_count, count, 0);
265
1.09k
         if (ext_len < 0) return ext_len;
266
1.04k
         if (!pad)
267
1.04k
            pad_amount = ext_len + ext_len/254 + 1;
268
1.04k
      }
269
125k
      if (pad_amount != 0)
270
77.6k
      {
271
77.6k
         int nb_255s;
272
77.6k
         data[1] |= 0x40;
273
77.6k
         nb_255s = (pad_amount-1)/255;
274
77.6k
         if (tot_size + ext_len + nb_255s + 1 > maxlen)
275
70
         {
276
70
            RESTORE_STACK;
277
70
            return OPUS_BUFFER_TOO_SMALL;
278
70
         }
279
77.5k
         ext_begin = tot_size+pad_amount-ext_len;
280
         /* Prepend 0x01 padding */
281
77.5k
         ones_begin = tot_size+nb_255s+1;
282
77.5k
         ones_end = tot_size+pad_amount-ext_len;
283
85.4k
         for (i=0;i<nb_255s;i++)
284
7.87k
            *ptr++ = 255;
285
77.5k
         *ptr++ = pad_amount-255*nb_255s-1;
286
77.5k
         tot_size += pad_amount;
287
77.5k
      }
288
125k
      if (vbr)
289
33.4k
      {
290
147k
         for (i=0;i<count-1;i++)
291
113k
            ptr += encode_size(len[i], ptr);
292
33.4k
      }
293
125k
   }
294
317k
   if (self_delimited) {
295
187k
      int sdlen = encode_size(len[count-1], ptr);
296
187k
      ptr += sdlen;
297
187k
   }
298
   /* Copy the actual data */
299
877k
   for (i=0;i<count;i++)
300
559k
   {
301
      /* Using OPUS_MOVE() instead of OPUS_COPY() in case we're doing in-place
302
         padding from opus_packet_pad or opus_packet_unpad(). */
303
      /* assert disabled because it's not valid in C. */
304
      /* celt_assert(frames[i] + len[i] <= data || ptr <= frames[i]); */
305
559k
      OPUS_MOVE(ptr, frames[i], len[i]);
306
559k
      ptr += len[i];
307
559k
   }
308
317k
   if (ext_len > 0) {
309
977
      int ret = opus_packet_extensions_generate(&data[ext_begin], ext_len,
310
977
       all_extensions, ext_count, count, 0);
311
977
      celt_assert(ret == ext_len);
312
977
   }
313
5.09M
   for (i=ones_begin;i<ones_end;i++)
314
4.77M
      data[i] = 0x01;
315
317k
   if (pad && ext_count==0)
316
90.8k
   {
317
      /* Fill padding with zeros. */
318
4.86M
      while (ptr<data+maxlen)
319
4.77M
         *ptr++=0;
320
90.8k
   }
321
317k
   RESTORE_STACK;
322
317k
   return tot_size;
323
317k
}
324
325
opus_int32 opus_repacketizer_out_range(OpusRepacketizer *rp, int begin, int end, unsigned char *data, opus_int32 maxlen)
326
0
{
327
0
   return opus_repacketizer_out_range_impl(rp, begin, end, data, maxlen, 0, 0, NULL, 0);
328
0
}
329
330
opus_int32 opus_repacketizer_out(OpusRepacketizer *rp, unsigned char *data, opus_int32 maxlen)
331
2.98k
{
332
2.98k
   return opus_repacketizer_out_range_impl(rp, 0, rp->nb_frames, data, maxlen, 0, 0, NULL, 0);
333
2.98k
}
334
335
opus_int32 opus_packet_pad_impl(unsigned char *data, opus_int32 len, opus_int32 new_len, int pad, const opus_extension_data  *extensions, int nb_extensions)
336
109k
{
337
109k
   OpusRepacketizer rp;
338
109k
   opus_int32 ret;
339
109k
   VARDECL(unsigned char, copy);
340
109k
   SAVE_STACK;
341
109k
   if (len < 1)
342
0
      return OPUS_BAD_ARG;
343
109k
   if (len==new_len)
344
48.3k
      return OPUS_OK;
345
61.3k
   else if (len > new_len)
346
0
      return OPUS_BAD_ARG;
347
61.3k
   ALLOC(copy, len, unsigned char);
348
61.3k
   opus_repacketizer_init(&rp);
349
   /* Moving payload to the end of the packet so we can do in-place padding */
350
61.3k
   OPUS_COPY(copy, data, len);
351
61.3k
   ret = opus_repacketizer_cat(&rp, copy, len);
352
61.3k
   if (ret != OPUS_OK)
353
0
      return ret;
354
61.3k
   ret = opus_repacketizer_out_range_impl(&rp, 0, rp.nb_frames, data, new_len, 0, pad, extensions, nb_extensions);
355
61.3k
   RESTORE_STACK;
356
61.3k
   return ret;
357
61.3k
}
358
359
int opus_packet_pad(unsigned char *data, opus_int32 len, opus_int32 new_len)
360
109k
{
361
109k
   opus_int32 ret;
362
109k
   ALLOC_STACK;
363
109k
   ret = opus_packet_pad_impl(data, len, new_len, 1, NULL, 0);
364
109k
   RESTORE_STACK;
365
109k
   if (ret > 0)
366
61.3k
      return OPUS_OK;
367
48.3k
   else
368
48.3k
      return ret;
369
109k
}
370
371
opus_int32 opus_packet_unpad(unsigned char *data, opus_int32 len)
372
0
{
373
0
   OpusRepacketizer rp;
374
0
   opus_int32 ret;
375
0
   int i;
376
0
   if (len < 1)
377
0
      return OPUS_BAD_ARG;
378
0
   opus_repacketizer_init(&rp);
379
0
   ret = opus_repacketizer_cat(&rp, data, len);
380
0
   if (ret < 0)
381
0
      return ret;
382
   /* Discard all padding and extensions. */
383
0
   for (i=0;i<rp.nb_frames;i++) {
384
0
      rp.padding_len[i] = 0;
385
0
      rp.paddings[i] = NULL;
386
0
   }
387
0
   ret = opus_repacketizer_out_range_impl(&rp, 0, rp.nb_frames, data, len, 0, 0, NULL, 0);
388
0
   celt_assert(ret > 0 && ret <= len);
389
0
   return ret;
390
0
}
391
392
int opus_multistream_packet_pad(unsigned char *data, opus_int32 len, opus_int32 new_len, int nb_streams)
393
0
{
394
0
   int s;
395
0
   int count;
396
0
   unsigned char toc;
397
0
   opus_int16 size[48];
398
0
   opus_int32 packet_offset;
399
0
   opus_int32 amount;
400
401
0
   if (len < 1)
402
0
      return OPUS_BAD_ARG;
403
0
   if (len==new_len)
404
0
      return OPUS_OK;
405
0
   else if (len > new_len)
406
0
      return OPUS_BAD_ARG;
407
0
   amount = new_len - len;
408
   /* Seek to last stream */
409
0
   for (s=0;s<nb_streams-1;s++)
410
0
   {
411
0
      if (len<=0)
412
0
         return OPUS_INVALID_PACKET;
413
0
      count = opus_packet_parse_impl(data, len, 1, &toc, NULL,
414
0
                                     size, NULL, &packet_offset, NULL, NULL);
415
0
      if (count<0)
416
0
         return count;
417
0
      data += packet_offset;
418
0
      len -= packet_offset;
419
0
   }
420
0
   return opus_packet_pad(data, len, len+amount);
421
0
}
422
423
opus_int32 opus_multistream_packet_unpad(unsigned char *data, opus_int32 len, int nb_streams)
424
0
{
425
0
   int s;
426
0
   unsigned char toc;
427
0
   opus_int16 size[48];
428
0
   opus_int32 packet_offset;
429
0
   OpusRepacketizer rp;
430
0
   unsigned char *dst;
431
0
   opus_int32 dst_len;
432
433
0
   if (len < 1)
434
0
      return OPUS_BAD_ARG;
435
0
   dst = data;
436
0
   dst_len = 0;
437
   /* Unpad all frames */
438
0
   for (s=0;s<nb_streams;s++)
439
0
   {
440
0
      opus_int32 ret;
441
0
      int i;
442
0
      int self_delimited = s!=nb_streams-1;
443
0
      if (len<=0)
444
0
         return OPUS_INVALID_PACKET;
445
0
      opus_repacketizer_init(&rp);
446
0
      ret = opus_packet_parse_impl(data, len, self_delimited, &toc, NULL,
447
0
                                     size, NULL, &packet_offset, NULL, NULL);
448
0
      if (ret<0)
449
0
         return ret;
450
0
      ret = opus_repacketizer_cat_impl(&rp, data, packet_offset, self_delimited);
451
0
      if (ret < 0)
452
0
         return ret;
453
      /* Discard all padding and extensions. */
454
0
      for (i=0;i<rp.nb_frames;i++) {
455
0
         rp.padding_len[i] = 0;
456
0
         rp.paddings[i] = NULL;
457
0
      }
458
0
      ret = opus_repacketizer_out_range_impl(&rp, 0, rp.nb_frames, dst, len, self_delimited, 0, NULL, 0);
459
0
      if (ret < 0)
460
0
         return ret;
461
0
      else
462
0
         dst_len += ret;
463
0
      dst += ret;
464
0
      data += packet_offset;
465
0
      len -= packet_offset;
466
0
   }
467
0
   return dst_len;
468
0
}
469