media/libtheora/lib/decinfo.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /********************************************************************
     2  *                                                                  *
     3  * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE.   *
     4  * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
     5  * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
     6  * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
     7  *                                                                  *
     8  * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009                *
     9  * by the Xiph.Org Foundation and contributors http://www.xiph.org/ *
    10  *                                                                  *
    11  ********************************************************************
    13   function:
    14     last mod: $Id: decinfo.c 17276 2010-06-05 05:57:05Z tterribe $
    16  ********************************************************************/
    18 #include <stdlib.h>
    19 #include <string.h>
    20 #include <limits.h>
    21 #include "decint.h"
    25 /*Unpacks a series of octets from a given byte array into the pack buffer.
    26   No checking is done to ensure the buffer contains enough data.
    27   _opb: The pack buffer to read the octets from.
    28   _buf: The byte array to store the unpacked bytes in.
    29   _len: The number of octets to unpack.*/
    30 static void oc_unpack_octets(oc_pack_buf *_opb,char *_buf,size_t _len){
    31   while(_len-->0){
    32     long val;
    33     val=oc_pack_read(_opb,8);
    34     *_buf++=(char)val;
    35   }
    36 }
    38 /*Unpacks a 32-bit integer encoded by octets in little-endian form.*/
    39 static long oc_unpack_length(oc_pack_buf *_opb){
    40   long ret[4];
    41   int  i;
    42   for(i=0;i<4;i++)ret[i]=oc_pack_read(_opb,8);
    43   return ret[0]|ret[1]<<8|ret[2]<<16|ret[3]<<24;
    44 }
    46 static int oc_info_unpack(oc_pack_buf *_opb,th_info *_info){
    47   long val;
    48   /*Check the codec bitstream version.*/
    49   val=oc_pack_read(_opb,8);
    50   _info->version_major=(unsigned char)val;
    51   val=oc_pack_read(_opb,8);
    52   _info->version_minor=(unsigned char)val;
    53   val=oc_pack_read(_opb,8);
    54   _info->version_subminor=(unsigned char)val;
    55   /*verify we can parse this bitstream version.
    56      We accept earlier minors and all subminors, by spec*/
    57   if(_info->version_major>TH_VERSION_MAJOR||
    58    _info->version_major==TH_VERSION_MAJOR&&
    59    _info->version_minor>TH_VERSION_MINOR){
    60     return TH_EVERSION;
    61   }
    62   /*Read the encoded frame description.*/
    63   val=oc_pack_read(_opb,16);
    64   _info->frame_width=(ogg_uint32_t)val<<4;
    65   val=oc_pack_read(_opb,16);
    66   _info->frame_height=(ogg_uint32_t)val<<4;
    67   val=oc_pack_read(_opb,24);
    68   _info->pic_width=(ogg_uint32_t)val;
    69   val=oc_pack_read(_opb,24);
    70   _info->pic_height=(ogg_uint32_t)val;
    71   val=oc_pack_read(_opb,8);
    72   _info->pic_x=(ogg_uint32_t)val;
    73   val=oc_pack_read(_opb,8);
    74   _info->pic_y=(ogg_uint32_t)val;
    75   val=oc_pack_read(_opb,32);
    76   _info->fps_numerator=(ogg_uint32_t)val;
    77   val=oc_pack_read(_opb,32);
    78   _info->fps_denominator=(ogg_uint32_t)val;
    79   if(_info->frame_width==0||_info->frame_height==0||
    80    _info->pic_width+_info->pic_x>_info->frame_width||
    81    _info->pic_height+_info->pic_y>_info->frame_height||
    82    _info->fps_numerator==0||_info->fps_denominator==0){
    83     return TH_EBADHEADER;
    84   }
    85   /*Note: The sense of pic_y is inverted in what we pass back to the
    86      application compared to how it is stored in the bitstream.
    87     This is because the bitstream uses a right-handed coordinate system, while
    88      applications expect a left-handed one.*/
    89   _info->pic_y=_info->frame_height-_info->pic_height-_info->pic_y;
    90   val=oc_pack_read(_opb,24);
    91   _info->aspect_numerator=(ogg_uint32_t)val;
    92   val=oc_pack_read(_opb,24);
    93   _info->aspect_denominator=(ogg_uint32_t)val;
    94   val=oc_pack_read(_opb,8);
    95   _info->colorspace=(th_colorspace)val;
    96   val=oc_pack_read(_opb,24);
    97   _info->target_bitrate=(int)val;
    98   val=oc_pack_read(_opb,6);
    99   _info->quality=(int)val;
   100   val=oc_pack_read(_opb,5);
   101   _info->keyframe_granule_shift=(int)val;
   102   val=oc_pack_read(_opb,2);
   103   _info->pixel_fmt=(th_pixel_fmt)val;
   104   if(_info->pixel_fmt==TH_PF_RSVD)return TH_EBADHEADER;
   105   val=oc_pack_read(_opb,3);
   106   if(val!=0||oc_pack_bytes_left(_opb)<0)return TH_EBADHEADER;
   107   return 0;
   108 }
   110 static int oc_comment_unpack(oc_pack_buf *_opb,th_comment *_tc){
   111   long len;
   112   int  i;
   113   /*Read the vendor string.*/
   114   len=oc_unpack_length(_opb);
   115   if(len<0||len>oc_pack_bytes_left(_opb))return TH_EBADHEADER;
   116   _tc->vendor=_ogg_malloc((size_t)len+1);
   117   if(_tc->vendor==NULL)return TH_EFAULT;
   118   oc_unpack_octets(_opb,_tc->vendor,len);
   119   _tc->vendor[len]='\0';
   120   /*Read the user comments.*/
   121   _tc->comments=(int)oc_unpack_length(_opb);
   122   len=_tc->comments;
   123   if(len<0||len>(LONG_MAX>>2)||len<<2>oc_pack_bytes_left(_opb)){
   124     _tc->comments=0;
   125     return TH_EBADHEADER;
   126   }
   127   _tc->comment_lengths=(int *)_ogg_malloc(
   128    _tc->comments*sizeof(_tc->comment_lengths[0]));
   129   _tc->user_comments=(char **)_ogg_malloc(
   130    _tc->comments*sizeof(_tc->user_comments[0]));
   131   if(_tc->comment_lengths==NULL||_tc->user_comments==NULL){
   132     _tc->comments=0;
   133     return TH_EFAULT;
   134   }
   135   for(i=0;i<_tc->comments;i++){
   136     len=oc_unpack_length(_opb);
   137     if(len<0||len>oc_pack_bytes_left(_opb)){
   138       _tc->comments=i;
   139       return TH_EBADHEADER;
   140     }
   141     _tc->comment_lengths[i]=len;
   142     _tc->user_comments[i]=_ogg_malloc((size_t)len+1);
   143     if(_tc->user_comments[i]==NULL){
   144       _tc->comments=i;
   145       return TH_EFAULT;
   146     }
   147     oc_unpack_octets(_opb,_tc->user_comments[i],len);
   148     _tc->user_comments[i][len]='\0';
   149   }
   150   return oc_pack_bytes_left(_opb)<0?TH_EBADHEADER:0;
   151 }
   153 static int oc_setup_unpack(oc_pack_buf *_opb,th_setup_info *_setup){
   154   int ret;
   155   /*Read the quantizer tables.*/
   156   ret=oc_quant_params_unpack(_opb,&_setup->qinfo);
   157   if(ret<0)return ret;
   158   /*Read the Huffman trees.*/
   159   return oc_huff_trees_unpack(_opb,_setup->huff_tables);
   160 }
   162 static void oc_setup_clear(th_setup_info *_setup){
   163   oc_quant_params_clear(&_setup->qinfo);
   164   oc_huff_trees_clear(_setup->huff_tables);
   165 }
   167 static int oc_dec_headerin(oc_pack_buf *_opb,th_info *_info,
   168  th_comment *_tc,th_setup_info **_setup,ogg_packet *_op){
   169   char buffer[6];
   170   long val;
   171   int  packtype;
   172   int  ret;
   173   val=oc_pack_read(_opb,8);
   174   packtype=(int)val;
   175   /*If we're at a data packet and we have received all three headers, we're
   176      done.*/
   177   if(!(packtype&0x80)&&_info->frame_width>0&&_tc->vendor!=NULL&&*_setup!=NULL){
   178     return 0;
   179   }
   180   /*Check the codec string.*/
   181   oc_unpack_octets(_opb,buffer,6);
   182   if(memcmp(buffer,"theora",6)!=0)return TH_ENOTFORMAT;
   183   switch(packtype){
   184     /*Codec info header.*/
   185     case 0x80:{
   186       /*This should be the first packet, and we should not already be
   187          initialized.*/
   188       if(!_op->b_o_s||_info->frame_width>0)return TH_EBADHEADER;
   189       ret=oc_info_unpack(_opb,_info);
   190       if(ret<0)th_info_clear(_info);
   191       else ret=3;
   192     }break;
   193     /*Comment header.*/
   194     case 0x81:{
   195       if(_tc==NULL)return TH_EFAULT;
   196       /*We shoud have already decoded the info header, and should not yet have
   197          decoded the comment header.*/
   198       if(_info->frame_width==0||_tc->vendor!=NULL)return TH_EBADHEADER;
   199       ret=oc_comment_unpack(_opb,_tc);
   200       if(ret<0)th_comment_clear(_tc);
   201       else ret=2;
   202     }break;
   203     /*Codec setup header.*/
   204     case 0x82:{
   205       oc_setup_info *setup;
   206       if(_tc==NULL||_setup==NULL)return TH_EFAULT;
   207       /*We should have already decoded the info header and the comment header,
   208          and should not yet have decoded the setup header.*/
   209       if(_info->frame_width==0||_tc->vendor==NULL||*_setup!=NULL){
   210         return TH_EBADHEADER;
   211       }
   212       setup=(oc_setup_info *)_ogg_calloc(1,sizeof(*setup));
   213       if(setup==NULL)return TH_EFAULT;
   214       ret=oc_setup_unpack(_opb,setup);
   215       if(ret<0){
   216         oc_setup_clear(setup);
   217         _ogg_free(setup);
   218       }
   219       else{
   220         *_setup=setup;
   221         ret=1;
   222       }
   223     }break;
   224     default:{
   225       /*We don't know what this header is.*/
   226       return TH_EBADHEADER;
   227     }break;
   228   }
   229   return ret;
   230 }
   233 /*Decodes one header packet.
   234   This should be called repeatedly with the packets at the beginning of the
   235    stream until it returns 0.*/
   236 int th_decode_headerin(th_info *_info,th_comment *_tc,
   237  th_setup_info **_setup,ogg_packet *_op){
   238   oc_pack_buf opb;
   239   if(_op==NULL)return TH_EBADHEADER;
   240   if(_info==NULL)return TH_EFAULT;
   241   oc_pack_readinit(&opb,_op->packet,_op->bytes);
   242   return oc_dec_headerin(&opb,_info,_tc,_setup,_op);
   243 }
   245 void th_setup_free(th_setup_info *_setup){
   246   if(_setup!=NULL){
   247     oc_setup_clear(_setup);
   248     _ogg_free(_setup);
   249   }
   250 }

mercurial