media/libopus/src/repacketizer.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/media/libopus/src/repacketizer.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,345 @@
     1.4 +/* Copyright (c) 2011 Xiph.Org Foundation
     1.5 +   Written by Jean-Marc Valin */
     1.6 +/*
     1.7 +   Redistribution and use in source and binary forms, with or without
     1.8 +   modification, are permitted provided that the following conditions
     1.9 +   are met:
    1.10 +
    1.11 +   - Redistributions of source code must retain the above copyright
    1.12 +   notice, this list of conditions and the following disclaimer.
    1.13 +
    1.14 +   - Redistributions in binary form must reproduce the above copyright
    1.15 +   notice, this list of conditions and the following disclaimer in the
    1.16 +   documentation and/or other materials provided with the distribution.
    1.17 +
    1.18 +   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    1.19 +   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    1.20 +   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    1.21 +   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
    1.22 +   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
    1.23 +   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
    1.24 +   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
    1.25 +   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
    1.26 +   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
    1.27 +   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
    1.28 +   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    1.29 +*/
    1.30 +
    1.31 +#ifdef HAVE_CONFIG_H
    1.32 +#include "config.h"
    1.33 +#endif
    1.34 +
    1.35 +#include "opus.h"
    1.36 +#include "opus_private.h"
    1.37 +#include "os_support.h"
    1.38 +
    1.39 +
    1.40 +int opus_repacketizer_get_size(void)
    1.41 +{
    1.42 +   return sizeof(OpusRepacketizer);
    1.43 +}
    1.44 +
    1.45 +OpusRepacketizer *opus_repacketizer_init(OpusRepacketizer *rp)
    1.46 +{
    1.47 +   rp->nb_frames = 0;
    1.48 +   return rp;
    1.49 +}
    1.50 +
    1.51 +OpusRepacketizer *opus_repacketizer_create(void)
    1.52 +{
    1.53 +   OpusRepacketizer *rp;
    1.54 +   rp=(OpusRepacketizer *)opus_alloc(opus_repacketizer_get_size());
    1.55 +   if(rp==NULL)return NULL;
    1.56 +   return opus_repacketizer_init(rp);
    1.57 +}
    1.58 +
    1.59 +void opus_repacketizer_destroy(OpusRepacketizer *rp)
    1.60 +{
    1.61 +   opus_free(rp);
    1.62 +}
    1.63 +
    1.64 +static int opus_repacketizer_cat_impl(OpusRepacketizer *rp, const unsigned char *data, opus_int32 len, int self_delimited)
    1.65 +{
    1.66 +   unsigned char tmp_toc;
    1.67 +   int curr_nb_frames,ret;
    1.68 +   /* Set of check ToC */
    1.69 +   if (len<1) return OPUS_INVALID_PACKET;
    1.70 +   if (rp->nb_frames == 0)
    1.71 +   {
    1.72 +      rp->toc = data[0];
    1.73 +      rp->framesize = opus_packet_get_samples_per_frame(data, 8000);
    1.74 +   } else if ((rp->toc&0xFC) != (data[0]&0xFC))
    1.75 +   {
    1.76 +      /*fprintf(stderr, "toc mismatch: 0x%x vs 0x%x\n", rp->toc, data[0]);*/
    1.77 +      return OPUS_INVALID_PACKET;
    1.78 +   }
    1.79 +   curr_nb_frames = opus_packet_get_nb_frames(data, len);
    1.80 +   if(curr_nb_frames<1) return OPUS_INVALID_PACKET;
    1.81 +
    1.82 +   /* Check the 120 ms maximum packet size */
    1.83 +   if ((curr_nb_frames+rp->nb_frames)*rp->framesize > 960)
    1.84 +   {
    1.85 +      return OPUS_INVALID_PACKET;
    1.86 +   }
    1.87 +
    1.88 +   ret=opus_packet_parse_impl(data, len, self_delimited, &tmp_toc, &rp->frames[rp->nb_frames], &rp->len[rp->nb_frames], NULL, NULL);
    1.89 +   if(ret<1)return ret;
    1.90 +
    1.91 +   rp->nb_frames += curr_nb_frames;
    1.92 +   return OPUS_OK;
    1.93 +}
    1.94 +
    1.95 +int opus_repacketizer_cat(OpusRepacketizer *rp, const unsigned char *data, opus_int32 len)
    1.96 +{
    1.97 +   return opus_repacketizer_cat_impl(rp, data, len, 0);
    1.98 +}
    1.99 +
   1.100 +int opus_repacketizer_get_nb_frames(OpusRepacketizer *rp)
   1.101 +{
   1.102 +   return rp->nb_frames;
   1.103 +}
   1.104 +
   1.105 +opus_int32 opus_repacketizer_out_range_impl(OpusRepacketizer *rp, int begin, int end,
   1.106 +      unsigned char *data, opus_int32 maxlen, int self_delimited, int pad)
   1.107 +{
   1.108 +   int i, count;
   1.109 +   opus_int32 tot_size;
   1.110 +   opus_int16 *len;
   1.111 +   const unsigned char **frames;
   1.112 +   unsigned char * ptr;
   1.113 +
   1.114 +   if (begin<0 || begin>=end || end>rp->nb_frames)
   1.115 +   {
   1.116 +      /*fprintf(stderr, "%d %d %d\n", begin, end, rp->nb_frames);*/
   1.117 +      return OPUS_BAD_ARG;
   1.118 +   }
   1.119 +   count = end-begin;
   1.120 +
   1.121 +   len = rp->len+begin;
   1.122 +   frames = rp->frames+begin;
   1.123 +   if (self_delimited)
   1.124 +      tot_size = 1 + (len[count-1]>=252);
   1.125 +   else
   1.126 +      tot_size = 0;
   1.127 +
   1.128 +   ptr = data;
   1.129 +   if (count==1)
   1.130 +   {
   1.131 +      /* Code 0 */
   1.132 +      tot_size += len[0]+1;
   1.133 +      if (tot_size > maxlen)
   1.134 +         return OPUS_BUFFER_TOO_SMALL;
   1.135 +      *ptr++ = rp->toc&0xFC;
   1.136 +   } else if (count==2)
   1.137 +   {
   1.138 +      if (len[1] == len[0])
   1.139 +      {
   1.140 +         /* Code 1 */
   1.141 +         tot_size += 2*len[0]+1;
   1.142 +         if (tot_size > maxlen)
   1.143 +            return OPUS_BUFFER_TOO_SMALL;
   1.144 +         *ptr++ = (rp->toc&0xFC) | 0x1;
   1.145 +      } else {
   1.146 +         /* Code 2 */
   1.147 +         tot_size += len[0]+len[1]+2+(len[0]>=252);
   1.148 +         if (tot_size > maxlen)
   1.149 +            return OPUS_BUFFER_TOO_SMALL;
   1.150 +         *ptr++ = (rp->toc&0xFC) | 0x2;
   1.151 +         ptr += encode_size(len[0], ptr);
   1.152 +      }
   1.153 +   }
   1.154 +   if (count > 2 || (pad && tot_size < maxlen))
   1.155 +   {
   1.156 +      /* Code 3 */
   1.157 +      int vbr;
   1.158 +      int pad_amount=0;
   1.159 +
   1.160 +      /* Restart the process for the padding case */
   1.161 +      ptr = data;
   1.162 +      if (self_delimited)
   1.163 +         tot_size = 1 + (len[count-1]>=252);
   1.164 +      else
   1.165 +         tot_size = 0;
   1.166 +      vbr = 0;
   1.167 +      for (i=1;i<count;i++)
   1.168 +      {
   1.169 +         if (len[i] != len[0])
   1.170 +         {
   1.171 +            vbr=1;
   1.172 +            break;
   1.173 +         }
   1.174 +      }
   1.175 +      if (vbr)
   1.176 +      {
   1.177 +         tot_size += 2;
   1.178 +         for (i=0;i<count-1;i++)
   1.179 +            tot_size += 1 + (len[i]>=252) + len[i];
   1.180 +         tot_size += len[count-1];
   1.181 +
   1.182 +         if (tot_size > maxlen)
   1.183 +            return OPUS_BUFFER_TOO_SMALL;
   1.184 +         *ptr++ = (rp->toc&0xFC) | 0x3;
   1.185 +         *ptr++ = count | 0x80;
   1.186 +      } else {
   1.187 +         tot_size += count*len[0]+2;
   1.188 +         if (tot_size > maxlen)
   1.189 +            return OPUS_BUFFER_TOO_SMALL;
   1.190 +         *ptr++ = (rp->toc&0xFC) | 0x3;
   1.191 +         *ptr++ = count;
   1.192 +      }
   1.193 +      pad_amount = pad ? (maxlen-tot_size) : 0;
   1.194 +      if (pad_amount != 0)
   1.195 +      {
   1.196 +         int nb_255s;
   1.197 +         data[1] |= 0x40;
   1.198 +         nb_255s = (pad_amount-1)/255;
   1.199 +         for (i=0;i<nb_255s;i++)
   1.200 +            *ptr++ = 255;
   1.201 +         *ptr++ = pad_amount-255*nb_255s-1;
   1.202 +         tot_size += pad_amount;
   1.203 +      }
   1.204 +      if (vbr)
   1.205 +      {
   1.206 +         for (i=0;i<count-1;i++)
   1.207 +            ptr += encode_size(len[i], ptr);
   1.208 +      }
   1.209 +   }
   1.210 +   if (self_delimited) {
   1.211 +      int sdlen = encode_size(len[count-1], ptr);
   1.212 +      ptr += sdlen;
   1.213 +   }
   1.214 +   /* Copy the actual data */
   1.215 +   for (i=0;i<count;i++)
   1.216 +   {
   1.217 +      /* Using OPUS_MOVE() instead of OPUS_COPY() in case we're doing in-place
   1.218 +         padding from opus_packet_pad or opus_packet_unpad(). */
   1.219 +      celt_assert(frames[i] + len[i] <= data || ptr <= frames[i]);
   1.220 +      OPUS_MOVE(ptr, frames[i], len[i]);
   1.221 +      ptr += len[i];
   1.222 +   }
   1.223 +   if (pad)
   1.224 +   {
   1.225 +      for (i=ptr-data;i<maxlen;i++)
   1.226 +         data[i] = 0;
   1.227 +   }
   1.228 +   return tot_size;
   1.229 +}
   1.230 +
   1.231 +opus_int32 opus_repacketizer_out_range(OpusRepacketizer *rp, int begin, int end, unsigned char *data, opus_int32 maxlen)
   1.232 +{
   1.233 +   return opus_repacketizer_out_range_impl(rp, begin, end, data, maxlen, 0, 0);
   1.234 +}
   1.235 +
   1.236 +opus_int32 opus_repacketizer_out(OpusRepacketizer *rp, unsigned char *data, opus_int32 maxlen)
   1.237 +{
   1.238 +   return opus_repacketizer_out_range_impl(rp, 0, rp->nb_frames, data, maxlen, 0, 0);
   1.239 +}
   1.240 +
   1.241 +int opus_packet_pad(unsigned char *data, opus_int32 len, opus_int32 new_len)
   1.242 +{
   1.243 +   OpusRepacketizer rp;
   1.244 +   opus_int32 ret;
   1.245 +   if (len < 1)
   1.246 +      return OPUS_BAD_ARG;
   1.247 +   if (len==new_len)
   1.248 +      return OPUS_OK;
   1.249 +   else if (len > new_len)
   1.250 +      return OPUS_BAD_ARG;
   1.251 +   opus_repacketizer_init(&rp);
   1.252 +   /* Moving payload to the end of the packet so we can do in-place padding */
   1.253 +   OPUS_MOVE(data+new_len-len, data, len);
   1.254 +   opus_repacketizer_cat(&rp, data+new_len-len, len);
   1.255 +   ret = opus_repacketizer_out_range_impl(&rp, 0, rp.nb_frames, data, new_len, 0, 1);
   1.256 +   if (ret > 0)
   1.257 +      return OPUS_OK;
   1.258 +   else
   1.259 +      return ret;
   1.260 +}
   1.261 +
   1.262 +opus_int32 opus_packet_unpad(unsigned char *data, opus_int32 len)
   1.263 +{
   1.264 +   OpusRepacketizer rp;
   1.265 +   opus_int32 ret;
   1.266 +   if (len < 1)
   1.267 +      return OPUS_BAD_ARG;
   1.268 +   opus_repacketizer_init(&rp);
   1.269 +   ret = opus_repacketizer_cat(&rp, data, len);
   1.270 +   if (ret < 0)
   1.271 +      return ret;
   1.272 +   ret = opus_repacketizer_out_range_impl(&rp, 0, rp.nb_frames, data, len, 0, 0);
   1.273 +   celt_assert(ret > 0 && ret <= len);
   1.274 +   return ret;
   1.275 +}
   1.276 +
   1.277 +int opus_multistream_packet_pad(unsigned char *data, opus_int32 len, opus_int32 new_len, int nb_streams)
   1.278 +{
   1.279 +   int s;
   1.280 +   int count;
   1.281 +   unsigned char toc;
   1.282 +   opus_int16 size[48];
   1.283 +   opus_int32 packet_offset;
   1.284 +   opus_int32 amount;
   1.285 +
   1.286 +   if (len < 1)
   1.287 +      return OPUS_BAD_ARG;
   1.288 +   if (len==new_len)
   1.289 +      return OPUS_OK;
   1.290 +   else if (len > new_len)
   1.291 +      return OPUS_BAD_ARG;
   1.292 +   amount = new_len - len;
   1.293 +   /* Seek to last stream */
   1.294 +   for (s=0;s<nb_streams-1;s++)
   1.295 +   {
   1.296 +      if (len<=0)
   1.297 +         return OPUS_INVALID_PACKET;
   1.298 +      count = opus_packet_parse_impl(data, len, 1, &toc, NULL,
   1.299 +                                     size, NULL, &packet_offset);
   1.300 +      if (count<0)
   1.301 +         return count;
   1.302 +      data += packet_offset;
   1.303 +      len -= packet_offset;
   1.304 +   }
   1.305 +   return opus_packet_pad(data, len, len+amount);
   1.306 +}
   1.307 +
   1.308 +opus_int32 opus_multistream_packet_unpad(unsigned char *data, opus_int32 len, int nb_streams)
   1.309 +{
   1.310 +   int s;
   1.311 +   unsigned char toc;
   1.312 +   opus_int16 size[48];
   1.313 +   opus_int32 packet_offset;
   1.314 +   OpusRepacketizer rp;
   1.315 +   unsigned char *dst;
   1.316 +   opus_int32 dst_len;
   1.317 +
   1.318 +   if (len < 1)
   1.319 +      return OPUS_BAD_ARG;
   1.320 +   dst = data;
   1.321 +   dst_len = 0;
   1.322 +   /* Unpad all frames */
   1.323 +   for (s=0;s<nb_streams;s++)
   1.324 +   {
   1.325 +      opus_int32 ret;
   1.326 +      int self_delimited = s!=nb_streams-1;
   1.327 +      if (len<=0)
   1.328 +         return OPUS_INVALID_PACKET;
   1.329 +      opus_repacketizer_init(&rp);
   1.330 +      ret = opus_packet_parse_impl(data, len, self_delimited, &toc, NULL,
   1.331 +                                     size, NULL, &packet_offset);
   1.332 +      if (ret<0)
   1.333 +         return ret;
   1.334 +      ret = opus_repacketizer_cat_impl(&rp, data, packet_offset, self_delimited);
   1.335 +      if (ret < 0)
   1.336 +         return ret;
   1.337 +      ret = opus_repacketizer_out_range_impl(&rp, 0, rp.nb_frames, dst, len, self_delimited, 0);
   1.338 +      if (ret < 0)
   1.339 +         return ret;
   1.340 +      else
   1.341 +         dst_len += ret;
   1.342 +      dst += ret;
   1.343 +      data += packet_offset;
   1.344 +      len -= packet_offset;
   1.345 +   }
   1.346 +   return dst_len;
   1.347 +}
   1.348 +

mercurial