Update the encoder datestamp so we can tell if the stream was produced
[platform/upstream/libvorbis.git] / lib / info.c
index 9f7a098..007c5e1 100644 (file)
@@ -1,18 +1,17 @@
 /********************************************************************
  *                                                                  *
  * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
- * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY *
- * THE GNU LESSER/LIBRARY PUBLIC LICENSE, WHICH IS INCLUDED WITH    *
- * THIS SOURCE. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.        *
+ * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
+ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
+ * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
  *                                                                  *
- * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2000             *
- * by Monty <monty@xiph.org> and the XIPHOPHORUS Company            *
- * http://www.xiph.org/                                             *
+ * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2003             *
+ * by the XIPHOPHORUS Company http://www.xiph.org/                  *
  *                                                                  *
  ********************************************************************
 
  function: maintain the info structure, info <-> header packets
- last mod: $Id: info.c,v 1.35 2001/01/22 01:38:24 xiphmont Exp $
+ last mod: $Id$
 
  ********************************************************************/
 
@@ -24,7 +23,6 @@
 #include <ctype.h>
 #include <ogg/ogg.h>
 #include "vorbis/codec.h"
-#include "backends.h"
 #include "codec_internal.h"
 #include "codebook.h"
 #include "registry.h"
 /* helpers */
 static int ilog2(unsigned int v){
   int ret=0;
-  while(v>1){
+  if(v)--v;
+  while(v){
     ret++;
     v>>=1;
   }
   return(ret);
 }
 
-static void _v_writestring(oggpack_buffer *o,char *s){
-  while(*s){
+static void _v_writestring(oggpack_buffer *o,char *s, int bytes){
+
+  while(bytes--){
     oggpack_write(o,*s++,8);
   }
 }
@@ -56,16 +56,17 @@ static void _v_readstring(oggpack_buffer *o,char *buf,int bytes){
 }
 
 void vorbis_comment_init(vorbis_comment *vc){
-  memset(vc,0,sizeof(vorbis_comment));
+  memset(vc,0,sizeof(*vc));
 }
 
 void vorbis_comment_add(vorbis_comment *vc,char *comment){
   vc->user_comments=_ogg_realloc(vc->user_comments,
-                           (vc->comments+2)*sizeof(char *));
+                           (vc->comments+2)*sizeof(*vc->user_comments));
   vc->comment_lengths=_ogg_realloc(vc->comment_lengths,
-                           (vc->comments+2)*sizeof(int));
-  vc->user_comments[vc->comments]=strdup(comment);
+                           (vc->comments+2)*sizeof(*vc->comment_lengths));
   vc->comment_lengths[vc->comments]=strlen(comment);
+  vc->user_comments[vc->comments]=_ogg_malloc(vc->comment_lengths[vc->comments]+1);
+  strcpy(vc->user_comments[vc->comments], comment);
   vc->comments++;
   vc->user_comments[vc->comments]=NULL;
 }
@@ -135,12 +136,19 @@ void vorbis_comment_clear(vorbis_comment *vc){
        if(vc->comment_lengths)_ogg_free(vc->comment_lengths);
     if(vc->vendor)_ogg_free(vc->vendor);
   }
-  memset(vc,0,sizeof(vorbis_comment));
+  memset(vc,0,sizeof(*vc));
+}
+
+/* blocksize 0 is guaranteed to be short, 1 is guarantted to be long.
+   They may be equal, but short will never ge greater than long */
+int vorbis_info_blocksize(vorbis_info *vi,int zo){
+  codec_setup_info *ci = vi->codec_setup;
+  return ci ? ci->blocksizes[zo] : -1;
 }
 
 /* used by synthesis, which has a full, alloced vi */
 void vorbis_info_init(vorbis_info *vi){
-  memset(vi,0,sizeof(vorbis_info));
+  memset(vi,0,sizeof(*vi));
   vi->codec_setup=_ogg_calloc(1,sizeof(codec_setup_info));
 }
 
@@ -156,9 +164,6 @@ void vorbis_info_clear(vorbis_info *vi){
     for(i=0;i<ci->maps;i++) /* unpack does the range checking */
       _mapping_P[ci->map_type[i]]->free_info(ci->map_param[i]);
 
-    for(i=0;i<ci->times;i++) /* unpack does the range checking */
-      _time_P[ci->time_type[i]]->free_info(ci->time_param[i]);
-
     for(i=0;i<ci->floors;i++) /* unpack does the range checking */
       _floor_P[ci->floor_type[i]]->free_info(ci->floor_param[i]);
     
@@ -170,7 +175,11 @@ void vorbis_info_clear(vorbis_info *vi){
        /* knows if the book was not alloced */
        vorbis_staticbook_destroy(ci->book_param[i]);
       }
+      if(ci->fullbooks)
+       vorbis_book_clear(ci->fullbooks+i);
     }
+    if(ci->fullbooks)
+       _ogg_free(ci->fullbooks);
     
     for(i=0;i<ci->psys;i++)
       _vi_psy_free(ci->psy_param[i]);
@@ -178,7 +187,7 @@ void vorbis_info_clear(vorbis_info *vi){
     _ogg_free(ci);
   }
 
-  memset(vi,0,sizeof(vorbis_info));
+  memset(vi,0,sizeof(*vi));
 }
 
 /* Header packing/unpacking ********************************************/
@@ -221,8 +230,8 @@ static int _vorbis_unpack_comment(vorbis_comment *vc,oggpack_buffer *opb){
   _v_readstring(opb,vc->vendor,vendorlen);
   vc->comments=oggpack_read(opb,32);
   if(vc->comments<0)goto err_out;
-  vc->user_comments=_ogg_calloc(vc->comments+1,sizeof(char **));
-  vc->comment_lengths=_ogg_calloc(vc->comments+1, sizeof(int));
+  vc->user_comments=_ogg_calloc(vc->comments+1,sizeof(*vc->user_comments));
+  vc->comment_lengths=_ogg_calloc(vc->comments+1, sizeof(*vc->comment_lengths));
            
   for(i=0;i<vc->comments;i++){
     int len=oggpack_read(opb,32);
@@ -248,26 +257,24 @@ static int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb){
 
   /* codebooks */
   ci->books=oggpack_read(opb,8)+1;
-  /*ci->book_param=_ogg_calloc(ci->books,sizeof(static_codebook *));*/
+  /*ci->book_param=_ogg_calloc(ci->books,sizeof(*ci->book_param));*/
   for(i=0;i<ci->books;i++){
-    ci->book_param[i]=_ogg_calloc(1,sizeof(static_codebook));
+    ci->book_param[i]=_ogg_calloc(1,sizeof(*ci->book_param[i]));
     if(vorbis_staticbook_unpack(opb,ci->book_param[i]))goto err_out;
   }
 
-  /* time backend settings */
-  ci->times=oggpack_read(opb,6)+1;
-  /*ci->time_type=_ogg_malloc(ci->times*sizeof(int));*/
-  /*ci->time_param=_ogg_calloc(ci->times,sizeof(void *));*/
-  for(i=0;i<ci->times;i++){
-    ci->time_type[i]=oggpack_read(opb,16);
-    if(ci->time_type[i]<0 || ci->time_type[i]>=VI_TIMEB)goto err_out;
-    ci->time_param[i]=_time_P[ci->time_type[i]]->unpack(vi,opb);
-    if(!ci->time_param[i])goto err_out;
+  /* time backend settings; hooks are unused */
+  {
+    int times=oggpack_read(opb,6)+1;
+    for(i=0;i<times;i++){
+      int test=oggpack_read(opb,16);
+      if(test<0 || test>=VI_TIMEB)goto err_out;
+    }
   }
 
   /* floor backend settings */
   ci->floors=oggpack_read(opb,6)+1;
-  /*ci->floor_type=_ogg_malloc(ci->floors*sizeof(int));*/
+  /*ci->floor_type=_ogg_malloc(ci->floors*sizeof(*ci->floor_type));*/
   /*ci->floor_param=_ogg_calloc(ci->floors,sizeof(void *));*/
   for(i=0;i<ci->floors;i++){
     ci->floor_type[i]=oggpack_read(opb,16);
@@ -278,7 +285,7 @@ static int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb){
 
   /* residue backend settings */
   ci->residues=oggpack_read(opb,6)+1;
-  /*ci->residue_type=_ogg_malloc(ci->residues*sizeof(int));*/
+  /*ci->residue_type=_ogg_malloc(ci->residues*sizeof(*ci->residue_type));*/
   /*ci->residue_param=_ogg_calloc(ci->residues,sizeof(void *));*/
   for(i=0;i<ci->residues;i++){
     ci->residue_type[i]=oggpack_read(opb,16);
@@ -289,7 +296,7 @@ static int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb){
 
   /* map backend settings */
   ci->maps=oggpack_read(opb,6)+1;
-  /*ci->map_type=_ogg_malloc(ci->maps*sizeof(int));*/
+  /*ci->map_type=_ogg_malloc(ci->maps*sizeof(*ci->map_type));*/
   /*ci->map_param=_ogg_calloc(ci->maps,sizeof(void *));*/
   for(i=0;i<ci->maps;i++){
     ci->map_type[i]=oggpack_read(opb,16);
@@ -302,7 +309,7 @@ static int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb){
   ci->modes=oggpack_read(opb,6)+1;
   /*vi->mode_param=_ogg_calloc(vi->modes,sizeof(void *));*/
   for(i=0;i<ci->modes;i++){
-    ci->mode_param[i]=_ogg_calloc(1,sizeof(vorbis_info_mode));
+    ci->mode_param[i]=_ogg_calloc(1,sizeof(*ci->mode_param[i]));
     ci->mode_param[i]->blockflag=oggpack_read(opb,1);
     ci->mode_param[i]->windowtype=oggpack_read(opb,16);
     ci->mode_param[i]->transformtype=oggpack_read(opb,16);
@@ -390,7 +397,7 @@ static int _vorbis_pack_info(oggpack_buffer *opb,vorbis_info *vi){
 
   /* preamble */  
   oggpack_write(opb,0x01,8);
-  _v_writestring(opb,"vorbis");
+  _v_writestring(opb,"vorbis", 6);
 
   /* basic information about the stream */
   oggpack_write(opb,0x00,32);
@@ -409,15 +416,16 @@ static int _vorbis_pack_info(oggpack_buffer *opb,vorbis_info *vi){
 }
 
 static int _vorbis_pack_comment(oggpack_buffer *opb,vorbis_comment *vc){
-  char temp[]="Xiphophorus libVorbis I 20010119";
+  char temp[]="Xiph.Org libVorbis I 20050304";
+  int bytes = strlen(temp);
 
   /* preamble */  
   oggpack_write(opb,0x03,8);
-  _v_writestring(opb,"vorbis");
+  _v_writestring(opb,"vorbis", 6);
 
   /* vendor */
-  oggpack_write(opb,strlen(temp),32);
-  _v_writestring(opb,temp);
+  oggpack_write(opb,bytes,32);
+  _v_writestring(opb,temp, bytes);
   
   /* comments */
 
@@ -427,7 +435,7 @@ static int _vorbis_pack_comment(oggpack_buffer *opb,vorbis_comment *vc){
     for(i=0;i<vc->comments;i++){
       if(vc->user_comments[i]){
        oggpack_write(opb,vc->comment_lengths[i],32);
-       _v_writestring(opb,vc->user_comments[i]);
+       _v_writestring(opb,vc->user_comments[i], vc->comment_lengths[i]);
       }else{
        oggpack_write(opb,0,32);
       }
@@ -444,25 +452,25 @@ static int _vorbis_pack_books(oggpack_buffer *opb,vorbis_info *vi){
   if(!ci)return(OV_EFAULT);
 
   oggpack_write(opb,0x05,8);
-  _v_writestring(opb,"vorbis");
+  _v_writestring(opb,"vorbis", 6);
 
   /* books */
   oggpack_write(opb,ci->books-1,8);
   for(i=0;i<ci->books;i++)
     if(vorbis_staticbook_pack(ci->book_param[i],opb))goto err_out;
 
-  /* times */
-  oggpack_write(opb,ci->times-1,6);
-  for(i=0;i<ci->times;i++){
-    oggpack_write(opb,ci->time_type[i],16);
-    _time_P[ci->time_type[i]]->pack(ci->time_param[i],opb);
-  }
+  /* times; hook placeholders */
+  oggpack_write(opb,0,6);
+  oggpack_write(opb,0,16);
 
   /* floors */
   oggpack_write(opb,ci->floors-1,6);
   for(i=0;i<ci->floors;i++){
     oggpack_write(opb,ci->floor_type[i],16);
-    _floor_P[ci->floor_type[i]]->pack(ci->floor_param[i],opb);
+    if(_floor_P[ci->floor_type[i]]->pack)
+      _floor_P[ci->floor_type[i]]->pack(ci->floor_param[i],opb);
+    else
+      goto err_out;
   }
 
   /* residues */
@@ -521,7 +529,7 @@ int vorbis_analysis_headerout(vorbis_dsp_state *v,
   int ret=OV_EIMPL;
   vorbis_info *vi=v->vi;
   oggpack_buffer opb;
-  backend_lookup_state *b=v->backend_state;
+  private_state *b=v->backend_state;
 
   if(!b){
     ret=OV_EFAULT;
@@ -575,9 +583,9 @@ int vorbis_analysis_headerout(vorbis_dsp_state *v,
   return(0);
  err_out:
   oggpack_writeclear(&opb);
-  memset(op,0,sizeof(ogg_packet));
-  memset(op_comm,0,sizeof(ogg_packet));
-  memset(op_code,0,sizeof(ogg_packet));
+  memset(op,0,sizeof(*op));
+  memset(op_comm,0,sizeof(*op_comm));
+  memset(op_code,0,sizeof(*op_code));
 
   if(b->header)_ogg_free(b->header);
   if(b->header1)_ogg_free(b->header1);
@@ -588,3 +596,8 @@ int vorbis_analysis_headerout(vorbis_dsp_state *v,
   return(ret);
 }
 
+double vorbis_granule_time(vorbis_dsp_state *v,ogg_int64_t granulepos){
+  if(granulepos>=0)
+    return((double)granulepos/v->vi->rate);
+  return(-1);
+}