PageRenderTime 434ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/apps/codecs/libtremor/info.c

https://github.com/ecrips/Rockbox-FuzeV2
C | 318 lines | 211 code | 49 blank | 58 comment | 63 complexity | 825d99a9e4a5c3c17c3c0c06dee76720 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, BSD-3-Clause, AGPL-1.0
  1. /********************************************************************
  2. * *
  3. * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. *
  4. * *
  5. * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
  6. * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
  7. * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
  8. * *
  9. * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2003 *
  10. * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ *
  11. * *
  12. ********************************************************************
  13. function: maintain the info structure, info <-> header packets
  14. ********************************************************************/
  15. /* general handling of the header and the vorbis_info structure (and
  16. substructures) */
  17. #include "config-tremor.h"
  18. #include <string.h>
  19. #include <ctype.h>
  20. #include "ogg.h"
  21. #include "ivorbiscodec.h"
  22. #include "codec_internal.h"
  23. #include "codebook.h"
  24. #include "registry.h"
  25. #include "window.h"
  26. #include "misc.h"
  27. #include "os.h"
  28. /* helpers */
  29. static void _v_readstring(oggpack_buffer *o,char *buf,int bytes){
  30. while(bytes--){
  31. *buf++=oggpack_read(o,8);
  32. }
  33. }
  34. void vorbis_comment_init(vorbis_comment *vc){
  35. memset(vc,0,sizeof(*vc));
  36. }
  37. void vorbis_comment_clear(vorbis_comment *vc){
  38. if(vc){
  39. long i;
  40. for(i=0;i<vc->comments;i++)
  41. if(vc->user_comments[i])_ogg_free(vc->user_comments[i]);
  42. if(vc->user_comments)_ogg_free(vc->user_comments);
  43. if(vc->comment_lengths)_ogg_free(vc->comment_lengths);
  44. if(vc->vendor)_ogg_free(vc->vendor);
  45. memset(vc,0,sizeof(*vc));
  46. }
  47. }
  48. /* blocksize 0 is guaranteed to be short, 1 is guarantted to be long.
  49. They may be equal, but short will never ge greater than long */
  50. int vorbis_info_blocksize(vorbis_info *vi,int zo){
  51. codec_setup_info *ci = (codec_setup_info *)vi->codec_setup;
  52. return ci ? ci->blocksizes[zo] : -1;
  53. }
  54. /* used by synthesis, which has a full, alloced vi */
  55. void vorbis_info_init(vorbis_info *vi){
  56. memset(vi,0,sizeof(*vi));
  57. vi->codec_setup=(codec_setup_info *)_ogg_calloc(1,sizeof(codec_setup_info));
  58. }
  59. void vorbis_info_clear(vorbis_info *vi){
  60. codec_setup_info *ci=(codec_setup_info *)vi->codec_setup;
  61. int i;
  62. if(ci){
  63. for(i=0;i<ci->modes;i++)
  64. if(ci->mode_param[i])_ogg_free(ci->mode_param[i]);
  65. for(i=0;i<ci->maps;i++) /* unpack does the range checking */
  66. if(ci->map_param[i])
  67. _mapping_P[ci->map_type[i]]->free_info(ci->map_param[i]);
  68. for(i=0;i<ci->floors;i++) /* unpack does the range checking */
  69. if(ci->floor_param[i])
  70. _floor_P[ci->floor_type[i]]->free_info(ci->floor_param[i]);
  71. for(i=0;i<ci->residues;i++) /* unpack does the range checking */
  72. if(ci->residue_param[i])
  73. _residue_P[ci->residue_type[i]]->free_info(ci->residue_param[i]);
  74. for(i=0;i<ci->books;i++){
  75. if(ci->book_param[i]){
  76. /* knows if the book was not alloced */
  77. vorbis_staticbook_destroy(ci->book_param[i]);
  78. }
  79. if(ci->fullbooks)
  80. vorbis_book_clear(ci->fullbooks+i);
  81. }
  82. if(ci->fullbooks)
  83. _ogg_free(ci->fullbooks);
  84. _ogg_free(ci);
  85. }
  86. memset(vi,0,sizeof(*vi));
  87. }
  88. /* Header packing/unpacking ********************************************/
  89. static int _vorbis_unpack_info(vorbis_info *vi,oggpack_buffer *opb){
  90. codec_setup_info *ci=(codec_setup_info *)vi->codec_setup;
  91. if(!ci)return(OV_EFAULT);
  92. vi->version=oggpack_read(opb,32);
  93. if(vi->version!=0)return(OV_EVERSION);
  94. vi->channels=oggpack_read(opb,8);
  95. vi->rate=oggpack_read(opb,32);
  96. vi->bitrate_upper=oggpack_read(opb,32);
  97. vi->bitrate_nominal=oggpack_read(opb,32);
  98. vi->bitrate_lower=oggpack_read(opb,32);
  99. ci->blocksizes[0]=1<<oggpack_read(opb,4);
  100. ci->blocksizes[1]=1<<oggpack_read(opb,4);
  101. if(vi->rate<1)goto err_out;
  102. if(vi->channels<1)goto err_out;
  103. if(ci->blocksizes[0]<64)goto err_out;
  104. if(ci->blocksizes[1]<ci->blocksizes[0])goto err_out;
  105. if(ci->blocksizes[1]>8192)goto err_out;
  106. if(oggpack_read(opb,1)!=1)goto err_out; /* EOP check */
  107. return(0);
  108. err_out:
  109. vorbis_info_clear(vi);
  110. return(OV_EBADHEADER);
  111. }
  112. static int _vorbis_unpack_comment(vorbis_comment *vc,oggpack_buffer *opb){
  113. int i;
  114. int vendorlen=oggpack_read(opb,32);
  115. if(vendorlen<0)goto err_out;
  116. vc->vendor=(char *)_ogg_calloc(vendorlen+1,1);
  117. _v_readstring(opb,vc->vendor,vendorlen);
  118. vc->comments=oggpack_read(opb,32);
  119. if(vc->comments<0)goto err_out;
  120. vc->user_comments=(char **)_ogg_calloc(vc->comments+1,sizeof(*vc->user_comments));
  121. vc->comment_lengths=(int *)_ogg_calloc(vc->comments+1, sizeof(*vc->comment_lengths));
  122. for(i=0;i<vc->comments;i++){
  123. int len=oggpack_read(opb,32);
  124. if(len<0)goto err_out;
  125. vc->comment_lengths[i]=len;
  126. if(len>10000){ /*truncate long comments rather then seg faulting*/
  127. vc->user_comments[i]=(char *)_ogg_calloc(10001,1);
  128. _v_readstring(opb,vc->user_comments[i],10000);
  129. /*just to be neat, consumed and discard the rest of the comment*/
  130. len-=10000;
  131. while(len--)
  132. oggpack_read(opb,8);
  133. }else{
  134. vc->user_comments[i]=(char *)_ogg_calloc(len+1,1);
  135. _v_readstring(opb,vc->user_comments[i],len);
  136. }
  137. }
  138. if(oggpack_read(opb,1)!=1)goto err_out; /* EOP check */
  139. return(0);
  140. err_out:
  141. vorbis_comment_clear(vc);
  142. return(OV_EBADHEADER);
  143. }
  144. /* all of the real encoding details are here. The modes, books,
  145. everything */
  146. static int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb){
  147. codec_setup_info *ci=(codec_setup_info *)vi->codec_setup;
  148. int i;
  149. if(!ci)return(OV_EFAULT);
  150. /* codebooks */
  151. ci->books=oggpack_read(opb,8)+1;
  152. /*ci->book_param=_ogg_calloc(ci->books,sizeof(*ci->book_param));*/
  153. for(i=0;i<ci->books;i++){
  154. ci->book_param[i]=(static_codebook *)_ogg_calloc(1,sizeof(*ci->book_param[i]));
  155. if(vorbis_staticbook_unpack(opb,ci->book_param[i]))goto err_out;
  156. }
  157. /* time backend settings */
  158. ci->times=oggpack_read(opb,6)+1;
  159. /*ci->time_type=_ogg_malloc(ci->times*sizeof(*ci->time_type));*/
  160. /*ci->time_param=_ogg_calloc(ci->times,sizeof(void *));*/
  161. for(i=0;i<ci->times;i++){
  162. ci->time_type[i]=oggpack_read(opb,16);
  163. if(ci->time_type[i]<0 || ci->time_type[i]>=VI_TIMEB)goto err_out;
  164. /* ci->time_param[i]=_time_P[ci->time_type[i]]->unpack(vi,opb);
  165. Vorbis I has no time backend */
  166. /*if(!ci->time_param[i])goto err_out;*/
  167. }
  168. /* floor backend settings */
  169. ci->floors=oggpack_read(opb,6)+1;
  170. /*ci->floor_type=_ogg_malloc(ci->floors*sizeof(*ci->floor_type));*/
  171. /*ci->floor_param=_ogg_calloc(ci->floors,sizeof(void *));*/
  172. for(i=0;i<ci->floors;i++){
  173. ci->floor_type[i]=oggpack_read(opb,16);
  174. if(ci->floor_type[i]<0 || ci->floor_type[i]>=VI_FLOORB)goto err_out;
  175. ci->floor_param[i]=_floor_P[ci->floor_type[i]]->unpack(vi,opb);
  176. if(!ci->floor_param[i])goto err_out;
  177. }
  178. /* residue backend settings */
  179. ci->residues=oggpack_read(opb,6)+1;
  180. /*ci->residue_type=_ogg_malloc(ci->residues*sizeof(*ci->residue_type));*/
  181. /*ci->residue_param=_ogg_calloc(ci->residues,sizeof(void *));*/
  182. for(i=0;i<ci->residues;i++){
  183. ci->residue_type[i]=oggpack_read(opb,16);
  184. if(ci->residue_type[i]<0 || ci->residue_type[i]>=VI_RESB)goto err_out;
  185. ci->residue_param[i]=_residue_P[ci->residue_type[i]]->unpack(vi,opb);
  186. if(!ci->residue_param[i])goto err_out;
  187. }
  188. /* map backend settings */
  189. ci->maps=oggpack_read(opb,6)+1;
  190. /*ci->map_type=_ogg_malloc(ci->maps*sizeof(*ci->map_type));*/
  191. /*ci->map_param=_ogg_calloc(ci->maps,sizeof(void *));*/
  192. for(i=0;i<ci->maps;i++){
  193. ci->map_type[i]=oggpack_read(opb,16);
  194. if(ci->map_type[i]<0 || ci->map_type[i]>=VI_MAPB)goto err_out;
  195. ci->map_param[i]=_mapping_P[ci->map_type[i]]->unpack(vi,opb);
  196. if(!ci->map_param[i])goto err_out;
  197. }
  198. /* mode settings */
  199. ci->modes=oggpack_read(opb,6)+1;
  200. /*vi->mode_param=_ogg_calloc(vi->modes,sizeof(void *));*/
  201. for(i=0;i<ci->modes;i++){
  202. ci->mode_param[i]=(vorbis_info_mode *)_ogg_calloc(1,sizeof(*ci->mode_param[i]));
  203. ci->mode_param[i]->blockflag=oggpack_read(opb,1);
  204. ci->mode_param[i]->windowtype=oggpack_read(opb,16);
  205. ci->mode_param[i]->transformtype=oggpack_read(opb,16);
  206. ci->mode_param[i]->mapping=oggpack_read(opb,8);
  207. if(ci->mode_param[i]->windowtype>=VI_WINDOWB)goto err_out;
  208. if(ci->mode_param[i]->transformtype>=VI_WINDOWB)goto err_out;
  209. if(ci->mode_param[i]->mapping>=ci->maps)goto err_out;
  210. }
  211. if(oggpack_read(opb,1)!=1)goto err_out; /* top level EOP check */
  212. return(0);
  213. err_out:
  214. vorbis_info_clear(vi);
  215. return(OV_EBADHEADER);
  216. }
  217. /* The Vorbis header is in three packets; the initial small packet in
  218. the first page that identifies basic parameters, a second packet
  219. with bitstream comments and a third packet that holds the
  220. codebook. */
  221. int vorbis_synthesis_headerin(vorbis_info *vi,vorbis_comment *vc,ogg_packet *op){
  222. oggpack_buffer opb;
  223. if(op){
  224. oggpack_readinit(&opb,op->packet);
  225. /* Which of the three types of header is this? */
  226. /* Also verify header-ness, vorbis */
  227. {
  228. char buffer[6];
  229. int packtype=oggpack_read(&opb,8);
  230. memset(buffer,0,6);
  231. _v_readstring(&opb,buffer,6);
  232. if(memcmp(buffer,"vorbis",6)){
  233. /* not a vorbis header */
  234. return(OV_ENOTVORBIS);
  235. }
  236. switch(packtype){
  237. case 0x01: /* least significant *bit* is read first */
  238. if(!op->b_o_s){
  239. /* Not the initial packet */
  240. return(OV_EBADHEADER);
  241. }
  242. if(vi->rate!=0){
  243. /* previously initialized info header */
  244. return(OV_EBADHEADER);
  245. }
  246. return(_vorbis_unpack_info(vi,&opb));
  247. case 0x03: /* least significant *bit* is read first */
  248. if(vi->rate==0){
  249. /* um... we didn't get the initial header */
  250. return(OV_EBADHEADER);
  251. }
  252. return(_vorbis_unpack_comment(vc,&opb));
  253. case 0x05: /* least significant *bit* is read first */
  254. if(vi->rate==0 || vc->vendor==NULL){
  255. /* um... we didn;t get the initial header or comments yet */
  256. return(OV_EBADHEADER);
  257. }
  258. return(_vorbis_unpack_books(vi,&opb));
  259. default:
  260. /* Not a valid vorbis header type */
  261. return(OV_EBADHEADER);
  262. break;
  263. }
  264. }
  265. }
  266. return(OV_EBADHEADER);
  267. }