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