1 /********************************************************************
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. *
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/ *
12 ********************************************************************
14 function: maintain the info structure, info <-> header packets
15 author: Monty <xiphmont@mit.edu>
16 modifications by: Monty
17 last modification date: Oct 22 1999
19 ********************************************************************/
21 /* This fills in a vorbis_info structure with settings from a few
22 pre-defined encoding modes. Also handles choosing/blowing in the
30 void vorbis_info_init(vorbis_info *vi){
31 memset(vi,0,sizeof(vorbis_info));
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);
38 /* handle the flat settings first */
39 memcpy(vi,&(predef_modes[mode]),sizeof(vorbis_info));
40 vi->threshhold_points=threshhold_points;
41 vi->user_comments=calloc(1,sizeof(char *));
42 vi->vendor=strdup("Xiphophorus libVorbis I 19991022");
47 /* convenience function */
48 int vorbis_info_addcomment(vorbis_info *vi,char *comment){
49 vi->user_comments=realloc(vi->user_comments,
50 (vi->comments+2)*sizeof(char *));
51 vi->user_comments[vi->comments]=strdup(comment);
53 vi->user_comments[vi->comments]=NULL;
57 static void _v_writestring(oggpack_buffer *o,char *s){
59 _oggpack_write(o,*s++,8);
63 static void _v_readstring(oggpack_buffer *o,char *buf,int bytes){
65 *buf++=_oggpack_read(o,8);
69 /* The Vorbis header is in three packets; the initial small packet in
70 the first page that identifies basic parameters, a second packet
71 with bitstream comments and a third packet that holds the
74 int vorbis_info_headerin(vorbis_info *vi,ogg_packet *op){
79 _oggpack_readinit(&opb,op->packet,op->bytes);
81 /* Which of the three types of header is this? */
82 /* Also verify header-ness, vorbis */
86 _v_readstring(&opb,buffer,6);
87 if(memcmp(buffer,"vorbis",6)){
88 /* not a vorbis header */
91 switch(_oggpack_read(&opb,8)){
94 /* Not the initial packet */
98 /* previously initialized info header */
102 if(_oggpack_read(&opb,32)!=0){
105 vi->channels=_oggpack_read(&opb,32);
106 vi->rate=_oggpack_read(&opb,32);
108 vi->blocksize[0]=_oggpack_read(&opb,32);
109 vi->blocksize[1]=_oggpack_read(&opb,32);
111 vi->floororder[0]=_oggpack_read(&opb,8);
112 vi->floororder[1]=_oggpack_read(&opb,8);
113 vi->flooroctaves[0]=_oggpack_read(&opb,8);
114 vi->flooroctaves[1]=_oggpack_read(&opb,8);
115 vi->floorch=_oggpack_read(&opb,16);
120 /* um... we didn;t get the initial header */
124 int vendorlen=_oggpack_read(&opb,32);
125 vi->vendor=calloc(vendorlen+1,1);
126 _v_readstring(&opb,vi->vendor,vendorlen);
130 vi->comments=_oggpack_read(&opb,32);
131 vi->user_comments=calloc(vi->comments+1,sizeof(char **));
133 for(i=0;i<vi->comments;i++){
134 int len=_oggpack_read(&opb,32);
135 vi->user_comments[i]=calloc(len+1,1);
136 _v_readstring(&opb,vi->user_comments[i],len);
143 /* um... we didn;t get the initial header */
147 /* not implemented quite yet */
151 /* Not a valid vorbis header type */
160 int vorbis_info_headerout(vorbis_info *vi,
163 ogg_packet *op_code){
169 header id 0x80 (byte)
170 codec ver (4 octets, lsb first: currently 0x00)
171 pcm channels (4 octets, lsb first)
172 pcm rate (4 octets, lsb first)
174 small block (4 octets, lsb first)
175 large block (4 octets, lsb first)
176 floor order for small block (octet)
177 floor order for large block (octet)
178 floor octaves for small block (octet)
179 floor octaves for large block (octet)
180 floorch (4 octets, lsb first)
183 _oggpack_writeinit(&opb);
184 _v_writestring(&opb,"vorbis");
185 _oggpack_write(&opb,0x80,8);
187 _oggpack_write(&opb,0x00,32);
189 _oggpack_write(&opb,vi->channels,32);
190 _oggpack_write(&opb,vi->rate,32);
191 _oggpack_write(&opb,vi->blocksize[0],32);
192 _oggpack_write(&opb,vi->blocksize[1],32);
193 _oggpack_write(&opb,vi->floororder[0],8);
194 _oggpack_write(&opb,vi->floororder[1],8);
195 _oggpack_write(&opb,vi->flooroctaves[0],8);
196 _oggpack_write(&opb,vi->flooroctaves[1],8);
197 _oggpack_write(&opb,vi->floorch,16);
199 /* build the packet */
200 if(vi->header)free(vi->header);
201 vi->header=malloc(_oggpack_bytes(&opb));
202 memcpy(vi->header,opb.buffer,_oggpack_bytes(&opb));
203 op->packet=vi->header;
204 op->bytes=_oggpack_bytes(&opb);
211 header id 0x81 (byte)
212 vendor len (4 octets, lsb first)
213 vendor and id (n octects as above)
214 comments (4 octets, lsb first)
215 comment 0 len (4 octets, lsb first)
216 comment 0 len (n octets as above)
218 comment n-1 len (4 octets, lsb first)
219 comment 0-1 len (n octets as above)
222 _oggpack_reset(&opb);
223 _v_writestring(&opb,"vorbis");
224 _oggpack_write(&opb,0x81,8);
227 _oggpack_write(&opb,strlen(vi->vendor),32);
228 _v_writestring(&opb,vi->vendor);
230 _oggpack_write(&opb,0,32);
233 _oggpack_write(&opb,vi->comments,32);
236 for(i=0;i<vi->comments;i++){
237 if(vi->user_comments[i]){
238 _oggpack_write(&opb,strlen(vi->user_comments[i]),32);
239 _v_writestring(&opb,vi->user_comments[i]);
241 _oggpack_write(&opb,0,32);
246 if(vi->header1)free(vi->header1);
247 vi->header1=malloc(_oggpack_bytes(&opb));
248 memcpy(vi->header1,opb.buffer,_oggpack_bytes(&opb));
249 op_comm->packet=vi->header1;
250 op_comm->bytes=_oggpack_bytes(&opb);
257 header id 0x82 (byte)
258 nul so far; not encoded yet */
260 _oggpack_reset(&opb);
261 _v_writestring(&opb,"vorbis");
262 _oggpack_write(&opb,0x82,8);
264 if(vi->header2)free(vi->header2);
265 vi->header2=malloc(_oggpack_bytes(&opb));
266 memcpy(vi->header2,opb.buffer,_oggpack_bytes(&opb));
267 op_code->packet=vi->header2;
268 op_code->bytes=_oggpack_bytes(&opb);
273 _oggpack_writeclear(&opb);
278 void vorbis_info_clear(vorbis_info *vi){
279 /* clear the non-flat storage before zeroing */
282 if(vi->user_comments){
283 char **ptr=vi->user_comments;
287 free(vi->user_comments);
291 if(vi->vendor)free(vi->vendor);
293 /* local encoding storage */
294 if(vi->header)free(vi->header);
295 if(vi->header1)free(vi->header1);
296 if(vi->header2)free(vi->header2);
298 memset(vi,0,sizeof(vorbis_info));