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-2000 *
9 * by Monty <monty@xiph.org> and The XIPHOPHORUS Company *
10 * http://www.xiph.org/ *
12 ********************************************************************
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 $
17 ********************************************************************/
19 /* general handling of the header and the vorbis_info structure (and
24 #include "vorbis/codec.h"
26 #include "bookinternal.h"
28 /* these modules were split out only to make this file more readable.
29 I don't want to expose the symbols */
34 static int ilog2(unsigned int v){
43 static void _v_writestring(oggpack_buffer *o,char *s){
45 _oggpack_write(o,*s++,8);
49 static void _v_readstring(oggpack_buffer *o,char *buf,int bytes){
51 *buf++=_oggpack_read(o,8);
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);
61 vi->user_comments[vi->comments]=NULL;
65 int vorbis_info_addvendor(vorbis_info *vi,char *vendor){
66 if(vi->vendor)free(vi->vendor);
67 vi->vendor=strdup(vendor);
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 */
77 /* note that due to codebook size, codebooks are not fully duplicated.
78 The info structure (aside from the embedded codebook elements) will
81 int vorbis_info_dup(vorbis_info *dest,vorbis_info *source){
83 memcpy(dest,source,sizeof(vorbis_info));
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]);
94 dest->vendor=strdup(source->vendor);
96 /* dup mode maps, blockflags and map types */
98 dest->blockflags=malloc(source->modes*sizeof(int));
99 dest->maptypes=malloc(source->modes*sizeof(int));
100 dest->maplist=calloc(source->modes,sizeof(void *));
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++){
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])))
109 dest->maplist[i]=dup;
113 /* dup (partially) 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]);
121 /* we do *not* dup local storage */
128 vorbis_info_clear(dest);
132 void vorbis_info_clear(vorbis_info *vi){
135 for(i=0;i<vi->comments;i++)
136 if(vi->user_comments[i])free(vi->user_comments[i]);
137 free(vi->user_comments);
139 if(vi->vendor)free(vi->vendor);
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]);
146 free(vi->blockflags);
149 for(i=0;i<vi->books;i++){
151 vorbis_book_clear(vi->booklist[i]);
152 free(vi->booklist[i]);
158 if(vi->header)free(vi->header);
159 if(vi->header1)free(vi->header1);
160 if(vi->header2)free(vi->header2);
162 memset(vi,0,sizeof(vorbis_info));
165 /* Header packing/unpacking ********************************************/
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);
171 vi->channels=_oggpack_read(opb,8);
172 vi->rate=_oggpack_read(opb,32);
174 vi->bitrate_upper=_oggpack_read(opb,32);
175 vi->bitrate_nominal=_oggpack_read(opb,32);
176 vi->bitrate_lower=_oggpack_read(opb,32);
178 vi->blocksizes[0]=1<<_oggpack_read(opb,4);
179 vi->blocksizes[1]=1<<_oggpack_read(opb,4);
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 */
189 vorbis_info_clear(vi);
193 static int _vorbis_unpack_comments(vorbis_info *vi,oggpack_buffer *opb){
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 **));
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);
211 vorbis_info_clear(vi);
215 /* all of the real encoding details are here. The modes, books,
217 static int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb){
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 *));
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;
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;
241 vorbis_info_clear(vi);
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
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));
255 int vorbis_info_headerin(vorbis_info *vi,ogg_packet *op){
260 _oggpack_readinit(&opb,op->packet,op->bytes);
262 /* Which of the three types of header is this? */
263 /* Also verify header-ness, vorbis */
267 _v_readstring(&opb,buffer,6);
268 if(memcmp(buffer,"vorbis",6)){
269 /* not a vorbis header */
272 switch(_oggpack_read(&opb,8)){
275 /* Not the initial packet */
279 /* previously initialized info header */
283 return(_vorbis_unpack_info(vi,&opb));
287 /* um... we didn't get the initial header */
291 return(_vorbis_unpack_comments(vi,&opb));
294 if(vi->rate==0 || vi->vendor==NULL){
295 /* um... we didn;t get the initial header or comments yet */
299 return(_vorbis_unpack_books(vi,&opb));
302 /* Not a valid vorbis header type */
311 /* pack side **********************************************************/
313 static int _vorbis_pack_info(oggpack_buffer *opb,vorbis_info *vi){
315 _v_writestring(opb,"vorbis");
316 _oggpack_write(opb,0x80,8);
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);
323 _oggpack_write(opb,vi->bitrate_upper,32);
324 _oggpack_write(opb,vi->bitrate_nominal,32);
325 _oggpack_write(opb,vi->bitrate_lower,32);
327 _oggpack_write(opb,ilog2(vi->blocksizes[0]),4);
328 _oggpack_write(opb,ilog2(vi->blocksizes[1]),4);
333 static int _vorbis_pack_comments(oggpack_buffer *opb,vorbis_info *vi){
334 char temp[]="Xiphophorus libVorbis I 20000114";
337 _v_writestring(opb,"vorbis");
338 _oggpack_write(opb,0x81,8);
341 _oggpack_write(opb,strlen(temp),32);
342 _v_writestring(opb,temp);
346 _oggpack_write(opb,vi->comments,32);
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]);
354 _oggpack_write(opb,0,32);
362 static int _vorbis_pack_books(oggpack_buffer *opb,vorbis_info *vi){
364 _v_writestring(opb,"vorbis");
365 _oggpack_write(opb,0x82,8);
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]);
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;
383 int vorbis_info_headerout(vorbis_info *vi,
386 ogg_packet *op_code){
390 /* first header packet **********************************************/
392 _oggpack_writeinit(&opb);
393 if(_vorbis_pack_info(&opb,vi))goto err_out;
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);
405 /* second header packet (comments) **********************************/
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;
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);
421 /* third header packet (modes/codebooks) ****************************/
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;
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);
437 _oggpack_writeclear(&opb);
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));