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