Added Makefile.in to vq/
[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-1999             *
9  * by 1999 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  author: Monty <xiphmont@mit.edu>
16  modifications by: Monty
17  last modification date: Nov 04 1999
18
19  ********************************************************************/
20
21 /* This fills in a vorbis_info structure with settings from a few
22    pre-defined encoding modes.  Also handles choosing/blowing in the
23    codebook */
24
25 #include <stdlib.h>
26 #include <string.h>
27 #include "modes.h"
28 #include "bitwise.h"
29
30 static int ilog2(unsigned int v){
31   int ret=0;
32   while(v>1){
33     ret++;
34     v>>=1;
35   }
36   return(ret);
37 }
38   
39 void vorbis_info_init(vorbis_info *vi){
40   memset(vi,0,sizeof(vorbis_info));
41 }
42
43 /* one test mode for now; temporary of course */
44 int vorbis_info_modeset(vorbis_info *vi, int mode){
45   if(mode<0 || mode>predef_mode_max)return(-1);
46
47   /* handle the flat settings first */
48   memcpy(vi,&(predef_modes[mode]),sizeof(vorbis_info));
49   vi->threshhold_points=threshhold_points;
50   vi->user_comments=calloc(1,sizeof(char *));
51   vi->vendor=strdup("Xiphophorus libVorbis I 19991104");
52
53   return(0);
54 }
55
56 /* convenience function */
57 int vorbis_info_addcomment(vorbis_info *vi,char *comment){
58   vi->user_comments=realloc(vi->user_comments,
59                             (vi->comments+2)*sizeof(char *));
60   vi->user_comments[vi->comments]=strdup(comment);
61   vi->comments++;
62   vi->user_comments[vi->comments]=NULL;
63   return(0);
64 }
65
66 static void _v_writestring(oggpack_buffer *o,char *s){
67   while(*s){
68     _oggpack_write(o,*s++,8);
69   }
70 }
71
72 static void _v_readstring(oggpack_buffer *o,char *buf,int bytes){
73   while(bytes--){
74     *buf++=_oggpack_read(o,8);
75   }
76 }
77
78 /* The Vorbis header is in three packets; the initial small packet in
79    the first page that identifies basic parameters, a second packet
80    with bitstream comments and a third packet that holds the
81    codebook. */
82
83 int vorbis_info_headerin(vorbis_info *vi,ogg_packet *op){
84
85   oggpack_buffer opb;
86   
87   if(op){
88     _oggpack_readinit(&opb,op->packet,op->bytes);
89
90     /* Which of the three types of header is this? */
91     /* Also verify header-ness, vorbis */
92     {
93       char buffer[6];
94       memset(buffer,0,6);
95       _v_readstring(&opb,buffer,6);
96       if(memcmp(buffer,"vorbis",6)){
97         /* not a vorbis header */
98         return(-1);
99       }
100       switch(_oggpack_read(&opb,8)){
101       case 0x80:
102         if(!op->b_o_s){
103           /* Not the initial packet */
104           return(-1);
105         }
106         if(vi->rate!=0){
107           /* previously initialized info header */
108           return(-1);
109         }
110
111         if(_oggpack_read(&opb,32)!=0){
112           return(-1);
113         }
114         vi->channels=_oggpack_read(&opb,8);
115         vi->rate=_oggpack_read(&opb,32);
116
117         vi->bitrate_upper=_oggpack_read(&opb,32);
118         vi->bitrate_nominal=_oggpack_read(&opb,32);
119         vi->bitrate_lower=_oggpack_read(&opb,32);
120
121         vi->blocksize[0]=1<<_oggpack_read(&opb,4);
122         vi->blocksize[1]=1<<_oggpack_read(&opb,4);
123
124         vi->floororder[0]=_oggpack_read(&opb,8);
125         vi->floororder[1]=_oggpack_read(&opb,8);
126         vi->flooroctaves[0]=_oggpack_read(&opb,8);
127         vi->flooroctaves[1]=_oggpack_read(&opb,8);
128         vi->floorch=_oggpack_read(&opb,8);
129
130         if(vi->rate<1)return(-1);
131         if(vi->floorch<1 || vi->floorch>vi->channels)return(-1);
132
133         return(0);
134       case 0x81:
135         if(vi->rate==0){
136           /* um... we didn;t get the initial header */
137           return(-1);
138         }
139         {
140           int vendorlen=_oggpack_read(&opb,32);
141           vi->vendor=calloc(vendorlen+1,1);
142           _v_readstring(&opb,vi->vendor,vendorlen);
143         }
144         {
145           int i;
146           vi->comments=_oggpack_read(&opb,32);
147           vi->user_comments=calloc(vi->comments+1,sizeof(char **));
148             
149           for(i=0;i<vi->comments;i++){
150             int len=_oggpack_read(&opb,32);
151             vi->user_comments[i]=calloc(len+1,1);
152             _v_readstring(&opb,vi->user_comments[i],len);
153           }       
154         }
155
156         return(0);
157       case 0x82:
158         if(vi->rate==0){
159           /* um... we didn;t get the initial header */
160           return(-1);
161         }
162
163         /* not implemented quite yet */
164
165         return(0);
166       default:
167         /* Not a valid vorbis header type */
168         return(-1);
169         break;
170       }
171     }
172   }
173   return(-1);
174 }
175
176 int vorbis_info_headerout(vorbis_info *vi,
177                           ogg_packet *op,
178                           ogg_packet *op_comm,
179                           ogg_packet *op_code){
180
181   oggpack_buffer opb;
182   /* initial header:
183
184      codec id     "vorbis"
185      header id    0x80 (byte)
186      codec ver    (4 octets, lsb first: currently 0x00)
187      pcm channels (4 octets, lsb first)
188      pcm rate     (4 octets, lsb first)
189      
190      small block  (4 octets, lsb first)
191      large block  (4 octets, lsb first)
192      floor order for small block (octet)
193      floor order for large block (octet)
194      floor octaves for small block (octet)
195      floor octaves for large block (octet)
196      floorch      (4 octets, lsb first)
197    */
198
199   _oggpack_writeinit(&opb);
200   _v_writestring(&opb,"vorbis");
201   _oggpack_write(&opb,0x80,8);
202
203   _oggpack_write(&opb,0x00,32);
204
205   _oggpack_write(&opb,vi->channels,8);
206   _oggpack_write(&opb,vi->rate,32);
207
208   _oggpack_write(&opb,vi->bitrate_upper,32);
209   _oggpack_write(&opb,vi->bitrate_nominal,32);
210   _oggpack_write(&opb,vi->bitrate_lower,32);
211
212   _oggpack_write(&opb,ilog2(vi->blocksize[0]),4);
213   _oggpack_write(&opb,ilog2(vi->blocksize[1]),4);
214   _oggpack_write(&opb,vi->floororder[0],8);
215   _oggpack_write(&opb,vi->floororder[1],8);
216   _oggpack_write(&opb,vi->flooroctaves[0],8);
217   _oggpack_write(&opb,vi->flooroctaves[1],8);
218   _oggpack_write(&opb,vi->floorch,8);
219
220   /* build the packet */
221   if(vi->header)free(vi->header);
222   vi->header=malloc(_oggpack_bytes(&opb));
223   memcpy(vi->header,opb.buffer,_oggpack_bytes(&opb));
224   op->packet=vi->header;
225   op->bytes=_oggpack_bytes(&opb);
226   op->b_o_s=1;
227   op->e_o_s=0;
228   op->frameno=0;
229
230   /* comment header:
231      codec id       "vorbis"
232      header id      0x81 (byte)
233      vendor len     (4 octets, lsb first)
234      vendor and id  (n octects as above)
235      comments       (4 octets, lsb first)
236      comment 0 len  (4 octets, lsb first)
237      comment 0 len  (n octets as above)
238      ...
239      comment n-1 len  (4 octets, lsb first)
240      comment 0-1 len  (n octets as above)
241   */
242
243   _oggpack_reset(&opb);
244   _v_writestring(&opb,"vorbis");
245   _oggpack_write(&opb,0x81,8);
246
247   if(vi->vendor){
248     _oggpack_write(&opb,strlen(vi->vendor),32);
249     _v_writestring(&opb,vi->vendor);
250   }else{
251     _oggpack_write(&opb,0,32);
252   }
253   
254   _oggpack_write(&opb,vi->comments,32);
255   if(vi->comments){
256     int i;
257     for(i=0;i<vi->comments;i++){
258       if(vi->user_comments[i]){
259         _oggpack_write(&opb,strlen(vi->user_comments[i]),32);
260         _v_writestring(&opb,vi->user_comments[i]);
261       }else{
262         _oggpack_write(&opb,0,32);
263       }
264     }
265   }
266   
267   if(vi->header1)free(vi->header1);
268   vi->header1=malloc(_oggpack_bytes(&opb));
269   memcpy(vi->header1,opb.buffer,_oggpack_bytes(&opb));
270   op_comm->packet=vi->header1;
271   op_comm->bytes=_oggpack_bytes(&opb);
272   op_comm->b_o_s=0;
273   op_comm->e_o_s=0;
274   op_comm->frameno=0;
275
276   /* codebook header:
277      codec id       "vorbis"
278      header id      0x82 (byte)
279      nul so far; not encoded yet */
280
281   _oggpack_reset(&opb);
282   _v_writestring(&opb,"vorbis");
283   _oggpack_write(&opb,0x82,8);
284
285   if(vi->header2)free(vi->header2);
286   vi->header2=malloc(_oggpack_bytes(&opb));
287   memcpy(vi->header2,opb.buffer,_oggpack_bytes(&opb));
288   op_code->packet=vi->header2;
289   op_code->bytes=_oggpack_bytes(&opb);
290   op_code->b_o_s=0;
291   op_code->e_o_s=0;
292   op_code->frameno=0;
293
294   _oggpack_writeclear(&opb);
295
296   return(0);
297 }
298
299 void vorbis_info_clear(vorbis_info *vi){
300   /* clear the non-flat storage before zeroing */
301
302   /* comments */
303   if(vi->user_comments){
304     char **ptr=vi->user_comments;
305     while(*ptr){
306       free(*(ptr++));
307     }
308     free(vi->user_comments);
309   }
310
311   /* vendor string */
312   if(vi->vendor)free(vi->vendor);
313
314   /* local encoding storage */
315   if(vi->header)free(vi->header);
316   if(vi->header1)free(vi->header1);
317   if(vi->header2)free(vi->header2);
318
319   memset(vi,0,sizeof(vorbis_info));
320 }
321   
322