It's all coming back together slowly. Incremental update.
[platform/upstream/libvorbis.git] / lib / info.c
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
14  function: maintain the info structure, info <-> header packets
15  last mod: $Id: info.c,v 1.17 2000/01/22 13:28:21 xiphmont Exp $
16
17  ********************************************************************/
18
19 /* general handling of the header and the vorbis_info structure (and
20    substructures) */
21
22 #include <stdlib.h>
23 #include <string.h>
24 #include "vorbis/codec.h"
25 #include "bitwise.h"
26 #include "bookinternal.h"
27 #include "registry.h"
28 #include "window.h"
29 #include "psy.h"
30
31 /* helpers */
32
33 static int ilog2(unsigned int v){
34   int ret=0;
35   while(v>1){
36     ret++;
37     v>>=1;
38   }
39   return(ret);
40 }
41
42 static void _v_writestring(oggpack_buffer *o,char *s){
43   while(*s){
44     _oggpack_write(o,*s++,8);
45   }
46 }
47
48 static void _v_readstring(oggpack_buffer *o,char *buf,int bytes){
49   while(bytes--){
50     *buf++=_oggpack_read(o,8);
51   }
52 }
53
54 /* convenience functions for the interface */
55 int vorbis_dsp_addcomment(vorbis_dsp_state *v,char *comment){
56   vorbis_info *vi=v->vi;
57   vi->user_comments=realloc(vi->user_comments,
58                             (vi->comments+2)*sizeof(char *));
59   vi->user_comments[vi->comments]=strdup(comment);
60   vi->comments++;
61   vi->user_comments[vi->comments]=NULL;
62   return(0);
63 }
64
65 /* used by analysis, which has a minimally replicated vi */
66 void _vorbis_info_anrep(vorbis_info *dest, vorbis_info *source){
67
68 /* libVorbis expects modes to be submitted in an already valid
69    vorbis_info structure, but also expects some of the elements to be
70    allocated storage.  To make this easier, the Vorbis distribution
71    includes a number of modes in static storage as headers.  To
72    allocate a copy, run it through vorbis_info_dup */
73
74 /* note that due to codebook size, codebooks are not fully duplicated.
75    The info structure (aside from the embedded codebook elements) will
76    be fully dupped */
77
78 int vorbis_info_dup(vorbis_info *dest,vorbis_info *source){
79   int i;
80   memcpy(dest,source,sizeof(vorbis_info));
81
82   /* also dup individual pieces that need to be allocated */
83   /* dup user comments (unlikely to have any, but for completeness */
84   if(source->comments>0){
85     dest->user_comments=calloc(source->comments+1,sizeof(char *));
86     for(i=0;i<source->comments;i++)
87       dest->user_comments[i]=strdup(source->user_comments[i]);
88   }
89   dest->vendor=NULL;
90
91   /* modes, maps, times, floors, residues, psychoacoustics are not
92      dupped; the pointer is just replicated by the above copy */
93
94   /* dup (partially) books */
95   if(source->books){
96     dest->booklist=malloc(source->books*sizeof(codebook *));
97     for(i=0;i<source->books;i++){
98       dest->booklist[i]=calloc(1,sizeof(codebook));
99       vorbis_book_dup(dest->booklist[i],source->booklist[i]);
100     }
101   }
102
103   return(0);
104 err_out:
105   vorbis_info_clear(dest);
106   return(-1);
107 }
108
109
110   memset(vi,0,sizeof(vorbis_info));
111 }
112
113 void vorbis_info_anclear(vorbis_info *vi){
114   memset(vi,0,sizeof(vorbis_info));
115 }
116
117
118
119 /* used by synthesis, which has a full, alloced vi */
120 void vorbis_info_init(vorbis_info *vi){
121   memset(vi,0,sizeof(vorbis_info));
122 }
123
124 void vorbis_info_clear(vorbis_info *vi){
125   int i;
126   if(vi->comments){
127     for(i=0;i<vi->comments;i++)
128       if(vi->user_comments[i])free(vi->user_comments[i]);
129     free(vi->user_comments);
130   }
131   if(vi->vendor)free(vi->vendor);
132   if(vi->windowtypes)free(vi->windowtypes);
133   if(vi->transformtypes)free(vi->transformtypes);
134   if(vi->modes){
135     for(i=0;i<vi->modes;i++)
136       if(vi->mappingtypes[i]>=0 && vi->mappingtypes[i]<VI_MAPB)
137         vorbis_map_free_P[vi->mappingtypes[i]](vi->modelist[i]);
138     free(vi->modelist);
139     free(vi->mappingtypes);
140     free(vi->blockflags);
141   }
142   if(vi->times){
143     for(i=0;i<vi->times;i++)
144       if(vi->timetypes[i]>=0 && vi->timetypes[i]<VI_TIMEB)
145         vorbis_time_free_P[vi->timetypes[i]](vi->timelist[i]);
146     free(vi->timelist);
147     free(vi->timetypes);
148   }
149   if(vi->floors){
150     for(i=0;i<vi->floors;i++)
151       if(vi->floortypes[i]>=0 && vi->floortypes[i]<VI_FLOORB)
152         vorbis_floor_free_P[vi->floortypes[i]](vi->floorlist[i]);
153     free(vi->floorlist);
154     free(vi->floortypes);
155   }
156   if(vi->residues){
157     for(i=0;i<vi->residues;i++)
158       if(vi->residuetypes[i]>=0 && vi->residuetypes[i]<VI_RESB)
159         vorbis_res_free_P[vi->residuetypes[i]](vi->residuelist[i]);
160     free(vi->residuelist);
161     free(vi->residuetypes);
162   }
163   if(vi->books){
164     for(i=0;i<vi->books;i++){
165       if(vi->booklist[i]){
166         vorbis_book_clear(vi->booklist[i]);
167         free(vi->booklist[i]);
168       }
169     }
170     free(vi->booklist);
171   }
172   if(vi->psys){
173     for(i=0;i<vi->psys;i++)
174       _vi_psy_free(vi->psylist[i]);
175     free(vi->psylist);
176   }
177   
178   if(vi->header)free(vi->header);
179   if(vi->header1)free(vi->header1);
180   if(vi->header2)free(vi->header2);
181
182   memset(vi,0,sizeof(vorbis_info));
183 }
184
185 /* Header packing/unpacking ********************************************/
186
187 static int _vorbis_unpack_info(vorbis_info *vi,oggpack_buffer *opb){
188   vi->version=_oggpack_read(opb,32);
189   if(vi->version!=0)return(-1);
190
191   vi->channels=_oggpack_read(opb,8);
192   vi->rate=_oggpack_read(opb,32);
193
194   vi->bitrate_upper=_oggpack_read(opb,32);
195   vi->bitrate_nominal=_oggpack_read(opb,32);
196   vi->bitrate_lower=_oggpack_read(opb,32);
197
198   vi->blocksizes[0]=1<<_oggpack_read(opb,4);
199   vi->blocksizes[1]=1<<_oggpack_read(opb,4);
200   
201   if(vi->rate<1)goto err_out;
202   if(vi->channels<1)goto err_out;
203   if(vi->blocksizes[0]<8)goto err_out; 
204   if(vi->blocksizes[1]<vi->blocksizes[0])goto err_out;
205   
206   if(_oggpack_read(opb,1)!=1)goto err_out; /* EOP check */
207
208   return(0);
209  err_out:
210   vorbis_info_clear(vi);
211   return(-1);
212 }
213
214 static int _vorbis_unpack_comments(vorbis_info *vi,oggpack_buffer *opb){
215   int i;
216   int vendorlen=_oggpack_read(opb,32);
217   if(vendorlen<0)goto err_out;
218   vi->vendor=calloc(vendorlen+1,1);
219   _v_readstring(opb,vi->vendor,vendorlen);
220   vi->comments=_oggpack_read(opb,32);
221   if(vi->comments<0)goto err_out;
222   vi->user_comments=calloc(vi->comments+1,sizeof(char **));
223             
224   for(i=0;i<vi->comments;i++){
225     int len=_oggpack_read(opb,32);
226     if(len<0)goto err_out;
227     vi->user_comments[i]=calloc(len+1,1);
228     _v_readstring(opb,vi->user_comments[i],len);
229   }       
230   if(_oggpack_read(opb,1)!=1)goto err_out; /* EOP check */
231
232   return(0);
233  err_out:
234   vorbis_info_clear(vi);
235   return(-1);
236 }
237
238 /* all of the real encoding details are here.  The modes, books,
239    everything */
240 static int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb){
241   int i;
242
243   /* time backend settings */
244   vi->times=_oggpack_read(opb,8);
245   vi->timetypes=malloc(vi->times*sizeof(int));
246   vi->timelist=calloc(vi->times,sizeof(void *));
247   for(i=0;i<vi->times;i++){
248     vi->timetypes[i]=_oggpack_read(opb,16);
249     if(vi->timetypes[i]<0 || vi->timetypes[i]>VI_TIMEB)goto err_out;
250     vi->timelist[i]=vorbis_time_unpack_P[vi->timetypes[i]](vi,opb);
251     if(!vi->timelist[i])goto err_out;
252   }
253
254   /* floor backend settings */
255   vi->floors=_oggpack_read(opb,8);
256   vi->floortypes=malloc(vi->floors*sizeof(int));
257   vi->floorlist=calloc(vi->floors,sizeof(void *));
258   for(i=0;i<vi->floors;i++){
259     vi->floortypes[i]=_oggpack_read(opb,16);
260     if(vi->floortypes[i]<0 || vi->floortypes[i]>VI_FLOORB)goto err_out;
261     vi->floorlist[i]=vorbis_floor_unpack_P[vi->floortypes[i]](vi,opb);
262     if(!vi->floorlist[i])goto err_out;
263   }
264
265   /* residue backend settings */
266   vi->residues=_oggpack_read(opb,8);
267   vi->residuetypes=malloc(vi->residues*sizeof(int));
268   vi->residuelist=calloc(vi->residues,sizeof(void *));
269   for(i=0;i<vi->residues;i++){
270     vi->residuetypes[i]=_oggpack_read(opb,16);
271     if(vi->residuetypes[i]<0 || vi->residuetypes[i]>VI_RESB)goto err_out;
272     vi->residuelist[i]=vorbis_res_unpack_P[vi->residuetypes[i]](vi,opb);
273     if(!vi->residuelist[i])goto err_out;
274   }
275
276   /* codebooks */
277   vi->books=_oggpack_read(opb,16);
278   vi->booklist=calloc(vi->books,sizeof(codebook *));
279   for(i=0;i<vi->books;i++){
280     vi->booklist[i]=calloc(1,sizeof(codebook));
281     if(vorbis_book_unpack(opb,vi->booklist[i]))goto err_out;
282   }
283
284   /* modes/mappings; these are loaded last in order that the mappings
285      can range-check their time/floor/res/book settings */
286   vi->modes=_oggpack_read(opb,8);
287   vi->blockflags=malloc(vi->modes*sizeof(int));
288   vi->windowtypes=malloc(vi->modes*sizeof(int));
289   vi->transformtypes=malloc(vi->modes*sizeof(int));
290   vi->mappingtypes=malloc(vi->modes*sizeof(int));
291   vi->modelist=calloc(vi->modes,sizeof(void *));
292   for(i=0;i<vi->modes;i++){
293     vi->blockflags[i]=_oggpack_read(opb,1);
294     vi->windowtypes[i]=_oggpack_read(opb,16);
295     vi->transformtypes[i]=_oggpack_read(opb,16);
296     vi->mappingtypes[i]=_oggpack_read(opb,16);
297     if(vi->windowtypes[i]<0 || vi->windowtypes[i]>VI_WINDOWB)goto err_out;
298     if(vi->transformtypes[i]<0 || vi->transformtypes[i]>VI_TRANSFORMB)goto err_out;
299     if(vi->mappingtypes[i]<0 || vi->mappingtypes[i]>VI_MAPB)goto err_out;
300     vi->modelist[i]=vorbis_map_unpack_P[vi->mappingtypes[i]](vi,opb);
301     if(!vi->modelist[i])goto err_out;
302   }
303
304   if(_oggpack_read(opb,1)!=1)goto err_out; /* top level EOP check */
305
306   return(0);
307 err_out:
308   vorbis_info_clear(vi);
309   return(-1);
310 }
311
312 /* The Vorbis header is in three packets; the initial small packet in
313    the first page that identifies basic parameters, a second packet
314    with bitstream comments and a third packet that holds the
315    codebook. */
316
317 int vorbis_info_headerin(vorbis_info *vi,ogg_packet *op){
318
319   oggpack_buffer opb;
320   
321   if(op){
322     _oggpack_readinit(&opb,op->packet,op->bytes);
323
324     /* Which of the three types of header is this? */
325     /* Also verify header-ness, vorbis */
326     {
327       char buffer[6];
328       memset(buffer,0,6);
329       _v_readstring(&opb,buffer,6);
330       if(memcmp(buffer,"vorbis",6)){
331         /* not a vorbis header */
332         return(-1);
333       }
334       switch(_oggpack_read(&opb,8)){
335       case 0x80:
336         if(!op->b_o_s){
337           /* Not the initial packet */
338           return(-1);
339         }
340         if(vi->rate!=0){
341           /* previously initialized info header */
342           return(-1);
343         }
344
345         return(_vorbis_unpack_info(vi,&opb));
346
347       case 0x81:
348         if(vi->rate==0){
349           /* um... we didn't get the initial header */
350           return(-1);
351         }
352
353         return(_vorbis_unpack_comments(vi,&opb));
354
355       case 0x82:
356         if(vi->rate==0 || vi->vendor==NULL){
357           /* um... we didn;t get the initial header or comments yet */
358           return(-1);
359         }
360
361         return(_vorbis_unpack_books(vi,&opb));
362
363       default:
364         /* Not a valid vorbis header type */
365         return(-1);
366         break;
367       }
368     }
369   }
370   return(-1);
371 }
372
373 /* pack side **********************************************************/
374
375 static int _vorbis_pack_info(oggpack_buffer *opb,vorbis_info *vi){
376   /* preamble */  
377   _v_writestring(opb,"vorbis");
378   _oggpack_write(opb,0x80,8);
379
380   /* basic information about the stream */
381   _oggpack_write(opb,0x00,32);
382   _oggpack_write(opb,vi->channels,8);
383   _oggpack_write(opb,vi->rate,32);
384
385   _oggpack_write(opb,vi->bitrate_upper,32);
386   _oggpack_write(opb,vi->bitrate_nominal,32);
387   _oggpack_write(opb,vi->bitrate_lower,32);
388
389   _oggpack_write(opb,ilog2(vi->blocksizes[0]),4);
390   _oggpack_write(opb,ilog2(vi->blocksizes[1]),4);
391   _oggpack_write(opb,1,1);
392
393   return(0);
394 }
395
396 static int _vorbis_pack_comments(oggpack_buffer *opb,vorbis_info *vi){
397   char temp[]="Xiphophorus libVorbis I 20000114";
398
399   /* preamble */  
400   _v_writestring(opb,"vorbis");
401   _oggpack_write(opb,0x81,8);
402
403   /* vendor */
404   _oggpack_write(opb,strlen(temp),32);
405   _v_writestring(opb,temp);
406   
407   /* comments */
408
409   _oggpack_write(opb,vi->comments,32);
410   if(vi->comments){
411     int i;
412     for(i=0;i<vi->comments;i++){
413       if(vi->user_comments[i]){
414         _oggpack_write(opb,strlen(vi->user_comments[i]),32);
415         _v_writestring(opb,vi->user_comments[i]);
416       }else{
417         _oggpack_write(opb,0,32);
418       }
419     }
420   }
421   _oggpack_write(opb,1,1);
422
423   return(0);
424 }
425  
426 static int _vorbis_pack_books(oggpack_buffer *opb,vorbis_info *vi){
427   int i;
428   _v_writestring(opb,"vorbis");
429   _oggpack_write(opb,0x82,8);
430
431   /* times */
432   _oggpack_write(opb,vi->times,8);
433   for(i=0;i<vi->times;i++){
434     _oggpack_write(opb,vi->timetypes[i],16);
435     vorbis_time_pack_P[vi->timetypes[i]](opb,vi->timelist[i]);
436   }
437
438   /* floors */
439   _oggpack_write(opb,vi->floors,8);
440   for(i=0;i<vi->floors;i++){
441     _oggpack_write(opb,vi->floortypes[i],16);
442     vorbis_floor_pack_P[vi->floortypes[i]](opb,vi->floorlist[i]);
443   }
444
445   /* residues */
446   _oggpack_write(opb,vi->residues,8);
447   for(i=0;i<vi->residues;i++){
448     _oggpack_write(opb,vi->residuetypes[i],16);
449     vorbis_res_pack_P[vi->residuetypes[i]](opb,vi->residuelist[i]);
450   }
451
452   /* books */
453   _oggpack_write(opb,vi->books,16);
454   for(i=0;i<vi->books;i++)
455     if(vorbis_book_pack(vi->booklist[i],opb))goto err_out;
456
457   /* mode mappings */
458
459   _oggpack_write(opb,vi->modes,8);
460   for(i=0;i<vi->modes;i++){
461     _oggpack_write(opb,vi->blockflags[i],1);
462     _oggpack_write(opb,vi->windowtypes[i],16);
463     _oggpack_write(opb,vi->transformtypes[i],16);
464     _oggpack_write(opb,vi->mappingtypes[i],16);
465     vorbis_map_pack_P[vi->mappingtypes[i]](vi,opb,vi->modelist[i]);
466   }
467
468   _oggpack_write(opb,1,1);
469
470   return(0);
471 err_out:
472   return(-1);
473
474
475 int vorbis_analysis_headerout(vorbis_dsp_state *v,
476                               ogg_packet *op,
477                               ogg_packet *op_comm,
478                               ogg_packet *op_code){
479   vorbis_info *vi=v->vi;
480   oggpack_buffer opb;
481
482   /* first header packet **********************************************/
483
484   _oggpack_writeinit(&opb);
485   if(_vorbis_pack_info(&opb,vi))goto err_out;
486
487   /* build the packet */
488   if(v->header)free(v->header);
489   v->header=malloc(_oggpack_bytes(&opb));
490   memcpy(v->header,opb.buffer,_oggpack_bytes(&opb));
491   op->packet=v->header;
492   op->bytes=_oggpack_bytes(&opb);
493   op->b_o_s=1;
494   op->e_o_s=0;
495   op->frameno=0;
496
497   /* second header packet (comments) **********************************/
498
499   _oggpack_reset(&opb);
500   _v_writestring(&opb,"vorbis");
501   _oggpack_write(&opb,0x81,8);
502   if(_vorbis_pack_comments(&opb,vi))goto err_out;
503
504   if(v->header1)free(v->header1);
505   v->header1=malloc(_oggpack_bytes(&opb));
506   memcpy(v->header1,opb.buffer,_oggpack_bytes(&opb));
507   op_comm->packet=v->header1;
508   op_comm->bytes=_oggpack_bytes(&opb);
509   op_comm->b_o_s=0;
510   op_comm->e_o_s=0;
511   op_comm->frameno=0;
512
513   /* third header packet (modes/codebooks) ****************************/
514
515   _oggpack_reset(&opb);
516   _v_writestring(&opb,"vorbis");
517   _oggpack_write(&opb,0x82,8);
518   if(_vorbis_pack_books(&opb,vi))goto err_out;
519
520   if(v->header2)free(v->header2);
521   v->header2=malloc(_oggpack_bytes(&opb));
522   memcpy(v->header2,opb.buffer,_oggpack_bytes(&opb));
523   op_code->packet=v->header2;
524   op_code->bytes=_oggpack_bytes(&opb);
525   op_code->b_o_s=0;
526   op_code->e_o_s=0;
527   op_code->frameno=0;
528
529   _oggpack_writeclear(&opb);
530   return(0);
531  err_out:
532   _oggpack_writeclear(&opb);
533   memset(op,0,sizeof(ogg_packet));
534   memset(op_comm,0,sizeof(ogg_packet));
535   memset(op_code,0,sizeof(ogg_packet));
536   return(-1);
537 }
538