media/libtheora/lib/decinfo.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/media/libtheora/lib/decinfo.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,250 @@
     1.4 +/********************************************************************
     1.5 + *                                                                  *
     1.6 + * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE.   *
     1.7 + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
     1.8 + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
     1.9 + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
    1.10 + *                                                                  *
    1.11 + * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009                *
    1.12 + * by the Xiph.Org Foundation and contributors http://www.xiph.org/ *
    1.13 + *                                                                  *
    1.14 + ********************************************************************
    1.15 +
    1.16 +  function:
    1.17 +    last mod: $Id: decinfo.c 17276 2010-06-05 05:57:05Z tterribe $
    1.18 +
    1.19 + ********************************************************************/
    1.20 +
    1.21 +#include <stdlib.h>
    1.22 +#include <string.h>
    1.23 +#include <limits.h>
    1.24 +#include "decint.h"
    1.25 +
    1.26 +
    1.27 +
    1.28 +/*Unpacks a series of octets from a given byte array into the pack buffer.
    1.29 +  No checking is done to ensure the buffer contains enough data.
    1.30 +  _opb: The pack buffer to read the octets from.
    1.31 +  _buf: The byte array to store the unpacked bytes in.
    1.32 +  _len: The number of octets to unpack.*/
    1.33 +static void oc_unpack_octets(oc_pack_buf *_opb,char *_buf,size_t _len){
    1.34 +  while(_len-->0){
    1.35 +    long val;
    1.36 +    val=oc_pack_read(_opb,8);
    1.37 +    *_buf++=(char)val;
    1.38 +  }
    1.39 +}
    1.40 +
    1.41 +/*Unpacks a 32-bit integer encoded by octets in little-endian form.*/
    1.42 +static long oc_unpack_length(oc_pack_buf *_opb){
    1.43 +  long ret[4];
    1.44 +  int  i;
    1.45 +  for(i=0;i<4;i++)ret[i]=oc_pack_read(_opb,8);
    1.46 +  return ret[0]|ret[1]<<8|ret[2]<<16|ret[3]<<24;
    1.47 +}
    1.48 +
    1.49 +static int oc_info_unpack(oc_pack_buf *_opb,th_info *_info){
    1.50 +  long val;
    1.51 +  /*Check the codec bitstream version.*/
    1.52 +  val=oc_pack_read(_opb,8);
    1.53 +  _info->version_major=(unsigned char)val;
    1.54 +  val=oc_pack_read(_opb,8);
    1.55 +  _info->version_minor=(unsigned char)val;
    1.56 +  val=oc_pack_read(_opb,8);
    1.57 +  _info->version_subminor=(unsigned char)val;
    1.58 +  /*verify we can parse this bitstream version.
    1.59 +     We accept earlier minors and all subminors, by spec*/
    1.60 +  if(_info->version_major>TH_VERSION_MAJOR||
    1.61 +   _info->version_major==TH_VERSION_MAJOR&&
    1.62 +   _info->version_minor>TH_VERSION_MINOR){
    1.63 +    return TH_EVERSION;
    1.64 +  }
    1.65 +  /*Read the encoded frame description.*/
    1.66 +  val=oc_pack_read(_opb,16);
    1.67 +  _info->frame_width=(ogg_uint32_t)val<<4;
    1.68 +  val=oc_pack_read(_opb,16);
    1.69 +  _info->frame_height=(ogg_uint32_t)val<<4;
    1.70 +  val=oc_pack_read(_opb,24);
    1.71 +  _info->pic_width=(ogg_uint32_t)val;
    1.72 +  val=oc_pack_read(_opb,24);
    1.73 +  _info->pic_height=(ogg_uint32_t)val;
    1.74 +  val=oc_pack_read(_opb,8);
    1.75 +  _info->pic_x=(ogg_uint32_t)val;
    1.76 +  val=oc_pack_read(_opb,8);
    1.77 +  _info->pic_y=(ogg_uint32_t)val;
    1.78 +  val=oc_pack_read(_opb,32);
    1.79 +  _info->fps_numerator=(ogg_uint32_t)val;
    1.80 +  val=oc_pack_read(_opb,32);
    1.81 +  _info->fps_denominator=(ogg_uint32_t)val;
    1.82 +  if(_info->frame_width==0||_info->frame_height==0||
    1.83 +   _info->pic_width+_info->pic_x>_info->frame_width||
    1.84 +   _info->pic_height+_info->pic_y>_info->frame_height||
    1.85 +   _info->fps_numerator==0||_info->fps_denominator==0){
    1.86 +    return TH_EBADHEADER;
    1.87 +  }
    1.88 +  /*Note: The sense of pic_y is inverted in what we pass back to the
    1.89 +     application compared to how it is stored in the bitstream.
    1.90 +    This is because the bitstream uses a right-handed coordinate system, while
    1.91 +     applications expect a left-handed one.*/
    1.92 +  _info->pic_y=_info->frame_height-_info->pic_height-_info->pic_y;
    1.93 +  val=oc_pack_read(_opb,24);
    1.94 +  _info->aspect_numerator=(ogg_uint32_t)val;
    1.95 +  val=oc_pack_read(_opb,24);
    1.96 +  _info->aspect_denominator=(ogg_uint32_t)val;
    1.97 +  val=oc_pack_read(_opb,8);
    1.98 +  _info->colorspace=(th_colorspace)val;
    1.99 +  val=oc_pack_read(_opb,24);
   1.100 +  _info->target_bitrate=(int)val;
   1.101 +  val=oc_pack_read(_opb,6);
   1.102 +  _info->quality=(int)val;
   1.103 +  val=oc_pack_read(_opb,5);
   1.104 +  _info->keyframe_granule_shift=(int)val;
   1.105 +  val=oc_pack_read(_opb,2);
   1.106 +  _info->pixel_fmt=(th_pixel_fmt)val;
   1.107 +  if(_info->pixel_fmt==TH_PF_RSVD)return TH_EBADHEADER;
   1.108 +  val=oc_pack_read(_opb,3);
   1.109 +  if(val!=0||oc_pack_bytes_left(_opb)<0)return TH_EBADHEADER;
   1.110 +  return 0;
   1.111 +}
   1.112 +
   1.113 +static int oc_comment_unpack(oc_pack_buf *_opb,th_comment *_tc){
   1.114 +  long len;
   1.115 +  int  i;
   1.116 +  /*Read the vendor string.*/
   1.117 +  len=oc_unpack_length(_opb);
   1.118 +  if(len<0||len>oc_pack_bytes_left(_opb))return TH_EBADHEADER;
   1.119 +  _tc->vendor=_ogg_malloc((size_t)len+1);
   1.120 +  if(_tc->vendor==NULL)return TH_EFAULT;
   1.121 +  oc_unpack_octets(_opb,_tc->vendor,len);
   1.122 +  _tc->vendor[len]='\0';
   1.123 +  /*Read the user comments.*/
   1.124 +  _tc->comments=(int)oc_unpack_length(_opb);
   1.125 +  len=_tc->comments;
   1.126 +  if(len<0||len>(LONG_MAX>>2)||len<<2>oc_pack_bytes_left(_opb)){
   1.127 +    _tc->comments=0;
   1.128 +    return TH_EBADHEADER;
   1.129 +  }
   1.130 +  _tc->comment_lengths=(int *)_ogg_malloc(
   1.131 +   _tc->comments*sizeof(_tc->comment_lengths[0]));
   1.132 +  _tc->user_comments=(char **)_ogg_malloc(
   1.133 +   _tc->comments*sizeof(_tc->user_comments[0]));
   1.134 +  if(_tc->comment_lengths==NULL||_tc->user_comments==NULL){
   1.135 +    _tc->comments=0;
   1.136 +    return TH_EFAULT;
   1.137 +  }
   1.138 +  for(i=0;i<_tc->comments;i++){
   1.139 +    len=oc_unpack_length(_opb);
   1.140 +    if(len<0||len>oc_pack_bytes_left(_opb)){
   1.141 +      _tc->comments=i;
   1.142 +      return TH_EBADHEADER;
   1.143 +    }
   1.144 +    _tc->comment_lengths[i]=len;
   1.145 +    _tc->user_comments[i]=_ogg_malloc((size_t)len+1);
   1.146 +    if(_tc->user_comments[i]==NULL){
   1.147 +      _tc->comments=i;
   1.148 +      return TH_EFAULT;
   1.149 +    }
   1.150 +    oc_unpack_octets(_opb,_tc->user_comments[i],len);
   1.151 +    _tc->user_comments[i][len]='\0';
   1.152 +  }
   1.153 +  return oc_pack_bytes_left(_opb)<0?TH_EBADHEADER:0;
   1.154 +}
   1.155 +
   1.156 +static int oc_setup_unpack(oc_pack_buf *_opb,th_setup_info *_setup){
   1.157 +  int ret;
   1.158 +  /*Read the quantizer tables.*/
   1.159 +  ret=oc_quant_params_unpack(_opb,&_setup->qinfo);
   1.160 +  if(ret<0)return ret;
   1.161 +  /*Read the Huffman trees.*/
   1.162 +  return oc_huff_trees_unpack(_opb,_setup->huff_tables);
   1.163 +}
   1.164 +
   1.165 +static void oc_setup_clear(th_setup_info *_setup){
   1.166 +  oc_quant_params_clear(&_setup->qinfo);
   1.167 +  oc_huff_trees_clear(_setup->huff_tables);
   1.168 +}
   1.169 +
   1.170 +static int oc_dec_headerin(oc_pack_buf *_opb,th_info *_info,
   1.171 + th_comment *_tc,th_setup_info **_setup,ogg_packet *_op){
   1.172 +  char buffer[6];
   1.173 +  long val;
   1.174 +  int  packtype;
   1.175 +  int  ret;
   1.176 +  val=oc_pack_read(_opb,8);
   1.177 +  packtype=(int)val;
   1.178 +  /*If we're at a data packet and we have received all three headers, we're
   1.179 +     done.*/
   1.180 +  if(!(packtype&0x80)&&_info->frame_width>0&&_tc->vendor!=NULL&&*_setup!=NULL){
   1.181 +    return 0;
   1.182 +  }
   1.183 +  /*Check the codec string.*/
   1.184 +  oc_unpack_octets(_opb,buffer,6);
   1.185 +  if(memcmp(buffer,"theora",6)!=0)return TH_ENOTFORMAT;
   1.186 +  switch(packtype){
   1.187 +    /*Codec info header.*/
   1.188 +    case 0x80:{
   1.189 +      /*This should be the first packet, and we should not already be
   1.190 +         initialized.*/
   1.191 +      if(!_op->b_o_s||_info->frame_width>0)return TH_EBADHEADER;
   1.192 +      ret=oc_info_unpack(_opb,_info);
   1.193 +      if(ret<0)th_info_clear(_info);
   1.194 +      else ret=3;
   1.195 +    }break;
   1.196 +    /*Comment header.*/
   1.197 +    case 0x81:{
   1.198 +      if(_tc==NULL)return TH_EFAULT;
   1.199 +      /*We shoud have already decoded the info header, and should not yet have
   1.200 +         decoded the comment header.*/
   1.201 +      if(_info->frame_width==0||_tc->vendor!=NULL)return TH_EBADHEADER;
   1.202 +      ret=oc_comment_unpack(_opb,_tc);
   1.203 +      if(ret<0)th_comment_clear(_tc);
   1.204 +      else ret=2;
   1.205 +    }break;
   1.206 +    /*Codec setup header.*/
   1.207 +    case 0x82:{
   1.208 +      oc_setup_info *setup;
   1.209 +      if(_tc==NULL||_setup==NULL)return TH_EFAULT;
   1.210 +      /*We should have already decoded the info header and the comment header,
   1.211 +         and should not yet have decoded the setup header.*/
   1.212 +      if(_info->frame_width==0||_tc->vendor==NULL||*_setup!=NULL){
   1.213 +        return TH_EBADHEADER;
   1.214 +      }
   1.215 +      setup=(oc_setup_info *)_ogg_calloc(1,sizeof(*setup));
   1.216 +      if(setup==NULL)return TH_EFAULT;
   1.217 +      ret=oc_setup_unpack(_opb,setup);
   1.218 +      if(ret<0){
   1.219 +        oc_setup_clear(setup);
   1.220 +        _ogg_free(setup);
   1.221 +      }
   1.222 +      else{
   1.223 +        *_setup=setup;
   1.224 +        ret=1;
   1.225 +      }
   1.226 +    }break;
   1.227 +    default:{
   1.228 +      /*We don't know what this header is.*/
   1.229 +      return TH_EBADHEADER;
   1.230 +    }break;
   1.231 +  }
   1.232 +  return ret;
   1.233 +}
   1.234 +
   1.235 +
   1.236 +/*Decodes one header packet.
   1.237 +  This should be called repeatedly with the packets at the beginning of the
   1.238 +   stream until it returns 0.*/
   1.239 +int th_decode_headerin(th_info *_info,th_comment *_tc,
   1.240 + th_setup_info **_setup,ogg_packet *_op){
   1.241 +  oc_pack_buf opb;
   1.242 +  if(_op==NULL)return TH_EBADHEADER;
   1.243 +  if(_info==NULL)return TH_EFAULT;
   1.244 +  oc_pack_readinit(&opb,_op->packet,_op->bytes);
   1.245 +  return oc_dec_headerin(&opb,_info,_tc,_setup,_op);
   1.246 +}
   1.247 +
   1.248 +void th_setup_free(th_setup_info *_setup){
   1.249 +  if(_setup!=NULL){
   1.250 +    oc_setup_clear(_setup);
   1.251 +    _ogg_free(_setup);
   1.252 +  }
   1.253 +}

mercurial