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