1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/media/libtremor/lib/tremor_info.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,390 @@ 1.4 +/******************************************************************** 1.5 + * * 1.6 + * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. * 1.7 + * * 1.8 + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * 1.9 + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * 1.10 + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * 1.11 + * * 1.12 + * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2003 * 1.13 + * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * 1.14 + * * 1.15 + ******************************************************************** 1.16 + 1.17 + function: maintain the info structure, info <-> header packets 1.18 + 1.19 + ********************************************************************/ 1.20 + 1.21 +/* general handling of the header and the vorbis_info structure (and 1.22 + substructures) */ 1.23 + 1.24 +#include <stdlib.h> 1.25 +#include <string.h> 1.26 +#include <ctype.h> 1.27 +#include <limits.h> 1.28 +#include <ogg/ogg.h> 1.29 +#include "ivorbiscodec.h" 1.30 +#include "codec_internal.h" 1.31 +#include "codebook.h" 1.32 +#include "registry.h" 1.33 +#include "window.h" 1.34 +#include "misc.h" 1.35 + 1.36 +/* helpers */ 1.37 +static void _v_readstring(oggpack_buffer *o,char *buf,int bytes){ 1.38 + while(bytes--){ 1.39 + *buf++=oggpack_read(o,8); 1.40 + } 1.41 +} 1.42 + 1.43 +void vorbis_comment_init(vorbis_comment *vc){ 1.44 + memset(vc,0,sizeof(*vc)); 1.45 +} 1.46 + 1.47 +/* This is more or less the same as strncasecmp - but that doesn't exist 1.48 + * everywhere, and this is a fairly trivial function, so we include it */ 1.49 +static int tagcompare(const char *s1, const char *s2, int n){ 1.50 + int c=0; 1.51 + while(c < n){ 1.52 + if(toupper(s1[c]) != toupper(s2[c])) 1.53 + return !0; 1.54 + c++; 1.55 + } 1.56 + return 0; 1.57 +} 1.58 + 1.59 +char *vorbis_comment_query(vorbis_comment *vc, char *tag, int count){ 1.60 + long i; 1.61 + int found = 0; 1.62 + int taglen = strlen(tag)+1; /* +1 for the = we append */ 1.63 + char *fulltag = (char *)alloca(taglen+ 1); 1.64 + 1.65 + strcpy(fulltag, tag); 1.66 + strcat(fulltag, "="); 1.67 + 1.68 + for(i=0;i<vc->comments;i++){ 1.69 + if(!tagcompare(vc->user_comments[i], fulltag, taglen)){ 1.70 + if(count == found) 1.71 + /* We return a pointer to the data, not a copy */ 1.72 + return vc->user_comments[i] + taglen; 1.73 + else 1.74 + found++; 1.75 + } 1.76 + } 1.77 + return NULL; /* didn't find anything */ 1.78 +} 1.79 + 1.80 +int vorbis_comment_query_count(vorbis_comment *vc, char *tag){ 1.81 + int i,count=0; 1.82 + int taglen = strlen(tag)+1; /* +1 for the = we append */ 1.83 + char *fulltag = (char *)alloca(taglen+1); 1.84 + strcpy(fulltag,tag); 1.85 + strcat(fulltag, "="); 1.86 + 1.87 + for(i=0;i<vc->comments;i++){ 1.88 + if(!tagcompare(vc->user_comments[i], fulltag, taglen)) 1.89 + count++; 1.90 + } 1.91 + 1.92 + return count; 1.93 +} 1.94 + 1.95 +void vorbis_comment_clear(vorbis_comment *vc){ 1.96 + if(vc){ 1.97 + long i; 1.98 + if(vc->user_comments){ 1.99 + for(i=0;i<vc->comments;i++) 1.100 + if(vc->user_comments[i])_ogg_free(vc->user_comments[i]); 1.101 + _ogg_free(vc->user_comments); 1.102 + } 1.103 + if(vc->comment_lengths)_ogg_free(vc->comment_lengths); 1.104 + if(vc->vendor)_ogg_free(vc->vendor); 1.105 + memset(vc,0,sizeof(*vc)); 1.106 + } 1.107 +} 1.108 + 1.109 +/* blocksize 0 is guaranteed to be short, 1 is guarantted to be long. 1.110 + They may be equal, but short will never ge greater than long */ 1.111 +int vorbis_info_blocksize(vorbis_info *vi,int zo){ 1.112 + codec_setup_info *ci = (codec_setup_info *)vi->codec_setup; 1.113 + return ci ? ci->blocksizes[zo] : -1; 1.114 +} 1.115 + 1.116 +/* used by synthesis, which has a full, alloced vi */ 1.117 +void vorbis_info_init(vorbis_info *vi){ 1.118 + memset(vi,0,sizeof(*vi)); 1.119 + vi->codec_setup=(codec_setup_info *)_ogg_calloc(1,sizeof(codec_setup_info)); 1.120 +} 1.121 + 1.122 +void vorbis_info_clear(vorbis_info *vi){ 1.123 + codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; 1.124 + int i; 1.125 + 1.126 + if(ci){ 1.127 + 1.128 + for(i=0;i<ci->modes;i++) 1.129 + if(ci->mode_param[i])_ogg_free(ci->mode_param[i]); 1.130 + 1.131 + for(i=0;i<ci->maps;i++) /* unpack does the range checking */ 1.132 + if(ci->map_param[i]) 1.133 + _mapping_P[ci->map_type[i]]->free_info(ci->map_param[i]); 1.134 + 1.135 + for(i=0;i<ci->floors;i++) /* unpack does the range checking */ 1.136 + if(ci->floor_param[i]) 1.137 + _floor_P[ci->floor_type[i]]->free_info(ci->floor_param[i]); 1.138 + 1.139 + for(i=0;i<ci->residues;i++) /* unpack does the range checking */ 1.140 + if(ci->residue_param[i]) 1.141 + _residue_P[ci->residue_type[i]]->free_info(ci->residue_param[i]); 1.142 + 1.143 + for(i=0;i<ci->books;i++){ 1.144 + if(ci->book_param[i]){ 1.145 + /* knows if the book was not alloced */ 1.146 + vorbis_staticbook_destroy(ci->book_param[i]); 1.147 + } 1.148 + if(ci->fullbooks) 1.149 + vorbis_book_clear(ci->fullbooks+i); 1.150 + } 1.151 + if(ci->fullbooks) 1.152 + _ogg_free(ci->fullbooks); 1.153 + 1.154 + _ogg_free(ci); 1.155 + } 1.156 + 1.157 + memset(vi,0,sizeof(*vi)); 1.158 +} 1.159 + 1.160 +/* Header packing/unpacking ********************************************/ 1.161 + 1.162 +static int _vorbis_unpack_info(vorbis_info *vi,oggpack_buffer *opb){ 1.163 + codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; 1.164 + if(!ci)return(OV_EFAULT); 1.165 + 1.166 + vi->version=oggpack_read(opb,32); 1.167 + if(vi->version!=0)return(OV_EVERSION); 1.168 + 1.169 + vi->channels=oggpack_read(opb,8); 1.170 + vi->rate=oggpack_read(opb,32); 1.171 + 1.172 + vi->bitrate_upper=oggpack_read(opb,32); 1.173 + vi->bitrate_nominal=oggpack_read(opb,32); 1.174 + vi->bitrate_lower=oggpack_read(opb,32); 1.175 + 1.176 + ci->blocksizes[0]=1<<oggpack_read(opb,4); 1.177 + ci->blocksizes[1]=1<<oggpack_read(opb,4); 1.178 + 1.179 + if(vi->rate<1)goto err_out; 1.180 + if(vi->channels<1)goto err_out; 1.181 + if(ci->blocksizes[0]<64)goto err_out; 1.182 + if(ci->blocksizes[1]<ci->blocksizes[0])goto err_out; 1.183 + if(ci->blocksizes[1]>8192)goto err_out; 1.184 + 1.185 + if(oggpack_read(opb,1)!=1)goto err_out; /* EOP check */ 1.186 + 1.187 + return(0); 1.188 + err_out: 1.189 + vorbis_info_clear(vi); 1.190 + return(OV_EBADHEADER); 1.191 +} 1.192 + 1.193 +static int _vorbis_unpack_comment(vorbis_comment *vc,oggpack_buffer *opb){ 1.194 + int i; 1.195 + int vendorlen; 1.196 + vendorlen=oggpack_read(opb,32); 1.197 + if(vendorlen<0)goto err_out; 1.198 + if(vendorlen>opb->storage-oggpack_bytes(opb))goto err_out; 1.199 + vc->vendor=(char *)_ogg_calloc(vendorlen+1,1); 1.200 + if(vc->vendor==NULL)goto err_out; 1.201 + _v_readstring(opb,vc->vendor,vendorlen); 1.202 + i=oggpack_read(opb,32); 1.203 + if(i<0||i>=INT_MAX||i>(opb->storage-oggpack_bytes(opb))>>2)goto err_out; 1.204 + vc->user_comments=(char **)_ogg_calloc(i+1,sizeof(*vc->user_comments)); 1.205 + vc->comment_lengths=(int *)_ogg_calloc(i+1, sizeof(*vc->comment_lengths)); 1.206 + if(vc->user_comments==NULL||vc->comment_lengths==NULL)goto err_out; 1.207 + vc->comments=i; 1.208 + 1.209 + for(i=0;i<vc->comments;i++){ 1.210 + int len=oggpack_read(opb,32); 1.211 + if(len<0||len>opb->storage-oggpack_bytes(opb))goto err_out; 1.212 + vc->comment_lengths[i]=len; 1.213 + vc->user_comments[i]=(char *)_ogg_calloc(len+1,1); 1.214 + if(vc->user_comments[i]==NULL){ 1.215 + vc->comments=i; 1.216 + goto err_out; 1.217 + } 1.218 + _v_readstring(opb,vc->user_comments[i],len); 1.219 + } 1.220 + if(oggpack_read(opb,1)!=1)goto err_out; /* EOP check */ 1.221 + 1.222 + return(0); 1.223 + err_out: 1.224 + vorbis_comment_clear(vc); 1.225 + return(OV_EBADHEADER); 1.226 +} 1.227 + 1.228 +/* all of the real encoding details are here. The modes, books, 1.229 + everything */ 1.230 +static int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb){ 1.231 + codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; 1.232 + int i; 1.233 + if(!ci)return(OV_EFAULT); 1.234 + 1.235 + /* codebooks */ 1.236 + ci->books=oggpack_read(opb,8)+1; 1.237 + if(ci->books<=0)goto err_out; 1.238 + for(i=0;i<ci->books;i++){ 1.239 + ci->book_param[i]=vorbis_staticbook_unpack(opb); 1.240 + if(!ci->book_param[i])goto err_out; 1.241 + } 1.242 + 1.243 + /* time backend settings */ 1.244 + ci->times=oggpack_read(opb,6)+1; 1.245 + if(ci->times<=0)goto err_out; 1.246 + for(i=0;i<ci->times;i++){ 1.247 + ci->time_type[i]=oggpack_read(opb,16); 1.248 + if(ci->time_type[i]<0 || ci->time_type[i]>=VI_TIMEB)goto err_out; 1.249 + /* ci->time_param[i]=_time_P[ci->time_type[i]]->unpack(vi,opb); 1.250 + Vorbis I has no time backend */ 1.251 + /*if(!ci->time_param[i])goto err_out;*/ 1.252 + } 1.253 + 1.254 + /* floor backend settings */ 1.255 + ci->floors=oggpack_read(opb,6)+1; 1.256 + if(ci->floors<=0)goto err_out; 1.257 + for(i=0;i<ci->floors;i++){ 1.258 + ci->floor_type[i]=oggpack_read(opb,16); 1.259 + if(ci->floor_type[i]<0 || ci->floor_type[i]>=VI_FLOORB)goto err_out; 1.260 + ci->floor_param[i]=_floor_P[ci->floor_type[i]]->unpack(vi,opb); 1.261 + if(!ci->floor_param[i])goto err_out; 1.262 + } 1.263 + 1.264 + /* residue backend settings */ 1.265 + ci->residues=oggpack_read(opb,6)+1; 1.266 + if(ci->residues<=0)goto err_out; 1.267 + for(i=0;i<ci->residues;i++){ 1.268 + ci->residue_type[i]=oggpack_read(opb,16); 1.269 + if(ci->residue_type[i]<0 || ci->residue_type[i]>=VI_RESB)goto err_out; 1.270 + ci->residue_param[i]=_residue_P[ci->residue_type[i]]->unpack(vi,opb); 1.271 + if(!ci->residue_param[i])goto err_out; 1.272 + } 1.273 + 1.274 + /* map backend settings */ 1.275 + ci->maps=oggpack_read(opb,6)+1; 1.276 + if(ci->maps<=0)goto err_out; 1.277 + for(i=0;i<ci->maps;i++){ 1.278 + ci->map_type[i]=oggpack_read(opb,16); 1.279 + if(ci->map_type[i]<0 || ci->map_type[i]>=VI_MAPB)goto err_out; 1.280 + ci->map_param[i]=_mapping_P[ci->map_type[i]]->unpack(vi,opb); 1.281 + if(!ci->map_param[i])goto err_out; 1.282 + } 1.283 + 1.284 + /* mode settings */ 1.285 + ci->modes=oggpack_read(opb,6)+1; 1.286 + if(ci->modes<=0)goto err_out; 1.287 + for(i=0;i<ci->modes;i++){ 1.288 + ci->mode_param[i]=(vorbis_info_mode *)_ogg_calloc(1,sizeof(*ci->mode_param[i])); 1.289 + ci->mode_param[i]->blockflag=oggpack_read(opb,1); 1.290 + ci->mode_param[i]->windowtype=oggpack_read(opb,16); 1.291 + ci->mode_param[i]->transformtype=oggpack_read(opb,16); 1.292 + ci->mode_param[i]->mapping=oggpack_read(opb,8); 1.293 + 1.294 + if(ci->mode_param[i]->windowtype>=VI_WINDOWB)goto err_out; 1.295 + if(ci->mode_param[i]->transformtype>=VI_WINDOWB)goto err_out; 1.296 + if(ci->mode_param[i]->mapping>=ci->maps)goto err_out; 1.297 + if(ci->mode_param[i]->mapping<0)goto err_out; 1.298 + } 1.299 + 1.300 + if(oggpack_read(opb,1)!=1)goto err_out; /* top level EOP check */ 1.301 + 1.302 + return(0); 1.303 + err_out: 1.304 + vorbis_info_clear(vi); 1.305 + return(OV_EBADHEADER); 1.306 +} 1.307 + 1.308 +/* Is this packet a vorbis ID header? */ 1.309 +int vorbis_synthesis_idheader(ogg_packet *op){ 1.310 + oggpack_buffer opb; 1.311 + char buffer[6]; 1.312 + 1.313 + if(op){ 1.314 + oggpack_readinit(&opb,op->packet,op->bytes); 1.315 + 1.316 + if(!op->b_o_s) 1.317 + return(0); /* Not the initial packet */ 1.318 + 1.319 + if(oggpack_read(&opb,8) != 1) 1.320 + return 0; /* not an ID header */ 1.321 + 1.322 + memset(buffer,0,6); 1.323 + _v_readstring(&opb,buffer,6); 1.324 + if(memcmp(buffer,"vorbis",6)) 1.325 + return 0; /* not vorbis */ 1.326 + 1.327 + return 1; 1.328 + } 1.329 + 1.330 + return 0; 1.331 +} 1.332 + 1.333 +/* The Vorbis header is in three packets; the initial small packet in 1.334 + the first page that identifies basic parameters, a second packet 1.335 + with bitstream comments and a third packet that holds the 1.336 + codebook. */ 1.337 + 1.338 +int vorbis_synthesis_headerin(vorbis_info *vi,vorbis_comment *vc,ogg_packet *op){ 1.339 + oggpack_buffer opb; 1.340 + 1.341 + if(op){ 1.342 + oggpack_readinit(&opb,op->packet,op->bytes); 1.343 + 1.344 + /* Which of the three types of header is this? */ 1.345 + /* Also verify header-ness, vorbis */ 1.346 + { 1.347 + char buffer[6]; 1.348 + int packtype=oggpack_read(&opb,8); 1.349 + memset(buffer,0,6); 1.350 + _v_readstring(&opb,buffer,6); 1.351 + if(memcmp(buffer,"vorbis",6)){ 1.352 + /* not a vorbis header */ 1.353 + return(OV_ENOTVORBIS); 1.354 + } 1.355 + switch(packtype){ 1.356 + case 0x01: /* least significant *bit* is read first */ 1.357 + if(!op->b_o_s){ 1.358 + /* Not the initial packet */ 1.359 + return(OV_EBADHEADER); 1.360 + } 1.361 + if(vi->rate!=0){ 1.362 + /* previously initialized info header */ 1.363 + return(OV_EBADHEADER); 1.364 + } 1.365 + 1.366 + return(_vorbis_unpack_info(vi,&opb)); 1.367 + 1.368 + case 0x03: /* least significant *bit* is read first */ 1.369 + if(vi->rate==0){ 1.370 + /* um... we didn't get the initial header */ 1.371 + return(OV_EBADHEADER); 1.372 + } 1.373 + 1.374 + return(_vorbis_unpack_comment(vc,&opb)); 1.375 + 1.376 + case 0x05: /* least significant *bit* is read first */ 1.377 + if(vi->rate==0 || vc->vendor==NULL){ 1.378 + /* um... we didn;t get the initial header or comments yet */ 1.379 + return(OV_EBADHEADER); 1.380 + } 1.381 + 1.382 + return(_vorbis_unpack_books(vi,&opb)); 1.383 + 1.384 + default: 1.385 + /* Not a valid vorbis header type */ 1.386 + return(OV_EBADHEADER); 1.387 + break; 1.388 + } 1.389 + } 1.390 + } 1.391 + return(OV_EBADHEADER); 1.392 +} 1.393 +