Coverage Report

Created: 2024-02-11 07:34

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