info.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572
  1. /********************************************************************
  2. * *
  3. * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
  4. * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY *
  5. * THE GNU LESSER/LIBRARY PUBLIC LICENSE, WHICH IS INCLUDED WITH *
  6. * THIS SOURCE. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
  7. * *
  8. * THE OggVorbis 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.31.2.5 2000/11/04 06:43:50 xiphmont 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 "backends.h"
  24. #include "codec_internal.h"
  25. #include "codebook.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=_ogg_realloc(vc->user_comments,
  55. (vc->comments+2)*sizeof(char *));
  56. vc->comment_lengths=_ogg_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. vi->codec_setup=_ogg_calloc(1,sizeof(codec_setup_info));
  126. }
  127. void vorbis_info_clear(vorbis_info *vi){
  128. codec_setup_info *ci=vi->codec_setup;
  129. int i;
  130. if(ci){
  131. for(i=0;i<ci->modes;i++)
  132. if(ci->mode_param[i])free(ci->mode_param[i]);
  133. for(i=0;i<ci->maps;i++) /* unpack does the range checking */
  134. _mapping_P[ci->map_type[i]]->free_info(ci->map_param[i]);
  135. for(i=0;i<ci->times;i++) /* unpack does the range checking */
  136. _time_P[ci->time_type[i]]->free_info(ci->time_param[i]);
  137. for(i=0;i<ci->floors;i++) /* unpack does the range checking */
  138. _floor_P[ci->floor_type[i]]->free_info(ci->floor_param[i]);
  139. for(i=0;i<ci->residues;i++) /* unpack does the range checking */
  140. _residue_P[ci->residue_type[i]]->free_info(ci->residue_param[i]);
  141. for(i=0;i<ci->books;i++){
  142. if(ci->book_param[i]){
  143. /* knows if the book was not alloced */
  144. vorbis_staticbook_destroy(ci->book_param[i]);
  145. }
  146. }
  147. for(i=0;i<ci->psys;i++)
  148. _vi_psy_free(ci->psy_param[i]);
  149. free(ci);
  150. }
  151. memset(vi,0,sizeof(vorbis_info));
  152. }
  153. /* Header packing/unpacking ********************************************/
  154. static int _vorbis_unpack_info(vorbis_info *vi,oggpack_buffer *opb){
  155. codec_setup_info *ci=vi->codec_setup;
  156. if(!ci)return(OV_EFAULT);
  157. vi->version=oggpack_read(opb,32);
  158. if(vi->version!=0)return(OV_EVERSION);
  159. vi->channels=oggpack_read(opb,8);
  160. vi->rate=oggpack_read(opb,32);
  161. vi->bitrate_upper=oggpack_read(opb,32);
  162. vi->bitrate_nominal=oggpack_read(opb,32);
  163. vi->bitrate_lower=oggpack_read(opb,32);
  164. ci->blocksizes[0]=1<<oggpack_read(opb,4);
  165. ci->blocksizes[1]=1<<oggpack_read(opb,4);
  166. if(vi->rate<1)goto err_out;
  167. if(vi->channels<1)goto err_out;
  168. if(ci->blocksizes[0]<8)goto err_out;
  169. if(ci->blocksizes[1]<ci->blocksizes[0])goto err_out;
  170. if(oggpack_read(opb,1)!=1)goto err_out; /* EOP check */
  171. return(0);
  172. err_out:
  173. vorbis_info_clear(vi);
  174. return(OV_EBADHEADER);
  175. }
  176. static int _vorbis_unpack_comment(vorbis_comment *vc,oggpack_buffer *opb){
  177. int i;
  178. int vendorlen=oggpack_read(opb,32);
  179. if(vendorlen<0)goto err_out;
  180. vc->vendor=_ogg_calloc(vendorlen+1,1);
  181. _v_readstring(opb,vc->vendor,vendorlen);
  182. vc->comments=oggpack_read(opb,32);
  183. if(vc->comments<0)goto err_out;
  184. vc->user_comments=_ogg_calloc(vc->comments+1,sizeof(char **));
  185. vc->comment_lengths=_ogg_calloc(vc->comments+1, sizeof(int));
  186. for(i=0;i<vc->comments;i++){
  187. int len=oggpack_read(opb,32);
  188. if(len<0)goto err_out;
  189. vc->comment_lengths[i]=len;
  190. vc->user_comments[i]=_ogg_calloc(len+1,1);
  191. _v_readstring(opb,vc->user_comments[i],len);
  192. }
  193. if(oggpack_read(opb,1)!=1)goto err_out; /* EOP check */
  194. return(0);
  195. err_out:
  196. vorbis_comment_clear(vc);
  197. return(OV_EBADHEADER);
  198. }
  199. /* all of the real encoding details are here. The modes, books,
  200. everything */
  201. static int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb){
  202. codec_setup_info *ci=vi->codec_setup;
  203. int i;
  204. if(!ci)return(OV_EFAULT);
  205. /* codebooks */
  206. ci->books=oggpack_read(opb,8)+1;
  207. /*ci->book_param=_ogg_calloc(ci->books,sizeof(static_codebook *));*/
  208. for(i=0;i<ci->books;i++){
  209. ci->book_param[i]=_ogg_calloc(1,sizeof(static_codebook));
  210. if(vorbis_staticbook_unpack(opb,ci->book_param[i]))goto err_out;
  211. }
  212. /* time backend settings */
  213. ci->times=oggpack_read(opb,6)+1;
  214. /*ci->time_type=_ogg_malloc(ci->times*sizeof(int));*/
  215. /*ci->time_param=_ogg_calloc(ci->times,sizeof(void *));*/
  216. for(i=0;i<ci->times;i++){
  217. ci->time_type[i]=oggpack_read(opb,16);
  218. if(ci->time_type[i]<0 || ci->time_type[i]>=VI_TIMEB)goto err_out;
  219. ci->time_param[i]=_time_P[ci->time_type[i]]->unpack(vi,opb);
  220. if(!ci->time_param[i])goto err_out;
  221. }
  222. /* floor backend settings */
  223. ci->floors=oggpack_read(opb,6)+1;
  224. /*ci->floor_type=_ogg_malloc(ci->floors*sizeof(int));*/
  225. /*ci->floor_param=_ogg_calloc(ci->floors,sizeof(void *));*/
  226. for(i=0;i<ci->floors;i++){
  227. ci->floor_type[i]=oggpack_read(opb,16);
  228. if(ci->floor_type[i]<0 || ci->floor_type[i]>=VI_FLOORB)goto err_out;
  229. ci->floor_param[i]=_floor_P[ci->floor_type[i]]->unpack(vi,opb);
  230. if(!ci->floor_param[i])goto err_out;
  231. }
  232. /* residue backend settings */
  233. ci->residues=oggpack_read(opb,6)+1;
  234. /*ci->residue_type=_ogg_malloc(ci->residues*sizeof(int));*/
  235. /*ci->residue_param=_ogg_calloc(ci->residues,sizeof(void *));*/
  236. for(i=0;i<ci->residues;i++){
  237. ci->residue_type[i]=oggpack_read(opb,16);
  238. if(ci->residue_type[i]<0 || ci->residue_type[i]>=VI_RESB)goto err_out;
  239. ci->residue_param[i]=_residue_P[ci->residue_type[i]]->unpack(vi,opb);
  240. if(!ci->residue_param[i])goto err_out;
  241. }
  242. /* map backend settings */
  243. ci->maps=oggpack_read(opb,6)+1;
  244. /*ci->map_type=_ogg_malloc(ci->maps*sizeof(int));*/
  245. /*ci->map_param=_ogg_calloc(ci->maps,sizeof(void *));*/
  246. for(i=0;i<ci->maps;i++){
  247. ci->map_type[i]=oggpack_read(opb,16);
  248. if(ci->map_type[i]<0 || ci->map_type[i]>=VI_MAPB)goto err_out;
  249. ci->map_param[i]=_mapping_P[ci->map_type[i]]->unpack(vi,opb);
  250. if(!ci->map_param[i])goto err_out;
  251. }
  252. /* mode settings */
  253. ci->modes=oggpack_read(opb,6)+1;
  254. /*vi->mode_param=_ogg_calloc(vi->modes,sizeof(void *));*/
  255. for(i=0;i<ci->modes;i++){
  256. ci->mode_param[i]=_ogg_calloc(1,sizeof(vorbis_info_mode));
  257. ci->mode_param[i]->blockflag=oggpack_read(opb,1);
  258. ci->mode_param[i]->windowtype=oggpack_read(opb,16);
  259. ci->mode_param[i]->transformtype=oggpack_read(opb,16);
  260. ci->mode_param[i]->mapping=oggpack_read(opb,8);
  261. if(ci->mode_param[i]->windowtype>=VI_WINDOWB)goto err_out;
  262. if(ci->mode_param[i]->transformtype>=VI_WINDOWB)goto err_out;
  263. if(ci->mode_param[i]->mapping>=ci->maps)goto err_out;
  264. }
  265. if(oggpack_read(opb,1)!=1)goto err_out; /* top level EOP check */
  266. return(0);
  267. err_out:
  268. vorbis_info_clear(vi);
  269. return(OV_EBADHEADER);
  270. }
  271. /* The Vorbis header is in three packets; the initial small packet in
  272. the first page that identifies basic parameters, a second packet
  273. with bitstream comments and a third packet that holds the
  274. codebook. */
  275. int vorbis_synthesis_headerin(vorbis_info *vi,vorbis_comment *vc,ogg_packet *op){
  276. oggpack_buffer opb;
  277. if(op){
  278. oggpack_readinit(&opb,op->packet,op->bytes);
  279. /* Which of the three types of header is this? */
  280. /* Also verify header-ness, vorbis */
  281. {
  282. char buffer[6];
  283. int packtype=oggpack_read(&opb,8);
  284. memset(buffer,0,6);
  285. _v_readstring(&opb,buffer,6);
  286. if(memcmp(buffer,"vorbis",6)){
  287. /* not a vorbis header */
  288. return(OV_ENOTVORBIS);
  289. }
  290. switch(packtype){
  291. case 0x01: /* least significant *bit* is read first */
  292. if(!op->b_o_s){
  293. /* Not the initial packet */
  294. return(OV_EBADHEADER);
  295. }
  296. if(vi->rate!=0){
  297. /* previously initialized info header */
  298. return(OV_EBADHEADER);
  299. }
  300. return(_vorbis_unpack_info(vi,&opb));
  301. case 0x03: /* least significant *bit* is read first */
  302. if(vi->rate==0){
  303. /* um... we didn't get the initial header */
  304. return(OV_EBADHEADER);
  305. }
  306. return(_vorbis_unpack_comment(vc,&opb));
  307. case 0x05: /* least significant *bit* is read first */
  308. if(vi->rate==0 || vc->vendor==NULL){
  309. /* um... we didn;t get the initial header or comments yet */
  310. return(OV_EBADHEADER);
  311. }
  312. return(_vorbis_unpack_books(vi,&opb));
  313. default:
  314. /* Not a valid vorbis header type */
  315. return(OV_EBADHEADER);
  316. break;
  317. }
  318. }
  319. }
  320. return(OV_EBADHEADER);
  321. }
  322. /* pack side **********************************************************/
  323. static int _vorbis_pack_info(oggpack_buffer *opb,vorbis_info *vi){
  324. codec_setup_info *ci=vi->codec_setup;
  325. if(!ci)return(OV_EFAULT);
  326. /* preamble */
  327. oggpack_write(opb,0x01,8);
  328. _v_writestring(opb,"vorbis");
  329. /* basic information about the stream */
  330. oggpack_write(opb,0x00,32);
  331. oggpack_write(opb,vi->channels,8);
  332. oggpack_write(opb,vi->rate,32);
  333. oggpack_write(opb,vi->bitrate_upper,32);
  334. oggpack_write(opb,vi->bitrate_nominal,32);
  335. oggpack_write(opb,vi->bitrate_lower,32);
  336. oggpack_write(opb,ilog2(ci->blocksizes[0]),4);
  337. oggpack_write(opb,ilog2(ci->blocksizes[1]),4);
  338. oggpack_write(opb,1,1);
  339. return(0);
  340. }
  341. static int _vorbis_pack_comment(oggpack_buffer *opb,vorbis_comment *vc){
  342. char temp[]="Xiphophorus libVorbis I 20001031";
  343. /* preamble */
  344. oggpack_write(opb,0x03,8);
  345. _v_writestring(opb,"vorbis");
  346. /* vendor */
  347. oggpack_write(opb,strlen(temp),32);
  348. _v_writestring(opb,temp);
  349. /* comments */
  350. oggpack_write(opb,vc->comments,32);
  351. if(vc->comments){
  352. int i;
  353. for(i=0;i<vc->comments;i++){
  354. if(vc->user_comments[i]){
  355. oggpack_write(opb,vc->comment_lengths[i],32);
  356. _v_writestring(opb,vc->user_comments[i]);
  357. }else{
  358. oggpack_write(opb,0,32);
  359. }
  360. }
  361. }
  362. oggpack_write(opb,1,1);
  363. return(0);
  364. }
  365. static int _vorbis_pack_books(oggpack_buffer *opb,vorbis_info *vi){
  366. codec_setup_info *ci=vi->codec_setup;
  367. int i;
  368. if(!ci)return(OV_EFAULT);
  369. oggpack_write(opb,0x05,8);
  370. _v_writestring(opb,"vorbis");
  371. /* books */
  372. oggpack_write(opb,ci->books-1,8);
  373. for(i=0;i<ci->books;i++)
  374. if(vorbis_staticbook_pack(ci->book_param[i],opb))goto err_out;
  375. /* times */
  376. oggpack_write(opb,ci->times-1,6);
  377. for(i=0;i<ci->times;i++){
  378. oggpack_write(opb,ci->time_type[i],16);
  379. _time_P[ci->time_type[i]]->pack(ci->time_param[i],opb);
  380. }
  381. /* floors */
  382. oggpack_write(opb,ci->floors-1,6);
  383. for(i=0;i<ci->floors;i++){
  384. oggpack_write(opb,ci->floor_type[i],16);
  385. _floor_P[ci->floor_type[i]]->pack(ci->floor_param[i],opb);
  386. }
  387. /* residues */
  388. oggpack_write(opb,ci->residues-1,6);
  389. for(i=0;i<ci->residues;i++){
  390. oggpack_write(opb,ci->residue_type[i],16);
  391. _residue_P[ci->residue_type[i]]->pack(ci->residue_param[i],opb);
  392. }
  393. /* maps */
  394. oggpack_write(opb,ci->maps-1,6);
  395. for(i=0;i<ci->maps;i++){
  396. oggpack_write(opb,ci->map_type[i],16);
  397. _mapping_P[ci->map_type[i]]->pack(vi,ci->map_param[i],opb);
  398. }
  399. /* modes */
  400. oggpack_write(opb,ci->modes-1,6);
  401. for(i=0;i<ci->modes;i++){
  402. oggpack_write(opb,ci->mode_param[i]->blockflag,1);
  403. oggpack_write(opb,ci->mode_param[i]->windowtype,16);
  404. oggpack_write(opb,ci->mode_param[i]->transformtype,16);
  405. oggpack_write(opb,ci->mode_param[i]->mapping,8);
  406. }
  407. oggpack_write(opb,1,1);
  408. return(0);
  409. err_out:
  410. return(-1);
  411. }
  412. int vorbis_analysis_headerout(vorbis_dsp_state *v,
  413. vorbis_comment *vc,
  414. ogg_packet *op,
  415. ogg_packet *op_comm,
  416. ogg_packet *op_code){
  417. int ret=OV_EIMPL;
  418. vorbis_info *vi=v->vi;
  419. oggpack_buffer opb;
  420. backend_lookup_state *b=v->backend_state;
  421. if(!b){
  422. ret=OV_EFAULT;
  423. goto err_out;
  424. }
  425. /* first header packet **********************************************/
  426. oggpack_writeinit(&opb);
  427. if(_vorbis_pack_info(&opb,vi))goto err_out;
  428. /* build the packet */
  429. if(b->header)free(b->header);
  430. b->header=_ogg_malloc(oggpack_bytes(&opb));
  431. memcpy(b->header,opb.buffer,oggpack_bytes(&opb));
  432. op->packet=b->header;
  433. op->bytes=oggpack_bytes(&opb);
  434. op->b_o_s=1;
  435. op->e_o_s=0;
  436. op->granulepos=0;
  437. /* second header packet (comments) **********************************/
  438. oggpack_reset(&opb);
  439. if(_vorbis_pack_comment(&opb,vc))goto err_out;
  440. if(b->header1)free(b->header1);
  441. b->header1=_ogg_malloc(oggpack_bytes(&opb));
  442. memcpy(b->header1,opb.buffer,oggpack_bytes(&opb));
  443. op_comm->packet=b->header1;
  444. op_comm->bytes=oggpack_bytes(&opb);
  445. op_comm->b_o_s=0;
  446. op_comm->e_o_s=0;
  447. op_comm->granulepos=0;
  448. /* third header packet (modes/codebooks) ****************************/
  449. oggpack_reset(&opb);
  450. if(_vorbis_pack_books(&opb,vi))goto err_out;
  451. if(b->header2)free(b->header2);
  452. b->header2=_ogg_malloc(oggpack_bytes(&opb));
  453. memcpy(b->header2,opb.buffer,oggpack_bytes(&opb));
  454. op_code->packet=b->header2;
  455. op_code->bytes=oggpack_bytes(&opb);
  456. op_code->b_o_s=0;
  457. op_code->e_o_s=0;
  458. op_code->granulepos=0;
  459. oggpack_writeclear(&opb);
  460. return(0);
  461. err_out:
  462. oggpack_writeclear(&opb);
  463. memset(op,0,sizeof(ogg_packet));
  464. memset(op_comm,0,sizeof(ogg_packet));
  465. memset(op_code,0,sizeof(ogg_packet));
  466. if(b->header)free(b->header);
  467. if(b->header1)free(b->header1);
  468. if(b->header2)free(b->header2);
  469. b->header=NULL;
  470. b->header1=NULL;
  471. b->header2=NULL;
  472. return(ret);
  473. }