media/libopus/src/repacketizer.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* Copyright (c) 2011 Xiph.Org Foundation
michael@0 2 Written by Jean-Marc Valin */
michael@0 3 /*
michael@0 4 Redistribution and use in source and binary forms, with or without
michael@0 5 modification, are permitted provided that the following conditions
michael@0 6 are met:
michael@0 7
michael@0 8 - Redistributions of source code must retain the above copyright
michael@0 9 notice, this list of conditions and the following disclaimer.
michael@0 10
michael@0 11 - Redistributions in binary form must reproduce the above copyright
michael@0 12 notice, this list of conditions and the following disclaimer in the
michael@0 13 documentation and/or other materials provided with the distribution.
michael@0 14
michael@0 15 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
michael@0 16 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
michael@0 17 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
michael@0 18 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
michael@0 19 OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
michael@0 20 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
michael@0 21 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
michael@0 22 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
michael@0 23 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
michael@0 24 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
michael@0 25 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
michael@0 26 */
michael@0 27
michael@0 28 #ifdef HAVE_CONFIG_H
michael@0 29 #include "config.h"
michael@0 30 #endif
michael@0 31
michael@0 32 #include "opus.h"
michael@0 33 #include "opus_private.h"
michael@0 34 #include "os_support.h"
michael@0 35
michael@0 36
michael@0 37 int opus_repacketizer_get_size(void)
michael@0 38 {
michael@0 39 return sizeof(OpusRepacketizer);
michael@0 40 }
michael@0 41
michael@0 42 OpusRepacketizer *opus_repacketizer_init(OpusRepacketizer *rp)
michael@0 43 {
michael@0 44 rp->nb_frames = 0;
michael@0 45 return rp;
michael@0 46 }
michael@0 47
michael@0 48 OpusRepacketizer *opus_repacketizer_create(void)
michael@0 49 {
michael@0 50 OpusRepacketizer *rp;
michael@0 51 rp=(OpusRepacketizer *)opus_alloc(opus_repacketizer_get_size());
michael@0 52 if(rp==NULL)return NULL;
michael@0 53 return opus_repacketizer_init(rp);
michael@0 54 }
michael@0 55
michael@0 56 void opus_repacketizer_destroy(OpusRepacketizer *rp)
michael@0 57 {
michael@0 58 opus_free(rp);
michael@0 59 }
michael@0 60
michael@0 61 static int opus_repacketizer_cat_impl(OpusRepacketizer *rp, const unsigned char *data, opus_int32 len, int self_delimited)
michael@0 62 {
michael@0 63 unsigned char tmp_toc;
michael@0 64 int curr_nb_frames,ret;
michael@0 65 /* Set of check ToC */
michael@0 66 if (len<1) return OPUS_INVALID_PACKET;
michael@0 67 if (rp->nb_frames == 0)
michael@0 68 {
michael@0 69 rp->toc = data[0];
michael@0 70 rp->framesize = opus_packet_get_samples_per_frame(data, 8000);
michael@0 71 } else if ((rp->toc&0xFC) != (data[0]&0xFC))
michael@0 72 {
michael@0 73 /*fprintf(stderr, "toc mismatch: 0x%x vs 0x%x\n", rp->toc, data[0]);*/
michael@0 74 return OPUS_INVALID_PACKET;
michael@0 75 }
michael@0 76 curr_nb_frames = opus_packet_get_nb_frames(data, len);
michael@0 77 if(curr_nb_frames<1) return OPUS_INVALID_PACKET;
michael@0 78
michael@0 79 /* Check the 120 ms maximum packet size */
michael@0 80 if ((curr_nb_frames+rp->nb_frames)*rp->framesize > 960)
michael@0 81 {
michael@0 82 return OPUS_INVALID_PACKET;
michael@0 83 }
michael@0 84
michael@0 85 ret=opus_packet_parse_impl(data, len, self_delimited, &tmp_toc, &rp->frames[rp->nb_frames], &rp->len[rp->nb_frames], NULL, NULL);
michael@0 86 if(ret<1)return ret;
michael@0 87
michael@0 88 rp->nb_frames += curr_nb_frames;
michael@0 89 return OPUS_OK;
michael@0 90 }
michael@0 91
michael@0 92 int opus_repacketizer_cat(OpusRepacketizer *rp, const unsigned char *data, opus_int32 len)
michael@0 93 {
michael@0 94 return opus_repacketizer_cat_impl(rp, data, len, 0);
michael@0 95 }
michael@0 96
michael@0 97 int opus_repacketizer_get_nb_frames(OpusRepacketizer *rp)
michael@0 98 {
michael@0 99 return rp->nb_frames;
michael@0 100 }
michael@0 101
michael@0 102 opus_int32 opus_repacketizer_out_range_impl(OpusRepacketizer *rp, int begin, int end,
michael@0 103 unsigned char *data, opus_int32 maxlen, int self_delimited, int pad)
michael@0 104 {
michael@0 105 int i, count;
michael@0 106 opus_int32 tot_size;
michael@0 107 opus_int16 *len;
michael@0 108 const unsigned char **frames;
michael@0 109 unsigned char * ptr;
michael@0 110
michael@0 111 if (begin<0 || begin>=end || end>rp->nb_frames)
michael@0 112 {
michael@0 113 /*fprintf(stderr, "%d %d %d\n", begin, end, rp->nb_frames);*/
michael@0 114 return OPUS_BAD_ARG;
michael@0 115 }
michael@0 116 count = end-begin;
michael@0 117
michael@0 118 len = rp->len+begin;
michael@0 119 frames = rp->frames+begin;
michael@0 120 if (self_delimited)
michael@0 121 tot_size = 1 + (len[count-1]>=252);
michael@0 122 else
michael@0 123 tot_size = 0;
michael@0 124
michael@0 125 ptr = data;
michael@0 126 if (count==1)
michael@0 127 {
michael@0 128 /* Code 0 */
michael@0 129 tot_size += len[0]+1;
michael@0 130 if (tot_size > maxlen)
michael@0 131 return OPUS_BUFFER_TOO_SMALL;
michael@0 132 *ptr++ = rp->toc&0xFC;
michael@0 133 } else if (count==2)
michael@0 134 {
michael@0 135 if (len[1] == len[0])
michael@0 136 {
michael@0 137 /* Code 1 */
michael@0 138 tot_size += 2*len[0]+1;
michael@0 139 if (tot_size > maxlen)
michael@0 140 return OPUS_BUFFER_TOO_SMALL;
michael@0 141 *ptr++ = (rp->toc&0xFC) | 0x1;
michael@0 142 } else {
michael@0 143 /* Code 2 */
michael@0 144 tot_size += len[0]+len[1]+2+(len[0]>=252);
michael@0 145 if (tot_size > maxlen)
michael@0 146 return OPUS_BUFFER_TOO_SMALL;
michael@0 147 *ptr++ = (rp->toc&0xFC) | 0x2;
michael@0 148 ptr += encode_size(len[0], ptr);
michael@0 149 }
michael@0 150 }
michael@0 151 if (count > 2 || (pad && tot_size < maxlen))
michael@0 152 {
michael@0 153 /* Code 3 */
michael@0 154 int vbr;
michael@0 155 int pad_amount=0;
michael@0 156
michael@0 157 /* Restart the process for the padding case */
michael@0 158 ptr = data;
michael@0 159 if (self_delimited)
michael@0 160 tot_size = 1 + (len[count-1]>=252);
michael@0 161 else
michael@0 162 tot_size = 0;
michael@0 163 vbr = 0;
michael@0 164 for (i=1;i<count;i++)
michael@0 165 {
michael@0 166 if (len[i] != len[0])
michael@0 167 {
michael@0 168 vbr=1;
michael@0 169 break;
michael@0 170 }
michael@0 171 }
michael@0 172 if (vbr)
michael@0 173 {
michael@0 174 tot_size += 2;
michael@0 175 for (i=0;i<count-1;i++)
michael@0 176 tot_size += 1 + (len[i]>=252) + len[i];
michael@0 177 tot_size += len[count-1];
michael@0 178
michael@0 179 if (tot_size > maxlen)
michael@0 180 return OPUS_BUFFER_TOO_SMALL;
michael@0 181 *ptr++ = (rp->toc&0xFC) | 0x3;
michael@0 182 *ptr++ = count | 0x80;
michael@0 183 } else {
michael@0 184 tot_size += count*len[0]+2;
michael@0 185 if (tot_size > maxlen)
michael@0 186 return OPUS_BUFFER_TOO_SMALL;
michael@0 187 *ptr++ = (rp->toc&0xFC) | 0x3;
michael@0 188 *ptr++ = count;
michael@0 189 }
michael@0 190 pad_amount = pad ? (maxlen-tot_size) : 0;
michael@0 191 if (pad_amount != 0)
michael@0 192 {
michael@0 193 int nb_255s;
michael@0 194 data[1] |= 0x40;
michael@0 195 nb_255s = (pad_amount-1)/255;
michael@0 196 for (i=0;i<nb_255s;i++)
michael@0 197 *ptr++ = 255;
michael@0 198 *ptr++ = pad_amount-255*nb_255s-1;
michael@0 199 tot_size += pad_amount;
michael@0 200 }
michael@0 201 if (vbr)
michael@0 202 {
michael@0 203 for (i=0;i<count-1;i++)
michael@0 204 ptr += encode_size(len[i], ptr);
michael@0 205 }
michael@0 206 }
michael@0 207 if (self_delimited) {
michael@0 208 int sdlen = encode_size(len[count-1], ptr);
michael@0 209 ptr += sdlen;
michael@0 210 }
michael@0 211 /* Copy the actual data */
michael@0 212 for (i=0;i<count;i++)
michael@0 213 {
michael@0 214 /* Using OPUS_MOVE() instead of OPUS_COPY() in case we're doing in-place
michael@0 215 padding from opus_packet_pad or opus_packet_unpad(). */
michael@0 216 celt_assert(frames[i] + len[i] <= data || ptr <= frames[i]);
michael@0 217 OPUS_MOVE(ptr, frames[i], len[i]);
michael@0 218 ptr += len[i];
michael@0 219 }
michael@0 220 if (pad)
michael@0 221 {
michael@0 222 for (i=ptr-data;i<maxlen;i++)
michael@0 223 data[i] = 0;
michael@0 224 }
michael@0 225 return tot_size;
michael@0 226 }
michael@0 227
michael@0 228 opus_int32 opus_repacketizer_out_range(OpusRepacketizer *rp, int begin, int end, unsigned char *data, opus_int32 maxlen)
michael@0 229 {
michael@0 230 return opus_repacketizer_out_range_impl(rp, begin, end, data, maxlen, 0, 0);
michael@0 231 }
michael@0 232
michael@0 233 opus_int32 opus_repacketizer_out(OpusRepacketizer *rp, unsigned char *data, opus_int32 maxlen)
michael@0 234 {
michael@0 235 return opus_repacketizer_out_range_impl(rp, 0, rp->nb_frames, data, maxlen, 0, 0);
michael@0 236 }
michael@0 237
michael@0 238 int opus_packet_pad(unsigned char *data, opus_int32 len, opus_int32 new_len)
michael@0 239 {
michael@0 240 OpusRepacketizer rp;
michael@0 241 opus_int32 ret;
michael@0 242 if (len < 1)
michael@0 243 return OPUS_BAD_ARG;
michael@0 244 if (len==new_len)
michael@0 245 return OPUS_OK;
michael@0 246 else if (len > new_len)
michael@0 247 return OPUS_BAD_ARG;
michael@0 248 opus_repacketizer_init(&rp);
michael@0 249 /* Moving payload to the end of the packet so we can do in-place padding */
michael@0 250 OPUS_MOVE(data+new_len-len, data, len);
michael@0 251 opus_repacketizer_cat(&rp, data+new_len-len, len);
michael@0 252 ret = opus_repacketizer_out_range_impl(&rp, 0, rp.nb_frames, data, new_len, 0, 1);
michael@0 253 if (ret > 0)
michael@0 254 return OPUS_OK;
michael@0 255 else
michael@0 256 return ret;
michael@0 257 }
michael@0 258
michael@0 259 opus_int32 opus_packet_unpad(unsigned char *data, opus_int32 len)
michael@0 260 {
michael@0 261 OpusRepacketizer rp;
michael@0 262 opus_int32 ret;
michael@0 263 if (len < 1)
michael@0 264 return OPUS_BAD_ARG;
michael@0 265 opus_repacketizer_init(&rp);
michael@0 266 ret = opus_repacketizer_cat(&rp, data, len);
michael@0 267 if (ret < 0)
michael@0 268 return ret;
michael@0 269 ret = opus_repacketizer_out_range_impl(&rp, 0, rp.nb_frames, data, len, 0, 0);
michael@0 270 celt_assert(ret > 0 && ret <= len);
michael@0 271 return ret;
michael@0 272 }
michael@0 273
michael@0 274 int opus_multistream_packet_pad(unsigned char *data, opus_int32 len, opus_int32 new_len, int nb_streams)
michael@0 275 {
michael@0 276 int s;
michael@0 277 int count;
michael@0 278 unsigned char toc;
michael@0 279 opus_int16 size[48];
michael@0 280 opus_int32 packet_offset;
michael@0 281 opus_int32 amount;
michael@0 282
michael@0 283 if (len < 1)
michael@0 284 return OPUS_BAD_ARG;
michael@0 285 if (len==new_len)
michael@0 286 return OPUS_OK;
michael@0 287 else if (len > new_len)
michael@0 288 return OPUS_BAD_ARG;
michael@0 289 amount = new_len - len;
michael@0 290 /* Seek to last stream */
michael@0 291 for (s=0;s<nb_streams-1;s++)
michael@0 292 {
michael@0 293 if (len<=0)
michael@0 294 return OPUS_INVALID_PACKET;
michael@0 295 count = opus_packet_parse_impl(data, len, 1, &toc, NULL,
michael@0 296 size, NULL, &packet_offset);
michael@0 297 if (count<0)
michael@0 298 return count;
michael@0 299 data += packet_offset;
michael@0 300 len -= packet_offset;
michael@0 301 }
michael@0 302 return opus_packet_pad(data, len, len+amount);
michael@0 303 }
michael@0 304
michael@0 305 opus_int32 opus_multistream_packet_unpad(unsigned char *data, opus_int32 len, int nb_streams)
michael@0 306 {
michael@0 307 int s;
michael@0 308 unsigned char toc;
michael@0 309 opus_int16 size[48];
michael@0 310 opus_int32 packet_offset;
michael@0 311 OpusRepacketizer rp;
michael@0 312 unsigned char *dst;
michael@0 313 opus_int32 dst_len;
michael@0 314
michael@0 315 if (len < 1)
michael@0 316 return OPUS_BAD_ARG;
michael@0 317 dst = data;
michael@0 318 dst_len = 0;
michael@0 319 /* Unpad all frames */
michael@0 320 for (s=0;s<nb_streams;s++)
michael@0 321 {
michael@0 322 opus_int32 ret;
michael@0 323 int self_delimited = s!=nb_streams-1;
michael@0 324 if (len<=0)
michael@0 325 return OPUS_INVALID_PACKET;
michael@0 326 opus_repacketizer_init(&rp);
michael@0 327 ret = opus_packet_parse_impl(data, len, self_delimited, &toc, NULL,
michael@0 328 size, NULL, &packet_offset);
michael@0 329 if (ret<0)
michael@0 330 return ret;
michael@0 331 ret = opus_repacketizer_cat_impl(&rp, data, packet_offset, self_delimited);
michael@0 332 if (ret < 0)
michael@0 333 return ret;
michael@0 334 ret = opus_repacketizer_out_range_impl(&rp, 0, rp.nb_frames, dst, len, self_delimited, 0);
michael@0 335 if (ret < 0)
michael@0 336 return ret;
michael@0 337 else
michael@0 338 dst_len += ret;
michael@0 339 dst += ret;
michael@0 340 data += packet_offset;
michael@0 341 len -= packet_offset;
michael@0 342 }
michael@0 343 return dst_len;
michael@0 344 }
michael@0 345

mercurial