tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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 }