Info struct needs initializer so that we know if we've not gotten the
authorMonty <xiphmont@xiph.org>
Mon, 4 Oct 1999 18:02:43 +0000 (18:02 +0000)
committerMonty <xiphmont@xiph.org>
Mon, 4 Oct 1999 18:02:43 +0000 (18:02 +0000)
initial header (*never* let a bad bitstream crash us!)

Monty

svn path=/trunk/vorbis/; revision=137

lib/codec.h
lib/info.c

index 8f8c622..82eb1ba 100644 (file)
@@ -80,7 +80,7 @@ typedef struct vorbis_info{
   int version;
 
   char **user_comments;
-  int    max_comment;
+  int    comments;
   char *vendor;
 
   int smallblock;
@@ -291,17 +291,18 @@ extern int    ogg_page_pageno(ogg_page *og);
 
 /* Vorbis PRIMITIVES: general ***************************************/
 
-extern int vorbis_info_clear(vorbis_info *vi); 
-extern int vorbis_info_modeset(vorbis_info *vi, int mode); 
-extern int vorbis_info_addcomment(vorbis_info *vi, char *comment); 
-extern int vorbis_info_headerin(vorbis_info *vi,ogg_packet *op);
-extern int vorbis_info_headerout(vorbis_info *vi,
-                                ogg_packet *op,
-                                ogg_packet *op_comm,
-                                ogg_packet *op_code);
-
-extern int vorbis_block_init(vorbis_dsp_state *v, vorbis_block *vb);
-extern int vorbis_block_clear(vorbis_block *vb);
+extern void vorbis_info_init(vorbis_info *vi); 
+extern int  vorbis_info_clear(vorbis_info *vi); 
+extern int  vorbis_info_modeset(vorbis_info *vi, int mode); 
+extern int  vorbis_info_addcomment(vorbis_info *vi, char *comment); 
+extern int  vorbis_info_headerin(vorbis_info *vi,ogg_packet *op);
+extern int  vorbis_info_headerout(vorbis_info *vi,
+                                 ogg_packet *op,
+                                 ogg_packet *op_comm,
+                                 ogg_packet *op_code);
+
+extern int  vorbis_block_init(vorbis_dsp_state *v, vorbis_block *vb);
+extern int  vorbis_block_clear(vorbis_block *vb);
 
 /* Vorbis PRIMITIVES: analysis/DSP layer ****************************/
 extern int      vorbis_analysis_init(vorbis_dsp_state *v,vorbis_info *vi);
index ee74ba2..e8b96bb 100644 (file)
@@ -14,7 +14,7 @@
  function: maintain the info structure, info <-> header packets
  author: Monty <xiphmont@mit.edu>
  modifications by: Monty
- last modification date: Oct 03 1999
+ last modification date: Oct 04 1999
 
  ********************************************************************/
 
 #include "modes.h"
 #include "bitwise.h"
 
+void vorbis_info_init(vorbis_info *vi){
+  memset(vi,0,sizeof(vorbis_info));
+}
+
 /* one test mode for now; temporary of course */
 int vorbis_info_modeset(vorbis_info *vi, int mode){
   if(mode<0 || mode>predef_mode_max)return(-1);
@@ -42,26 +46,23 @@ int vorbis_info_modeset(vorbis_info *vi, int mode){
 /* convenience function */
 int vorbis_info_add_comment(vorbis_info *vi,char *comment){
   vi->user_comments=realloc(vi->user_comments,
-                           (vi->max_comment+2)*sizeof(char *));
-  vi->user_comments[vi->max_comment]=strdup(comment);
-  vi->max_comment++;
-  vi->user_comments[vi->max_comment]=NULL;
+                           (vi->comments+1)*sizeof(char *));
+  vi->user_comments[vi->comments]=strdup(comment);
+  vi->comments++;
+  vi->user_comments[vi->comments]=NULL;
   return(0);
 }
 
-static int _v_writestring(oggpack_buffer *o,char *s){
+static void _v_writestring(oggpack_buffer *o,char *s){
   while(*s){
     _oggpack_write(o,*s++,8);
   }
 }
 
-static char *_v_readstring(oggpack_buffer *o,int bytes){
-  char *ret=calloc(bytes+1,1);
-  char *ptr=ret;
+static void _v_readstring(oggpack_buffer *o,char *buf,int bytes){
   while(bytes--){
-    *ptr++=_oggpack_read(o,8);
+    *buf++=_oggpack_read(o,8);
   }
-  return(ret);
 }
 
 /* The Vorbis header is in three packets; the initial small packet in
@@ -71,6 +72,84 @@ static char *_v_readstring(oggpack_buffer *o,int bytes){
 
 int vorbis_info_headerin(vorbis_info *vi,ogg_packet *op){
 
+  oggpack_buffer opb;
+  
+  if(op){
+    _oggpack_readinit(&opb,op->packet,op->bytes);
+
+    /* Which of the three types of header is this? */
+    /* Also verify header-ness, vorbis */
+    {
+      char buffer[6];
+      int type;
+      memset(buffer,0,6);
+      _v_readstring(&opb,buffer,6);
+      if(memcmp(buffer,"vorbis",6)){
+       /* not a vorbis header */
+       return(-1);
+      }
+      switch(_oggpack_read(&opb,8)){
+      case 0:
+       if(!op->b_o_s){
+         /* Not the initial packet */
+         return(-1);
+       }
+       if(vi->rate!=0){
+         /* previously initialized info header */
+         return(-1);
+       }
+
+       vi->channels=_oggpack_read(&opb,32);
+       vi->rate=_oggpack_read(&opb,32);
+       vi->smallblock=_oggpack_read(&opb,32);
+       vi->largeblock=_oggpack_read(&opb,32);
+       vi->envelopesa=_oggpack_read(&opb,32);
+       vi->envelopech=_oggpack_read(&opb,16);
+       vi->floororder=_oggpack_read(&opb,8);
+       vi->flooroctaves=_oggpack_read(&opb,8);
+       vi->floorch=_oggpack_read(&opb,16);
+
+       return(0);
+      case 1:
+       if(vi->rate==0){
+         /* um... we didn;t get the initial header */
+         return(-1);
+       }
+       {
+         int vendorlen=_oggpack_read(&opb,32);
+         vi->vendor=calloc(vendorlen+1,1);
+         _v_readstring(&opb,vi->vendor,vendorlen);
+       }
+       {
+         int i;
+         vi->comments=_oggpack_read(&opb,32);
+         vi->user_comments=calloc(vi->comments+1,sizeof(char **));
+           
+         for(i=0;i<=vi->comments;i++){
+           int len=_oggpack_read(&opb,32);
+           vi->user_comments[i]=calloc(len+1,1);
+           _v_readstring(&opb,vi->user_comments[i],len);
+         }       
+       }
+
+       return(0);
+      case 2:
+       if(vi->rate==0){
+         /* um... we didn;t get the initial header */
+         return(-1);
+       }
+
+       /* not implemented quite yet */
+
+       return(0);
+      default:
+       /* Not a valid vorbis header type */
+       return(-1);
+       break;
+      }
+    }
+  }
+  return(-1);
 }
 
 int vorbis_info_headerout(vorbis_info *vi,
@@ -82,6 +161,7 @@ int vorbis_info_headerout(vorbis_info *vi,
   /* initial header:
 
      codec id     "vorbis"
+     header id    0 (byte)
      codec ver    (4 octets, lsb first: currently 0x00)
      pcm channels (4 octets, lsb first)
      pcm rate     (4 octets, lsb first)
@@ -96,7 +176,9 @@ int vorbis_info_headerout(vorbis_info *vi,
    */
 
   _oggpack_writeinit(&opb);
-  _v_writestring(&obp,"vorbis");
+  _v_writestring(&opb,"vorbis");
+  _oggpack_write(&opb,0x00,8);
+
   _oggpack_write(&opb,0x00,32);
 
   _oggpack_write(&opb,vi->channels,32);
@@ -104,14 +186,14 @@ int vorbis_info_headerout(vorbis_info *vi,
   _oggpack_write(&opb,vi->smallblock,32);
   _oggpack_write(&opb,vi->largeblock,32);
   _oggpack_write(&opb,vi->envelopesa,32);
-  _oggpack_write(&opb,vi->envelopech,32);
+  _oggpack_write(&opb,vi->envelopech,16);
   _oggpack_write(&opb,vi->floororder,8);
   _oggpack_write(&opb,vi->flooroctaves,8);
-  _oggpack_write(&opb,vi->floorch,32);
+  _oggpack_write(&opb,vi->floorch,16);
 
   /* build the packet */
   if(vi->header)free(vi->header);
-  vi->header=memcpy(opb.buffer,_oggpack_bytes(&opb));
+  memcpy(vi->header,opb.buffer,_oggpack_bytes(&opb));
   op->packet=vi->header;
   op->bytes=_oggpack_bytes(&opb);
   op->b_o_s=1;
@@ -119,6 +201,8 @@ int vorbis_info_headerout(vorbis_info *vi,
   op->frameno=0;
 
   /* comment header:
+     codec id       "vorbis"
+     header id      1 (byte)
      vendor len     (4 octets, lsb first)
      vendor and id  (n octects as above)
      comments       (4 octets, lsb first)
@@ -130,20 +214,23 @@ int vorbis_info_headerout(vorbis_info *vi,
   */
 
   _oggpack_reset(&opb);
+  _v_writestring(&opb,"vorbis");
+  _oggpack_write(&opb,0x01,8);
+
   if(vi->vendor){
     _oggpack_write(&opb,strlen(vi->vendor),32);
-    _oggpack_write(&opb,vi->vendor,strlen(vi->vendor));
+    _v_writestring(&opb,vi->vendor);
   }else{
     _oggpack_write(&opb,0,32);
   }
   
-  _oggpack_write(&opb,vi->max_comment,32);
-  if(vi->max_comment){
+  _oggpack_write(&opb,vi->comments,32);
+  if(vi->comments){
     int i;
-    for(i=0;i<=vi->max_comment;i++){
+    for(i=0;i<vi->comments;i++){
       if(vi->user_comments[i]){
        _oggpack_write(&opb,strlen(vi->user_comments[i]),32);
-       _oggpack_write(&opb,vi->user_comments[i],strlen(vi->user_comments[i]));
+       _v_writestring(&opb,vi->user_comments[i]);
       }else{
        _oggpack_write(&opb,0,32);
       }
@@ -151,7 +238,7 @@ int vorbis_info_headerout(vorbis_info *vi,
   }
   
   if(vi->header1)free(vi->header1);
-  vi->header1=memcpy(opb.buffer,_oggpack_bytes(&opb));
+  memcpy(vi->header1,opb.buffer,_oggpack_bytes(&opb));
   op_comm->packet=vi->header1;
   op_comm->bytes=_oggpack_bytes(&opb);
   op_comm->b_o_s=0;
@@ -159,16 +246,24 @@ int vorbis_info_headerout(vorbis_info *vi,
   op_comm->frameno=0;
 
   /* codebook header:
+     codec id       "vorbis"
+     header id      2 (byte)
      nul so far; not encoded yet */
 
+  _oggpack_reset(&opb);
+  _v_writestring(&opb,"vorbis");
+  _oggpack_write(&opb,0x02,8);
+
   if(vi->header2)free(vi->header2);
-  vi->header2=NULL;
+  memcpy(vi->header2,opb.buffer,_oggpack_bytes(&opb));
   op_code->packet=vi->header2;
-  op_code->bytes=0;
+  op_code->bytes=_oggpack_bytes(&opb);
   op_code->b_o_s=0;
   op_code->e_o_s=0;
   op_code->frameno=0;
 
+  _oggpack_writefree(&opb);
+
   return(0);
 }