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