~arkadini/fogg/trunk

« back to all changes in this revision

Viewing changes to reference/tremor/info.c

  • Committer: Arek Korbik
  • Date: 2008-10-03 00:34:01 UTC
  • Revision ID: arkadini@gmail.com-20081003003401-9eahru9hcz3o2qht
Remove the Tremor reference files for now.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
 
 
14
 
 function: maintain the info structure, info <-> header packets
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.h"
25
 
#include "ivorbiscodec.h"
26
 
#include "codec_internal.h"
27
 
#include "codebook.h"
28
 
#include "registry.h"
29
 
#include "window.h"
30
 
#include "misc.h"
31
 
 
32
 
/* helpers */
33
 
static void _v_readstring(oggpack_buffer *o,char *buf,int bytes){
34
 
  while(bytes--){
35
 
    *buf++=oggpack_read(o,8);
36
 
  }
37
 
}
38
 
 
39
 
void vorbis_comment_init(vorbis_comment *vc){
40
 
  memset(vc,0,sizeof(*vc));
41
 
}
42
 
 
43
 
/* This is more or less the same as strncasecmp - but that doesn't exist
44
 
 * everywhere, and this is a fairly trivial function, so we include it */
45
 
static int tagcompare(const char *s1, const char *s2, int n){
46
 
  int c=0;
47
 
  while(c < n){
48
 
    if(toupper(s1[c]) != toupper(s2[c]))
49
 
      return !0;
50
 
    c++;
51
 
  }
52
 
  return 0;
53
 
}
54
 
 
55
 
char *vorbis_comment_query(vorbis_comment *vc, char *tag, int count){
56
 
  long i;
57
 
  int found = 0;
58
 
  int taglen = strlen(tag)+1; /* +1 for the = we append */
59
 
  char *fulltag = (char *)alloca(taglen+ 1);
60
 
 
61
 
  strcpy(fulltag, tag);
62
 
  strcat(fulltag, "=");
63
 
  
64
 
  for(i=0;i<vc->comments;i++){
65
 
    if(!tagcompare(vc->user_comments[i], fulltag, taglen)){
66
 
      if(count == found)
67
 
        /* We return a pointer to the data, not a copy */
68
 
        return vc->user_comments[i] + taglen;
69
 
      else
70
 
        found++;
71
 
    }
72
 
  }
73
 
  return NULL; /* didn't find anything */
74
 
}
75
 
 
76
 
int vorbis_comment_query_count(vorbis_comment *vc, char *tag){
77
 
  int i,count=0;
78
 
  int taglen = strlen(tag)+1; /* +1 for the = we append */
79
 
  char *fulltag = (char *)alloca(taglen+1);
80
 
  strcpy(fulltag,tag);
81
 
  strcat(fulltag, "=");
82
 
 
83
 
  for(i=0;i<vc->comments;i++){
84
 
    if(!tagcompare(vc->user_comments[i], fulltag, taglen))
85
 
      count++;
86
 
  }
87
 
 
88
 
  return count;
89
 
}
90
 
 
91
 
void vorbis_comment_clear(vorbis_comment *vc){
92
 
  if(vc){
93
 
    long i;
94
 
    for(i=0;i<vc->comments;i++)
95
 
      if(vc->user_comments[i])_ogg_free(vc->user_comments[i]);
96
 
    if(vc->user_comments)_ogg_free(vc->user_comments);
97
 
        if(vc->comment_lengths)_ogg_free(vc->comment_lengths);
98
 
    if(vc->vendor)_ogg_free(vc->vendor);
99
 
    memset(vc,0,sizeof(*vc));
100
 
  }
101
 
}
102
 
 
103
 
/* blocksize 0 is guaranteed to be short, 1 is guarantted to be long.
104
 
   They may be equal, but short will never ge greater than long */
105
 
int vorbis_info_blocksize(vorbis_info *vi,int zo){
106
 
  codec_setup_info *ci = (codec_setup_info *)vi->codec_setup;
107
 
  return ci ? ci->blocksizes[zo] : -1;
108
 
}
109
 
 
110
 
/* used by synthesis, which has a full, alloced vi */
111
 
void vorbis_info_init(vorbis_info *vi){
112
 
  memset(vi,0,sizeof(*vi));
113
 
  vi->codec_setup=(codec_setup_info *)_ogg_calloc(1,sizeof(codec_setup_info));
114
 
}
115
 
 
116
 
void vorbis_info_clear(vorbis_info *vi){
117
 
  codec_setup_info     *ci=(codec_setup_info *)vi->codec_setup;
118
 
  int i;
119
 
 
120
 
  if(ci){
121
 
 
122
 
    for(i=0;i<ci->modes;i++)
123
 
      if(ci->mode_param[i])_ogg_free(ci->mode_param[i]);
124
 
 
125
 
    for(i=0;i<ci->maps;i++) /* unpack does the range checking */
126
 
      if(ci->map_param[i])
127
 
        _mapping_P[ci->map_type[i]]->free_info(ci->map_param[i]);
128
 
 
129
 
    for(i=0;i<ci->floors;i++) /* unpack does the range checking */
130
 
      if(ci->floor_param[i])
131
 
        _floor_P[ci->floor_type[i]]->free_info(ci->floor_param[i]);
132
 
    
133
 
    for(i=0;i<ci->residues;i++) /* unpack does the range checking */
134
 
      if(ci->residue_param[i])
135
 
        _residue_P[ci->residue_type[i]]->free_info(ci->residue_param[i]);
136
 
 
137
 
    for(i=0;i<ci->books;i++){
138
 
      if(ci->book_param[i]){
139
 
        /* knows if the book was not alloced */
140
 
        vorbis_staticbook_destroy(ci->book_param[i]);
141
 
      }
142
 
      if(ci->fullbooks)
143
 
        vorbis_book_clear(ci->fullbooks+i);
144
 
    }
145
 
    if(ci->fullbooks)
146
 
        _ogg_free(ci->fullbooks);
147
 
    
148
 
    _ogg_free(ci);
149
 
  }
150
 
 
151
 
  memset(vi,0,sizeof(*vi));
152
 
}
153
 
 
154
 
/* Header packing/unpacking ********************************************/
155
 
 
156
 
static int _vorbis_unpack_info(vorbis_info *vi,oggpack_buffer *opb){
157
 
  codec_setup_info     *ci=(codec_setup_info *)vi->codec_setup;
158
 
  if(!ci)return(OV_EFAULT);
159
 
 
160
 
  vi->version=oggpack_read(opb,32);
161
 
  if(vi->version!=0)return(OV_EVERSION);
162
 
 
163
 
  vi->channels=oggpack_read(opb,8);
164
 
  vi->rate=oggpack_read(opb,32);
165
 
 
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
 
 
170
 
  ci->blocksizes[0]=1<<oggpack_read(opb,4);
171
 
  ci->blocksizes[1]=1<<oggpack_read(opb,4);
172
 
  
173
 
  if(vi->rate<1)goto err_out;
174
 
  if(vi->channels<1)goto err_out;
175
 
  if(ci->blocksizes[0]<64)goto err_out; 
176
 
  if(ci->blocksizes[1]<ci->blocksizes[0])goto err_out;
177
 
  if(ci->blocksizes[1]>8192)goto err_out;
178
 
  
179
 
  if(oggpack_read(opb,1)!=1)goto err_out; /* EOP check */
180
 
 
181
 
  return(0);
182
 
 err_out:
183
 
  vorbis_info_clear(vi);
184
 
  return(OV_EBADHEADER);
185
 
}
186
 
 
187
 
static int _vorbis_unpack_comment(vorbis_comment *vc,oggpack_buffer *opb){
188
 
  int i;
189
 
  int vendorlen=oggpack_read(opb,32);
190
 
  if(vendorlen<0)goto err_out;
191
 
  vc->vendor=(char *)_ogg_calloc(vendorlen+1,1);
192
 
  _v_readstring(opb,vc->vendor,vendorlen);
193
 
  vc->comments=oggpack_read(opb,32);
194
 
  if(vc->comments<0)goto err_out;
195
 
  vc->user_comments=(char **)_ogg_calloc(vc->comments+1,sizeof(*vc->user_comments));
196
 
  vc->comment_lengths=(int *)_ogg_calloc(vc->comments+1, sizeof(*vc->comment_lengths));
197
 
            
198
 
  for(i=0;i<vc->comments;i++){
199
 
    int len=oggpack_read(opb,32);
200
 
    if(len<0)goto err_out;
201
 
        vc->comment_lengths[i]=len;
202
 
    vc->user_comments[i]=(char *)_ogg_calloc(len+1,1);
203
 
    _v_readstring(opb,vc->user_comments[i],len);
204
 
  }       
205
 
  if(oggpack_read(opb,1)!=1)goto err_out; /* EOP check */
206
 
 
207
 
  return(0);
208
 
 err_out:
209
 
  vorbis_comment_clear(vc);
210
 
  return(OV_EBADHEADER);
211
 
}
212
 
 
213
 
/* all of the real encoding details are here.  The modes, books,
214
 
   everything */
215
 
static int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb){
216
 
  codec_setup_info     *ci=(codec_setup_info *)vi->codec_setup;
217
 
  int i;
218
 
  if(!ci)return(OV_EFAULT);
219
 
 
220
 
  /* codebooks */
221
 
  ci->books=oggpack_read(opb,8)+1;
222
 
  /*ci->book_param=_ogg_calloc(ci->books,sizeof(*ci->book_param));*/
223
 
  for(i=0;i<ci->books;i++){
224
 
    ci->book_param[i]=(static_codebook *)_ogg_calloc(1,sizeof(*ci->book_param[i]));
225
 
    if(vorbis_staticbook_unpack(opb,ci->book_param[i]))goto err_out;
226
 
  }
227
 
 
228
 
  /* time backend settings */
229
 
  ci->times=oggpack_read(opb,6)+1;
230
 
  /*ci->time_type=_ogg_malloc(ci->times*sizeof(*ci->time_type));*/
231
 
  /*ci->time_param=_ogg_calloc(ci->times,sizeof(void *));*/
232
 
  for(i=0;i<ci->times;i++){
233
 
    ci->time_type[i]=oggpack_read(opb,16);
234
 
    if(ci->time_type[i]<0 || ci->time_type[i]>=VI_TIMEB)goto err_out;
235
 
    /* ci->time_param[i]=_time_P[ci->time_type[i]]->unpack(vi,opb);
236
 
       Vorbis I has no time backend */
237
 
    /*if(!ci->time_param[i])goto err_out;*/
238
 
  }
239
 
 
240
 
  /* floor backend settings */
241
 
  ci->floors=oggpack_read(opb,6)+1;
242
 
  /*ci->floor_type=_ogg_malloc(ci->floors*sizeof(*ci->floor_type));*/
243
 
  /*ci->floor_param=_ogg_calloc(ci->floors,sizeof(void *));*/
244
 
  for(i=0;i<ci->floors;i++){
245
 
    ci->floor_type[i]=oggpack_read(opb,16);
246
 
    if(ci->floor_type[i]<0 || ci->floor_type[i]>=VI_FLOORB)goto err_out;
247
 
    ci->floor_param[i]=_floor_P[ci->floor_type[i]]->unpack(vi,opb);
248
 
    if(!ci->floor_param[i])goto err_out;
249
 
  }
250
 
 
251
 
  /* residue backend settings */
252
 
  ci->residues=oggpack_read(opb,6)+1;
253
 
  /*ci->residue_type=_ogg_malloc(ci->residues*sizeof(*ci->residue_type));*/
254
 
  /*ci->residue_param=_ogg_calloc(ci->residues,sizeof(void *));*/
255
 
  for(i=0;i<ci->residues;i++){
256
 
    ci->residue_type[i]=oggpack_read(opb,16);
257
 
    if(ci->residue_type[i]<0 || ci->residue_type[i]>=VI_RESB)goto err_out;
258
 
    ci->residue_param[i]=_residue_P[ci->residue_type[i]]->unpack(vi,opb);
259
 
    if(!ci->residue_param[i])goto err_out;
260
 
  }
261
 
 
262
 
  /* map backend settings */
263
 
  ci->maps=oggpack_read(opb,6)+1;
264
 
  /*ci->map_type=_ogg_malloc(ci->maps*sizeof(*ci->map_type));*/
265
 
  /*ci->map_param=_ogg_calloc(ci->maps,sizeof(void *));*/
266
 
  for(i=0;i<ci->maps;i++){
267
 
    ci->map_type[i]=oggpack_read(opb,16);
268
 
    if(ci->map_type[i]<0 || ci->map_type[i]>=VI_MAPB)goto err_out;
269
 
    ci->map_param[i]=_mapping_P[ci->map_type[i]]->unpack(vi,opb);
270
 
    if(!ci->map_param[i])goto err_out;
271
 
  }
272
 
  
273
 
  /* mode settings */
274
 
  ci->modes=oggpack_read(opb,6)+1;
275
 
  /*vi->mode_param=_ogg_calloc(vi->modes,sizeof(void *));*/
276
 
  for(i=0;i<ci->modes;i++){
277
 
    ci->mode_param[i]=(vorbis_info_mode *)_ogg_calloc(1,sizeof(*ci->mode_param[i]));
278
 
    ci->mode_param[i]->blockflag=oggpack_read(opb,1);
279
 
    ci->mode_param[i]->windowtype=oggpack_read(opb,16);
280
 
    ci->mode_param[i]->transformtype=oggpack_read(opb,16);
281
 
    ci->mode_param[i]->mapping=oggpack_read(opb,8);
282
 
 
283
 
    if(ci->mode_param[i]->windowtype>=VI_WINDOWB)goto err_out;
284
 
    if(ci->mode_param[i]->transformtype>=VI_WINDOWB)goto err_out;
285
 
    if(ci->mode_param[i]->mapping>=ci->maps)goto err_out;
286
 
  }
287
 
  
288
 
  if(oggpack_read(opb,1)!=1)goto err_out; /* top level EOP check */
289
 
 
290
 
  return(0);
291
 
 err_out:
292
 
  vorbis_info_clear(vi);
293
 
  return(OV_EBADHEADER);
294
 
}
295
 
 
296
 
/* The Vorbis header is in three packets; the initial small packet in
297
 
   the first page that identifies basic parameters, a second packet
298
 
   with bitstream comments and a third packet that holds the
299
 
   codebook. */
300
 
 
301
 
int vorbis_synthesis_headerin(vorbis_info *vi,vorbis_comment *vc,ogg_packet *op){
302
 
  oggpack_buffer opb;
303
 
  
304
 
  if(op){
305
 
    oggpack_readinit(&opb,op->packet);
306
 
 
307
 
    /* Which of the three types of header is this? */
308
 
    /* Also verify header-ness, vorbis */
309
 
    {
310
 
      char buffer[6];
311
 
      int packtype=oggpack_read(&opb,8);
312
 
      memset(buffer,0,6);
313
 
      _v_readstring(&opb,buffer,6);
314
 
      if(memcmp(buffer,"vorbis",6)){
315
 
        /* not a vorbis header */
316
 
        return(OV_ENOTVORBIS);
317
 
      }
318
 
      switch(packtype){
319
 
      case 0x01: /* least significant *bit* is read first */
320
 
        if(!op->b_o_s){
321
 
          /* Not the initial packet */
322
 
          return(OV_EBADHEADER);
323
 
        }
324
 
        if(vi->rate!=0){
325
 
          /* previously initialized info header */
326
 
          return(OV_EBADHEADER);
327
 
        }
328
 
 
329
 
        return(_vorbis_unpack_info(vi,&opb));
330
 
 
331
 
      case 0x03: /* least significant *bit* is read first */
332
 
        if(vi->rate==0){
333
 
          /* um... we didn't get the initial header */
334
 
          return(OV_EBADHEADER);
335
 
        }
336
 
 
337
 
        return(_vorbis_unpack_comment(vc,&opb));
338
 
 
339
 
      case 0x05: /* least significant *bit* is read first */
340
 
        if(vi->rate==0 || vc->vendor==NULL){
341
 
          /* um... we didn;t get the initial header or comments yet */
342
 
          return(OV_EBADHEADER);
343
 
        }
344
 
 
345
 
        return(_vorbis_unpack_books(vi,&opb));
346
 
 
347
 
      default:
348
 
        /* Not a valid vorbis header type */
349
 
        return(OV_EBADHEADER);
350
 
        break;
351
 
      }
352
 
    }
353
 
  }
354
 
  return(OV_EBADHEADER);
355
 
}
356