info.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559
  1. /********************************************************************
  2. * *
  3. * THIS FILE IS PART OF THE Ogg Vorbis SOFTWARE CODEC SOURCE CODE. *
  4. * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY *
  5. * THE GNU PUBLIC LICENSE 2, WHICH IS INCLUDED WITH THIS SOURCE. *
  6. * PLEASE READ THESE TERMS DISTRIBUTING. *
  7. * *
  8. * THE OggSQUISH SOURCE CODE IS (C) COPYRIGHT 1994-2000 *
  9. * by Monty <monty@xiph.org> and The XIPHOPHORUS Company *
  10. * http://www.xiph.org/ *
  11. * *
  12. ********************************************************************
  13. function: maintain the info structure, info <-> header packets
  14. last mod: $Id: info.c,v 1.30.2.1 2000/09/27 06:20:59 jack Exp $
  15. ********************************************************************/
  16. /* general handling of the header and the vorbis_info structure (and
  17. substructures) */
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include <ctype.h>
  21. #include <ogg/ogg.h>
  22. #include "vorbis/codec.h"
  23. #include "vorbis/backends.h"
  24. #include "sharedbook.h"
  25. #include "bookinternal.h"
  26. #include "registry.h"
  27. #include "window.h"
  28. #include "psy.h"
  29. #include "misc.h"
  30. #include "os.h"
  31. /* helpers */
  32. static int ilog2(unsigned int v){
  33. int ret=0;
  34. while(v>1){
  35. ret++;
  36. v>>=1;
  37. }
  38. return(ret);
  39. }
  40. static void _v_writestring(oggpack_buffer *o,char *s){
  41. while(*s){
  42. oggpack_write(o,*s++,8);
  43. }
  44. }
  45. static void _v_readstring(oggpack_buffer *o,char *buf,int bytes){
  46. while(bytes--){
  47. *buf++=oggpack_read(o,8);
  48. }
  49. }
  50. void vorbis_comment_init(vorbis_comment *vc){
  51. memset(vc,0,sizeof(vorbis_comment));
  52. }
  53. void vorbis_comment_add(vorbis_comment *vc,char *comment){
  54. vc->user_comments=realloc(vc->user_comments,
  55. (vc->comments+2)*sizeof(char *));
  56. vc->comment_lengths=realloc(vc->comment_lengths,
  57. (vc->comments+2)*sizeof(int));
  58. vc->user_comments[vc->comments]=strdup(comment);
  59. vc->comment_lengths[vc->comments]=strlen(comment);
  60. vc->comments++;
  61. vc->user_comments[vc->comments]=NULL;
  62. }
  63. void vorbis_comment_add_tag(vorbis_comment *vc, char *tag, char *contents){
  64. char *comment=alloca(strlen(tag)+strlen(contents)+2); /* +2 for = and \0 */
  65. strcpy(comment, tag);
  66. strcat(comment, "=");
  67. strcat(comment, contents);
  68. vorbis_comment_add(vc, comment);
  69. }
  70. /* This is more or less the same as strncasecmp - but that doesn't exist
  71. * everywhere, and this is a fairly trivial function, so we include it */
  72. static int tagcompare(const char *s1, const char *s2, int n){
  73. int c=0;
  74. while(c < n){
  75. if(toupper(s1[c]) != toupper(s2[c]))
  76. return !0;
  77. c++;
  78. }
  79. return 0;
  80. }
  81. char *vorbis_comment_query(vorbis_comment *vc, char *tag, int count){
  82. long i;
  83. int found = 0;
  84. int taglen = strlen(tag)+1; /* +1 for the = we append */
  85. char *fulltag = alloca(taglen+ 1);
  86. strcpy(fulltag, tag);
  87. strcat(fulltag, "=");
  88. for(i=0;i<vc->comments;i++){
  89. if(!tagcompare(vc->user_comments[i], fulltag, taglen)){
  90. if(count == found)
  91. /* We return a pointer to the data, not a copy */
  92. return vc->user_comments[i] + taglen;
  93. else
  94. found++;
  95. }
  96. }
  97. return NULL; /* didn't find anything */
  98. }
  99. int vorbis_comment_query_count(vorbis_comment *vc, char *tag){
  100. int i,count=0;
  101. int taglen = strlen(tag)+1; /* +1 for the = we append */
  102. char *fulltag = alloca(taglen+1);
  103. strcpy(fulltag,tag);
  104. strcat(fulltag, "=");
  105. for(i=0;i<vc->comments;i++){
  106. if(!tagcompare(vc->user_comments[i], fulltag, taglen))
  107. count++;
  108. }
  109. return count;
  110. }
  111. void vorbis_comment_clear(vorbis_comment *vc){
  112. if(vc){
  113. long i;
  114. for(i=0;i<vc->comments;i++)
  115. if(vc->user_comments[i])free(vc->user_comments[i]);
  116. if(vc->user_comments)free(vc->user_comments);
  117. if(vc->comment_lengths)free(vc->comment_lengths);
  118. if(vc->vendor)free(vc->vendor);
  119. }
  120. memset(vc,0,sizeof(vorbis_comment));
  121. }
  122. /* used by synthesis, which has a full, alloced vi */
  123. void vorbis_info_init(vorbis_info *vi){
  124. memset(vi,0,sizeof(vorbis_info));
  125. }
  126. void vorbis_info_clear(vorbis_info *vi){
  127. int i;
  128. for(i=0;i<vi->modes;i++)
  129. if(vi->mode_param[i])free(vi->mode_param[i]);
  130. /*if(vi->mode_param)free(vi->mode_param);*/
  131. for(i=0;i<vi->maps;i++) /* unpack does the range checking */
  132. _mapping_P[vi->map_type[i]]->free_info(vi->map_param[i]);
  133. /*if(vi->map_param)free(vi->map_param);*/
  134. for(i=0;i<vi->times;i++) /* unpack does the range checking */
  135. _time_P[vi->time_type[i]]->free_info(vi->time_param[i]);
  136. /*if(vi->time_param)free(vi->time_param);*/
  137. for(i=0;i<vi->floors;i++) /* unpack does the range checking */
  138. _floor_P[vi->floor_type[i]]->free_info(vi->floor_param[i]);
  139. /*if(vi->floor_param)free(vi->floor_param);*/
  140. for(i=0;i<vi->residues;i++) /* unpack does the range checking */
  141. _residue_P[vi->residue_type[i]]->free_info(vi->residue_param[i]);
  142. /*if(vi->residue_param)free(vi->residue_param);*/
  143. /* the static codebooks *are* freed if you call info_clear, because
  144. decode side does alloc a 'static' codebook. Calling clear on the
  145. full codebook does not clear the static codebook (that's our
  146. responsibility) */
  147. for(i=0;i<vi->books;i++){
  148. /* just in case the decoder pre-cleared to save space */
  149. if(vi->book_param[i]){
  150. vorbis_staticbook_clear(vi->book_param[i]);
  151. free(vi->book_param[i]);
  152. }
  153. }
  154. /*if(vi->book_param)free(vi->book_param);*/
  155. for(i=0;i<vi->psys;i++)
  156. _vi_psy_free(vi->psy_param[i]);
  157. /*if(vi->psy_param)free(vi->psy_param);*/
  158. memset(vi,0,sizeof(vorbis_info));
  159. }
  160. /* Header packing/unpacking ********************************************/
  161. static int _vorbis_unpack_info(vorbis_info *vi,oggpack_buffer *opb){
  162. vi->version=oggpack_read(opb,32);
  163. if(vi->version!=0)return(-1);
  164. vi->channels=oggpack_read(opb,8);
  165. vi->rate=oggpack_read(opb,32);
  166. vi->bitrate_upper=oggpack_read(opb,32);
  167. vi->bitrate_nominal=oggpack_read(opb,32);
  168. vi->bitrate_lower=oggpack_read(opb,32);
  169. vi->blocksizes[0]=1<<oggpack_read(opb,4);
  170. vi->blocksizes[1]=1<<oggpack_read(opb,4);
  171. if(vi->rate<1)goto err_out;
  172. if(vi->channels<1)goto err_out;
  173. if(vi->blocksizes[0]<8)goto err_out;
  174. if(vi->blocksizes[1]<vi->blocksizes[0])goto err_out;
  175. if(oggpack_read(opb,1)!=1)goto err_out; /* EOP check */
  176. return(0);
  177. err_out:
  178. vorbis_info_clear(vi);
  179. return(-1);
  180. }
  181. static int _vorbis_unpack_comment(vorbis_comment *vc,oggpack_buffer *opb){
  182. int i;
  183. int vendorlen=oggpack_read(opb,32);
  184. if(vendorlen<0)goto err_out;
  185. vc->vendor=calloc(vendorlen+1,1);
  186. _v_readstring(opb,vc->vendor,vendorlen);
  187. vc->comments=oggpack_read(opb,32);
  188. if(vc->comments<0)goto err_out;
  189. vc->user_comments=calloc(vc->comments+1,sizeof(char **));
  190. vc->comment_lengths=calloc(vc->comments+1, sizeof(int));
  191. for(i=0;i<vc->comments;i++){
  192. int len=oggpack_read(opb,32);
  193. if(len<0)goto err_out;
  194. vc->comment_lengths[i]=len;
  195. vc->user_comments[i]=calloc(len+1,1);
  196. _v_readstring(opb,vc->user_comments[i],len);
  197. }
  198. if(oggpack_read(opb,1)!=1)goto err_out; /* EOP check */
  199. return(0);
  200. err_out:
  201. vorbis_comment_clear(vc);
  202. return(-1);
  203. }
  204. /* all of the real encoding details are here. The modes, books,
  205. everything */
  206. static int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb){
  207. int i;
  208. /* codebooks */
  209. vi->books=oggpack_read(opb,8)+1;
  210. /*vi->book_param=calloc(vi->books,sizeof(static_codebook *));*/
  211. for(i=0;i<vi->books;i++){
  212. vi->book_param[i]=calloc(1,sizeof(static_codebook));
  213. if(vorbis_staticbook_unpack(opb,vi->book_param[i]))goto err_out;
  214. }
  215. /* time backend settings */
  216. vi->times=oggpack_read(opb,6)+1;
  217. /*vi->time_type=malloc(vi->times*sizeof(int));*/
  218. /*vi->time_param=calloc(vi->times,sizeof(void *));*/
  219. for(i=0;i<vi->times;i++){
  220. vi->time_type[i]=oggpack_read(opb,16);
  221. if(vi->time_type[i]<0 || vi->time_type[i]>=VI_TIMEB)goto err_out;
  222. vi->time_param[i]=_time_P[vi->time_type[i]]->unpack(vi,opb);
  223. if(!vi->time_param[i])goto err_out;
  224. }
  225. /* floor backend settings */
  226. vi->floors=oggpack_read(opb,6)+1;
  227. /*vi->floor_type=malloc(vi->floors*sizeof(int));*/
  228. /*vi->floor_param=calloc(vi->floors,sizeof(void *));*/
  229. for(i=0;i<vi->floors;i++){
  230. vi->floor_type[i]=oggpack_read(opb,16);
  231. if(vi->floor_type[i]<0 || vi->floor_type[i]>=VI_FLOORB)goto err_out;
  232. vi->floor_param[i]=_floor_P[vi->floor_type[i]]->unpack(vi,opb);
  233. if(!vi->floor_param[i])goto err_out;
  234. }
  235. /* residue backend settings */
  236. vi->residues=oggpack_read(opb,6)+1;
  237. /*vi->residue_type=malloc(vi->residues*sizeof(int));*/
  238. /*vi->residue_param=calloc(vi->residues,sizeof(void *));*/
  239. for(i=0;i<vi->residues;i++){
  240. vi->residue_type[i]=oggpack_read(opb,16);
  241. if(vi->residue_type[i]<0 || vi->residue_type[i]>=VI_RESB)goto err_out;
  242. vi->residue_param[i]=_residue_P[vi->residue_type[i]]->unpack(vi,opb);
  243. if(!vi->residue_param[i])goto err_out;
  244. }
  245. /* map backend settings */
  246. vi->maps=oggpack_read(opb,6)+1;
  247. /*vi->map_type=malloc(vi->maps*sizeof(int));*/
  248. /*vi->map_param=calloc(vi->maps,sizeof(void *));*/
  249. for(i=0;i<vi->maps;i++){
  250. vi->map_type[i]=oggpack_read(opb,16);
  251. if(vi->map_type[i]<0 || vi->map_type[i]>=VI_MAPB)goto err_out;
  252. vi->map_param[i]=_mapping_P[vi->map_type[i]]->unpack(vi,opb);
  253. if(!vi->map_param[i])goto err_out;
  254. }
  255. /* mode settings */
  256. vi->modes=oggpack_read(opb,6)+1;
  257. /*vi->mode_param=calloc(vi->modes,sizeof(void *));*/
  258. for(i=0;i<vi->modes;i++){
  259. vi->mode_param[i]=calloc(1,sizeof(vorbis_info_mode));
  260. vi->mode_param[i]->blockflag=oggpack_read(opb,1);
  261. vi->mode_param[i]->windowtype=oggpack_read(opb,16);
  262. vi->mode_param[i]->transformtype=oggpack_read(opb,16);
  263. vi->mode_param[i]->mapping=oggpack_read(opb,8);
  264. if(vi->mode_param[i]->windowtype>=VI_WINDOWB)goto err_out;
  265. if(vi->mode_param[i]->transformtype>=VI_WINDOWB)goto err_out;
  266. if(vi->mode_param[i]->mapping>=vi->maps)goto err_out;
  267. }
  268. if(oggpack_read(opb,1)!=1)goto err_out; /* top level EOP check */
  269. return(0);
  270. err_out:
  271. vorbis_info_clear(vi);
  272. return(-1);
  273. }
  274. /* The Vorbis header is in three packets; the initial small packet in
  275. the first page that identifies basic parameters, a second packet
  276. with bitstream comments and a third packet that holds the
  277. codebook. */
  278. int vorbis_synthesis_headerin(vorbis_info *vi,vorbis_comment *vc,ogg_packet *op){
  279. oggpack_buffer opb;
  280. if(op){
  281. oggpack_readinit(&opb,op->packet,op->bytes);
  282. /* Which of the three types of header is this? */
  283. /* Also verify header-ness, vorbis */
  284. {
  285. char buffer[6];
  286. int packtype=oggpack_read(&opb,8);
  287. memset(buffer,0,6);
  288. _v_readstring(&opb,buffer,6);
  289. if(memcmp(buffer,"vorbis",6)){
  290. /* not a vorbis header */
  291. return(-1);
  292. }
  293. switch(packtype){
  294. case 0x01: /* least significant *bit* is read first */
  295. if(!op->b_o_s){
  296. /* Not the initial packet */
  297. return(-1);
  298. }
  299. if(vi->rate!=0){
  300. /* previously initialized info header */
  301. return(-1);
  302. }
  303. return(_vorbis_unpack_info(vi,&opb));
  304. case 0x03: /* least significant *bit* is read first */
  305. if(vi->rate==0){
  306. /* um... we didn't get the initial header */
  307. return(-1);
  308. }
  309. return(_vorbis_unpack_comment(vc,&opb));
  310. case 0x05: /* least significant *bit* is read first */
  311. if(vi->rate==0 || vc->vendor==NULL){
  312. /* um... we didn;t get the initial header or comments yet */
  313. return(-1);
  314. }
  315. return(_vorbis_unpack_books(vi,&opb));
  316. default:
  317. /* Not a valid vorbis header type */
  318. return(-1);
  319. break;
  320. }
  321. }
  322. }
  323. return(-1);
  324. }
  325. /* pack side **********************************************************/
  326. static int _vorbis_pack_info(oggpack_buffer *opb,vorbis_info *vi){
  327. /* preamble */
  328. oggpack_write(opb,0x01,8);
  329. _v_writestring(opb,"vorbis");
  330. /* basic information about the stream */
  331. oggpack_write(opb,0x00,32);
  332. oggpack_write(opb,vi->channels,8);
  333. oggpack_write(opb,vi->rate,32);
  334. oggpack_write(opb,vi->bitrate_upper,32);
  335. oggpack_write(opb,vi->bitrate_nominal,32);
  336. oggpack_write(opb,vi->bitrate_lower,32);
  337. oggpack_write(opb,ilog2(vi->blocksizes[0]),4);
  338. oggpack_write(opb,ilog2(vi->blocksizes[1]),4);
  339. oggpack_write(opb,1,1);
  340. return(0);
  341. }
  342. static int _vorbis_pack_comment(oggpack_buffer *opb,vorbis_comment *vc){
  343. char temp[]="Xiphophorus libVorbis I 20000508";
  344. /* preamble */
  345. oggpack_write(opb,0x03,8);
  346. _v_writestring(opb,"vorbis");
  347. /* vendor */
  348. oggpack_write(opb,strlen(temp),32);
  349. _v_writestring(opb,temp);
  350. /* comments */
  351. oggpack_write(opb,vc->comments,32);
  352. if(vc->comments){
  353. int i;
  354. for(i=0;i<vc->comments;i++){
  355. if(vc->user_comments[i]){
  356. oggpack_write(opb,vc->comment_lengths[i],32);
  357. _v_writestring(opb,vc->user_comments[i]);
  358. }else{
  359. oggpack_write(opb,0,32);
  360. }
  361. }
  362. }
  363. oggpack_write(opb,1,1);
  364. return(0);
  365. }
  366. static int _vorbis_pack_books(oggpack_buffer *opb,vorbis_info *vi){
  367. int i;
  368. oggpack_write(opb,0x05,8);
  369. _v_writestring(opb,"vorbis");
  370. /* books */
  371. oggpack_write(opb,vi->books-1,8);
  372. for(i=0;i<vi->books;i++)
  373. if(vorbis_staticbook_pack(vi->book_param[i],opb))goto err_out;
  374. /* times */
  375. oggpack_write(opb,vi->times-1,6);
  376. for(i=0;i<vi->times;i++){
  377. oggpack_write(opb,vi->time_type[i],16);
  378. _time_P[vi->time_type[i]]->pack(vi->time_param[i],opb);
  379. }
  380. /* floors */
  381. oggpack_write(opb,vi->floors-1,6);
  382. for(i=0;i<vi->floors;i++){
  383. oggpack_write(opb,vi->floor_type[i],16);
  384. _floor_P[vi->floor_type[i]]->pack(vi->floor_param[i],opb);
  385. }
  386. /* residues */
  387. oggpack_write(opb,vi->residues-1,6);
  388. for(i=0;i<vi->residues;i++){
  389. oggpack_write(opb,vi->residue_type[i],16);
  390. _residue_P[vi->residue_type[i]]->pack(vi->residue_param[i],opb);
  391. }
  392. /* maps */
  393. oggpack_write(opb,vi->maps-1,6);
  394. for(i=0;i<vi->maps;i++){
  395. oggpack_write(opb,vi->map_type[i],16);
  396. _mapping_P[vi->map_type[i]]->pack(vi,vi->map_param[i],opb);
  397. }
  398. /* modes */
  399. oggpack_write(opb,vi->modes-1,6);
  400. for(i=0;i<vi->modes;i++){
  401. oggpack_write(opb,vi->mode_param[i]->blockflag,1);
  402. oggpack_write(opb,vi->mode_param[i]->windowtype,16);
  403. oggpack_write(opb,vi->mode_param[i]->transformtype,16);
  404. oggpack_write(opb,vi->mode_param[i]->mapping,8);
  405. }
  406. oggpack_write(opb,1,1);
  407. return(0);
  408. err_out:
  409. return(-1);
  410. }
  411. int vorbis_analysis_headerout(vorbis_dsp_state *v,
  412. vorbis_comment *vc,
  413. ogg_packet *op,
  414. ogg_packet *op_comm,
  415. ogg_packet *op_code){
  416. vorbis_info *vi=v->vi;
  417. oggpack_buffer opb;
  418. /* first header packet **********************************************/
  419. oggpack_writeinit(&opb);
  420. if(_vorbis_pack_info(&opb,vi))goto err_out;
  421. /* build the packet */
  422. if(v->header)free(v->header);
  423. v->header=malloc(oggpack_bytes(&opb));
  424. memcpy(v->header,opb.buffer,oggpack_bytes(&opb));
  425. op->packet=v->header;
  426. op->bytes=oggpack_bytes(&opb);
  427. op->b_o_s=1;
  428. op->e_o_s=0;
  429. op->granulepos=0;
  430. /* second header packet (comments) **********************************/
  431. oggpack_reset(&opb);
  432. if(_vorbis_pack_comment(&opb,vc))goto err_out;
  433. if(v->header1)free(v->header1);
  434. v->header1=malloc(oggpack_bytes(&opb));
  435. memcpy(v->header1,opb.buffer,oggpack_bytes(&opb));
  436. op_comm->packet=v->header1;
  437. op_comm->bytes=oggpack_bytes(&opb);
  438. op_comm->b_o_s=0;
  439. op_comm->e_o_s=0;
  440. op_comm->granulepos=0;
  441. /* third header packet (modes/codebooks) ****************************/
  442. oggpack_reset(&opb);
  443. if(_vorbis_pack_books(&opb,vi))goto err_out;
  444. if(v->header2)free(v->header2);
  445. v->header2=malloc(oggpack_bytes(&opb));
  446. memcpy(v->header2,opb.buffer,oggpack_bytes(&opb));
  447. op_code->packet=v->header2;
  448. op_code->bytes=oggpack_bytes(&opb);
  449. op_code->b_o_s=0;
  450. op_code->e_o_s=0;
  451. op_code->granulepos=0;
  452. oggpack_writeclear(&opb);
  453. return(0);
  454. err_out:
  455. oggpack_writeclear(&opb);
  456. memset(op,0,sizeof(ogg_packet));
  457. memset(op_comm,0,sizeof(ogg_packet));
  458. memset(op_code,0,sizeof(ogg_packet));
  459. if(v->header)free(v->header);
  460. if(v->header1)free(v->header1);
  461. if(v->header2)free(v->header2);
  462. v->header=NULL;
  463. v->header1=NULL;
  464. v->header2=NULL;
  465. return(-1);
  466. }