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.15 2000/01/19 08:57: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
28 /* these modules were split out only to make this file more readable.
29    I don't want to expose the symbols */
30 #include "infomap.c"
31
32 /* helpers */
33
34 static int ilog2(unsigned int v){
35   int ret=0;
36   while(v>1){
37     ret++;
38     v>>=1;
39   }
40   return(ret);
41 }
42
43 static void _v_writestring(oggpack_buffer *o,char *s){
44   while(*s){
45     _oggpack_write(o,*s++,8);
46   }
47 }
48
49 static void _v_readstring(oggpack_buffer *o,char *buf,int bytes){
50   while(bytes--){
51     *buf++=_oggpack_read(o,8);
52   }
53 }
54
55 /* convenience functions for the interface */
56 int vorbis_info_addcomment(vorbis_info *vi,char *comment){
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 int vorbis_info_addvendor(vorbis_info *vi,char *vendor){
66   if(vi->vendor)free(vi->vendor);
67   vi->vendor=strdup(vendor);
68   return(0);
69 }
70   
71 /* libVorbis expects modes to be submitted in an already valid
72    vorbis_info structure, but also expects some of the elements to be
73    allocated storage.  To make this easier, the Vorbis distribution
74    includes a number of modes in static storage as headers.  To
75    allocate a copy, run it through vorbis_info_dup */
76
77 /* note that due to codebook size, codebooks are not fully duplicated.
78    The info structure (aside from the embedded codebook elements) will
79    be fully dupped */
80
81 int vorbis_info_dup(vorbis_info *dest,vorbis_info *source){
82   int i;
83   memcpy(dest,source,sizeof(vorbis_info));
84
85   /* also dup individual pieces that need to be allocated */
86   /* dup user comments (unlikely to have any, but for completeness */
87   if(source->comments>0){
88     dest->user_comments=calloc(source->comments+1,sizeof(char *));
89     for(i=0;i<source->comments;i++)
90       dest->user_comments[i]=strdup(source->user_comments[i]);
91   }
92   /* dup vendor */
93   if(source->vendor)
94     dest->vendor=strdup(source->vendor);
95
96   /* dup mode maps, blockflags and map types */
97   if(source->modes){
98     dest->blockflags=malloc(source->modes*sizeof(int));
99     dest->maptypes=malloc(source->modes*sizeof(int));
100     dest->maplist=calloc(source->modes,sizeof(void *));
101
102     memcpy(dest->blockflags,source->blockflags,sizeof(int)*dest->modes);
103     memcpy(dest->maptypes,source->maptypes,sizeof(int)*dest->modes);
104     for(i=0;i<source->modes;i++){
105       void *dup;
106       if(dest->maptypes[i]<0|| dest->maptypes[i]>=VI_MAPB)goto err_out;
107       if(!(dup=vorbis_map_dup_P[dest->maptypes[i]](source->maplist[i])))
108         goto err_out; 
109       dest->maplist[i]=dup;
110     }
111   }
112
113   /* dup (partially) books */
114   if(source->books){
115     dest->booklist=malloc(source->books*sizeof(codebook *));
116     for(i=0;i<source->books;i++){
117       dest->booklist[i]=calloc(1,sizeof(codebook));
118       vorbis_book_dup(dest->booklist[i],source->booklist[i]);
119     }
120   }
121   /* we do *not* dup local storage */
122   dest->header=NULL;
123   dest->header1=NULL;
124   dest->header2=NULL;
125   
126   return(0);
127 err_out:
128   vorbis_info_clear(dest);
129   return(-1);
130 }
131
132 void vorbis_info_clear(vorbis_info *vi){
133   int i;
134   if(vi->comments){
135     for(i=0;i<vi->comments;i++)
136       if(vi->user_comments[i])free(vi->user_comments[i]);
137     free(vi->user_comments);
138   }
139   if(vi->vendor)free(vi->vendor);
140   if(vi->modes){
141     for(i=0;i<vi->modes;i++)
142       if(vi->maptypes[i]>=0 && vi->maptypes[i]<VI_MAPB)
143         vorbis_map_free_P[vi->maptypes[i]](vi->maplist[i]);
144     free(vi->maplist);
145     free(vi->maptypes);
146     free(vi->blockflags);
147   }
148   if(vi->books){
149     for(i=0;i<vi->books;i++){
150       if(vi->booklist[i]){
151         vorbis_book_clear(vi->booklist[i]);
152         free(vi->booklist[i]);
153       }
154     }
155     free(vi->booklist);
156   }
157   
158   if(vi->header)free(vi->header);
159   if(vi->header1)free(vi->header1);
160   if(vi->header2)free(vi->header2);
161
162   memset(vi,0,sizeof(vorbis_info));
163 }
164
165 /* Header packing/unpacking ********************************************/
166
167 static int _vorbis_unpack_info(vorbis_info *vi,oggpack_buffer *opb){
168   vi->version=_oggpack_read(opb,32);
169   if(vi->version!=0)return(-1);
170
171   vi->channels=_oggpack_read(opb,8);
172   vi->rate=_oggpack_read(opb,32);
173
174   vi->bitrate_upper=_oggpack_read(opb,32);
175   vi->bitrate_nominal=_oggpack_read(opb,32);
176   vi->bitrate_lower=_oggpack_read(opb,32);
177
178   vi->blocksizes[0]=1<<_oggpack_read(opb,4);
179   vi->blocksizes[1]=1<<_oggpack_read(opb,4);
180   
181   if(vi->rate<1)goto err_out;
182   if(vi->channels<1)goto err_out;
183   if(vi->blocksizes[0]<8)goto err_out; 
184   if(vi->blocksizes[1]<vi->blocksizes[0])
185     goto err_out; /* doubles as EOF check */
186
187   return(0);
188  err_out:
189   vorbis_info_clear(vi);
190   return(-1);
191 }
192
193 static int _vorbis_unpack_comments(vorbis_info *vi,oggpack_buffer *opb){
194   int i;
195   int vendorlen=_oggpack_read(opb,32);
196   if(vendorlen<0)goto err_out;
197   vi->vendor=calloc(vendorlen+1,1);
198   _v_readstring(opb,vi->vendor,vendorlen);
199   vi->comments=_oggpack_read(opb,32);
200   if(vi->comments<0)goto err_out;
201   vi->user_comments=calloc(vi->comments+1,sizeof(char **));
202             
203   for(i=0;i<vi->comments;i++){
204     int len=_oggpack_read(opb,32);
205     if(len<0)goto err_out;
206     vi->user_comments[i]=calloc(len+1,1);
207     _v_readstring(opb,vi->user_comments[i],len);
208   }       
209   return(0);
210  err_out:
211   vorbis_info_clear(vi);
212   return(-1);
213 }
214
215 /* all of the real encoding details are here.  The modes, books,
216    everything */
217 static int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb){
218   int i;
219
220   vi->modes=_oggpack_read(opb,16);
221   vi->blockflags=malloc(vi->modes*sizeof(int));
222   vi->maptypes=malloc(vi->modes*sizeof(int));
223   vi->maplist=calloc(vi->modes,sizeof(void *));
224
225   for(i=0;i<vi->modes;i++){
226     vi->blockflags[i]=_oggpack_read(opb,1);
227     vi->maptypes[i]=_oggpack_read(opb,8);
228     if(vi->maptypes[i]<0 || vi->maptypes[i]>VI_MAPB)goto err_out;
229     vi->maplist[i]=vorbis_map_unpack_P[vi->maptypes[i]](opb);
230     if(!vi->maplist[i])goto err_out;
231   }
232
233   vi->books=_oggpack_read(opb,16);
234   vi->booklist=calloc(vi->books,sizeof(codebook *));
235   for(i=0;i<vi->books;i++){
236     vi->booklist[i]=calloc(1,sizeof(codebook));
237     if(vorbis_book_unpack(opb,vi->booklist[i]))goto err_out;
238   }
239   return(0);
240 err_out:
241   vorbis_info_clear(vi);
242   return(-1);
243 }
244
245 /* The Vorbis header is in three packets; the initial small packet in
246    the first page that identifies basic parameters, a second packet
247    with bitstream comments and a third packet that holds the
248    codebook. */
249
250 /* call before header in, or just to zero out uninitialized mem */
251 void vorbis_info_init(vorbis_info *vi){
252   memset(vi,0,sizeof(vorbis_info));
253 }
254
255 int vorbis_info_headerin(vorbis_info *vi,ogg_packet *op){
256
257   oggpack_buffer opb;
258   
259   if(op){
260     _oggpack_readinit(&opb,op->packet,op->bytes);
261
262     /* Which of the three types of header is this? */
263     /* Also verify header-ness, vorbis */
264     {
265       char buffer[6];
266       memset(buffer,0,6);
267       _v_readstring(&opb,buffer,6);
268       if(memcmp(buffer,"vorbis",6)){
269         /* not a vorbis header */
270         return(-1);
271       }
272       switch(_oggpack_read(&opb,8)){
273       case 0x80:
274         if(!op->b_o_s){
275           /* Not the initial packet */
276           return(-1);
277         }
278         if(vi->rate!=0){
279           /* previously initialized info header */
280           return(-1);
281         }
282
283         return(_vorbis_unpack_info(vi,&opb));
284
285       case 0x81:
286         if(vi->rate==0){
287           /* um... we didn't get the initial header */
288           return(-1);
289         }
290
291         return(_vorbis_unpack_comments(vi,&opb));
292
293       case 0x82:
294         if(vi->rate==0 || vi->vendor==NULL){
295           /* um... we didn;t get the initial header or comments yet */
296           return(-1);
297         }
298
299         return(_vorbis_unpack_books(vi,&opb));
300
301       default:
302         /* Not a valid vorbis header type */
303         return(-1);
304         break;
305       }
306     }
307   }
308   return(-1);
309 }
310
311 /* pack side **********************************************************/
312
313 static int _vorbis_pack_info(oggpack_buffer *opb,vorbis_info *vi){
314   /* preamble */  
315   _v_writestring(opb,"vorbis");
316   _oggpack_write(opb,0x80,8);
317
318   /* basic information about the stream */
319   _oggpack_write(opb,0x00,32);
320   _oggpack_write(opb,vi->channels,8);
321   _oggpack_write(opb,vi->rate,32);
322
323   _oggpack_write(opb,vi->bitrate_upper,32);
324   _oggpack_write(opb,vi->bitrate_nominal,32);
325   _oggpack_write(opb,vi->bitrate_lower,32);
326
327   _oggpack_write(opb,ilog2(vi->blocksizes[0]),4);
328   _oggpack_write(opb,ilog2(vi->blocksizes[1]),4);
329   
330   return(0);
331 }
332
333 static int _vorbis_pack_comments(oggpack_buffer *opb,vorbis_info *vi){
334   char temp[]="Xiphophorus libVorbis I 20000114";
335
336   /* preamble */  
337   _v_writestring(opb,"vorbis");
338   _oggpack_write(opb,0x81,8);
339
340   /* vendor */
341   _oggpack_write(opb,strlen(temp),32);
342   _v_writestring(opb,temp);
343   
344   /* comments */
345
346   _oggpack_write(opb,vi->comments,32);
347   if(vi->comments){
348     int i;
349     for(i=0;i<vi->comments;i++){
350       if(vi->user_comments[i]){
351         _oggpack_write(opb,strlen(vi->user_comments[i]),32);
352         _v_writestring(opb,vi->user_comments[i]);
353       }else{
354         _oggpack_write(opb,0,32);
355       }
356     }
357   }
358
359   return(0);
360 }
361  
362 static int _vorbis_pack_books(oggpack_buffer *opb,vorbis_info *vi){
363   int i;
364   _v_writestring(opb,"vorbis");
365   _oggpack_write(opb,0x82,8);
366
367   _oggpack_write(opb,vi->modes,16);
368   for(i=0;i<vi->modes;i++){
369     _oggpack_write(opb,vi->blockflags[i],1);
370     _oggpack_write(opb,vi->maptypes[i],8);
371     if(vi->maptypes[i]<0 || vi->maptypes[i]>VI_MAPB)goto err_out;
372     vorbis_map_pack_P[vi->maptypes[i]](opb,vi->maplist[i]);
373   }
374
375   _oggpack_write(opb,vi->books,16);
376   for(i=0;i<vi->books;i++)
377     if(vorbis_book_pack(vi->booklist[i],opb))goto err_out;
378   return(0);
379 err_out:
380   return(-1);
381
382
383 int vorbis_info_headerout(vorbis_info *vi,
384                           ogg_packet *op,
385                           ogg_packet *op_comm,
386                           ogg_packet *op_code){
387
388   oggpack_buffer opb;
389
390   /* first header packet **********************************************/
391
392   _oggpack_writeinit(&opb);
393   if(_vorbis_pack_info(&opb,vi))goto err_out;
394
395   /* build the packet */
396   if(vi->header)free(vi->header);
397   vi->header=malloc(_oggpack_bytes(&opb));
398   memcpy(vi->header,opb.buffer,_oggpack_bytes(&opb));
399   op->packet=vi->header;
400   op->bytes=_oggpack_bytes(&opb);
401   op->b_o_s=1;
402   op->e_o_s=0;
403   op->frameno=0;
404
405   /* second header packet (comments) **********************************/
406
407   _oggpack_reset(&opb);
408   _v_writestring(&opb,"vorbis");
409   _oggpack_write(&opb,0x81,8);
410   if(_vorbis_pack_comments(&opb,vi))goto err_out;
411
412   if(vi->header1)free(vi->header1);
413   vi->header1=malloc(_oggpack_bytes(&opb));
414   memcpy(vi->header1,opb.buffer,_oggpack_bytes(&opb));
415   op_comm->packet=vi->header1;
416   op_comm->bytes=_oggpack_bytes(&opb);
417   op_comm->b_o_s=0;
418   op_comm->e_o_s=0;
419   op_comm->frameno=0;
420
421   /* third header packet (modes/codebooks) ****************************/
422
423   _oggpack_reset(&opb);
424   _v_writestring(&opb,"vorbis");
425   _oggpack_write(&opb,0x82,8);
426   if(_vorbis_pack_books(&opb,vi))goto err_out;
427
428   if(vi->header2)free(vi->header2);
429   vi->header2=malloc(_oggpack_bytes(&opb));
430   memcpy(vi->header2,opb.buffer,_oggpack_bytes(&opb));
431   op_code->packet=vi->header2;
432   op_code->bytes=_oggpack_bytes(&opb);
433   op_code->b_o_s=0;
434   op_code->e_o_s=0;
435   op_code->frameno=0;
436
437   _oggpack_writeclear(&opb);
438   return(0);
439  err_out:
440   _oggpack_writeclear(&opb);
441   memset(op,0,sizeof(ogg_packet));
442   memset(op_comm,0,sizeof(ogg_packet));
443   memset(op_code,0,sizeof(ogg_packet));
444   return(-1);
445 }
446