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