info.c (17109B)
1 /******************************************************************** 2 * * 3 * THIS FILE IS PART OF THE OggVorbis 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 OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2003 * 9 * by the XIPHOPHORUS Company http://www.xiph.org/ * 10 * * 11 ******************************************************************** 12 13 function: maintain the info structure, info <-> header packets 14 last mod: $Id: info.c 1919 2005-07-24 14:18:04Z baford $ 15 16 ********************************************************************/ 17 18 /* general handling of the header and the vorbis_info structure (and 19 substructures) */ 20 21 #include <stdlib.h> 22 #include <string.h> 23 #include <ctype.h> 24 #include <ogg/ogg.h> 25 #include "vorbis/codec.h" 26 #include "codec_internal.h" 27 #include "codebook.h" 28 #include "registry.h" 29 #include "window.h" 30 #include "psy.h" 31 #include "misc.h" 32 #include "os.h" 33 34 /* helpers */ 35 static int ilog2(unsigned int v){ 36 int ret=0; 37 if(v)--v; 38 while(v){ 39 ret++; 40 v>>=1; 41 } 42 return(ret); 43 } 44 45 static void _v_writestring(oggpack_buffer *o,char *s, int bytes){ 46 47 while(bytes--){ 48 oggpack_write(o,*s++,8); 49 } 50 } 51 52 static void _v_readstring(oggpack_buffer *o,char *buf,int bytes){ 53 while(bytes--){ 54 *buf++=oggpack_read(o,8); 55 } 56 } 57 58 void vorbis_comment_init(vorbis_comment *vc){ 59 memset(vc,0,sizeof(*vc)); 60 } 61 62 void vorbis_comment_add(vorbis_comment *vc,char *comment){ 63 vc->user_comments=_ogg_realloc(vc->user_comments, 64 (vc->comments+2)*sizeof(*vc->user_comments)); 65 vc->comment_lengths=_ogg_realloc(vc->comment_lengths, 66 (vc->comments+2)*sizeof(*vc->comment_lengths)); 67 vc->comment_lengths[vc->comments]=strlen(comment); 68 vc->user_comments[vc->comments]=_ogg_malloc(vc->comment_lengths[vc->comments]+1); 69 strcpy(vc->user_comments[vc->comments], comment); 70 vc->comments++; 71 vc->user_comments[vc->comments]=NULL; 72 } 73 74 void vorbis_comment_add_tag(vorbis_comment *vc, char *tag, char *contents){ 75 char *comment=alloca(strlen(tag)+strlen(contents)+2); /* +2 for = and \0 */ 76 strcpy(comment, tag); 77 strcat(comment, "="); 78 strcat(comment, contents); 79 vorbis_comment_add(vc, comment); 80 } 81 82 /* This is more or less the same as strncasecmp - but that doesn't exist 83 * everywhere, and this is a fairly trivial function, so we include it */ 84 static int tagcompare(const char *s1, const char *s2, int n){ 85 int c=0; 86 while(c < n){ 87 if(toupper(s1[c]) != toupper(s2[c])) 88 return !0; 89 c++; 90 } 91 return 0; 92 } 93 94 char *vorbis_comment_query(vorbis_comment *vc, char *tag, int count){ 95 long i; 96 int found = 0; 97 int taglen = strlen(tag)+1; /* +1 for the = we append */ 98 char *fulltag = alloca(taglen+ 1); 99 100 strcpy(fulltag, tag); 101 strcat(fulltag, "="); 102 103 for(i=0;i<vc->comments;i++){ 104 if(!tagcompare(vc->user_comments[i], fulltag, taglen)){ 105 if(count == found) 106 /* We return a pointer to the data, not a copy */ 107 return vc->user_comments[i] + taglen; 108 else 109 found++; 110 } 111 } 112 return NULL; /* didn't find anything */ 113 } 114 115 int vorbis_comment_query_count(vorbis_comment *vc, char *tag){ 116 int i,count=0; 117 int taglen = strlen(tag)+1; /* +1 for the = we append */ 118 char *fulltag = alloca(taglen+1); 119 strcpy(fulltag,tag); 120 strcat(fulltag, "="); 121 122 for(i=0;i<vc->comments;i++){ 123 if(!tagcompare(vc->user_comments[i], fulltag, taglen)) 124 count++; 125 } 126 127 return count; 128 } 129 130 void vorbis_comment_clear(vorbis_comment *vc){ 131 if(vc){ 132 long i; 133 for(i=0;i<vc->comments;i++) 134 if(vc->user_comments[i])_ogg_free(vc->user_comments[i]); 135 if(vc->user_comments)_ogg_free(vc->user_comments); 136 if(vc->comment_lengths)_ogg_free(vc->comment_lengths); 137 if(vc->vendor)_ogg_free(vc->vendor); 138 } 139 memset(vc,0,sizeof(*vc)); 140 } 141 142 /* blocksize 0 is guaranteed to be short, 1 is guarantted to be long. 143 They may be equal, but short will never ge greater than long */ 144 int vorbis_info_blocksize(vorbis_info *vi,int zo){ 145 codec_setup_info *ci = vi->codec_setup; 146 return ci ? ci->blocksizes[zo] : -1; 147 } 148 149 /* used by synthesis, which has a full, alloced vi */ 150 void vorbis_info_init(vorbis_info *vi){ 151 memset(vi,0,sizeof(*vi)); 152 vi->codec_setup=_ogg_calloc(1,sizeof(codec_setup_info)); 153 } 154 155 void vorbis_info_clear(vorbis_info *vi){ 156 codec_setup_info *ci=vi->codec_setup; 157 int i; 158 159 if(ci){ 160 161 for(i=0;i<ci->modes;i++) 162 if(ci->mode_param[i])_ogg_free(ci->mode_param[i]); 163 164 for(i=0;i<ci->maps;i++) /* unpack does the range checking */ 165 _mapping_P[ci->map_type[i]]->free_info(ci->map_param[i]); 166 167 for(i=0;i<ci->floors;i++) /* unpack does the range checking */ 168 _floor_P[ci->floor_type[i]]->free_info(ci->floor_param[i]); 169 170 for(i=0;i<ci->residues;i++) /* unpack does the range checking */ 171 _residue_P[ci->residue_type[i]]->free_info(ci->residue_param[i]); 172 173 for(i=0;i<ci->books;i++){ 174 if(ci->book_param[i]){ 175 /* knows if the book was not alloced */ 176 vorbis_staticbook_destroy(ci->book_param[i]); 177 } 178 if(ci->fullbooks) 179 vorbis_book_clear(ci->fullbooks+i); 180 } 181 if(ci->fullbooks) 182 _ogg_free(ci->fullbooks); 183 184 for(i=0;i<ci->psys;i++) 185 _vi_psy_free(ci->psy_param[i]); 186 187 _ogg_free(ci); 188 } 189 190 memset(vi,0,sizeof(*vi)); 191 } 192 193 /* Header packing/unpacking ********************************************/ 194 195 static int _vorbis_unpack_info(vorbis_info *vi,oggpack_buffer *opb){ 196 codec_setup_info *ci=vi->codec_setup; 197 if(!ci)return(OV_EFAULT); 198 199 vi->version=oggpack_read(opb,32); 200 if(vi->version!=0)return(OV_EVERSION); 201 202 vi->channels=oggpack_read(opb,8); 203 vi->rate=oggpack_read(opb,32); 204 205 vi->bitrate_upper=oggpack_read(opb,32); 206 vi->bitrate_nominal=oggpack_read(opb,32); 207 vi->bitrate_lower=oggpack_read(opb,32); 208 209 ci->blocksizes[0]=1<<oggpack_read(opb,4); 210 ci->blocksizes[1]=1<<oggpack_read(opb,4); 211 212 if(vi->rate<1)goto err_out; 213 if(vi->channels<1)goto err_out; 214 if(ci->blocksizes[0]<8)goto err_out; 215 if(ci->blocksizes[1]<ci->blocksizes[0])goto err_out; 216 217 if(oggpack_read(opb,1)!=1)goto err_out; /* EOP check */ 218 219 return(0); 220 err_out: 221 vorbis_info_clear(vi); 222 return(OV_EBADHEADER); 223 } 224 225 static int _vorbis_unpack_comment(vorbis_comment *vc,oggpack_buffer *opb){ 226 int i; 227 int vendorlen=oggpack_read(opb,32); 228 if(vendorlen<0)goto err_out; 229 vc->vendor=_ogg_calloc(vendorlen+1,1); 230 _v_readstring(opb,vc->vendor,vendorlen); 231 vc->comments=oggpack_read(opb,32); 232 if(vc->comments<0)goto err_out; 233 vc->user_comments=_ogg_calloc(vc->comments+1,sizeof(*vc->user_comments)); 234 vc->comment_lengths=_ogg_calloc(vc->comments+1, sizeof(*vc->comment_lengths)); 235 236 for(i=0;i<vc->comments;i++){ 237 int len=oggpack_read(opb,32); 238 if(len<0)goto err_out; 239 vc->comment_lengths[i]=len; 240 vc->user_comments[i]=_ogg_calloc(len+1,1); 241 _v_readstring(opb,vc->user_comments[i],len); 242 } 243 if(oggpack_read(opb,1)!=1)goto err_out; /* EOP check */ 244 245 return(0); 246 err_out: 247 vorbis_comment_clear(vc); 248 return(OV_EBADHEADER); 249 } 250 251 /* all of the real encoding details are here. The modes, books, 252 everything */ 253 static int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb){ 254 codec_setup_info *ci=vi->codec_setup; 255 int i; 256 if(!ci)return(OV_EFAULT); 257 258 /* codebooks */ 259 ci->books=oggpack_read(opb,8)+1; 260 /*ci->book_param=_ogg_calloc(ci->books,sizeof(*ci->book_param));*/ 261 for(i=0;i<ci->books;i++){ 262 ci->book_param[i]=_ogg_calloc(1,sizeof(*ci->book_param[i])); 263 if(vorbis_staticbook_unpack(opb,ci->book_param[i]))goto err_out; 264 } 265 266 /* time backend settings; hooks are unused */ 267 { 268 int times=oggpack_read(opb,6)+1; 269 for(i=0;i<times;i++){ 270 int test=oggpack_read(opb,16); 271 if(test<0 || test>=VI_TIMEB)goto err_out; 272 } 273 } 274 275 /* floor backend settings */ 276 ci->floors=oggpack_read(opb,6)+1; 277 /*ci->floor_type=_ogg_malloc(ci->floors*sizeof(*ci->floor_type));*/ 278 /*ci->floor_param=_ogg_calloc(ci->floors,sizeof(void *));*/ 279 for(i=0;i<ci->floors;i++){ 280 ci->floor_type[i]=oggpack_read(opb,16); 281 if(ci->floor_type[i]<0 || ci->floor_type[i]>=VI_FLOORB)goto err_out; 282 ci->floor_param[i]=_floor_P[ci->floor_type[i]]->unpack(vi,opb); 283 if(!ci->floor_param[i])goto err_out; 284 } 285 286 /* residue backend settings */ 287 ci->residues=oggpack_read(opb,6)+1; 288 /*ci->residue_type=_ogg_malloc(ci->residues*sizeof(*ci->residue_type));*/ 289 /*ci->residue_param=_ogg_calloc(ci->residues,sizeof(void *));*/ 290 for(i=0;i<ci->residues;i++){ 291 ci->residue_type[i]=oggpack_read(opb,16); 292 if(ci->residue_type[i]<0 || ci->residue_type[i]>=VI_RESB)goto err_out; 293 ci->residue_param[i]=_residue_P[ci->residue_type[i]]->unpack(vi,opb); 294 if(!ci->residue_param[i])goto err_out; 295 } 296 297 /* map backend settings */ 298 ci->maps=oggpack_read(opb,6)+1; 299 /*ci->map_type=_ogg_malloc(ci->maps*sizeof(*ci->map_type));*/ 300 /*ci->map_param=_ogg_calloc(ci->maps,sizeof(void *));*/ 301 for(i=0;i<ci->maps;i++){ 302 ci->map_type[i]=oggpack_read(opb,16); 303 if(ci->map_type[i]<0 || ci->map_type[i]>=VI_MAPB)goto err_out; 304 ci->map_param[i]=_mapping_P[ci->map_type[i]]->unpack(vi,opb); 305 if(!ci->map_param[i])goto err_out; 306 } 307 308 /* mode settings */ 309 ci->modes=oggpack_read(opb,6)+1; 310 /*vi->mode_param=_ogg_calloc(vi->modes,sizeof(void *));*/ 311 for(i=0;i<ci->modes;i++){ 312 ci->mode_param[i]=_ogg_calloc(1,sizeof(*ci->mode_param[i])); 313 ci->mode_param[i]->blockflag=oggpack_read(opb,1); 314 ci->mode_param[i]->windowtype=oggpack_read(opb,16); 315 ci->mode_param[i]->transformtype=oggpack_read(opb,16); 316 ci->mode_param[i]->mapping=oggpack_read(opb,8); 317 318 if(ci->mode_param[i]->windowtype>=VI_WINDOWB)goto err_out; 319 if(ci->mode_param[i]->transformtype>=VI_WINDOWB)goto err_out; 320 if(ci->mode_param[i]->mapping>=ci->maps)goto err_out; 321 } 322 323 if(oggpack_read(opb,1)!=1)goto err_out; /* top level EOP check */ 324 325 return(0); 326 err_out: 327 vorbis_info_clear(vi); 328 return(OV_EBADHEADER); 329 } 330 331 /* The Vorbis header is in three packets; the initial small packet in 332 the first page that identifies basic parameters, a second packet 333 with bitstream comments and a third packet that holds the 334 codebook. */ 335 336 int vorbis_synthesis_headerin(vorbis_info *vi,vorbis_comment *vc,ogg_packet *op){ 337 oggpack_buffer opb; 338 339 if(op){ 340 oggpack_readinit(&opb,op->packet,op->bytes); 341 342 /* Which of the three types of header is this? */ 343 /* Also verify header-ness, vorbis */ 344 { 345 char buffer[6]; 346 int packtype=oggpack_read(&opb,8); 347 memset(buffer,0,6); 348 _v_readstring(&opb,buffer,6); 349 if(memcmp(buffer,"vorbis",6)){ 350 /* not a vorbis header */ 351 return(OV_ENOTVORBIS); 352 } 353 switch(packtype){ 354 case 0x01: /* least significant *bit* is read first */ 355 if(!op->b_o_s){ 356 /* Not the initial packet */ 357 return(OV_EBADHEADER); 358 } 359 if(vi->rate!=0){ 360 /* previously initialized info header */ 361 return(OV_EBADHEADER); 362 } 363 364 return(_vorbis_unpack_info(vi,&opb)); 365 366 case 0x03: /* least significant *bit* is read first */ 367 if(vi->rate==0){ 368 /* um... we didn't get the initial header */ 369 return(OV_EBADHEADER); 370 } 371 372 return(_vorbis_unpack_comment(vc,&opb)); 373 374 case 0x05: /* least significant *bit* is read first */ 375 if(vi->rate==0 || vc->vendor==NULL){ 376 /* um... we didn;t get the initial header or comments yet */ 377 return(OV_EBADHEADER); 378 } 379 380 return(_vorbis_unpack_books(vi,&opb)); 381 382 default: 383 /* Not a valid vorbis header type */ 384 return(OV_EBADHEADER); 385 break; 386 } 387 } 388 } 389 return(OV_EBADHEADER); 390 } 391 392 /* pack side **********************************************************/ 393 394 static int _vorbis_pack_info(oggpack_buffer *opb,vorbis_info *vi){ 395 codec_setup_info *ci=vi->codec_setup; 396 if(!ci)return(OV_EFAULT); 397 398 /* preamble */ 399 oggpack_write(opb,0x01,8); 400 _v_writestring(opb,"vorbis", 6); 401 402 /* basic information about the stream */ 403 oggpack_write(opb,0x00,32); 404 oggpack_write(opb,vi->channels,8); 405 oggpack_write(opb,vi->rate,32); 406 407 oggpack_write(opb,vi->bitrate_upper,32); 408 oggpack_write(opb,vi->bitrate_nominal,32); 409 oggpack_write(opb,vi->bitrate_lower,32); 410 411 oggpack_write(opb,ilog2(ci->blocksizes[0]),4); 412 oggpack_write(opb,ilog2(ci->blocksizes[1]),4); 413 oggpack_write(opb,1,1); 414 415 return(0); 416 } 417 418 static int _vorbis_pack_comment(oggpack_buffer *opb,vorbis_comment *vc){ 419 char temp[]="Xiph.Org libVorbis I 20030909"; 420 int bytes = strlen(temp); 421 422 /* preamble */ 423 oggpack_write(opb,0x03,8); 424 _v_writestring(opb,"vorbis", 6); 425 426 /* vendor */ 427 oggpack_write(opb,bytes,32); 428 _v_writestring(opb,temp, bytes); 429 430 /* comments */ 431 432 oggpack_write(opb,vc->comments,32); 433 if(vc->comments){ 434 int i; 435 for(i=0;i<vc->comments;i++){ 436 if(vc->user_comments[i]){ 437 oggpack_write(opb,vc->comment_lengths[i],32); 438 _v_writestring(opb,vc->user_comments[i], vc->comment_lengths[i]); 439 }else{ 440 oggpack_write(opb,0,32); 441 } 442 } 443 } 444 oggpack_write(opb,1,1); 445 446 return(0); 447 } 448 449 static int _vorbis_pack_books(oggpack_buffer *opb,vorbis_info *vi){ 450 codec_setup_info *ci=vi->codec_setup; 451 int i; 452 if(!ci)return(OV_EFAULT); 453 454 oggpack_write(opb,0x05,8); 455 _v_writestring(opb,"vorbis", 6); 456 457 /* books */ 458 oggpack_write(opb,ci->books-1,8); 459 for(i=0;i<ci->books;i++) 460 if(vorbis_staticbook_pack(ci->book_param[i],opb))goto err_out; 461 462 /* times; hook placeholders */ 463 oggpack_write(opb,0,6); 464 oggpack_write(opb,0,16); 465 466 /* floors */ 467 oggpack_write(opb,ci->floors-1,6); 468 for(i=0;i<ci->floors;i++){ 469 oggpack_write(opb,ci->floor_type[i],16); 470 if(_floor_P[ci->floor_type[i]]->pack) 471 _floor_P[ci->floor_type[i]]->pack(ci->floor_param[i],opb); 472 else 473 goto err_out; 474 } 475 476 /* residues */ 477 oggpack_write(opb,ci->residues-1,6); 478 for(i=0;i<ci->residues;i++){ 479 oggpack_write(opb,ci->residue_type[i],16); 480 _residue_P[ci->residue_type[i]]->pack(ci->residue_param[i],opb); 481 } 482 483 /* maps */ 484 oggpack_write(opb,ci->maps-1,6); 485 for(i=0;i<ci->maps;i++){ 486 oggpack_write(opb,ci->map_type[i],16); 487 _mapping_P[ci->map_type[i]]->pack(vi,ci->map_param[i],opb); 488 } 489 490 /* modes */ 491 oggpack_write(opb,ci->modes-1,6); 492 for(i=0;i<ci->modes;i++){ 493 oggpack_write(opb,ci->mode_param[i]->blockflag,1); 494 oggpack_write(opb,ci->mode_param[i]->windowtype,16); 495 oggpack_write(opb,ci->mode_param[i]->transformtype,16); 496 oggpack_write(opb,ci->mode_param[i]->mapping,8); 497 } 498 oggpack_write(opb,1,1); 499 500 return(0); 501 err_out: 502 return(-1); 503 } 504 505 int vorbis_commentheader_out(vorbis_comment *vc, 506 ogg_packet *op){ 507 508 oggpack_buffer opb; 509 510 oggpack_writeinit(&opb); 511 if(_vorbis_pack_comment(&opb,vc)) return OV_EIMPL; 512 513 op->packet = _ogg_malloc(oggpack_bytes(&opb)); 514 memcpy(op->packet, opb.buffer, oggpack_bytes(&opb)); 515 516 op->bytes=oggpack_bytes(&opb); 517 op->b_o_s=0; 518 op->e_o_s=0; 519 op->granulepos=0; 520 521 return 0; 522 } 523 524 int vorbis_analysis_headerout(vorbis_dsp_state *v, 525 vorbis_comment *vc, 526 ogg_packet *op, 527 ogg_packet *op_comm, 528 ogg_packet *op_code){ 529 int ret=OV_EIMPL; 530 vorbis_info *vi=v->vi; 531 oggpack_buffer opb; 532 private_state *b=v->backend_state; 533 534 if(!b){ 535 ret=OV_EFAULT; 536 goto err_out; 537 } 538 539 /* first header packet **********************************************/ 540 541 oggpack_writeinit(&opb); 542 if(_vorbis_pack_info(&opb,vi))goto err_out; 543 544 /* build the packet */ 545 if(b->header)_ogg_free(b->header); 546 b->header=_ogg_malloc(oggpack_bytes(&opb)); 547 memcpy(b->header,opb.buffer,oggpack_bytes(&opb)); 548 op->packet=b->header; 549 op->bytes=oggpack_bytes(&opb); 550 op->b_o_s=1; 551 op->e_o_s=0; 552 op->granulepos=0; 553 554 /* second header packet (comments) **********************************/ 555 556 oggpack_reset(&opb); 557 if(_vorbis_pack_comment(&opb,vc))goto err_out; 558 559 if(b->header1)_ogg_free(b->header1); 560 b->header1=_ogg_malloc(oggpack_bytes(&opb)); 561 memcpy(b->header1,opb.buffer,oggpack_bytes(&opb)); 562 op_comm->packet=b->header1; 563 op_comm->bytes=oggpack_bytes(&opb); 564 op_comm->b_o_s=0; 565 op_comm->e_o_s=0; 566 op_comm->granulepos=0; 567 568 /* third header packet (modes/codebooks) ****************************/ 569 570 oggpack_reset(&opb); 571 if(_vorbis_pack_books(&opb,vi))goto err_out; 572 573 if(b->header2)_ogg_free(b->header2); 574 b->header2=_ogg_malloc(oggpack_bytes(&opb)); 575 memcpy(b->header2,opb.buffer,oggpack_bytes(&opb)); 576 op_code->packet=b->header2; 577 op_code->bytes=oggpack_bytes(&opb); 578 op_code->b_o_s=0; 579 op_code->e_o_s=0; 580 op_code->granulepos=0; 581 582 oggpack_writeclear(&opb); 583 return(0); 584 err_out: 585 oggpack_writeclear(&opb); 586 memset(op,0,sizeof(*op)); 587 memset(op_comm,0,sizeof(*op_comm)); 588 memset(op_code,0,sizeof(*op_code)); 589 590 if(b->header)_ogg_free(b->header); 591 if(b->header1)_ogg_free(b->header1); 592 if(b->header2)_ogg_free(b->header2); 593 b->header=NULL; 594 b->header1=NULL; 595 b->header2=NULL; 596 return(ret); 597 } 598 599 double vorbis_granule_time(vorbis_dsp_state *v,ogg_int64_t granulepos){ 600 if(granulepos>=0) 601 return((double)granulepos/v->vi->rate); 602 return(-1); 603 }