00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <stdlib.h>
00022 #include <string.h>
00023 #include <ctype.h>
00024 #include "ogg.h"
00025 #include "ivorbiscodec.h"
00026 #include "codec_internal.h"
00027 #include "codebook.h"
00028 #include "registry.h"
00029 #include "window.h"
00030 #include "misc.h"
00031 #include "os.h"
00032
00033
00034 static void _v_readstring(oggpack_buffer *o,char *buf,int bytes){
00035 while(bytes--){
00036 *buf++=oggpack_read(o,8);
00037 }
00038 }
00039
00040 void vorbis_comment_init(vorbis_comment *vc){
00041 memset(vc,0,sizeof(*vc));
00042 }
00043
00044
00045
00046 static int tagcompare(const char *s1, const char *s2, int n){
00047 int c=0;
00048 while(c < n){
00049 if(toupper(s1[c]) != toupper(s2[c]))
00050 return !0;
00051 c++;
00052 }
00053 return 0;
00054 }
00055
00056 char *vorbis_comment_query(vorbis_comment *vc, char *tag, int count){
00057 long i;
00058 int found = 0;
00059 int taglen = strlen(tag)+1;
00060 char *fulltag = (char *)_ogg_malloc(taglen+ 1);
00061 strcpy(fulltag, tag);
00062 strcat(fulltag, "=");
00063
00064 for(i=0;i<vc->comments;i++){
00065 if(!tagcompare(vc->user_comments[i], fulltag, taglen)){
00066 if(count == found)
00067 {
00068 _ogg_free(fulltag);
00069
00070 return vc->user_comments[i] + taglen;
00071 }
00072
00073 else
00074 found++;
00075 }
00076 }
00077 _ogg_free(fulltag);
00078 return NULL;
00079 }
00080
00081 int vorbis_comment_query_count(vorbis_comment *vc, char *tag){
00082 int i,count=0;
00083 int taglen = strlen(tag)+1;
00084 char *fulltag = (char *)_ogg_malloc(taglen+1);
00085 strcpy(fulltag,tag);
00086 strcat(fulltag, "=");
00087
00088 for(i=0;i<vc->comments;i++){
00089 if(!tagcompare(vc->user_comments[i], fulltag, taglen))
00090 count++;
00091 }
00092 _ogg_free(fulltag);
00093 return count;
00094 }
00095
00096 void vorbis_comment_clear(vorbis_comment *vc){
00097 if(vc){
00098 long i;
00099 for(i=0;i<vc->comments;i++)
00100 if(vc->user_comments[i])_ogg_free(vc->user_comments[i]);
00101 if(vc->user_comments)_ogg_free(vc->user_comments);
00102 if(vc->comment_lengths)_ogg_free(vc->comment_lengths);
00103 if(vc->vendor)_ogg_free(vc->vendor);
00104 memset(vc,0,sizeof(*vc));
00105 }
00106 }
00107
00108
00109
00110 int vorbis_info_blocksize(vorbis_info *vi,int zo){
00111 codec_setup_info *ci = (codec_setup_info *)vi->codec_setup;
00112 return ci ? ci->blocksizes[zo] : -1;
00113 }
00114
00115
00116 void vorbis_info_init(vorbis_info *vi){
00117 memset(vi,0,sizeof(*vi));
00118 vi->codec_setup=(codec_setup_info *)_ogg_calloc(1,sizeof(codec_setup_info));
00119 }
00120
00121 void vorbis_info_clear(vorbis_info *vi){
00122 codec_setup_info *ci=(codec_setup_info *)vi->codec_setup;
00123 int i;
00124
00125 if(ci){
00126
00127 for(i=0;i<ci->modes;i++)
00128 if(ci->mode_param[i])_ogg_free(ci->mode_param[i]);
00129
00130 for(i=0;i<ci->maps;i++)
00131 _mapping_P[ci->map_type[i]]->free_info(ci->map_param[i]);
00132
00133 for(i=0;i<ci->floors;i++)
00134 _floor_P[ci->floor_type[i]]->free_info(ci->floor_param[i]);
00135
00136 for(i=0;i<ci->residues;i++)
00137 _residue_P[ci->residue_type[i]]->free_info(ci->residue_param[i]);
00138
00139 for(i=0;i<ci->books;i++){
00140 if(ci->book_param[i]){
00141
00142 vorbis_staticbook_destroy(ci->book_param[i]);
00143 }
00144 if(ci->fullbooks)
00145 vorbis_book_clear(ci->fullbooks+i);
00146 }
00147 if(ci->fullbooks)
00148 _ogg_free(ci->fullbooks);
00149
00150 _ogg_free(ci);
00151 }
00152
00153 memset(vi,0,sizeof(*vi));
00154 }
00155
00156
00157
00158 static int _vorbis_unpack_info(vorbis_info *vi,oggpack_buffer *opb){
00159 codec_setup_info *ci=(codec_setup_info *)vi->codec_setup;
00160 if(!ci)return(OV_EFAULT);
00161
00162 vi->version=oggpack_read(opb,32);
00163 if(vi->version!=0)return(OV_EVERSION);
00164
00165 vi->channels=oggpack_read(opb,8);
00166 vi->rate=oggpack_read(opb,32);
00167
00168 vi->bitrate_upper=oggpack_read(opb,32);
00169 vi->bitrate_nominal=oggpack_read(opb,32);
00170 vi->bitrate_lower=oggpack_read(opb,32);
00171
00172 ci->blocksizes[0]=1<<oggpack_read(opb,4);
00173 ci->blocksizes[1]=1<<oggpack_read(opb,4);
00174
00175 if(vi->rate<1)goto err_out;
00176 if(vi->channels<1)goto err_out;
00177 if(ci->blocksizes[0]<64)goto err_out;
00178 if(ci->blocksizes[1]<ci->blocksizes[0])goto err_out;
00179 if(ci->blocksizes[1]>8192)goto err_out;
00180
00181 if(oggpack_read(opb,1)!=1)goto err_out;
00182
00183 return(0);
00184 err_out:
00185 vorbis_info_clear(vi);
00186 return(OV_EBADHEADER);
00187 }
00188
00189 static int _vorbis_unpack_comment(vorbis_comment *vc,oggpack_buffer *opb){
00190 int i;
00191 int vendorlen=oggpack_read(opb,32);
00192 if(vendorlen<0)goto err_out;
00193 vc->vendor=(char *)_ogg_calloc(vendorlen+1,1);
00194 _v_readstring(opb,vc->vendor,vendorlen);
00195 vc->comments=oggpack_read(opb,32);
00196 if(vc->comments<0)goto err_out;
00197 vc->user_comments=(char **)_ogg_calloc(vc->comments+1,sizeof(*vc->user_comments));
00198 vc->comment_lengths=(int *)_ogg_calloc(vc->comments+1, sizeof(*vc->comment_lengths));
00199
00200 for(i=0;i<vc->comments;i++){
00201 int len=oggpack_read(opb,32);
00202 if(len<0)goto err_out;
00203 vc->comment_lengths[i]=len;
00204 vc->user_comments[i]=(char *)_ogg_calloc(len+1,1);
00205 _v_readstring(opb,vc->user_comments[i],len);
00206 }
00207 if(oggpack_read(opb,1)!=1)goto err_out;
00208
00209 return(0);
00210 err_out:
00211 vorbis_comment_clear(vc);
00212 return(OV_EBADHEADER);
00213 }
00214
00215
00216
00217 static int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb){
00218 codec_setup_info *ci=(codec_setup_info *)vi->codec_setup;
00219 int i;
00220 if(!ci)return(OV_EFAULT);
00221
00222
00223 ci->books=oggpack_read(opb,8)+1;
00224
00225 for(i=0;i<ci->books;i++){
00226 ci->book_param[i]=(static_codebook *)_ogg_calloc(1,sizeof(*ci->book_param[i]));
00227 if(vorbis_staticbook_unpack(opb,ci->book_param[i]))goto err_out;
00228 }
00229
00230
00231 ci->times=oggpack_read(opb,6)+1;
00232
00233
00234 for(i=0;i<ci->times;i++){
00235 ci->time_type[i]=oggpack_read(opb,16);
00236 if(ci->time_type[i]<0 || ci->time_type[i]>=VI_TIMEB)goto err_out;
00237
00238
00239
00240 }
00241
00242
00243 ci->floors=oggpack_read(opb,6)+1;
00244
00245
00246 for(i=0;i<ci->floors;i++){
00247 ci->floor_type[i]=oggpack_read(opb,16);
00248 if(ci->floor_type[i]<0 || ci->floor_type[i]>=VI_FLOORB)goto err_out;
00249 ci->floor_param[i]=_floor_P[ci->floor_type[i]]->unpack(vi,opb);
00250 if(!ci->floor_param[i])goto err_out;
00251 }
00252
00253
00254 ci->residues=oggpack_read(opb,6)+1;
00255
00256
00257 for(i=0;i<ci->residues;i++){
00258 ci->residue_type[i]=oggpack_read(opb,16);
00259 if(ci->residue_type[i]<0 || ci->residue_type[i]>=VI_RESB)goto err_out;
00260 ci->residue_param[i]=_residue_P[ci->residue_type[i]]->unpack(vi,opb);
00261 if(!ci->residue_param[i])goto err_out;
00262 }
00263
00264
00265 ci->maps=oggpack_read(opb,6)+1;
00266
00267
00268 for(i=0;i<ci->maps;i++){
00269 ci->map_type[i]=oggpack_read(opb,16);
00270 if(ci->map_type[i]<0 || ci->map_type[i]>=VI_MAPB)goto err_out;
00271 ci->map_param[i]=_mapping_P[ci->map_type[i]]->unpack(vi,opb);
00272 if(!ci->map_param[i])goto err_out;
00273 }
00274
00275
00276 ci->modes=oggpack_read(opb,6)+1;
00277
00278 for(i=0;i<ci->modes;i++){
00279 ci->mode_param[i]=(vorbis_info_mode *)_ogg_calloc(1,sizeof(*ci->mode_param[i]));
00280 ci->mode_param[i]->blockflag=oggpack_read(opb,1);
00281 ci->mode_param[i]->windowtype=oggpack_read(opb,16);
00282 ci->mode_param[i]->transformtype=oggpack_read(opb,16);
00283 ci->mode_param[i]->mapping=oggpack_read(opb,8);
00284
00285 if(ci->mode_param[i]->windowtype>=VI_WINDOWB)goto err_out;
00286 if(ci->mode_param[i]->transformtype>=VI_WINDOWB)goto err_out;
00287 if(ci->mode_param[i]->mapping>=ci->maps)goto err_out;
00288 }
00289
00290 if(oggpack_read(opb,1)!=1)goto err_out;
00291
00292 return(0);
00293 err_out:
00294 vorbis_info_clear(vi);
00295 return(OV_EBADHEADER);
00296 }
00297
00298
00299
00300
00301
00302
00303 int vorbis_synthesis_headerin(vorbis_info *vi,vorbis_comment *vc,ogg_packet *op){
00304 oggpack_buffer opb;
00305
00306 if(op){
00307 oggpack_readinit(&opb,op->packet);
00308
00309
00310
00311 {
00312 char buffer[6];
00313 int packtype=oggpack_read(&opb,8);
00314 memset(buffer,0,6);
00315 _v_readstring(&opb,buffer,6);
00316 if(memcmp(buffer,"vorbis",6)){
00317
00318 return(OV_ENOTVORBIS);
00319 }
00320 switch(packtype){
00321 case 0x01:
00322 if(!op->b_o_s){
00323
00324 return(OV_EBADHEADER);
00325 }
00326 if(vi->rate!=0){
00327
00328 return(OV_EBADHEADER);
00329 }
00330
00331 return(_vorbis_unpack_info(vi,&opb));
00332
00333 case 0x03:
00334 if(vi->rate==0){
00335
00336 return(OV_EBADHEADER);
00337 }
00338
00339 return(_vorbis_unpack_comment(vc,&opb));
00340
00341 case 0x05:
00342 if(vi->rate==0 || vc->vendor==NULL){
00343
00344 return(OV_EBADHEADER);
00345 }
00346
00347 return(_vorbis_unpack_books(vi,&opb));
00348
00349 default:
00350
00351 return(OV_EBADHEADER);
00352 }
00353 }
00354 }
00355 return(OV_EBADHEADER);
00356 }
00357