vrshoot
diff libs/vorbis/info.c @ 0:b2f14e535253
initial commit
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sat, 01 Feb 2014 19:58:19 +0200 |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/libs/vorbis/info.c Sat Feb 01 19:58:19 2014 +0200 1.3 @@ -0,0 +1,668 @@ 1.4 +/******************************************************************** 1.5 + * * 1.6 + * THIS FILE IS PART OF THE OggVorbis 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 OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2010 * 1.12 + * by the Xiph.Org Foundation http://www.xiph.org/ * 1.13 + * * 1.14 + ******************************************************************** 1.15 + 1.16 + function: maintain the info structure, info <-> header packets 1.17 + last mod: $Id: info.c 18186 2012-02-03 22:08:44Z xiphmont $ 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 <ogg/ogg.h> 1.28 +#include "vorbis/codec.h" 1.29 +#include "codec_internal.h" 1.30 +#include "codebook.h" 1.31 +#include "registry.h" 1.32 +#include "window.h" 1.33 +#include "psy.h" 1.34 +#include "misc.h" 1.35 +#include "os.h" 1.36 + 1.37 +#define GENERAL_VENDOR_STRING "Xiph.Org libVorbis 1.3.3" 1.38 +#define ENCODE_VENDOR_STRING "Xiph.Org libVorbis I 20120203 (Omnipresent)" 1.39 + 1.40 +/* helpers */ 1.41 +static int ilog2(unsigned int v){ 1.42 + int ret=0; 1.43 + if(v)--v; 1.44 + while(v){ 1.45 + ret++; 1.46 + v>>=1; 1.47 + } 1.48 + return(ret); 1.49 +} 1.50 + 1.51 +static void _v_writestring(oggpack_buffer *o,const char *s, int bytes){ 1.52 + 1.53 + while(bytes--){ 1.54 + oggpack_write(o,*s++,8); 1.55 + } 1.56 +} 1.57 + 1.58 +static void _v_readstring(oggpack_buffer *o,char *buf,int bytes){ 1.59 + while(bytes--){ 1.60 + *buf++=oggpack_read(o,8); 1.61 + } 1.62 +} 1.63 + 1.64 +void vorbis_comment_init(vorbis_comment *vc){ 1.65 + memset(vc,0,sizeof(*vc)); 1.66 +} 1.67 + 1.68 +void vorbis_comment_add(vorbis_comment *vc,const char *comment){ 1.69 + vc->user_comments=_ogg_realloc(vc->user_comments, 1.70 + (vc->comments+2)*sizeof(*vc->user_comments)); 1.71 + vc->comment_lengths=_ogg_realloc(vc->comment_lengths, 1.72 + (vc->comments+2)*sizeof(*vc->comment_lengths)); 1.73 + vc->comment_lengths[vc->comments]=strlen(comment); 1.74 + vc->user_comments[vc->comments]=_ogg_malloc(vc->comment_lengths[vc->comments]+1); 1.75 + strcpy(vc->user_comments[vc->comments], comment); 1.76 + vc->comments++; 1.77 + vc->user_comments[vc->comments]=NULL; 1.78 +} 1.79 + 1.80 +void vorbis_comment_add_tag(vorbis_comment *vc, const char *tag, const char *contents){ 1.81 + char *comment=alloca(strlen(tag)+strlen(contents)+2); /* +2 for = and \0 */ 1.82 + strcpy(comment, tag); 1.83 + strcat(comment, "="); 1.84 + strcat(comment, contents); 1.85 + vorbis_comment_add(vc, comment); 1.86 +} 1.87 + 1.88 +/* This is more or less the same as strncasecmp - but that doesn't exist 1.89 + * everywhere, and this is a fairly trivial function, so we include it */ 1.90 +static int tagcompare(const char *s1, const char *s2, int n){ 1.91 + int c=0; 1.92 + while(c < n){ 1.93 + if(toupper(s1[c]) != toupper(s2[c])) 1.94 + return !0; 1.95 + c++; 1.96 + } 1.97 + return 0; 1.98 +} 1.99 + 1.100 +char *vorbis_comment_query(vorbis_comment *vc, const char *tag, int count){ 1.101 + long i; 1.102 + int found = 0; 1.103 + int taglen = strlen(tag)+1; /* +1 for the = we append */ 1.104 + char *fulltag = alloca(taglen+ 1); 1.105 + 1.106 + strcpy(fulltag, tag); 1.107 + strcat(fulltag, "="); 1.108 + 1.109 + for(i=0;i<vc->comments;i++){ 1.110 + if(!tagcompare(vc->user_comments[i], fulltag, taglen)){ 1.111 + if(count == found) 1.112 + /* We return a pointer to the data, not a copy */ 1.113 + return vc->user_comments[i] + taglen; 1.114 + else 1.115 + found++; 1.116 + } 1.117 + } 1.118 + return NULL; /* didn't find anything */ 1.119 +} 1.120 + 1.121 +int vorbis_comment_query_count(vorbis_comment *vc, const char *tag){ 1.122 + int i,count=0; 1.123 + int taglen = strlen(tag)+1; /* +1 for the = we append */ 1.124 + char *fulltag = alloca(taglen+1); 1.125 + strcpy(fulltag,tag); 1.126 + strcat(fulltag, "="); 1.127 + 1.128 + for(i=0;i<vc->comments;i++){ 1.129 + if(!tagcompare(vc->user_comments[i], fulltag, taglen)) 1.130 + count++; 1.131 + } 1.132 + 1.133 + return count; 1.134 +} 1.135 + 1.136 +void vorbis_comment_clear(vorbis_comment *vc){ 1.137 + if(vc){ 1.138 + long i; 1.139 + if(vc->user_comments){ 1.140 + for(i=0;i<vc->comments;i++) 1.141 + if(vc->user_comments[i])_ogg_free(vc->user_comments[i]); 1.142 + _ogg_free(vc->user_comments); 1.143 + } 1.144 + if(vc->comment_lengths)_ogg_free(vc->comment_lengths); 1.145 + if(vc->vendor)_ogg_free(vc->vendor); 1.146 + memset(vc,0,sizeof(*vc)); 1.147 + } 1.148 +} 1.149 + 1.150 +/* blocksize 0 is guaranteed to be short, 1 is guaranteed to be long. 1.151 + They may be equal, but short will never ge greater than long */ 1.152 +int vorbis_info_blocksize(vorbis_info *vi,int zo){ 1.153 + codec_setup_info *ci = vi->codec_setup; 1.154 + return ci ? ci->blocksizes[zo] : -1; 1.155 +} 1.156 + 1.157 +/* used by synthesis, which has a full, alloced vi */ 1.158 +void vorbis_info_init(vorbis_info *vi){ 1.159 + memset(vi,0,sizeof(*vi)); 1.160 + vi->codec_setup=_ogg_calloc(1,sizeof(codec_setup_info)); 1.161 +} 1.162 + 1.163 +void vorbis_info_clear(vorbis_info *vi){ 1.164 + codec_setup_info *ci=vi->codec_setup; 1.165 + int i; 1.166 + 1.167 + if(ci){ 1.168 + 1.169 + for(i=0;i<ci->modes;i++) 1.170 + if(ci->mode_param[i])_ogg_free(ci->mode_param[i]); 1.171 + 1.172 + for(i=0;i<ci->maps;i++) /* unpack does the range checking */ 1.173 + if(ci->map_param[i]) /* this may be cleaning up an aborted 1.174 + unpack, in which case the below type 1.175 + cannot be trusted */ 1.176 + _mapping_P[ci->map_type[i]]->free_info(ci->map_param[i]); 1.177 + 1.178 + for(i=0;i<ci->floors;i++) /* unpack does the range checking */ 1.179 + if(ci->floor_param[i]) /* this may be cleaning up an aborted 1.180 + unpack, in which case the below type 1.181 + cannot be trusted */ 1.182 + _floor_P[ci->floor_type[i]]->free_info(ci->floor_param[i]); 1.183 + 1.184 + for(i=0;i<ci->residues;i++) /* unpack does the range checking */ 1.185 + if(ci->residue_param[i]) /* this may be cleaning up an aborted 1.186 + unpack, in which case the below type 1.187 + cannot be trusted */ 1.188 + _residue_P[ci->residue_type[i]]->free_info(ci->residue_param[i]); 1.189 + 1.190 + for(i=0;i<ci->books;i++){ 1.191 + if(ci->book_param[i]){ 1.192 + /* knows if the book was not alloced */ 1.193 + vorbis_staticbook_destroy(ci->book_param[i]); 1.194 + } 1.195 + if(ci->fullbooks) 1.196 + vorbis_book_clear(ci->fullbooks+i); 1.197 + } 1.198 + if(ci->fullbooks) 1.199 + _ogg_free(ci->fullbooks); 1.200 + 1.201 + for(i=0;i<ci->psys;i++) 1.202 + _vi_psy_free(ci->psy_param[i]); 1.203 + 1.204 + _ogg_free(ci); 1.205 + } 1.206 + 1.207 + memset(vi,0,sizeof(*vi)); 1.208 +} 1.209 + 1.210 +/* Header packing/unpacking ********************************************/ 1.211 + 1.212 +static int _vorbis_unpack_info(vorbis_info *vi,oggpack_buffer *opb){ 1.213 + codec_setup_info *ci=vi->codec_setup; 1.214 + if(!ci)return(OV_EFAULT); 1.215 + 1.216 + vi->version=oggpack_read(opb,32); 1.217 + if(vi->version!=0)return(OV_EVERSION); 1.218 + 1.219 + vi->channels=oggpack_read(opb,8); 1.220 + vi->rate=oggpack_read(opb,32); 1.221 + 1.222 + vi->bitrate_upper=oggpack_read(opb,32); 1.223 + vi->bitrate_nominal=oggpack_read(opb,32); 1.224 + vi->bitrate_lower=oggpack_read(opb,32); 1.225 + 1.226 + ci->blocksizes[0]=1<<oggpack_read(opb,4); 1.227 + ci->blocksizes[1]=1<<oggpack_read(opb,4); 1.228 + 1.229 + if(vi->rate<1)goto err_out; 1.230 + if(vi->channels<1)goto err_out; 1.231 + if(ci->blocksizes[0]<64)goto err_out; 1.232 + if(ci->blocksizes[1]<ci->blocksizes[0])goto err_out; 1.233 + if(ci->blocksizes[1]>8192)goto err_out; 1.234 + 1.235 + if(oggpack_read(opb,1)!=1)goto err_out; /* EOP check */ 1.236 + 1.237 + return(0); 1.238 + err_out: 1.239 + vorbis_info_clear(vi); 1.240 + return(OV_EBADHEADER); 1.241 +} 1.242 + 1.243 +static int _vorbis_unpack_comment(vorbis_comment *vc,oggpack_buffer *opb){ 1.244 + int i; 1.245 + int vendorlen=oggpack_read(opb,32); 1.246 + if(vendorlen<0)goto err_out; 1.247 + if(vendorlen>opb->storage-8)goto err_out; 1.248 + vc->vendor=_ogg_calloc(vendorlen+1,1); 1.249 + _v_readstring(opb,vc->vendor,vendorlen); 1.250 + i=oggpack_read(opb,32); 1.251 + if(i<0)goto err_out; 1.252 + if(i>((opb->storage-oggpack_bytes(opb))>>2))goto err_out; 1.253 + vc->comments=i; 1.254 + vc->user_comments=_ogg_calloc(vc->comments+1,sizeof(*vc->user_comments)); 1.255 + vc->comment_lengths=_ogg_calloc(vc->comments+1, sizeof(*vc->comment_lengths)); 1.256 + 1.257 + for(i=0;i<vc->comments;i++){ 1.258 + int len=oggpack_read(opb,32); 1.259 + if(len<0)goto err_out; 1.260 + if(len>opb->storage-oggpack_bytes(opb))goto err_out; 1.261 + vc->comment_lengths[i]=len; 1.262 + vc->user_comments[i]=_ogg_calloc(len+1,1); 1.263 + _v_readstring(opb,vc->user_comments[i],len); 1.264 + } 1.265 + if(oggpack_read(opb,1)!=1)goto err_out; /* EOP check */ 1.266 + 1.267 + return(0); 1.268 + err_out: 1.269 + vorbis_comment_clear(vc); 1.270 + return(OV_EBADHEADER); 1.271 +} 1.272 + 1.273 +/* all of the real encoding details are here. The modes, books, 1.274 + everything */ 1.275 +static int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb){ 1.276 + codec_setup_info *ci=vi->codec_setup; 1.277 + int i; 1.278 + if(!ci)return(OV_EFAULT); 1.279 + 1.280 + /* codebooks */ 1.281 + ci->books=oggpack_read(opb,8)+1; 1.282 + if(ci->books<=0)goto err_out; 1.283 + for(i=0;i<ci->books;i++){ 1.284 + ci->book_param[i]=vorbis_staticbook_unpack(opb); 1.285 + if(!ci->book_param[i])goto err_out; 1.286 + } 1.287 + 1.288 + /* time backend settings; hooks are unused */ 1.289 + { 1.290 + int times=oggpack_read(opb,6)+1; 1.291 + if(times<=0)goto err_out; 1.292 + for(i=0;i<times;i++){ 1.293 + int test=oggpack_read(opb,16); 1.294 + if(test<0 || test>=VI_TIMEB)goto err_out; 1.295 + } 1.296 + } 1.297 + 1.298 + /* floor backend settings */ 1.299 + ci->floors=oggpack_read(opb,6)+1; 1.300 + if(ci->floors<=0)goto err_out; 1.301 + for(i=0;i<ci->floors;i++){ 1.302 + ci->floor_type[i]=oggpack_read(opb,16); 1.303 + if(ci->floor_type[i]<0 || ci->floor_type[i]>=VI_FLOORB)goto err_out; 1.304 + ci->floor_param[i]=_floor_P[ci->floor_type[i]]->unpack(vi,opb); 1.305 + if(!ci->floor_param[i])goto err_out; 1.306 + } 1.307 + 1.308 + /* residue backend settings */ 1.309 + ci->residues=oggpack_read(opb,6)+1; 1.310 + if(ci->residues<=0)goto err_out; 1.311 + for(i=0;i<ci->residues;i++){ 1.312 + ci->residue_type[i]=oggpack_read(opb,16); 1.313 + if(ci->residue_type[i]<0 || ci->residue_type[i]>=VI_RESB)goto err_out; 1.314 + ci->residue_param[i]=_residue_P[ci->residue_type[i]]->unpack(vi,opb); 1.315 + if(!ci->residue_param[i])goto err_out; 1.316 + } 1.317 + 1.318 + /* map backend settings */ 1.319 + ci->maps=oggpack_read(opb,6)+1; 1.320 + if(ci->maps<=0)goto err_out; 1.321 + for(i=0;i<ci->maps;i++){ 1.322 + ci->map_type[i]=oggpack_read(opb,16); 1.323 + if(ci->map_type[i]<0 || ci->map_type[i]>=VI_MAPB)goto err_out; 1.324 + ci->map_param[i]=_mapping_P[ci->map_type[i]]->unpack(vi,opb); 1.325 + if(!ci->map_param[i])goto err_out; 1.326 + } 1.327 + 1.328 + /* mode settings */ 1.329 + ci->modes=oggpack_read(opb,6)+1; 1.330 + if(ci->modes<=0)goto err_out; 1.331 + for(i=0;i<ci->modes;i++){ 1.332 + ci->mode_param[i]=_ogg_calloc(1,sizeof(*ci->mode_param[i])); 1.333 + ci->mode_param[i]->blockflag=oggpack_read(opb,1); 1.334 + ci->mode_param[i]->windowtype=oggpack_read(opb,16); 1.335 + ci->mode_param[i]->transformtype=oggpack_read(opb,16); 1.336 + ci->mode_param[i]->mapping=oggpack_read(opb,8); 1.337 + 1.338 + if(ci->mode_param[i]->windowtype>=VI_WINDOWB)goto err_out; 1.339 + if(ci->mode_param[i]->transformtype>=VI_WINDOWB)goto err_out; 1.340 + if(ci->mode_param[i]->mapping>=ci->maps)goto err_out; 1.341 + if(ci->mode_param[i]->mapping<0)goto err_out; 1.342 + } 1.343 + 1.344 + if(oggpack_read(opb,1)!=1)goto err_out; /* top level EOP check */ 1.345 + 1.346 + return(0); 1.347 + err_out: 1.348 + vorbis_info_clear(vi); 1.349 + return(OV_EBADHEADER); 1.350 +} 1.351 + 1.352 +/* Is this packet a vorbis ID header? */ 1.353 +int vorbis_synthesis_idheader(ogg_packet *op){ 1.354 + oggpack_buffer opb; 1.355 + char buffer[6]; 1.356 + 1.357 + if(op){ 1.358 + oggpack_readinit(&opb,op->packet,op->bytes); 1.359 + 1.360 + if(!op->b_o_s) 1.361 + return(0); /* Not the initial packet */ 1.362 + 1.363 + if(oggpack_read(&opb,8) != 1) 1.364 + return 0; /* not an ID header */ 1.365 + 1.366 + memset(buffer,0,6); 1.367 + _v_readstring(&opb,buffer,6); 1.368 + if(memcmp(buffer,"vorbis",6)) 1.369 + return 0; /* not vorbis */ 1.370 + 1.371 + return 1; 1.372 + } 1.373 + 1.374 + return 0; 1.375 +} 1.376 + 1.377 +/* The Vorbis header is in three packets; the initial small packet in 1.378 + the first page that identifies basic parameters, a second packet 1.379 + with bitstream comments and a third packet that holds the 1.380 + codebook. */ 1.381 + 1.382 +int vorbis_synthesis_headerin(vorbis_info *vi,vorbis_comment *vc,ogg_packet *op){ 1.383 + oggpack_buffer opb; 1.384 + 1.385 + if(op){ 1.386 + oggpack_readinit(&opb,op->packet,op->bytes); 1.387 + 1.388 + /* Which of the three types of header is this? */ 1.389 + /* Also verify header-ness, vorbis */ 1.390 + { 1.391 + char buffer[6]; 1.392 + int packtype=oggpack_read(&opb,8); 1.393 + memset(buffer,0,6); 1.394 + _v_readstring(&opb,buffer,6); 1.395 + if(memcmp(buffer,"vorbis",6)){ 1.396 + /* not a vorbis header */ 1.397 + return(OV_ENOTVORBIS); 1.398 + } 1.399 + switch(packtype){ 1.400 + case 0x01: /* least significant *bit* is read first */ 1.401 + if(!op->b_o_s){ 1.402 + /* Not the initial packet */ 1.403 + return(OV_EBADHEADER); 1.404 + } 1.405 + if(vi->rate!=0){ 1.406 + /* previously initialized info header */ 1.407 + return(OV_EBADHEADER); 1.408 + } 1.409 + 1.410 + return(_vorbis_unpack_info(vi,&opb)); 1.411 + 1.412 + case 0x03: /* least significant *bit* is read first */ 1.413 + if(vi->rate==0){ 1.414 + /* um... we didn't get the initial header */ 1.415 + return(OV_EBADHEADER); 1.416 + } 1.417 + 1.418 + return(_vorbis_unpack_comment(vc,&opb)); 1.419 + 1.420 + case 0x05: /* least significant *bit* is read first */ 1.421 + if(vi->rate==0 || vc->vendor==NULL){ 1.422 + /* um... we didn;t get the initial header or comments yet */ 1.423 + return(OV_EBADHEADER); 1.424 + } 1.425 + 1.426 + return(_vorbis_unpack_books(vi,&opb)); 1.427 + 1.428 + default: 1.429 + /* Not a valid vorbis header type */ 1.430 + return(OV_EBADHEADER); 1.431 + break; 1.432 + } 1.433 + } 1.434 + } 1.435 + return(OV_EBADHEADER); 1.436 +} 1.437 + 1.438 +/* pack side **********************************************************/ 1.439 + 1.440 +static int _vorbis_pack_info(oggpack_buffer *opb,vorbis_info *vi){ 1.441 + codec_setup_info *ci=vi->codec_setup; 1.442 + if(!ci)return(OV_EFAULT); 1.443 + 1.444 + /* preamble */ 1.445 + oggpack_write(opb,0x01,8); 1.446 + _v_writestring(opb,"vorbis", 6); 1.447 + 1.448 + /* basic information about the stream */ 1.449 + oggpack_write(opb,0x00,32); 1.450 + oggpack_write(opb,vi->channels,8); 1.451 + oggpack_write(opb,vi->rate,32); 1.452 + 1.453 + oggpack_write(opb,vi->bitrate_upper,32); 1.454 + oggpack_write(opb,vi->bitrate_nominal,32); 1.455 + oggpack_write(opb,vi->bitrate_lower,32); 1.456 + 1.457 + oggpack_write(opb,ilog2(ci->blocksizes[0]),4); 1.458 + oggpack_write(opb,ilog2(ci->blocksizes[1]),4); 1.459 + oggpack_write(opb,1,1); 1.460 + 1.461 + return(0); 1.462 +} 1.463 + 1.464 +static int _vorbis_pack_comment(oggpack_buffer *opb,vorbis_comment *vc){ 1.465 + int bytes = strlen(ENCODE_VENDOR_STRING); 1.466 + 1.467 + /* preamble */ 1.468 + oggpack_write(opb,0x03,8); 1.469 + _v_writestring(opb,"vorbis", 6); 1.470 + 1.471 + /* vendor */ 1.472 + oggpack_write(opb,bytes,32); 1.473 + _v_writestring(opb,ENCODE_VENDOR_STRING, bytes); 1.474 + 1.475 + /* comments */ 1.476 + 1.477 + oggpack_write(opb,vc->comments,32); 1.478 + if(vc->comments){ 1.479 + int i; 1.480 + for(i=0;i<vc->comments;i++){ 1.481 + if(vc->user_comments[i]){ 1.482 + oggpack_write(opb,vc->comment_lengths[i],32); 1.483 + _v_writestring(opb,vc->user_comments[i], vc->comment_lengths[i]); 1.484 + }else{ 1.485 + oggpack_write(opb,0,32); 1.486 + } 1.487 + } 1.488 + } 1.489 + oggpack_write(opb,1,1); 1.490 + 1.491 + return(0); 1.492 +} 1.493 + 1.494 +static int _vorbis_pack_books(oggpack_buffer *opb,vorbis_info *vi){ 1.495 + codec_setup_info *ci=vi->codec_setup; 1.496 + int i; 1.497 + if(!ci)return(OV_EFAULT); 1.498 + 1.499 + oggpack_write(opb,0x05,8); 1.500 + _v_writestring(opb,"vorbis", 6); 1.501 + 1.502 + /* books */ 1.503 + oggpack_write(opb,ci->books-1,8); 1.504 + for(i=0;i<ci->books;i++) 1.505 + if(vorbis_staticbook_pack(ci->book_param[i],opb))goto err_out; 1.506 + 1.507 + /* times; hook placeholders */ 1.508 + oggpack_write(opb,0,6); 1.509 + oggpack_write(opb,0,16); 1.510 + 1.511 + /* floors */ 1.512 + oggpack_write(opb,ci->floors-1,6); 1.513 + for(i=0;i<ci->floors;i++){ 1.514 + oggpack_write(opb,ci->floor_type[i],16); 1.515 + if(_floor_P[ci->floor_type[i]]->pack) 1.516 + _floor_P[ci->floor_type[i]]->pack(ci->floor_param[i],opb); 1.517 + else 1.518 + goto err_out; 1.519 + } 1.520 + 1.521 + /* residues */ 1.522 + oggpack_write(opb,ci->residues-1,6); 1.523 + for(i=0;i<ci->residues;i++){ 1.524 + oggpack_write(opb,ci->residue_type[i],16); 1.525 + _residue_P[ci->residue_type[i]]->pack(ci->residue_param[i],opb); 1.526 + } 1.527 + 1.528 + /* maps */ 1.529 + oggpack_write(opb,ci->maps-1,6); 1.530 + for(i=0;i<ci->maps;i++){ 1.531 + oggpack_write(opb,ci->map_type[i],16); 1.532 + _mapping_P[ci->map_type[i]]->pack(vi,ci->map_param[i],opb); 1.533 + } 1.534 + 1.535 + /* modes */ 1.536 + oggpack_write(opb,ci->modes-1,6); 1.537 + for(i=0;i<ci->modes;i++){ 1.538 + oggpack_write(opb,ci->mode_param[i]->blockflag,1); 1.539 + oggpack_write(opb,ci->mode_param[i]->windowtype,16); 1.540 + oggpack_write(opb,ci->mode_param[i]->transformtype,16); 1.541 + oggpack_write(opb,ci->mode_param[i]->mapping,8); 1.542 + } 1.543 + oggpack_write(opb,1,1); 1.544 + 1.545 + return(0); 1.546 +err_out: 1.547 + return(-1); 1.548 +} 1.549 + 1.550 +int vorbis_commentheader_out(vorbis_comment *vc, 1.551 + ogg_packet *op){ 1.552 + 1.553 + oggpack_buffer opb; 1.554 + 1.555 + oggpack_writeinit(&opb); 1.556 + if(_vorbis_pack_comment(&opb,vc)){ 1.557 + oggpack_writeclear(&opb); 1.558 + return OV_EIMPL; 1.559 + } 1.560 + 1.561 + op->packet = _ogg_malloc(oggpack_bytes(&opb)); 1.562 + memcpy(op->packet, opb.buffer, oggpack_bytes(&opb)); 1.563 + 1.564 + op->bytes=oggpack_bytes(&opb); 1.565 + op->b_o_s=0; 1.566 + op->e_o_s=0; 1.567 + op->granulepos=0; 1.568 + op->packetno=1; 1.569 + 1.570 + oggpack_writeclear(&opb); 1.571 + return 0; 1.572 +} 1.573 + 1.574 +int vorbis_analysis_headerout(vorbis_dsp_state *v, 1.575 + vorbis_comment *vc, 1.576 + ogg_packet *op, 1.577 + ogg_packet *op_comm, 1.578 + ogg_packet *op_code){ 1.579 + int ret=OV_EIMPL; 1.580 + vorbis_info *vi=v->vi; 1.581 + oggpack_buffer opb; 1.582 + private_state *b=v->backend_state; 1.583 + 1.584 + if(!b){ 1.585 + ret=OV_EFAULT; 1.586 + goto err_out; 1.587 + } 1.588 + 1.589 + /* first header packet **********************************************/ 1.590 + 1.591 + oggpack_writeinit(&opb); 1.592 + if(_vorbis_pack_info(&opb,vi))goto err_out; 1.593 + 1.594 + /* build the packet */ 1.595 + if(b->header)_ogg_free(b->header); 1.596 + b->header=_ogg_malloc(oggpack_bytes(&opb)); 1.597 + memcpy(b->header,opb.buffer,oggpack_bytes(&opb)); 1.598 + op->packet=b->header; 1.599 + op->bytes=oggpack_bytes(&opb); 1.600 + op->b_o_s=1; 1.601 + op->e_o_s=0; 1.602 + op->granulepos=0; 1.603 + op->packetno=0; 1.604 + 1.605 + /* second header packet (comments) **********************************/ 1.606 + 1.607 + oggpack_reset(&opb); 1.608 + if(_vorbis_pack_comment(&opb,vc))goto err_out; 1.609 + 1.610 + if(b->header1)_ogg_free(b->header1); 1.611 + b->header1=_ogg_malloc(oggpack_bytes(&opb)); 1.612 + memcpy(b->header1,opb.buffer,oggpack_bytes(&opb)); 1.613 + op_comm->packet=b->header1; 1.614 + op_comm->bytes=oggpack_bytes(&opb); 1.615 + op_comm->b_o_s=0; 1.616 + op_comm->e_o_s=0; 1.617 + op_comm->granulepos=0; 1.618 + op_comm->packetno=1; 1.619 + 1.620 + /* third header packet (modes/codebooks) ****************************/ 1.621 + 1.622 + oggpack_reset(&opb); 1.623 + if(_vorbis_pack_books(&opb,vi))goto err_out; 1.624 + 1.625 + if(b->header2)_ogg_free(b->header2); 1.626 + b->header2=_ogg_malloc(oggpack_bytes(&opb)); 1.627 + memcpy(b->header2,opb.buffer,oggpack_bytes(&opb)); 1.628 + op_code->packet=b->header2; 1.629 + op_code->bytes=oggpack_bytes(&opb); 1.630 + op_code->b_o_s=0; 1.631 + op_code->e_o_s=0; 1.632 + op_code->granulepos=0; 1.633 + op_code->packetno=2; 1.634 + 1.635 + oggpack_writeclear(&opb); 1.636 + return(0); 1.637 + err_out: 1.638 + memset(op,0,sizeof(*op)); 1.639 + memset(op_comm,0,sizeof(*op_comm)); 1.640 + memset(op_code,0,sizeof(*op_code)); 1.641 + 1.642 + if(b){ 1.643 + oggpack_writeclear(&opb); 1.644 + if(b->header)_ogg_free(b->header); 1.645 + if(b->header1)_ogg_free(b->header1); 1.646 + if(b->header2)_ogg_free(b->header2); 1.647 + b->header=NULL; 1.648 + b->header1=NULL; 1.649 + b->header2=NULL; 1.650 + } 1.651 + return(ret); 1.652 +} 1.653 + 1.654 +double vorbis_granule_time(vorbis_dsp_state *v,ogg_int64_t granulepos){ 1.655 + if(granulepos == -1) return -1; 1.656 + 1.657 + /* We're not guaranteed a 64 bit unsigned type everywhere, so we 1.658 + have to put the unsigned granpo in a signed type. */ 1.659 + if(granulepos>=0){ 1.660 + return((double)granulepos/v->vi->rate); 1.661 + }else{ 1.662 + ogg_int64_t granuleoff=0xffffffff; 1.663 + granuleoff<<=31; 1.664 + granuleoff|=0x7ffffffff; 1.665 + return(((double)granulepos+2+granuleoff+granuleoff)/v->vi->rate); 1.666 + } 1.667 +} 1.668 + 1.669 +const char *vorbis_version_string(void){ 1.670 + return GENERAL_VENDOR_STRING; 1.671 +}