summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMonty <xiphmont@xiph.org>2009-06-10 14:01:19 +0000
committerMonty <xiphmont@xiph.org>2009-06-10 14:01:19 +0000
commitb204eb53c8135f2582612a8c14deb13e321c2135 (patch)
tree4ff9c57e9a093e5c079e2ddce20f367e26a84d23
parent01dc791e674592b0d0f0cce0cdbe57d8f0452f2f (diff)
downloadlibvorbis-git-vorbis-malloccheck.tar.gz
Begin async error reporting interface; added to vorbis_comment and vorbis_infovorbis-malloccheck
svn path=/branches/vorbis-malloccheck/; revision=16097
-rw-r--r--include/vorbis/codec.h8
-rw-r--r--lib/block.c2
-rw-r--r--lib/info.c789
3 files changed, 462 insertions, 337 deletions
diff --git a/include/vorbis/codec.h b/include/vorbis/codec.h
index 4509eff0..d76f9e77 100644
--- a/include/vorbis/codec.h
+++ b/include/vorbis/codec.h
@@ -26,7 +26,7 @@ extern "C"
#include <ogg/ogg.h>
typedef struct vorbis_info{
- int version;
+ int version; /* < 0 indicates error state */
int channels;
long rate;
@@ -161,9 +161,10 @@ typedef struct vorbis_comment{
and the streaming layer is not used */
/* Vorbis PRIMITIVES: general ***************************************/
-
+
extern void vorbis_info_init(vorbis_info *vi);
extern void vorbis_info_clear(vorbis_info *vi);
+extern int vorbis_info_check(vorbis_info *vi);
extern int vorbis_info_blocksize(vorbis_info *vi,int zo);
extern void vorbis_comment_init(vorbis_comment *vc);
extern void vorbis_comment_add(vorbis_comment *vc, const char *comment);
@@ -172,6 +173,7 @@ extern void vorbis_comment_add_tag(vorbis_comment *vc,
extern char *vorbis_comment_query(vorbis_comment *vc, const char *tag, int count);
extern int vorbis_comment_query_count(vorbis_comment *vc, const char *tag);
extern void vorbis_comment_clear(vorbis_comment *vc);
+ extern int vorbis_comment_check(vorbis_comment *vc);
extern int vorbis_block_init(vorbis_dsp_state *v, vorbis_block *vb);
extern int vorbis_block_clear(vorbis_block *vb);
@@ -234,6 +236,8 @@ extern int vorbis_synthesis_halfrate_p(vorbis_info *v);
#define OV_EBADPACKET -136
#define OV_EBADLINK -137
#define OV_ENOSEEK -138
+#define OV_ESTACK -139
+#define OV_EHEAP -140
#ifdef __cplusplus
}
diff --git a/lib/block.c b/lib/block.c
index ca8e30cb..008ec5cd 100644
--- a/lib/block.c
+++ b/lib/block.c
@@ -91,7 +91,7 @@ int vorbis_block_init(vorbis_dsp_state *v, vorbis_block *vb){
vb->vd=v;
vb->localalloc=0;
vb->localstore=NULL;
- if(v->analysisp){
+ if(v->analysisp>0){
vorbis_block_internal *vbi=
vb->internal=_ogg_calloc(1,sizeof(vorbis_block_internal));
vbi->ampmax=-9999;
diff --git a/lib/info.c b/lib/info.c
index 996d2346..693f558c 100644
--- a/lib/info.c
+++ b/lib/info.c
@@ -31,8 +31,8 @@
#include "misc.h"
#include "os.h"
-#define GENERAL_VENDOR_STRING "Xiph.Org libVorbis 1.2.2rc1"
-#define ENCODE_VENDOR_STRING "Xiph.Org libVorbis I 20090604"
+#define GENERAL_VENDOR_STRING "Xiph.Org libVorbis 1.2.3pre"
+#define ENCODE_VENDOR_STRING "Xiph.Org libVorbis I 20090610"
/* helpers */
static int ilog2(unsigned int v){
@@ -46,7 +46,6 @@ static int ilog2(unsigned int v){
}
static void _v_writestring(oggpack_buffer *o,const char *s, int bytes){
-
while(bytes--){
oggpack_write(o,*s++,8);
}
@@ -59,27 +58,49 @@ static void _v_readstring(oggpack_buffer *o,char *buf,int bytes){
}
void vorbis_comment_init(vorbis_comment *vc){
- memset(vc,0,sizeof(*vc));
+ if(vc)
+ memset(vc,0,sizeof(*vc));
}
void vorbis_comment_add(vorbis_comment *vc,const char *comment){
- vc->user_comments=_ogg_realloc(vc->user_comments,
- (vc->comments+2)*sizeof(*vc->user_comments));
- vc->comment_lengths=_ogg_realloc(vc->comment_lengths,
- (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;
+ if(vc && vc->comments>=0){
+ void *ret =_ogg_realloc(vc->user_comments,
+ (vc->comments+2)*sizeof(*vc->user_comments));
+ if(!ret)goto err;
+ vc->user_comments=ret;
+
+ ret=_ogg_realloc(vc->comment_lengths,
+ (vc->comments+2)*sizeof(*vc->comment_lengths));
+ if(!ret)goto err;
+ vc->comment_lengths=ret;
+ vc->comment_lengths[vc->comments]=strlen(comment);
+
+ ret=_ogg_malloc(vc->comment_lengths[vc->comments]+1);
+ if(!ret)goto err;
+ vc->user_comments[vc->comments]=ret;
+ strcpy(vc->user_comments[vc->comments], comment);
+ vc->comments++;
+ vc->user_comments[vc->comments]=NULL;
+ }
+ return;
+ err:
+ vorbis_comment_clear(vc);
+ vc->comments=OV_EHEAP;
}
void vorbis_comment_add_tag(vorbis_comment *vc, const char *tag, const char *contents){
- char *comment=alloca(strlen(tag)+strlen(contents)+2); /* +2 for = and \0 */
- strcpy(comment, tag);
- strcat(comment, "=");
- strcat(comment, contents);
- vorbis_comment_add(vc, comment);
+ if(vc && vc->comments>=0 && tag && contents){
+ char *comment=alloca(strlen(tag)+strlen(contents)+2); /* +2 for = and \0 */
+ if(comment==NULL){
+ vorbis_comment_clear(vc);
+ vc->comments=OV_ESTACK;
+ }else{
+ strcpy(comment, tag);
+ strcat(comment, "=");
+ strcat(comment, contents);
+ vorbis_comment_add(vc, comment);
+ }
+ }
}
/* This is more or less the same as strncasecmp - but that doesn't exist
@@ -100,17 +121,22 @@ char *vorbis_comment_query(vorbis_comment *vc, const char *tag, int count){
int taglen = strlen(tag)+1; /* +1 for the = we append */
char *fulltag = alloca(taglen+ 1);
- strcpy(fulltag, tag);
- strcat(fulltag, "=");
-
- for(i=0;i<vc->comments;i++){
- if(!tagcompare(vc->user_comments[i], fulltag, taglen)){
- if(count == found)
- /* We return a pointer to the data, not a copy */
- return vc->user_comments[i] + taglen;
- else
- found++;
+ if(fulltag){
+ strcpy(fulltag, tag);
+ strcat(fulltag, "=");
+
+ for(i=0;i<vc->comments;i++){
+ if(!tagcompare(vc->user_comments[i], fulltag, taglen)){
+ if(count == found)
+ /* We return a pointer to the data, not a copy */
+ return vc->user_comments[i] + taglen;
+ else
+ found++;
+ }
}
+ }else{
+ vorbis_comment_clear(vc);
+ vc->comments=OV_ESTACK;
}
return NULL; /* didn't find anything */
}
@@ -119,14 +145,21 @@ int vorbis_comment_query_count(vorbis_comment *vc, const char *tag){
int i,count=0;
int taglen = strlen(tag)+1; /* +1 for the = we append */
char *fulltag = alloca(taglen+1);
- strcpy(fulltag,tag);
- strcat(fulltag, "=");
- for(i=0;i<vc->comments;i++){
- if(!tagcompare(vc->user_comments[i], fulltag, taglen))
- count++;
+ if(fulltag){
+ strcpy(fulltag,tag);
+ strcat(fulltag, "=");
+
+ for(i=0;i<vc->comments;i++){
+ if(!tagcompare(vc->user_comments[i], fulltag, taglen))
+ count++;
+ }
+
+ }else{
+ vorbis_comment_clear(vc);
+ vc->comments=OV_ESTACK;
}
-
+
return count;
}
@@ -144,119 +177,156 @@ void vorbis_comment_clear(vorbis_comment *vc){
}
}
+int vorbis_comment_check(vorbis_comment *vc){
+ return (vc ? (vc->comments<0 ? vc->comments:0) : OV_EFAULT);
+}
+
/* blocksize 0 is guaranteed to be short, 1 is guaranteed 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;
+ if(vi && vi->version>=0){
+ codec_setup_info *ci = vi->codec_setup;
+ return ci ? ci->blocksizes[zo] : -1;
+ }
+ return -1;
}
/* used by synthesis, which has a full, alloced vi */
void vorbis_info_init(vorbis_info *vi){
- memset(vi,0,sizeof(*vi));
- vi->codec_setup=_ogg_calloc(1,sizeof(codec_setup_info));
+ if(vi){
+ memset(vi,0,sizeof(*vi));
+ vi->codec_setup=_ogg_calloc(1,sizeof(codec_setup_info));
+ if(!vi->codec_setup){
+ vi->version = OV_EHEAP;
+ }
+ }
}
void vorbis_info_clear(vorbis_info *vi){
- codec_setup_info *ci=vi->codec_setup;
- int i;
-
- if(ci){
-
- for(i=0;i<ci->modes;i++)
- if(ci->mode_param[i])_ogg_free(ci->mode_param[i]);
-
- for(i=0;i<ci->maps;i++) /* unpack does the range checking */
- if(ci->map_param[i]) /* this may be cleaning up an aborted
- unpack, in which case the below type
- cannot be trusted */
- _mapping_P[ci->map_type[i]]->free_info(ci->map_param[i]);
-
- for(i=0;i<ci->floors;i++) /* unpack does the range checking */
- if(ci->floor_param[i]) /* this may be cleaning up an aborted
- unpack, in which case the below type
- cannot be trusted */
- _floor_P[ci->floor_type[i]]->free_info(ci->floor_param[i]);
-
- for(i=0;i<ci->residues;i++) /* unpack does the range checking */
- if(ci->residue_param[i]) /* this may be cleaning up an aborted
- unpack, in which case the below type
- cannot be trusted */
- _residue_P[ci->residue_type[i]]->free_info(ci->residue_param[i]);
+ if(vi){
+ codec_setup_info *ci=vi->codec_setup;
+ int i;
- for(i=0;i<ci->books;i++){
- if(ci->book_param[i]){
- /* knows if the book was not alloced */
- vorbis_staticbook_destroy(ci->book_param[i]);
+ if(ci){
+
+ for(i=0;i<ci->modes;i++)
+ if(ci->mode_param[i])_ogg_free(ci->mode_param[i]);
+
+ for(i=0;i<ci->maps;i++) /* unpack does the range checking */
+ if(ci->map_param[i]) /* this may be cleaning up an aborted
+ unpack, in which case the below type
+ cannot be trusted */
+ _mapping_P[ci->map_type[i]]->free_info(ci->map_param[i]);
+
+ for(i=0;i<ci->floors;i++) /* unpack does the range checking */
+ if(ci->floor_param[i]) /* this may be cleaning up an aborted
+ unpack, in which case the below type
+ cannot be trusted */
+ _floor_P[ci->floor_type[i]]->free_info(ci->floor_param[i]);
+
+ for(i=0;i<ci->residues;i++) /* unpack does the range checking */
+ if(ci->residue_param[i]) /* this may be cleaning up an aborted
+ unpack, in which case the below type
+ cannot be trusted */
+ _residue_P[ci->residue_type[i]]->free_info(ci->residue_param[i]);
+
+ for(i=0;i<ci->books;i++){
+ if(ci->book_param[i]){
+ /* 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)
- 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]);
+
+ _ogg_free(ci);
+ }
- for(i=0;i<ci->psys;i++)
- _vi_psy_free(ci->psy_param[i]);
-
- _ogg_free(ci);
+ memset(vi,0,sizeof(*vi));
}
+}
- memset(vi,0,sizeof(*vi));
+int vorbis_info_check(vorbis_info *vi){
+ return(vi ? (vi->version>=0?0:vi->version) : OV_EFAULT);
}
/* Header packing/unpacking ********************************************/
static int _vorbis_unpack_info(vorbis_info *vi,oggpack_buffer *opb){
- codec_setup_info *ci=vi->codec_setup;
- if(!ci)return(OV_EFAULT);
-
- vi->version=oggpack_read(opb,32);
- if(vi->version!=0)return(OV_EVERSION);
-
- vi->channels=oggpack_read(opb,8);
- vi->rate=oggpack_read(opb,32);
-
- vi->bitrate_upper=oggpack_read(opb,32);
- vi->bitrate_nominal=oggpack_read(opb,32);
- vi->bitrate_lower=oggpack_read(opb,32);
-
- ci->blocksizes[0]=1<<oggpack_read(opb,4);
- ci->blocksizes[1]=1<<oggpack_read(opb,4);
-
- if(vi->rate<1)goto err_out;
- if(vi->channels<1)goto err_out;
- if(ci->blocksizes[0]<64)goto err_out;
- if(ci->blocksizes[1]<ci->blocksizes[0])goto err_out;
- if(ci->blocksizes[1]>8192)goto err_out;
-
- if(oggpack_read(opb,1)!=1)goto err_out; /* EOP check */
-
- return(0);
- err_out:
- vorbis_info_clear(vi);
- return(OV_EBADHEADER);
+ if(vi && opb){
+ codec_setup_info *ci=vi->codec_setup;
+ if(vi->version<0)return vi->version;
+ if(!ci)return(OV_EFAULT);
+
+ vi->version=oggpack_read(opb,32);
+ if(vi->version!=0)return(OV_EVERSION);
+
+ vi->channels=oggpack_read(opb,8);
+ vi->rate=oggpack_read(opb,32);
+
+ vi->bitrate_upper=oggpack_read(opb,32);
+ vi->bitrate_nominal=oggpack_read(opb,32);
+ vi->bitrate_lower=oggpack_read(opb,32);
+
+ ci->blocksizes[0]=1<<oggpack_read(opb,4);
+ ci->blocksizes[1]=1<<oggpack_read(opb,4);
+
+ if(vi->rate<1)goto err_out;
+ if(vi->channels<1)goto err_out;
+ if(ci->blocksizes[0]<64)goto err_out;
+ if(ci->blocksizes[1]<ci->blocksizes[0])goto err_out;
+ if(ci->blocksizes[1]>8192)goto err_out;
+
+ if(oggpack_read(opb,1)!=1)goto err_out; /* EOP check */
+
+ return(0);
+ err_out:
+ vorbis_info_clear(vi);
+ vi->version=OV_EBADHEADER;
+ return(vi->version=OV_EBADHEADER);
+ }
+ return(OV_EFAULT);
}
static int _vorbis_unpack_comment(vorbis_comment *vc,oggpack_buffer *opb){
int i;
+ int ret=OV_EBADHEADER;
int vendorlen=oggpack_read(opb,32);
if(vendorlen<0)goto err_out;
if(vendorlen+8>opb->storage)goto err_out;
vc->vendor=_ogg_calloc(vendorlen+1,1);
+ if(!vc->vendor){
+ ret=OV_EHEAP;
+ goto err_out;
+ }
_v_readstring(opb,vc->vendor,vendorlen);
i=oggpack_read(opb,32);
if(i<0)goto err_out;
if(4*i+oggpack_bytes(opb)>opb->storage)goto err_out;
vc->comments=i;
+
vc->user_comments=_ogg_calloc(vc->comments+1,sizeof(*vc->user_comments));
vc->comment_lengths=_ogg_calloc(vc->comments+1, sizeof(*vc->comment_lengths));
-
+ if(!vc->user_comments || !vc->comment_lengths){
+ ret=OV_EHEAP;
+ goto err_out;
+ }
+
for(i=0;i<vc->comments;i++){
int len=oggpack_read(opb,32);
if(len<0)goto err_out;
if(len+oggpack_bytes(opb)>opb->storage)goto err_out;
vc->comment_lengths[i]=len;
vc->user_comments[i]=_ogg_calloc(len+1,1);
+ if(!vc->user_comments[i]){
+ ret=OV_EHEAP;
+ goto err_out;
+ }
_v_readstring(opb,vc->user_comments[i],len);
}
if(oggpack_read(opb,1)!=1)goto err_out; /* EOP check */
@@ -264,87 +334,106 @@ static int _vorbis_unpack_comment(vorbis_comment *vc,oggpack_buffer *opb){
return(0);
err_out:
vorbis_comment_clear(vc);
- return(OV_EBADHEADER);
+ vc->comments= -1;
+ return(ret);
}
/* all of the real encoding details are here. The modes, books,
everything */
static int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb){
- codec_setup_info *ci=vi->codec_setup;
- int i;
- if(!ci)return(OV_EFAULT);
-
- /* codebooks */
- ci->books=oggpack_read(opb,8)+1;
- /*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(*ci->book_param[i]));
- if(vorbis_staticbook_unpack(opb,ci->book_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(*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);
- if(ci->floor_type[i]<0 || ci->floor_type[i]>=VI_FLOORB)goto err_out;
- ci->floor_param[i]=_floor_P[ci->floor_type[i]]->unpack(vi,opb);
- if(!ci->floor_param[i])goto err_out;
- }
+ if(vi){
+ codec_setup_info *ci=vi->codec_setup;
+ int i;
+ int ret=OV_EBADHEADER;
- /* residue backend settings */
- ci->residues=oggpack_read(opb,6)+1;
- /*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);
- if(ci->residue_type[i]<0 || ci->residue_type[i]>=VI_RESB)goto err_out;
- ci->residue_param[i]=_residue_P[ci->residue_type[i]]->unpack(vi,opb);
- if(!ci->residue_param[i])goto err_out;
- }
+ if(vi->version<0)return(vi->version);
+ if(!ci)return(OV_EFAULT);
- /* map backend settings */
- ci->maps=oggpack_read(opb,6)+1;
- /*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);
- if(ci->map_type[i]<0 || ci->map_type[i]>=VI_MAPB)goto err_out;
- ci->map_param[i]=_mapping_P[ci->map_type[i]]->unpack(vi,opb);
- if(!ci->map_param[i])goto err_out;
- }
-
- /* mode settings */
- 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(*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);
- ci->mode_param[i]->mapping=oggpack_read(opb,8);
-
- if(ci->mode_param[i]->windowtype>=VI_WINDOWB)goto err_out;
- if(ci->mode_param[i]->transformtype>=VI_WINDOWB)goto err_out;
- if(ci->mode_param[i]->mapping>=ci->maps)goto err_out;
+ /* codebooks */
+ ci->books=oggpack_read(opb,8)+1;
+ /*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(*ci->book_param[i]));
+ if(!ci->book_param[i]){
+ ret=OV_EHEAP;
+ goto err_out;
+ }
+ if((ret=vorbis_staticbook_unpack(opb,ci->book_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(*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);
+ if(ci->floor_type[i]<0 || ci->floor_type[i]>=VI_FLOORB)goto err_out;
+ ci->floor_param[i]=_floor_P[ci->floor_type[i]]->unpack(vi,opb);
+ if(!ci->floor_param[i])goto err_out;
+ }
+
+ /* residue backend settings */
+ ci->residues=oggpack_read(opb,6)+1;
+ /*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);
+ if(ci->residue_type[i]<0 || ci->residue_type[i]>=VI_RESB)goto err_out;
+ ci->residue_param[i]=_residue_P[ci->residue_type[i]]->unpack(vi,opb);
+ if(!ci->residue_param[i])goto err_out;
+ }
+
+ /* map backend settings */
+ ci->maps=oggpack_read(opb,6)+1;
+ /*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);
+ if(ci->map_type[i]<0 || ci->map_type[i]>=VI_MAPB)goto err_out;
+ ci->map_param[i]=_mapping_P[ci->map_type[i]]->unpack(vi,opb);
+ if(!ci->map_param[i])goto err_out;
+ }
+
+ /* mode settings */
+ 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(*ci->mode_param[i]));
+ if(!ci->mode_param[i]){
+ ret=OV_EHEAP;
+ goto err_out;
+ }
+ 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);
+ ci->mode_param[i]->mapping=oggpack_read(opb,8);
+
+ if(ci->mode_param[i]->windowtype>=VI_WINDOWB)goto err_out;
+ if(ci->mode_param[i]->transformtype>=VI_WINDOWB)goto err_out;
+ if(ci->mode_param[i]->mapping>=ci->maps)goto err_out;
+ }
+
+ if(oggpack_read(opb,1)!=1)goto err_out; /* top level EOP check */
+
+ return(0);
+ err_out:
+ if(vi->version<0)ret=vi->version; /* hack to return error state
+ from unpack functions called
+ through dispatch table */
+ vorbis_info_clear(vi);
+ vi->version=ret;
+ return(ret);
}
-
- if(oggpack_read(opb,1)!=1)goto err_out; /* top level EOP check */
-
- return(0);
- err_out:
- vorbis_info_clear(vi);
- return(OV_EBADHEADER);
+ return(OV_EFAULT);
}
/* Is this packet a vorbis ID header? */
@@ -436,27 +525,30 @@ int vorbis_synthesis_headerin(vorbis_info *vi,vorbis_comment *vc,ogg_packet *op)
/* pack side **********************************************************/
static int _vorbis_pack_info(oggpack_buffer *opb,vorbis_info *vi){
- codec_setup_info *ci=vi->codec_setup;
- if(!ci)return(OV_EFAULT);
-
- /* preamble */
- oggpack_write(opb,0x01,8);
- _v_writestring(opb,"vorbis", 6);
-
- /* basic information about the stream */
- oggpack_write(opb,0x00,32);
- oggpack_write(opb,vi->channels,8);
- oggpack_write(opb,vi->rate,32);
-
- oggpack_write(opb,vi->bitrate_upper,32);
- oggpack_write(opb,vi->bitrate_nominal,32);
- oggpack_write(opb,vi->bitrate_lower,32);
-
- oggpack_write(opb,ilog2(ci->blocksizes[0]),4);
- oggpack_write(opb,ilog2(ci->blocksizes[1]),4);
- oggpack_write(opb,1,1);
-
- return(0);
+ if(opb && vi){
+ codec_setup_info *ci=vi->codec_setup;
+ if(vi->version<0)return(vi->version);
+ if(!ci)return(OV_EFAULT);
+
+ /* preamble */
+ oggpack_write(opb,0x01,8);
+ _v_writestring(opb,"vorbis", 6);
+
+ /* basic information about the stream */
+ oggpack_write(opb,0x00,32);
+ oggpack_write(opb,vi->channels,8);
+ oggpack_write(opb,vi->rate,32);
+
+ oggpack_write(opb,vi->bitrate_upper,32);
+ oggpack_write(opb,vi->bitrate_nominal,32);
+ oggpack_write(opb,vi->bitrate_lower,32);
+
+ oggpack_write(opb,ilog2(ci->blocksizes[0]),4);
+ oggpack_write(opb,ilog2(ci->blocksizes[1]),4);
+ oggpack_write(opb,1,1);
+ return(oggpack_writecheck(opb)?OV_EHEAP:0);
+ }
+ return OV_EFAULT;
}
static int _vorbis_pack_comment(oggpack_buffer *opb,vorbis_comment *vc){
@@ -486,83 +578,99 @@ static int _vorbis_pack_comment(oggpack_buffer *opb,vorbis_comment *vc){
}
oggpack_write(opb,1,1);
- return(0);
+ return(oggpack_writecheck(opb)?OV_EHEAP:0);
}
static int _vorbis_pack_books(oggpack_buffer *opb,vorbis_info *vi){
- codec_setup_info *ci=vi->codec_setup;
- int i;
- if(!ci)return(OV_EFAULT);
-
- oggpack_write(opb,0x05,8);
- _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; 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);
- 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 */
- oggpack_write(opb,ci->residues-1,6);
- for(i=0;i<ci->residues;i++){
- oggpack_write(opb,ci->residue_type[i],16);
- _residue_P[ci->residue_type[i]]->pack(ci->residue_param[i],opb);
- }
+ int ret=OV_EFAULT;
+ if(opb && vi){
+ codec_setup_info *ci=vi->codec_setup;
+ int i;
+ if(vi->version<0)return(vi->version);
+ if(!ci)goto err_out;
+
+ oggpack_write(opb,0x05,8);
+ _v_writestring(opb,"vorbis", 6);
+
+ /* books */
+ oggpack_write(opb,ci->books-1,8);
+ for(i=0;i<ci->books;i++)
+ if((ret=vorbis_staticbook_pack(ci->book_param[i],opb)))goto err_out;
+
+ /* 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);
+ if(_floor_P[ci->floor_type[i]]->pack){
+ _floor_P[ci->floor_type[i]]->pack(ci->floor_param[i],opb);
+ }else{
+ ret=OV_EFAULT;
+ goto err_out;
+ }
+ }
+
+ /* residues */
+ oggpack_write(opb,ci->residues-1,6);
+ for(i=0;i<ci->residues;i++){
+ oggpack_write(opb,ci->residue_type[i],16);
+ _residue_P[ci->residue_type[i]]->pack(ci->residue_param[i],opb);
+ }
- /* maps */
- oggpack_write(opb,ci->maps-1,6);
- for(i=0;i<ci->maps;i++){
- oggpack_write(opb,ci->map_type[i],16);
- _mapping_P[ci->map_type[i]]->pack(vi,ci->map_param[i],opb);
- }
+ /* maps */
+ oggpack_write(opb,ci->maps-1,6);
+ for(i=0;i<ci->maps;i++){
+ oggpack_write(opb,ci->map_type[i],16);
+ _mapping_P[ci->map_type[i]]->pack(vi,ci->map_param[i],opb);
+ }
- /* modes */
- oggpack_write(opb,ci->modes-1,6);
- for(i=0;i<ci->modes;i++){
- oggpack_write(opb,ci->mode_param[i]->blockflag,1);
- oggpack_write(opb,ci->mode_param[i]->windowtype,16);
- oggpack_write(opb,ci->mode_param[i]->transformtype,16);
- oggpack_write(opb,ci->mode_param[i]->mapping,8);
+ /* modes */
+ oggpack_write(opb,ci->modes-1,6);
+ for(i=0;i<ci->modes;i++){
+ oggpack_write(opb,ci->mode_param[i]->blockflag,1);
+ oggpack_write(opb,ci->mode_param[i]->windowtype,16);
+ oggpack_write(opb,ci->mode_param[i]->transformtype,16);
+ oggpack_write(opb,ci->mode_param[i]->mapping,8);
+ }
+ oggpack_write(opb,1,1);
+
+ return(oggpack_writecheck(opb)?OV_EHEAP:0);
}
- oggpack_write(opb,1,1);
-
- return(0);
err_out:
- return(-1);
+ return(ret);
}
int vorbis_commentheader_out(vorbis_comment *vc,
- ogg_packet *op){
+ ogg_packet *op){
- oggpack_buffer opb;
-
- oggpack_writeinit(&opb);
- if(_vorbis_pack_comment(&opb,vc)) return OV_EIMPL;
-
- op->packet = _ogg_malloc(oggpack_bytes(&opb));
- memcpy(op->packet, opb.buffer, oggpack_bytes(&opb));
-
- op->bytes=oggpack_bytes(&opb);
- op->b_o_s=0;
- op->e_o_s=0;
- op->granulepos=0;
- op->packetno=1;
+ if(op){
+ oggpack_buffer opb;
+ int ret;
- return 0;
+ oggpack_writeinit(&opb);
+ if((ret=_vorbis_pack_comment(&opb,vc)))return(ret);
+
+ op->packet = _ogg_malloc(oggpack_bytes(&opb));
+ if(!op->packet){
+ oggpack_writeclear(&opb);
+ memset(op,0,sizeof(*op));
+ return OV_EHEAP;
+ }
+ memcpy(op->packet, opb.buffer, oggpack_bytes(&opb));
+
+ op->bytes=oggpack_bytes(&opb);
+ op->b_o_s=0;
+ op->e_o_s=0;
+ op->granulepos=0;
+ op->packetno=1;
+ oggpack_writeclear(&opb);
+
+ return 0;
+ }
+ return OV_EFAULT;
}
int vorbis_analysis_headerout(vorbis_dsp_state *v,
@@ -570,84 +678,97 @@ int vorbis_analysis_headerout(vorbis_dsp_state *v,
ogg_packet *op,
ogg_packet *op_comm,
ogg_packet *op_code){
- int ret=OV_EIMPL;
- vorbis_info *vi=v->vi;
- oggpack_buffer opb;
- private_state *b=v->backend_state;
-
- if(!b){
- ret=OV_EFAULT;
- goto err_out;
- }
-
- /* first header packet **********************************************/
-
- oggpack_writeinit(&opb);
- if(_vorbis_pack_info(&opb,vi))goto err_out;
-
- /* build the packet */
- if(b->header)_ogg_free(b->header);
- b->header=_ogg_malloc(oggpack_bytes(&opb));
- memcpy(b->header,opb.buffer,oggpack_bytes(&opb));
- op->packet=b->header;
- op->bytes=oggpack_bytes(&opb);
- op->b_o_s=1;
- op->e_o_s=0;
- op->granulepos=0;
- op->packetno=0;
-
- /* second header packet (comments) **********************************/
-
- oggpack_reset(&opb);
- if(_vorbis_pack_comment(&opb,vc))goto err_out;
-
- if(b->header1)_ogg_free(b->header1);
- b->header1=_ogg_malloc(oggpack_bytes(&opb));
- memcpy(b->header1,opb.buffer,oggpack_bytes(&opb));
- op_comm->packet=b->header1;
- op_comm->bytes=oggpack_bytes(&opb);
- op_comm->b_o_s=0;
- op_comm->e_o_s=0;
- op_comm->granulepos=0;
- op_comm->packetno=1;
-
- /* third header packet (modes/codebooks) ****************************/
-
- oggpack_reset(&opb);
- if(_vorbis_pack_books(&opb,vi))goto err_out;
-
- if(b->header2)_ogg_free(b->header2);
- b->header2=_ogg_malloc(oggpack_bytes(&opb));
- memcpy(b->header2,opb.buffer,oggpack_bytes(&opb));
- op_code->packet=b->header2;
- op_code->bytes=oggpack_bytes(&opb);
- op_code->b_o_s=0;
- op_code->e_o_s=0;
- op_code->granulepos=0;
- op_code->packetno=2;
-
- oggpack_writeclear(&opb);
- return(0);
- err_out:
- oggpack_writeclear(&opb);
- memset(op,0,sizeof(*op));
- memset(op_comm,0,sizeof(*op_comm));
- memset(op_code,0,sizeof(*op_code));
-
- if(b){
+ if(v){
+ vorbis_info *vi=v->vi;
+ oggpack_buffer opb;
+ private_state *b=v->backend_state;
+ int ret=0;
+
+ if(!vc || !b || !op || !op_comm || !op_code) goto err_out;
+
+ /* first header packet **********************************************/
+
+ oggpack_writeinit(&opb);
+ if((ret=_vorbis_pack_info(&opb,vi)))goto err_out;
+
+ /* build the packet */
if(b->header)_ogg_free(b->header);
+ b->header=_ogg_malloc(oggpack_bytes(&opb));
+ if(!b->header){
+ ret=OV_EHEAP;
+ goto err_out;
+ }
+ memcpy(b->header,opb.buffer,oggpack_bytes(&opb));
+ op->packet=b->header;
+ op->bytes=oggpack_bytes(&opb);
+ op->b_o_s=1;
+ op->e_o_s=0;
+ op->granulepos=0;
+ op->packetno=0;
+
+ /* second header packet (comments) **********************************/
+
+ oggpack_reset(&opb);
+ if((ret=_vorbis_pack_comment(&opb,vc)))goto err_out;
if(b->header1)_ogg_free(b->header1);
+ b->header1=_ogg_malloc(oggpack_bytes(&opb));
+ if(!b->header1){
+ ret=OV_EHEAP;
+ goto err_out;
+ }
+ memcpy(b->header1,opb.buffer,oggpack_bytes(&opb));
+ op_comm->packet=b->header1;
+ op_comm->bytes=oggpack_bytes(&opb);
+ op_comm->b_o_s=0;
+ op_comm->e_o_s=0;
+ op_comm->granulepos=0;
+ op_comm->packetno=1;
+
+ /* third header packet (modes/codebooks) ****************************/
+
+ oggpack_reset(&opb);
+ if((ret=_vorbis_pack_books(&opb,vi)))goto err_out;
+
if(b->header2)_ogg_free(b->header2);
- b->header=NULL;
- b->header1=NULL;
- b->header2=NULL;
+ b->header2=_ogg_malloc(oggpack_bytes(&opb));
+ if(!b->header2){
+ ret=OV_EHEAP;
+ goto err_out;
+ }
+ memcpy(b->header2,opb.buffer,oggpack_bytes(&opb));
+ op_code->packet=b->header2;
+ op_code->bytes=oggpack_bytes(&opb);
+ op_code->b_o_s=0;
+ op_code->e_o_s=0;
+ op_code->granulepos=0;
+ op_code->packetno=2;
+
+ oggpack_writeclear(&opb);
+ return(0);
+ err_out:
+ oggpack_writeclear(&opb);
+ memset(op,0,sizeof(*op));
+ memset(op_comm,0,sizeof(*op_comm));
+ memset(op_code,0,sizeof(*op_code));
+
+ if(b){
+ if(b->header)_ogg_free(b->header);
+ if(b->header1)_ogg_free(b->header1);
+ if(b->header2)_ogg_free(b->header2);
+ b->header=NULL;
+ b->header1=NULL;
+ b->header2=NULL;
+ }
+ return(ret);
}
- return(ret);
+
+ return(OV_EFAULT);
}
double vorbis_granule_time(vorbis_dsp_state *v,ogg_int64_t granulepos){
- if(granulepos>=0)
- return((double)granulepos/v->vi->rate);
+ if(v && v->vi && v->vi->version>=0)
+ if(granulepos>=0)
+ return((double)granulepos/v->vi->rate);
return(-1);
}