| OLD | NEW |
| 1 /* Copyright (c) 2011 Xiph.Org Foundation | 1 /* Copyright (c) 2011 Xiph.Org Foundation |
| 2 Written by Jean-Marc Valin */ | 2 Written by Jean-Marc Valin */ |
| 3 /* | 3 /* |
| 4 Redistribution and use in source and binary forms, with or without | 4 Redistribution and use in source and binary forms, with or without |
| 5 modification, are permitted provided that the following conditions | 5 modification, are permitted provided that the following conditions |
| 6 are met: | 6 are met: |
| 7 | 7 |
| 8 - Redistributions of source code must retain the above copyright | 8 - Redistributions of source code must retain the above copyright |
| 9 notice, this list of conditions and the following disclaimer. | 9 notice, this list of conditions and the following disclaimer. |
| 10 | 10 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 51 rp=(OpusRepacketizer *)opus_alloc(opus_repacketizer_get_size()); | 51 rp=(OpusRepacketizer *)opus_alloc(opus_repacketizer_get_size()); |
| 52 if(rp==NULL)return NULL; | 52 if(rp==NULL)return NULL; |
| 53 return opus_repacketizer_init(rp); | 53 return opus_repacketizer_init(rp); |
| 54 } | 54 } |
| 55 | 55 |
| 56 void opus_repacketizer_destroy(OpusRepacketizer *rp) | 56 void opus_repacketizer_destroy(OpusRepacketizer *rp) |
| 57 { | 57 { |
| 58 opus_free(rp); | 58 opus_free(rp); |
| 59 } | 59 } |
| 60 | 60 |
| 61 int opus_repacketizer_cat(OpusRepacketizer *rp, const unsigned char *data, opus_
int32 len) | 61 static int opus_repacketizer_cat_impl(OpusRepacketizer *rp, const unsigned char
*data, opus_int32 len, int self_delimited) |
| 62 { | 62 { |
| 63 unsigned char tmp_toc; | 63 unsigned char tmp_toc; |
| 64 int curr_nb_frames,ret; | 64 int curr_nb_frames,ret; |
| 65 /* Set of check ToC */ | 65 /* Set of check ToC */ |
| 66 if (len<1) return OPUS_INVALID_PACKET; | 66 if (len<1) return OPUS_INVALID_PACKET; |
| 67 if (rp->nb_frames == 0) | 67 if (rp->nb_frames == 0) |
| 68 { | 68 { |
| 69 rp->toc = data[0]; | 69 rp->toc = data[0]; |
| 70 rp->framesize = opus_packet_get_samples_per_frame(data, 8000); | 70 rp->framesize = opus_packet_get_samples_per_frame(data, 8000); |
| 71 } else if ((rp->toc&0xFC) != (data[0]&0xFC)) | 71 } else if ((rp->toc&0xFC) != (data[0]&0xFC)) |
| 72 { | 72 { |
| 73 /*fprintf(stderr, "toc mismatch: 0x%x vs 0x%x\n", rp->toc, data[0]);*/ | 73 /*fprintf(stderr, "toc mismatch: 0x%x vs 0x%x\n", rp->toc, data[0]);*/ |
| 74 return OPUS_INVALID_PACKET; | 74 return OPUS_INVALID_PACKET; |
| 75 } | 75 } |
| 76 curr_nb_frames = opus_packet_get_nb_frames(data, len); | 76 curr_nb_frames = opus_packet_get_nb_frames(data, len); |
| 77 if(curr_nb_frames<1) return OPUS_INVALID_PACKET; | 77 if(curr_nb_frames<1) return OPUS_INVALID_PACKET; |
| 78 | 78 |
| 79 /* Check the 120 ms maximum packet size */ | 79 /* Check the 120 ms maximum packet size */ |
| 80 if ((curr_nb_frames+rp->nb_frames)*rp->framesize > 960) | 80 if ((curr_nb_frames+rp->nb_frames)*rp->framesize > 960) |
| 81 { | 81 { |
| 82 return OPUS_INVALID_PACKET; | 82 return OPUS_INVALID_PACKET; |
| 83 } | 83 } |
| 84 | 84 |
| 85 ret=opus_packet_parse(data, len, &tmp_toc, &rp->frames[rp->nb_frames], &rp->l
en[rp->nb_frames], NULL); | 85 ret=opus_packet_parse_impl(data, len, self_delimited, &tmp_toc, &rp->frames[r
p->nb_frames], &rp->len[rp->nb_frames], NULL, NULL); |
| 86 if(ret<1)return ret; | 86 if(ret<1)return ret; |
| 87 | 87 |
| 88 rp->nb_frames += curr_nb_frames; | 88 rp->nb_frames += curr_nb_frames; |
| 89 return OPUS_OK; | 89 return OPUS_OK; |
| 90 } | 90 } |
| 91 | 91 |
| 92 int opus_repacketizer_cat(OpusRepacketizer *rp, const unsigned char *data, opus_
int32 len) |
| 93 { |
| 94 return opus_repacketizer_cat_impl(rp, data, len, 0); |
| 95 } |
| 96 |
| 92 int opus_repacketizer_get_nb_frames(OpusRepacketizer *rp) | 97 int opus_repacketizer_get_nb_frames(OpusRepacketizer *rp) |
| 93 { | 98 { |
| 94 return rp->nb_frames; | 99 return rp->nb_frames; |
| 95 } | 100 } |
| 96 | 101 |
| 97 opus_int32 opus_repacketizer_out_range_impl(OpusRepacketizer *rp, int begin, int
end, unsigned char *data, opus_int32 maxlen, int self_delimited) | 102 opus_int32 opus_repacketizer_out_range_impl(OpusRepacketizer *rp, int begin, int
end, |
| 103 unsigned char *data, opus_int32 maxlen, int self_delimited, int pad) |
| 98 { | 104 { |
| 99 int i, count; | 105 int i, count; |
| 100 opus_int32 tot_size; | 106 opus_int32 tot_size; |
| 101 opus_int16 *len; | 107 opus_int16 *len; |
| 102 const unsigned char **frames; | 108 const unsigned char **frames; |
| 109 unsigned char * ptr; |
| 103 | 110 |
| 104 if (begin<0 || begin>=end || end>rp->nb_frames) | 111 if (begin<0 || begin>=end || end>rp->nb_frames) |
| 105 { | 112 { |
| 106 /*fprintf(stderr, "%d %d %d\n", begin, end, rp->nb_frames);*/ | 113 /*fprintf(stderr, "%d %d %d\n", begin, end, rp->nb_frames);*/ |
| 107 return OPUS_BAD_ARG; | 114 return OPUS_BAD_ARG; |
| 108 } | 115 } |
| 109 count = end-begin; | 116 count = end-begin; |
| 110 | 117 |
| 111 len = rp->len+begin; | 118 len = rp->len+begin; |
| 112 frames = rp->frames+begin; | 119 frames = rp->frames+begin; |
| 113 if (self_delimited) | 120 if (self_delimited) |
| 114 tot_size = 1 + (len[count-1]>=252); | 121 tot_size = 1 + (len[count-1]>=252); |
| 115 else | 122 else |
| 116 tot_size = 0; | 123 tot_size = 0; |
| 117 | 124 |
| 118 switch (count) | 125 ptr = data; |
| 119 { | 126 if (count==1) |
| 120 case 1: | |
| 121 { | 127 { |
| 122 /* Code 0 */ | 128 /* Code 0 */ |
| 123 tot_size += len[0]+1; | 129 tot_size += len[0]+1; |
| 124 if (tot_size > maxlen) | 130 if (tot_size > maxlen) |
| 125 return OPUS_BUFFER_TOO_SMALL; | 131 return OPUS_BUFFER_TOO_SMALL; |
| 126 *data++ = rp->toc&0xFC; | 132 *ptr++ = rp->toc&0xFC; |
| 127 } | 133 } else if (count==2) |
| 128 break; | |
| 129 case 2: | |
| 130 { | 134 { |
| 131 if (len[1] == len[0]) | 135 if (len[1] == len[0]) |
| 132 { | 136 { |
| 133 /* Code 1 */ | 137 /* Code 1 */ |
| 134 tot_size += 2*len[0]+1; | 138 tot_size += 2*len[0]+1; |
| 135 if (tot_size > maxlen) | 139 if (tot_size > maxlen) |
| 136 return OPUS_BUFFER_TOO_SMALL; | 140 return OPUS_BUFFER_TOO_SMALL; |
| 137 *data++ = (rp->toc&0xFC) | 0x1; | 141 *ptr++ = (rp->toc&0xFC) | 0x1; |
| 138 } else { | 142 } else { |
| 139 /* Code 2 */ | 143 /* Code 2 */ |
| 140 tot_size += len[0]+len[1]+2+(len[0]>=252); | 144 tot_size += len[0]+len[1]+2+(len[0]>=252); |
| 141 if (tot_size > maxlen) | 145 if (tot_size > maxlen) |
| 142 return OPUS_BUFFER_TOO_SMALL; | 146 return OPUS_BUFFER_TOO_SMALL; |
| 143 *data++ = (rp->toc&0xFC) | 0x2; | 147 *ptr++ = (rp->toc&0xFC) | 0x2; |
| 144 data += encode_size(len[0], data); | 148 ptr += encode_size(len[0], ptr); |
| 145 } | 149 } |
| 146 } | 150 } |
| 147 break; | 151 if (count > 2 || (pad && tot_size < maxlen)) |
| 148 default: | |
| 149 { | 152 { |
| 150 /* Code 3 */ | 153 /* Code 3 */ |
| 151 int vbr; | 154 int vbr; |
| 155 int pad_amount=0; |
| 152 | 156 |
| 157 /* Restart the process for the padding case */ |
| 158 ptr = data; |
| 159 if (self_delimited) |
| 160 tot_size = 1 + (len[count-1]>=252); |
| 161 else |
| 162 tot_size = 0; |
| 153 vbr = 0; | 163 vbr = 0; |
| 154 for (i=1;i<count;i++) | 164 for (i=1;i<count;i++) |
| 155 { | 165 { |
| 156 if (len[i] != len[0]) | 166 if (len[i] != len[0]) |
| 157 { | 167 { |
| 158 vbr=1; | 168 vbr=1; |
| 159 break; | 169 break; |
| 160 } | 170 } |
| 161 } | 171 } |
| 162 if (vbr) | 172 if (vbr) |
| 163 { | 173 { |
| 164 tot_size += 2; | 174 tot_size += 2; |
| 165 for (i=0;i<count-1;i++) | 175 for (i=0;i<count-1;i++) |
| 166 tot_size += 1 + (len[i]>=252) + len[i]; | 176 tot_size += 1 + (len[i]>=252) + len[i]; |
| 167 tot_size += len[count-1]; | 177 tot_size += len[count-1]; |
| 168 | 178 |
| 169 if (tot_size > maxlen) | 179 if (tot_size > maxlen) |
| 170 return OPUS_BUFFER_TOO_SMALL; | 180 return OPUS_BUFFER_TOO_SMALL; |
| 171 *data++ = (rp->toc&0xFC) | 0x3; | 181 *ptr++ = (rp->toc&0xFC) | 0x3; |
| 172 *data++ = count | 0x80; | 182 *ptr++ = count | 0x80; |
| 173 for (i=0;i<count-1;i++) | |
| 174 data += encode_size(len[i], data); | |
| 175 } else { | 183 } else { |
| 176 tot_size += count*len[0]+2; | 184 tot_size += count*len[0]+2; |
| 177 if (tot_size > maxlen) | 185 if (tot_size > maxlen) |
| 178 return OPUS_BUFFER_TOO_SMALL; | 186 return OPUS_BUFFER_TOO_SMALL; |
| 179 *data++ = (rp->toc&0xFC) | 0x3; | 187 *ptr++ = (rp->toc&0xFC) | 0x3; |
| 180 *data++ = count; | 188 *ptr++ = count; |
| 189 } |
| 190 pad_amount = pad ? (maxlen-tot_size) : 0; |
| 191 if (pad_amount != 0) |
| 192 { |
| 193 int nb_255s; |
| 194 data[1] |= 0x40; |
| 195 nb_255s = (pad_amount-1)/255; |
| 196 for (i=0;i<nb_255s;i++) |
| 197 *ptr++ = 255; |
| 198 *ptr++ = pad_amount-255*nb_255s-1; |
| 199 tot_size += pad_amount; |
| 200 } |
| 201 if (vbr) |
| 202 { |
| 203 for (i=0;i<count-1;i++) |
| 204 ptr += encode_size(len[i], ptr); |
| 181 } | 205 } |
| 182 } | 206 } |
| 183 break; | |
| 184 } | |
| 185 if (self_delimited) { | 207 if (self_delimited) { |
| 186 int sdlen = encode_size(len[count-1], data); | 208 int sdlen = encode_size(len[count-1], ptr); |
| 187 data += sdlen; | 209 ptr += sdlen; |
| 188 } | 210 } |
| 189 /* Copy the actual data */ | 211 /* Copy the actual data */ |
| 190 for (i=0;i<count;i++) | 212 for (i=0;i<count;i++) |
| 191 { | 213 { |
| 192 OPUS_COPY(data, frames[i], len[i]); | 214 /* Using OPUS_MOVE() instead of OPUS_COPY() in case we're doing in-place |
| 193 data += len[i]; | 215 padding from opus_packet_pad or opus_packet_unpad(). */ |
| 216 celt_assert(frames[i] + len[i] <= data || ptr <= frames[i]); |
| 217 OPUS_MOVE(ptr, frames[i], len[i]); |
| 218 ptr += len[i]; |
| 219 } |
| 220 if (pad) |
| 221 { |
| 222 for (i=ptr-data;i<maxlen;i++) |
| 223 data[i] = 0; |
| 194 } | 224 } |
| 195 return tot_size; | 225 return tot_size; |
| 196 } | 226 } |
| 197 | 227 |
| 198 opus_int32 opus_repacketizer_out_range(OpusRepacketizer *rp, int begin, int end,
unsigned char *data, opus_int32 maxlen) | 228 opus_int32 opus_repacketizer_out_range(OpusRepacketizer *rp, int begin, int end,
unsigned char *data, opus_int32 maxlen) |
| 199 { | 229 { |
| 200 return opus_repacketizer_out_range_impl(rp, begin, end, data, maxlen, 0); | 230 return opus_repacketizer_out_range_impl(rp, begin, end, data, maxlen, 0, 0); |
| 201 } | 231 } |
| 202 | 232 |
| 203 opus_int32 opus_repacketizer_out(OpusRepacketizer *rp, unsigned char *data, opus
_int32 maxlen) | 233 opus_int32 opus_repacketizer_out(OpusRepacketizer *rp, unsigned char *data, opus
_int32 maxlen) |
| 204 { | 234 { |
| 205 return opus_repacketizer_out_range_impl(rp, 0, rp->nb_frames, data, maxlen, 0
); | 235 return opus_repacketizer_out_range_impl(rp, 0, rp->nb_frames, data, maxlen, 0
, 0); |
| 206 } | 236 } |
| 207 | 237 |
| 238 int opus_packet_pad(unsigned char *data, opus_int32 len, opus_int32 new_len) |
| 239 { |
| 240 OpusRepacketizer rp; |
| 241 opus_int32 ret; |
| 242 if (len < 1) |
| 243 return OPUS_BAD_ARG; |
| 244 if (len==new_len) |
| 245 return OPUS_OK; |
| 246 else if (len > new_len) |
| 247 return OPUS_BAD_ARG; |
| 248 opus_repacketizer_init(&rp); |
| 249 /* Moving payload to the end of the packet so we can do in-place padding */ |
| 250 OPUS_MOVE(data+new_len-len, data, len); |
| 251 opus_repacketizer_cat(&rp, data+new_len-len, len); |
| 252 ret = opus_repacketizer_out_range_impl(&rp, 0, rp.nb_frames, data, new_len, 0
, 1); |
| 253 if (ret > 0) |
| 254 return OPUS_OK; |
| 255 else |
| 256 return ret; |
| 257 } |
| 208 | 258 |
| 259 opus_int32 opus_packet_unpad(unsigned char *data, opus_int32 len) |
| 260 { |
| 261 OpusRepacketizer rp; |
| 262 opus_int32 ret; |
| 263 if (len < 1) |
| 264 return OPUS_BAD_ARG; |
| 265 opus_repacketizer_init(&rp); |
| 266 ret = opus_repacketizer_cat(&rp, data, len); |
| 267 if (ret < 0) |
| 268 return ret; |
| 269 ret = opus_repacketizer_out_range_impl(&rp, 0, rp.nb_frames, data, len, 0, 0)
; |
| 270 celt_assert(ret > 0 && ret <= len); |
| 271 return ret; |
| 272 } |
| 273 |
| 274 int opus_multistream_packet_pad(unsigned char *data, opus_int32 len, opus_int32
new_len, int nb_streams) |
| 275 { |
| 276 int s; |
| 277 int count; |
| 278 unsigned char toc; |
| 279 opus_int16 size[48]; |
| 280 opus_int32 packet_offset; |
| 281 opus_int32 amount; |
| 282 |
| 283 if (len < 1) |
| 284 return OPUS_BAD_ARG; |
| 285 if (len==new_len) |
| 286 return OPUS_OK; |
| 287 else if (len > new_len) |
| 288 return OPUS_BAD_ARG; |
| 289 amount = new_len - len; |
| 290 /* Seek to last stream */ |
| 291 for (s=0;s<nb_streams-1;s++) |
| 292 { |
| 293 if (len<=0) |
| 294 return OPUS_INVALID_PACKET; |
| 295 count = opus_packet_parse_impl(data, len, 1, &toc, NULL, |
| 296 size, NULL, &packet_offset); |
| 297 if (count<0) |
| 298 return count; |
| 299 data += packet_offset; |
| 300 len -= packet_offset; |
| 301 } |
| 302 return opus_packet_pad(data, len, len+amount); |
| 303 } |
| 304 |
| 305 opus_int32 opus_multistream_packet_unpad(unsigned char *data, opus_int32 len, in
t nb_streams) |
| 306 { |
| 307 int s; |
| 308 unsigned char toc; |
| 309 opus_int16 size[48]; |
| 310 opus_int32 packet_offset; |
| 311 OpusRepacketizer rp; |
| 312 unsigned char *dst; |
| 313 opus_int32 dst_len; |
| 314 |
| 315 if (len < 1) |
| 316 return OPUS_BAD_ARG; |
| 317 dst = data; |
| 318 dst_len = 0; |
| 319 /* Unpad all frames */ |
| 320 for (s=0;s<nb_streams;s++) |
| 321 { |
| 322 opus_int32 ret; |
| 323 int self_delimited = s!=nb_streams-1; |
| 324 if (len<=0) |
| 325 return OPUS_INVALID_PACKET; |
| 326 opus_repacketizer_init(&rp); |
| 327 ret = opus_packet_parse_impl(data, len, self_delimited, &toc, NULL, |
| 328 size, NULL, &packet_offset); |
| 329 if (ret<0) |
| 330 return ret; |
| 331 ret = opus_repacketizer_cat_impl(&rp, data, packet_offset, self_delimited)
; |
| 332 if (ret < 0) |
| 333 return ret; |
| 334 ret = opus_repacketizer_out_range_impl(&rp, 0, rp.nb_frames, dst, len, sel
f_delimited, 0); |
| 335 if (ret < 0) |
| 336 return ret; |
| 337 else |
| 338 dst_len += ret; |
| 339 dst += ret; |
| 340 data += packet_offset; |
| 341 len -= packet_offset; |
| 342 } |
| 343 return dst_len; |
| 344 } |
| 345 |
| OLD | NEW |