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