Updates libogg to v1.3.0

This commit is contained in:
thecelloman 2013-02-24 19:32:54 -05:00
parent 77505ee162
commit 9a7664b0fa
5 changed files with 1132 additions and 694 deletions

View file

@ -1,3 +1,47 @@
Version 1.3.0 (2011 August 4)
* Add ogg_stream_flush_fill() call
This produces longer packets on flush, similar to
what ogg_stream_pageout_fill() does for single pages.
* Windows build fixes
Version 1.2.2 (2010 December 07)
* Build fix (types correction) for Mac OS X
* Update win32 project files to Visual Studio 2008
* ogg_stream_pageout_fill documentation fix
Version 1.2.1 (2010 November 01)
* Various build updates (see SVN)
* Add ogg_stream_pageout_fill() to API to allow applications
greater explicit flexibility in page sizing.
* Documentation updates including multiplexing description,
terminology and API (incl. ogg_packet_clear(),
ogg_stream_pageout_fill())
* Correct possible buffer overwrite in stream encoding on 32 bit
when a single packet exceed 250MB.
* Correct read-buffer overrun [without side effects] under
similar circumstances.
* Update unit testing to work properly with new page spill
heuristic.
Version 1.2.0 (2010 March 25)
* Alter default flushing behavior to span less often and use larger page
sizes when packet sizes are large.
* Build fixes for additional compilers
* Documentation updates
Version 1.1.4 (2009 June 24)
* New async error reporting mechanism. Calls made after a fatal error are
now safely handled in the event an error code is ignored
* Added allocation checks useful to some embedded applications
* fix possible read past end of buffer when reading 0 bits
* Updates to API documentation
* Build fixes
Version 1.1.3 (2005 November 27) Version 1.1.3 (2005 November 27)
* Correct a bug in the granulepos field of pages where no packet ends * Correct a bug in the granulepos field of pages where no packet ends

View file

@ -5,13 +5,13 @@
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
* * * *
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002 * * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2007 *
* by the Xiph.Org Foundation http://www.xiph.org/ * * by the Xiph.Org Foundation http://www.xiph.org/ *
* * * *
******************************************************************** ********************************************************************
function: toplevel libogg include function: toplevel libogg include
last mod: $Id: ogg.h 7188 2004-07-20 07:26:04Z xiphmont $ last mod: $Id: ogg.h 18044 2011-08-01 17:55:20Z gmaxwell $
********************************************************************/ ********************************************************************/
#ifndef _OGG_H #ifndef _OGG_H
@ -21,8 +21,14 @@
extern "C" { extern "C" {
#endif #endif
#include <stddef.h>
#include <ogg/os_types.h> #include <ogg/os_types.h>
typedef struct {
void *iov_base;
size_t iov_len;
} ogg_iovec_t;
typedef struct { typedef struct {
long endbyte; long endbyte;
int endbit; int endbit;
@ -72,7 +78,7 @@ typedef struct {
ogg_int64_t packetno; /* sequence number for decode; the framing ogg_int64_t packetno; /* sequence number for decode; the framing
knows where there's a hole in the data, knows where there's a hole in the data,
but we need coupling so that the codec but we need coupling so that the codec
(which is in a seperate abstraction (which is in a separate abstraction
layer) also knows about the gap */ layer) also knows about the gap */
ogg_int64_t granulepos; ogg_int64_t granulepos;
@ -92,7 +98,7 @@ typedef struct {
ogg_int64_t packetno; /* sequence number for decode; the framing ogg_int64_t packetno; /* sequence number for decode; the framing
knows where there's a hole in the data, knows where there's a hole in the data,
but we need coupling so that the codec but we need coupling so that the codec
(which is in a seperate abstraction (which is in a separate abstraction
layer) also knows about the gap */ layer) also knows about the gap */
} ogg_packet; } ogg_packet;
@ -110,6 +116,7 @@ typedef struct {
/* Ogg BITSTREAM PRIMITIVES: bitstream ************************/ /* Ogg BITSTREAM PRIMITIVES: bitstream ************************/
extern void oggpack_writeinit(oggpack_buffer *b); extern void oggpack_writeinit(oggpack_buffer *b);
extern int oggpack_writecheck(oggpack_buffer *b);
extern void oggpack_writetrunc(oggpack_buffer *b,long bits); extern void oggpack_writetrunc(oggpack_buffer *b,long bits);
extern void oggpack_writealign(oggpack_buffer *b); extern void oggpack_writealign(oggpack_buffer *b);
extern void oggpack_writecopy(oggpack_buffer *b,void *source,long bits); extern void oggpack_writecopy(oggpack_buffer *b,void *source,long bits);
@ -128,6 +135,7 @@ extern long oggpack_bits(oggpack_buffer *b);
extern unsigned char *oggpack_get_buffer(oggpack_buffer *b); extern unsigned char *oggpack_get_buffer(oggpack_buffer *b);
extern void oggpackB_writeinit(oggpack_buffer *b); extern void oggpackB_writeinit(oggpack_buffer *b);
extern int oggpackB_writecheck(oggpack_buffer *b);
extern void oggpackB_writetrunc(oggpack_buffer *b,long bits); extern void oggpackB_writetrunc(oggpack_buffer *b,long bits);
extern void oggpackB_writealign(oggpack_buffer *b); extern void oggpackB_writealign(oggpack_buffer *b);
extern void oggpackB_writecopy(oggpack_buffer *b,void *source,long bits); extern void oggpackB_writecopy(oggpack_buffer *b,void *source,long bits);
@ -148,8 +156,12 @@ extern unsigned char *oggpackB_get_buffer(oggpack_buffer *b);
/* Ogg BITSTREAM PRIMITIVES: encoding **************************/ /* Ogg BITSTREAM PRIMITIVES: encoding **************************/
extern int ogg_stream_packetin(ogg_stream_state *os, ogg_packet *op); extern int ogg_stream_packetin(ogg_stream_state *os, ogg_packet *op);
extern int ogg_stream_iovecin(ogg_stream_state *os, ogg_iovec_t *iov,
int count, long e_o_s, ogg_int64_t granulepos);
extern int ogg_stream_pageout(ogg_stream_state *os, ogg_page *og); extern int ogg_stream_pageout(ogg_stream_state *os, ogg_page *og);
extern int ogg_stream_pageout_fill(ogg_stream_state *os, ogg_page *og, int nfill);
extern int ogg_stream_flush(ogg_stream_state *os, ogg_page *og); extern int ogg_stream_flush(ogg_stream_state *os, ogg_page *og);
extern int ogg_stream_flush_fill(ogg_stream_state *os, ogg_page *og, int nfill);
/* Ogg BITSTREAM PRIMITIVES: decoding **************************/ /* Ogg BITSTREAM PRIMITIVES: decoding **************************/
@ -157,6 +169,7 @@ extern int ogg_sync_init(ogg_sync_state *oy);
extern int ogg_sync_clear(ogg_sync_state *oy); extern int ogg_sync_clear(ogg_sync_state *oy);
extern int ogg_sync_reset(ogg_sync_state *oy); extern int ogg_sync_reset(ogg_sync_state *oy);
extern int ogg_sync_destroy(ogg_sync_state *oy); extern int ogg_sync_destroy(ogg_sync_state *oy);
extern int ogg_sync_check(ogg_sync_state *oy);
extern char *ogg_sync_buffer(ogg_sync_state *oy, long size); extern char *ogg_sync_buffer(ogg_sync_state *oy, long size);
extern int ogg_sync_wrote(ogg_sync_state *oy, long bytes); extern int ogg_sync_wrote(ogg_sync_state *oy, long bytes);
@ -173,18 +186,19 @@ extern int ogg_stream_clear(ogg_stream_state *os);
extern int ogg_stream_reset(ogg_stream_state *os); extern int ogg_stream_reset(ogg_stream_state *os);
extern int ogg_stream_reset_serialno(ogg_stream_state *os,int serialno); extern int ogg_stream_reset_serialno(ogg_stream_state *os,int serialno);
extern int ogg_stream_destroy(ogg_stream_state *os); extern int ogg_stream_destroy(ogg_stream_state *os);
extern int ogg_stream_check(ogg_stream_state *os);
extern int ogg_stream_eos(ogg_stream_state *os); extern int ogg_stream_eos(ogg_stream_state *os);
extern void ogg_page_checksum_set(ogg_page *og); extern void ogg_page_checksum_set(ogg_page *og);
extern int ogg_page_version(ogg_page *og); extern int ogg_page_version(const ogg_page *og);
extern int ogg_page_continued(ogg_page *og); extern int ogg_page_continued(const ogg_page *og);
extern int ogg_page_bos(ogg_page *og); extern int ogg_page_bos(const ogg_page *og);
extern int ogg_page_eos(ogg_page *og); extern int ogg_page_eos(const ogg_page *og);
extern ogg_int64_t ogg_page_granulepos(ogg_page *og); extern ogg_int64_t ogg_page_granulepos(const ogg_page *og);
extern int ogg_page_serialno(ogg_page *og); extern int ogg_page_serialno(const ogg_page *og);
extern long ogg_page_pageno(ogg_page *og); extern long ogg_page_pageno(const ogg_page *og);
extern int ogg_page_packets(ogg_page *og); extern int ogg_page_packets(const ogg_page *og);
extern void ogg_packet_clear(ogg_packet *op); extern void ogg_packet_clear(ogg_packet *op);
@ -194,9 +208,3 @@ extern void ogg_packet_clear(ogg_packet *op);
#endif #endif
#endif /* _OGG_H */ #endif /* _OGG_H */

View file

@ -11,7 +11,7 @@
******************************************************************** ********************************************************************
function: #ifdef jail to whip a few platforms into the UNIX ideal. function: #ifdef jail to whip a few platforms into the UNIX ideal.
last mod: $Id: os_types.h 7524 2004-08-11 04:20:36Z conrad $ last mod: $Id: os_types.h 17712 2010-12-03 17:10:02Z xiphmont $
********************************************************************/ ********************************************************************/
#ifndef _OS_TYPES_H #ifndef _OS_TYPES_H
@ -27,13 +27,15 @@
#if defined(_WIN32) #if defined(_WIN32)
# if defined(__CYGWIN__) # if defined(__CYGWIN__)
# include <_G_config.h> # include <stdint.h>
typedef _G_int64_t ogg_int64_t; typedef int16_t ogg_int16_t;
typedef _G_int32_t ogg_int32_t; typedef uint16_t ogg_uint16_t;
typedef _G_uint32_t ogg_uint32_t; typedef int32_t ogg_int32_t;
typedef _G_int16_t ogg_int16_t; typedef uint32_t ogg_uint32_t;
typedef _G_uint16_t ogg_uint16_t; typedef int64_t ogg_int64_t;
typedef uint64_t ogg_uint64_t;
# elif defined(__MINGW32__) # elif defined(__MINGW32__)
# include <sys/types.h>
typedef short ogg_int16_t; typedef short ogg_int16_t;
typedef unsigned short ogg_uint16_t; typedef unsigned short ogg_uint16_t;
typedef int ogg_int32_t; typedef int ogg_int32_t;
@ -64,23 +66,33 @@
typedef UInt32 ogg_uint32_t; typedef UInt32 ogg_uint32_t;
typedef SInt64 ogg_int64_t; typedef SInt64 ogg_int64_t;
#elif defined(__MACOSX__) /* MacOS X Framework build */ #elif (defined(__APPLE__) && defined(__MACH__)) /* MacOS X Framework build */
# include <sys/types.h> # include <inttypes.h>
typedef int16_t ogg_int16_t; typedef int16_t ogg_int16_t;
typedef u_int16_t ogg_uint16_t; typedef uint16_t ogg_uint16_t;
typedef int32_t ogg_int32_t; typedef int32_t ogg_int32_t;
typedef u_int32_t ogg_uint32_t; typedef uint32_t ogg_uint32_t;
typedef int64_t ogg_int64_t; typedef int64_t ogg_int64_t;
#elif defined(__HAIKU__)
/* Haiku */
# include <sys/types.h>
typedef short ogg_int16_t;
typedef unsigned short ogg_uint16_t;
typedef int ogg_int32_t;
typedef unsigned int ogg_uint32_t;
typedef long long ogg_int64_t;
#elif defined(__BEOS__) #elif defined(__BEOS__)
/* Be */ /* Be */
# include <inttypes.h> # include <inttypes.h>
typedef int16_t ogg_int16_t; typedef int16_t ogg_int16_t;
typedef u_int16_t ogg_uint16_t; typedef uint16_t ogg_uint16_t;
typedef int32_t ogg_int32_t; typedef int32_t ogg_int32_t;
typedef u_int32_t ogg_uint32_t; typedef uint32_t ogg_uint32_t;
typedef int64_t ogg_int64_t; typedef int64_t ogg_int64_t;
#elif defined (__EMX__) #elif defined (__EMX__)
@ -117,9 +129,17 @@
typedef unsigned int ogg_uint32_t; typedef unsigned int ogg_uint32_t;
typedef long long int ogg_int64_t; typedef long long int ogg_int64_t;
#elif defined(__TMS320C6X__)
/* TI C64x compiler */
typedef signed short ogg_int16_t;
typedef unsigned short ogg_uint16_t;
typedef signed int ogg_int32_t;
typedef unsigned int ogg_uint32_t;
typedef long long int ogg_int64_t;
#else #else
# include <sys/types.h>
# include <ogg/config_types.h> # include <ogg/config_types.h>
#endif #endif

View file

@ -1,17 +1,17 @@
/******************************************************************** /********************************************************************
* * * *
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * * THIS FILE IS PART OF THE Ogg CONTAINER SOURCE CODE. *
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
* * * *
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002 * * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2010 *
* by the Xiph.Org Foundation http://www.xiph.org/ * * by the Xiph.Org Foundation http://www.xiph.org/ *
* * * *
******************************************************************** ********************************************************************
function: packing variable sized words into an octet stream function: packing variable sized words into an octet stream
last mod: $Id: bitwise.c 7675 2004-09-01 00:34:39Z xiphmont $ last mod: $Id: bitwise.c 18051 2011-08-04 17:56:39Z giles $
********************************************************************/ ********************************************************************/
@ -20,6 +20,7 @@
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <limits.h>
#include <ogg/ogg.h> #include <ogg/ogg.h>
#define BUFFER_INCREMENT 256 #define BUFFER_INCREMENT 256
@ -47,28 +48,47 @@ void oggpackB_writeinit(oggpack_buffer *b){
oggpack_writeinit(b); oggpack_writeinit(b);
} }
int oggpack_writecheck(oggpack_buffer *b){
if(!b->ptr || !b->storage)return -1;
return 0;
}
int oggpackB_writecheck(oggpack_buffer *b){
return oggpack_writecheck(b);
}
void oggpack_writetrunc(oggpack_buffer *b,long bits){ void oggpack_writetrunc(oggpack_buffer *b,long bits){
long bytes=bits>>3; long bytes=bits>>3;
if(b->ptr){
bits-=bytes*8; bits-=bytes*8;
b->ptr=b->buffer+bytes; b->ptr=b->buffer+bytes;
b->endbit=bits; b->endbit=bits;
b->endbyte=bytes; b->endbyte=bytes;
*b->ptr&=mask[bits]; *b->ptr&=mask[bits];
}
} }
void oggpackB_writetrunc(oggpack_buffer *b,long bits){ void oggpackB_writetrunc(oggpack_buffer *b,long bits){
long bytes=bits>>3; long bytes=bits>>3;
if(b->ptr){
bits-=bytes*8; bits-=bytes*8;
b->ptr=b->buffer+bytes; b->ptr=b->buffer+bytes;
b->endbit=bits; b->endbit=bits;
b->endbyte=bytes; b->endbyte=bytes;
*b->ptr&=mask8B[bits]; *b->ptr&=mask8B[bits];
}
} }
/* Takes only up to 32 bits. */ /* Takes only up to 32 bits. */
void oggpack_write(oggpack_buffer *b,unsigned long value,int bits){ void oggpack_write(oggpack_buffer *b,unsigned long value,int bits){
if(b->endbyte+4>=b->storage){ if(bits<0 || bits>32) goto err;
b->buffer=_ogg_realloc(b->buffer,b->storage+BUFFER_INCREMENT); if(b->endbyte>=b->storage-4){
void *ret;
if(!b->ptr)return;
if(b->storage>LONG_MAX-BUFFER_INCREMENT) goto err;
ret=_ogg_realloc(b->buffer,b->storage+BUFFER_INCREMENT);
if(!ret) goto err;
b->buffer=ret;
b->storage+=BUFFER_INCREMENT; b->storage+=BUFFER_INCREMENT;
b->ptr=b->buffer+b->endbyte; b->ptr=b->buffer+b->endbyte;
} }
@ -97,12 +117,21 @@ void oggpack_write(oggpack_buffer *b,unsigned long value,int bits){
b->endbyte+=bits/8; b->endbyte+=bits/8;
b->ptr+=bits/8; b->ptr+=bits/8;
b->endbit=bits&7; b->endbit=bits&7;
return;
err:
oggpack_writeclear(b);
} }
/* Takes only up to 32 bits. */ /* Takes only up to 32 bits. */
void oggpackB_write(oggpack_buffer *b,unsigned long value,int bits){ void oggpackB_write(oggpack_buffer *b,unsigned long value,int bits){
if(b->endbyte+4>=b->storage){ if(bits<0 || bits>32) goto err;
b->buffer=_ogg_realloc(b->buffer,b->storage+BUFFER_INCREMENT); if(b->endbyte>=b->storage-4){
void *ret;
if(!b->ptr)return;
if(b->storage>LONG_MAX-BUFFER_INCREMENT) goto err;
ret=_ogg_realloc(b->buffer,b->storage+BUFFER_INCREMENT);
if(!ret) goto err;
b->buffer=ret;
b->storage+=BUFFER_INCREMENT; b->storage+=BUFFER_INCREMENT;
b->ptr=b->buffer+b->endbyte; b->ptr=b->buffer+b->endbyte;
} }
@ -131,6 +160,9 @@ void oggpackB_write(oggpack_buffer *b,unsigned long value,int bits){
b->endbyte+=bits/8; b->endbyte+=bits/8;
b->ptr+=bits/8; b->ptr+=bits/8;
b->endbit=bits&7; b->endbit=bits&7;
return;
err:
oggpack_writeclear(b);
} }
void oggpack_writealign(oggpack_buffer *b){ void oggpack_writealign(oggpack_buffer *b){
@ -165,8 +197,13 @@ static void oggpack_writecopy_helper(oggpack_buffer *b,
}else{ }else{
/* aligned block copy */ /* aligned block copy */
if(b->endbyte+bytes+1>=b->storage){ if(b->endbyte+bytes+1>=b->storage){
void *ret;
if(!b->ptr) goto err;
if(b->endbyte+bytes+BUFFER_INCREMENT>b->storage) goto err;
b->storage=b->endbyte+bytes+BUFFER_INCREMENT; b->storage=b->endbyte+bytes+BUFFER_INCREMENT;
b->buffer=_ogg_realloc(b->buffer,b->storage); ret=_ogg_realloc(b->buffer,b->storage);
if(!ret) goto err;
b->buffer=ret;
b->ptr=b->buffer+b->endbyte; b->ptr=b->buffer+b->endbyte;
} }
@ -182,6 +219,9 @@ static void oggpack_writecopy_helper(oggpack_buffer *b,
else else
w(b,(unsigned long)(ptr[bytes]),bits); w(b,(unsigned long)(ptr[bytes]),bits);
} }
return;
err:
oggpack_writeclear(b);
} }
void oggpack_writecopy(oggpack_buffer *b,void *source,long bits){ void oggpack_writecopy(oggpack_buffer *b,void *source,long bits){
@ -193,6 +233,7 @@ void oggpackB_writecopy(oggpack_buffer *b,void *source,long bits){
} }
void oggpack_reset(oggpack_buffer *b){ void oggpack_reset(oggpack_buffer *b){
if(!b->ptr)return;
b->ptr=b->buffer; b->ptr=b->buffer;
b->buffer[0]=0; b->buffer[0]=0;
b->endbit=b->endbyte=0; b->endbit=b->endbyte=0;
@ -203,7 +244,7 @@ void oggpackB_reset(oggpack_buffer *b){
} }
void oggpack_writeclear(oggpack_buffer *b){ void oggpack_writeclear(oggpack_buffer *b){
_ogg_free(b->buffer); if(b->buffer)_ogg_free(b->buffer);
memset(b,0,sizeof(*b)); memset(b,0,sizeof(*b));
} }
@ -224,13 +265,18 @@ void oggpackB_readinit(oggpack_buffer *b,unsigned char *buf,int bytes){
/* Read in bits without advancing the bitptr; bits <= 32 */ /* Read in bits without advancing the bitptr; bits <= 32 */
long oggpack_look(oggpack_buffer *b,int bits){ long oggpack_look(oggpack_buffer *b,int bits){
unsigned long ret; unsigned long ret;
unsigned long m=mask[bits]; unsigned long m;
if(bits<0 || bits>32) return -1;
m=mask[bits];
bits+=b->endbit; bits+=b->endbit;
if(b->endbyte+4>=b->storage){ if(b->endbyte >= b->storage-4){
/* not the main path */ /* not the main path */
if(b->endbyte*8+bits>b->storage*8)return(-1); if(b->endbyte > b->storage-((bits+7)>>3)) return -1;
/* special case to avoid reading b->ptr[0], which might be past the end of
the buffer; also skips some useless accounting */
else if(!bits)return(0L);
} }
ret=b->ptr[0]>>b->endbit; ret=b->ptr[0]>>b->endbit;
@ -253,11 +299,15 @@ long oggpackB_look(oggpack_buffer *b,int bits){
unsigned long ret; unsigned long ret;
int m=32-bits; int m=32-bits;
if(m<0 || m>32) return -1;
bits+=b->endbit; bits+=b->endbit;
if(b->endbyte+4>=b->storage){ if(b->endbyte >= b->storage-4){
/* not the main path */ /* not the main path */
if(b->endbyte*8+bits>b->storage*8)return(-1); if(b->endbyte > b->storage-((bits+7)>>3)) return -1;
/* special case to avoid reading b->ptr[0], which might be past the end of
the buffer; also skips some useless accounting */
else if(!bits)return(0L);
} }
ret=b->ptr[0]<<(24+b->endbit); ret=b->ptr[0]<<(24+b->endbit);
@ -287,9 +337,18 @@ long oggpackB_look1(oggpack_buffer *b){
void oggpack_adv(oggpack_buffer *b,int bits){ void oggpack_adv(oggpack_buffer *b,int bits){
bits+=b->endbit; bits+=b->endbit;
if(b->endbyte > b->storage-((bits+7)>>3)) goto overflow;
b->ptr+=bits/8; b->ptr+=bits/8;
b->endbyte+=bits/8; b->endbyte+=bits/8;
b->endbit=bits&7; b->endbit=bits&7;
return;
overflow:
b->ptr=NULL;
b->endbyte=b->storage;
b->endbit=1;
} }
void oggpackB_adv(oggpack_buffer *b,int bits){ void oggpackB_adv(oggpack_buffer *b,int bits){
@ -311,14 +370,18 @@ void oggpackB_adv1(oggpack_buffer *b){
/* bits <= 32 */ /* bits <= 32 */
long oggpack_read(oggpack_buffer *b,int bits){ long oggpack_read(oggpack_buffer *b,int bits){
long ret; long ret;
unsigned long m=mask[bits]; unsigned long m;
if(bits<0 || bits>32) goto err;
m=mask[bits];
bits+=b->endbit; bits+=b->endbit;
if(b->endbyte+4>=b->storage){ if(b->endbyte >= b->storage-4){
/* not the main path */ /* not the main path */
ret=-1L; if(b->endbyte > b->storage-((bits+7)>>3)) goto overflow;
if(b->endbyte*8+bits>b->storage*8)goto overflow; /* special case to avoid reading b->ptr[0], which might be past the end of
the buffer; also skips some useless accounting */
else if(!bits)return(0L);
} }
ret=b->ptr[0]>>b->endbit; ret=b->ptr[0]>>b->endbit;
@ -335,13 +398,17 @@ long oggpack_read(oggpack_buffer *b,int bits){
} }
} }
ret&=m; ret&=m;
overflow:
b->ptr+=bits/8; b->ptr+=bits/8;
b->endbyte+=bits/8; b->endbyte+=bits/8;
b->endbit=bits&7; b->endbit=bits&7;
return(ret); return ret;
overflow:
err:
b->ptr=NULL;
b->endbyte=b->storage;
b->endbit=1;
return -1L;
} }
/* bits <= 32 */ /* bits <= 32 */
@ -349,12 +416,15 @@ long oggpackB_read(oggpack_buffer *b,int bits){
long ret; long ret;
long m=32-bits; long m=32-bits;
if(m<0 || m>32) goto err;
bits+=b->endbit; bits+=b->endbit;
if(b->endbyte+4>=b->storage){ if(b->endbyte+4>=b->storage){
/* not the main path */ /* not the main path */
ret=-1L; if(b->endbyte > b->storage-((bits+7)>>3)) goto overflow;
if(b->endbyte*8+bits>b->storage*8)goto overflow; /* special case to avoid reading b->ptr[0], which might be past the end of
the buffer; also skips some useless accounting */
else if(!bits)return(0L);
} }
ret=b->ptr[0]<<(24+b->endbit); ret=b->ptr[0]<<(24+b->endbit);
@ -371,56 +441,59 @@ long oggpackB_read(oggpack_buffer *b,int bits){
} }
ret=((ret&0xffffffffUL)>>(m>>1))>>((m+1)>>1); ret=((ret&0xffffffffUL)>>(m>>1))>>((m+1)>>1);
overflow:
b->ptr+=bits/8; b->ptr+=bits/8;
b->endbyte+=bits/8; b->endbyte+=bits/8;
b->endbit=bits&7; b->endbit=bits&7;
return(ret); return ret;
overflow:
err:
b->ptr=NULL;
b->endbyte=b->storage;
b->endbit=1;
return -1L;
} }
long oggpack_read1(oggpack_buffer *b){ long oggpack_read1(oggpack_buffer *b){
long ret; long ret;
if(b->endbyte>=b->storage){ if(b->endbyte >= b->storage) goto overflow;
/* not the main path */
ret=-1L;
goto overflow;
}
ret=(b->ptr[0]>>b->endbit)&1; ret=(b->ptr[0]>>b->endbit)&1;
overflow:
b->endbit++; b->endbit++;
if(b->endbit>7){ if(b->endbit>7){
b->endbit=0; b->endbit=0;
b->ptr++; b->ptr++;
b->endbyte++; b->endbyte++;
} }
return(ret); return ret;
overflow:
b->ptr=NULL;
b->endbyte=b->storage;
b->endbit=1;
return -1L;
} }
long oggpackB_read1(oggpack_buffer *b){ long oggpackB_read1(oggpack_buffer *b){
long ret; long ret;
if(b->endbyte>=b->storage){ if(b->endbyte >= b->storage) goto overflow;
/* not the main path */
ret=-1L;
goto overflow;
}
ret=(b->ptr[0]>>(7-b->endbit))&1; ret=(b->ptr[0]>>(7-b->endbit))&1;
overflow:
b->endbit++; b->endbit++;
if(b->endbit>7){ if(b->endbit>7){
b->endbit=0; b->endbit=0;
b->ptr++; b->ptr++;
b->endbyte++; b->endbyte++;
} }
return(ret); return ret;
overflow:
b->ptr=NULL;
b->endbyte=b->storage;
b->endbit=1;
return -1L;
} }
long oggpack_bytes(oggpack_buffer *b){ long oggpack_bytes(oggpack_buffer *b){
@ -654,7 +727,7 @@ int main(void){
fprintf(stderr,"ok."); fprintf(stderr,"ok.");
fprintf(stderr,"\nTesting read past end (LSb): "); fprintf(stderr,"\nTesting read past end (LSb): ");
oggpack_readinit(&r,"\0\0\0\0\0\0\0\0",8); oggpack_readinit(&r,(unsigned char *)"\0\0\0\0\0\0\0\0",8);
for(i=0;i<64;i++){ for(i=0;i<64;i++){
if(oggpack_read(&r,1)!=0){ if(oggpack_read(&r,1)!=0){
fprintf(stderr,"failed; got -1 prematurely.\n"); fprintf(stderr,"failed; got -1 prematurely.\n");
@ -666,7 +739,7 @@ int main(void){
fprintf(stderr,"failed; read past end without -1.\n"); fprintf(stderr,"failed; read past end without -1.\n");
exit(1); exit(1);
} }
oggpack_readinit(&r,"\0\0\0\0\0\0\0\0",8); oggpack_readinit(&r,(unsigned char *)"\0\0\0\0\0\0\0\0",8);
if(oggpack_read(&r,30)!=0 || oggpack_read(&r,16)!=0){ if(oggpack_read(&r,30)!=0 || oggpack_read(&r,16)!=0){
fprintf(stderr,"failed 2; got -1 prematurely.\n"); fprintf(stderr,"failed 2; got -1 prematurely.\n");
exit(1); exit(1);
@ -740,7 +813,7 @@ int main(void){
fprintf(stderr,"ok."); fprintf(stderr,"ok.");
fprintf(stderr,"\nTesting read past end (MSb): "); fprintf(stderr,"\nTesting read past end (MSb): ");
oggpackB_readinit(&r,"\0\0\0\0\0\0\0\0",8); oggpackB_readinit(&r,(unsigned char *)"\0\0\0\0\0\0\0\0",8);
for(i=0;i<64;i++){ for(i=0;i<64;i++){
if(oggpackB_read(&r,1)!=0){ if(oggpackB_read(&r,1)!=0){
fprintf(stderr,"failed; got -1 prematurely.\n"); fprintf(stderr,"failed; got -1 prematurely.\n");
@ -752,7 +825,7 @@ int main(void){
fprintf(stderr,"failed; read past end without -1.\n"); fprintf(stderr,"failed; read past end without -1.\n");
exit(1); exit(1);
} }
oggpackB_readinit(&r,"\0\0\0\0\0\0\0\0",8); oggpackB_readinit(&r,(unsigned char *)"\0\0\0\0\0\0\0\0",8);
if(oggpackB_read(&r,30)!=0 || oggpackB_read(&r,16)!=0){ if(oggpackB_read(&r,30)!=0 || oggpackB_read(&r,16)!=0){
fprintf(stderr,"failed 2; got -1 prematurely.\n"); fprintf(stderr,"failed 2; got -1 prematurely.\n");
exit(1); exit(1);

View file

@ -1,18 +1,18 @@
/******************************************************************** /********************************************************************
* * * *
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * * THIS FILE IS PART OF THE Ogg CONTAINER SOURCE CODE. *
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
* * * *
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002 * * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2010 *
* by the Xiph.Org Foundation http://www.xiph.org/ * * by the Xiph.Org Foundation http://www.xiph.org/ *
* * * *
******************************************************************** ********************************************************************
function: code raw [Vorbis] packets into framed OggSquish stream and function: code raw packets into framed OggSquish stream and
decode Ogg streams back into raw packets decode Ogg streams back into raw packets
last mod: $Id: framing.c 9601 2005-07-23 00:19:14Z giles $ last mod: $Id: framing.c 18052 2011-08-04 17:57:02Z giles $
note: The CRC code is directly derived from public domain code by note: The CRC code is directly derived from public domain code by
Ross Williams (ross@guest.adelaide.edu.au). See docs/framing.html Ross Williams (ross@guest.adelaide.edu.au). See docs/framing.html
@ -26,23 +26,23 @@
/* A complete description of Ogg framing exists in docs/framing.html */ /* A complete description of Ogg framing exists in docs/framing.html */
int ogg_page_version(ogg_page *og){ int ogg_page_version(const ogg_page *og){
return((int)(og->header[4])); return((int)(og->header[4]));
} }
int ogg_page_continued(ogg_page *og){ int ogg_page_continued(const ogg_page *og){
return((int)(og->header[5]&0x01)); return((int)(og->header[5]&0x01));
} }
int ogg_page_bos(ogg_page *og){ int ogg_page_bos(const ogg_page *og){
return((int)(og->header[5]&0x02)); return((int)(og->header[5]&0x02));
} }
int ogg_page_eos(ogg_page *og){ int ogg_page_eos(const ogg_page *og){
return((int)(og->header[5]&0x04)); return((int)(og->header[5]&0x04));
} }
ogg_int64_t ogg_page_granulepos(ogg_page *og){ ogg_int64_t ogg_page_granulepos(const ogg_page *og){
unsigned char *page=og->header; unsigned char *page=og->header;
ogg_int64_t granulepos=page[13]&(0xff); ogg_int64_t granulepos=page[13]&(0xff);
granulepos= (granulepos<<8)|(page[12]&0xff); granulepos= (granulepos<<8)|(page[12]&0xff);
@ -55,14 +55,14 @@ ogg_int64_t ogg_page_granulepos(ogg_page *og){
return(granulepos); return(granulepos);
} }
int ogg_page_serialno(ogg_page *og){ int ogg_page_serialno(const ogg_page *og){
return(og->header[14] | return(og->header[14] |
(og->header[15]<<8) | (og->header[15]<<8) |
(og->header[16]<<16) | (og->header[16]<<16) |
(og->header[17]<<24)); (og->header[17]<<24));
} }
long ogg_page_pageno(ogg_page *og){ long ogg_page_pageno(const ogg_page *og){
return(og->header[18] | return(og->header[18] |
(og->header[19]<<8) | (og->header[19]<<8) |
(og->header[20]<<16) | (og->header[20]<<16) |
@ -76,19 +76,19 @@ long ogg_page_pageno(ogg_page *og){
page, it's counted */ page, it's counted */
/* NOTE: /* NOTE:
If a page consists of a packet begun on a previous page, and a new If a page consists of a packet begun on a previous page, and a new
packet begun (but not completed) on this page, the return will be: packet begun (but not completed) on this page, the return will be:
ogg_page_packets(page) ==1, ogg_page_packets(page) ==1,
ogg_page_continued(page) !=0 ogg_page_continued(page) !=0
If a page happens to be a single packet that was begun on a If a page happens to be a single packet that was begun on a
previous page, and spans to the next page (in the case of a three or previous page, and spans to the next page (in the case of a three or
more page packet), the return will be: more page packet), the return will be:
ogg_page_packets(page) ==0, ogg_page_packets(page) ==0,
ogg_page_continued(page) !=0 ogg_page_continued(page) !=0
*/ */
int ogg_page_packets(ogg_page *og){ int ogg_page_packets(const ogg_page *og){
int i,n=og->header[26],count=0; int i,n=og->header[26],count=0;
for(i=0;i<n;i++) for(i=0;i<n;i++)
if(og->header[27+i]<255)count++; if(og->header[27+i]<255)count++;
@ -189,12 +189,17 @@ int ogg_stream_init(ogg_stream_state *os,int serialno){
if(os){ if(os){
memset(os,0,sizeof(*os)); memset(os,0,sizeof(*os));
os->body_storage=16*1024; os->body_storage=16*1024;
os->body_data=_ogg_malloc(os->body_storage*sizeof(*os->body_data));
os->lacing_storage=1024; os->lacing_storage=1024;
os->body_data=_ogg_malloc(os->body_storage*sizeof(*os->body_data));
os->lacing_vals=_ogg_malloc(os->lacing_storage*sizeof(*os->lacing_vals)); os->lacing_vals=_ogg_malloc(os->lacing_storage*sizeof(*os->lacing_vals));
os->granule_vals=_ogg_malloc(os->lacing_storage*sizeof(*os->granule_vals)); os->granule_vals=_ogg_malloc(os->lacing_storage*sizeof(*os->granule_vals));
if(!os->body_data || !os->lacing_vals || !os->granule_vals){
ogg_stream_clear(os);
return -1;
}
os->serialno=serialno; os->serialno=serialno;
return(0); return(0);
@ -202,6 +207,12 @@ int ogg_stream_init(ogg_stream_state *os,int serialno){
return(-1); return(-1);
} }
/* async/delayed error detection for the ogg_stream_state */
int ogg_stream_check(ogg_stream_state *os){
if(!os || !os->body_data) return -1;
return 0;
}
/* _clear does not free os, only the non-flat storage within */ /* _clear does not free os, only the non-flat storage within */
int ogg_stream_clear(ogg_stream_state *os){ int ogg_stream_clear(ogg_stream_state *os){
if(os){ if(os){
@ -225,24 +236,46 @@ int ogg_stream_destroy(ogg_stream_state *os){
/* Helpers for ogg_stream_encode; this keeps the structure and /* Helpers for ogg_stream_encode; this keeps the structure and
what's happening fairly clear */ what's happening fairly clear */
static void _os_body_expand(ogg_stream_state *os,int needed){ static int _os_body_expand(ogg_stream_state *os,int needed){
if(os->body_storage<=os->body_fill+needed){ if(os->body_storage<=os->body_fill+needed){
os->body_storage+=(needed+1024); void *ret;
os->body_data=_ogg_realloc(os->body_data,os->body_storage*sizeof(*os->body_data)); ret=_ogg_realloc(os->body_data,(os->body_storage+needed+1024)*
sizeof(*os->body_data));
if(!ret){
ogg_stream_clear(os);
return -1;
} }
os->body_storage+=(needed+1024);
os->body_data=ret;
}
return 0;
} }
static void _os_lacing_expand(ogg_stream_state *os,int needed){ static int _os_lacing_expand(ogg_stream_state *os,int needed){
if(os->lacing_storage<=os->lacing_fill+needed){ if(os->lacing_storage<=os->lacing_fill+needed){
os->lacing_storage+=(needed+32); void *ret;
os->lacing_vals=_ogg_realloc(os->lacing_vals,os->lacing_storage*sizeof(*os->lacing_vals)); ret=_ogg_realloc(os->lacing_vals,(os->lacing_storage+needed+32)*
os->granule_vals=_ogg_realloc(os->granule_vals,os->lacing_storage*sizeof(*os->granule_vals)); sizeof(*os->lacing_vals));
if(!ret){
ogg_stream_clear(os);
return -1;
} }
os->lacing_vals=ret;
ret=_ogg_realloc(os->granule_vals,(os->lacing_storage+needed+32)*
sizeof(*os->granule_vals));
if(!ret){
ogg_stream_clear(os);
return -1;
}
os->granule_vals=ret;
os->lacing_storage+=(needed+32);
}
return 0;
} }
/* checksum the page */ /* checksum the page */
/* Direct table CRC; note that this will be faster in the future if we /* Direct table CRC; note that this will be faster in the future if we
perform the checksum silmultaneously with other copies */ perform the checksum simultaneously with other copies */
void ogg_page_checksum_set(ogg_page *og){ void ogg_page_checksum_set(ogg_page *og){
if(og){ if(og){
@ -268,8 +301,16 @@ void ogg_page_checksum_set(ogg_page *og){
} }
/* submit data to the internal buffer of the framing engine */ /* submit data to the internal buffer of the framing engine */
int ogg_stream_packetin(ogg_stream_state *os,ogg_packet *op){ int ogg_stream_iovecin(ogg_stream_state *os, ogg_iovec_t *iov, int count,
int lacing_vals=op->bytes/255+1,i; long e_o_s, ogg_int64_t granulepos){
int bytes = 0, lacing_vals, i;
if(ogg_stream_check(os)) return -1;
if(!iov) return 0;
for (i = 0; i < count; ++i) bytes += (int)iov[i].iov_len;
lacing_vals=bytes/255+1;
if(os->body_returned){ if(os->body_returned){
/* advance packet data according to the body_returned pointer. We /* advance packet data according to the body_returned pointer. We
@ -284,24 +325,26 @@ int ogg_stream_packetin(ogg_stream_state *os,ogg_packet *op){
} }
/* make sure we have the buffer storage */ /* make sure we have the buffer storage */
_os_body_expand(os,op->bytes); if(_os_body_expand(os,bytes) || _os_lacing_expand(os,lacing_vals))
_os_lacing_expand(os,lacing_vals); return -1;
/* Copy in the submitted packet. Yes, the copy is a waste; this is /* Copy in the submitted packet. Yes, the copy is a waste; this is
the liability of overly clean abstraction for the time being. It the liability of overly clean abstraction for the time being. It
will actually be fairly easy to eliminate the extra copy in the will actually be fairly easy to eliminate the extra copy in the
future */ future */
memcpy(os->body_data+os->body_fill,op->packet,op->bytes); for (i = 0; i < count; ++i) {
os->body_fill+=op->bytes; memcpy(os->body_data+os->body_fill, iov[i].iov_base, iov[i].iov_len);
os->body_fill += (int)iov[i].iov_len;
}
/* Store lacing vals for this packet */ /* Store lacing vals for this packet */
for(i=0;i<lacing_vals-1;i++){ for(i=0;i<lacing_vals-1;i++){
os->lacing_vals[os->lacing_fill+i]=255; os->lacing_vals[os->lacing_fill+i]=255;
os->granule_vals[os->lacing_fill+i]=os->granulepos; os->granule_vals[os->lacing_fill+i]=os->granulepos;
} }
os->lacing_vals[os->lacing_fill+i]=(op->bytes)%255; os->lacing_vals[os->lacing_fill+i]=bytes%255;
os->granulepos=os->granule_vals[os->lacing_fill+i]=op->granulepos; os->granulepos=os->granule_vals[os->lacing_fill+i]=granulepos;
/* flag the first segment as the beginning of the packet */ /* flag the first segment as the beginning of the packet */
os->lacing_vals[os->lacing_fill]|= 0x100; os->lacing_vals[os->lacing_fill]|= 0x100;
@ -311,26 +354,22 @@ int ogg_stream_packetin(ogg_stream_state *os,ogg_packet *op){
/* for the sake of completeness */ /* for the sake of completeness */
os->packetno++; os->packetno++;
if(op->e_o_s)os->e_o_s=1; if(e_o_s)os->e_o_s=1;
return(0); return(0);
} }
/* This will flush remaining packets into a page (returning nonzero), int ogg_stream_packetin(ogg_stream_state *os,ogg_packet *op){
even if there is not enough data to trigger a flush normally ogg_iovec_t iov;
(undersized page). If there are no packets or partial packets to iov.iov_base = op->packet;
flush, ogg_stream_flush returns 0. Note that ogg_stream_flush will iov.iov_len = op->bytes;
try to flush a normal sized page like ogg_stream_pageout; a call to return ogg_stream_iovecin(os, &iov, 1, op->e_o_s, op->granulepos);
ogg_stream_flush does not guarantee that all packets have flushed. }
Only a return value of 0 from ogg_stream_flush indicates all packet
data is flushed into pages.
since ogg_stream_flush will flush the last page in a stream even if /* Conditionally flush a page; force==0 will only flush nominal-size
it's undersized, you almost certainly want to use ogg_stream_pageout pages, force==1 forces us to flush a page regardless of page size
(and *not* ogg_stream_flush) unless you specifically need to flush so long as there's any data available at all. */
an page regardless of size in the middle of a stream. */ static int ogg_stream_flush_i(ogg_stream_state *os,ogg_page *og, int force, int nfill){
int ogg_stream_flush(ogg_stream_state *os,ogg_page *og){
int i; int i;
int vals=0; int vals=0;
int maxvals=(os->lacing_fill>255?255:os->lacing_fill); int maxvals=(os->lacing_fill>255?255:os->lacing_fill);
@ -338,7 +377,8 @@ int ogg_stream_flush(ogg_stream_state *os,ogg_page *og){
long acc=0; long acc=0;
ogg_int64_t granule_pos=-1; ogg_int64_t granule_pos=-1;
if(maxvals==0)return(0); if(ogg_stream_check(os)) return(0);
if(maxvals==0) return(0);
/* construct a page */ /* construct a page */
/* decide how many segments to include */ /* decide how many segments to include */
@ -354,14 +394,35 @@ int ogg_stream_flush(ogg_stream_state *os,ogg_page *og){
} }
} }
}else{ }else{
/* The extra packets_done, packet_just_done logic here attempts to do two things:
1) Don't unneccessarily span pages.
2) Unless necessary, don't flush pages if there are less than four packets on
them; this expands page size to reduce unneccessary overhead if incoming packets
are large.
These are not necessary behaviors, just 'always better than naive flushing'
without requiring an application to explicitly request a specific optimized
behavior. We'll want an explicit behavior setup pathway eventually as well. */
int packets_done=0;
int packet_just_done=0;
for(vals=0;vals<maxvals;vals++){ for(vals=0;vals<maxvals;vals++){
if(acc>4096)break; if(acc>nfill && packet_just_done>=4){
force=1;
break;
}
acc+=os->lacing_vals[vals]&0x0ff; acc+=os->lacing_vals[vals]&0x0ff;
if((os->lacing_vals[vals]&0xff)<255) if((os->lacing_vals[vals]&0xff)<255){
granule_pos=os->granule_vals[vals]; granule_pos=os->granule_vals[vals];
packet_just_done=++packets_done;
}else
packet_just_done=0;
} }
if(vals==255)force=1;
} }
if(!force) return(0);
/* construct the header in temp storage */ /* construct the header in temp storage */
memcpy(os->header,"OggS",4); memcpy(os->header,"OggS",4);
@ -439,26 +500,64 @@ int ogg_stream_flush(ogg_stream_state *os,ogg_page *og){
return(1); return(1);
} }
/* This will flush remaining packets into a page (returning nonzero),
even if there is not enough data to trigger a flush normally
(undersized page). If there are no packets or partial packets to
flush, ogg_stream_flush returns 0. Note that ogg_stream_flush will
try to flush a normal sized page like ogg_stream_pageout; a call to
ogg_stream_flush does not guarantee that all packets have flushed.
Only a return value of 0 from ogg_stream_flush indicates all packet
data is flushed into pages.
since ogg_stream_flush will flush the last page in a stream even if
it's undersized, you almost certainly want to use ogg_stream_pageout
(and *not* ogg_stream_flush) unless you specifically need to flush
a page regardless of size in the middle of a stream. */
int ogg_stream_flush(ogg_stream_state *os,ogg_page *og){
return ogg_stream_flush_i(os,og,1,4096);
}
/* Like the above, but an argument is provided to adjust the nominal
page size for applications which are smart enough to provide their
own delay based flushing */
int ogg_stream_flush_fill(ogg_stream_state *os,ogg_page *og, int nfill){
return ogg_stream_flush_i(os,og,1,nfill);
}
/* This constructs pages from buffered packet segments. The pointers /* This constructs pages from buffered packet segments. The pointers
returned are to static buffers; do not free. The returned buffers are returned are to static buffers; do not free. The returned buffers are
good only until the next call (using the same ogg_stream_state) */ good only until the next call (using the same ogg_stream_state) */
int ogg_stream_pageout(ogg_stream_state *os, ogg_page *og){ int ogg_stream_pageout(ogg_stream_state *os, ogg_page *og){
int force=0;
if(ogg_stream_check(os)) return 0;
if((os->e_o_s&&os->lacing_fill) || /* 'were done, now flush' case */ if((os->e_o_s&&os->lacing_fill) || /* 'were done, now flush' case */
os->body_fill-os->body_returned > 4096 ||/* 'page nominal size' case */ (os->lacing_fill&&!os->b_o_s)) /* 'initial header page' case */
os->lacing_fill>=255 || /* 'segment table full' case */ force=1;
(os->lacing_fill&&!os->b_o_s)){ /* 'initial header page' case */
return(ogg_stream_flush(os,og)); return(ogg_stream_flush_i(os,og,force,4096));
} }
/* not enough data to construct a page and not end of stream */ /* Like the above, but an argument is provided to adjust the nominal
return(0); page size for applications which are smart enough to provide their
own delay based flushing */
int ogg_stream_pageout_fill(ogg_stream_state *os, ogg_page *og, int nfill){
int force=0;
if(ogg_stream_check(os)) return 0;
if((os->e_o_s&&os->lacing_fill) || /* 'were done, now flush' case */
(os->lacing_fill&&!os->b_o_s)) /* 'initial header page' case */
force=1;
return(ogg_stream_flush_i(os,og,force,nfill));
} }
int ogg_stream_eos(ogg_stream_state *os){ int ogg_stream_eos(ogg_stream_state *os){
if(ogg_stream_check(os)) return 1;
return os->e_o_s; return os->e_o_s;
} }
@ -480,6 +579,7 @@ int ogg_stream_eos(ogg_stream_state *os){
/* initialize the struct to a known state */ /* initialize the struct to a known state */
int ogg_sync_init(ogg_sync_state *oy){ int ogg_sync_init(ogg_sync_state *oy){
if(oy){ if(oy){
oy->storage = -1; /* used as a readiness flag */
memset(oy,0,sizeof(*oy)); memset(oy,0,sizeof(*oy));
} }
return(0); return(0);
@ -489,7 +589,7 @@ int ogg_sync_init(ogg_sync_state *oy){
int ogg_sync_clear(ogg_sync_state *oy){ int ogg_sync_clear(ogg_sync_state *oy){
if(oy){ if(oy){
if(oy->data)_ogg_free(oy->data); if(oy->data)_ogg_free(oy->data);
ogg_sync_init(oy); memset(oy,0,sizeof(*oy));
} }
return(0); return(0);
} }
@ -502,7 +602,13 @@ int ogg_sync_destroy(ogg_sync_state *oy){
return(0); return(0);
} }
int ogg_sync_check(ogg_sync_state *oy){
if(oy->storage<0) return -1;
return 0;
}
char *ogg_sync_buffer(ogg_sync_state *oy, long size){ char *ogg_sync_buffer(ogg_sync_state *oy, long size){
if(ogg_sync_check(oy)) return NULL;
/* first, clear out any space that has been previously returned */ /* first, clear out any space that has been previously returned */
if(oy->returned){ if(oy->returned){
@ -515,11 +621,17 @@ char *ogg_sync_buffer(ogg_sync_state *oy, long size){
if(size>oy->storage-oy->fill){ if(size>oy->storage-oy->fill){
/* We need to extend the internal buffer */ /* We need to extend the internal buffer */
long newsize=size+oy->fill+4096; /* an extra page to be nice */ long newsize=size+oy->fill+4096; /* an extra page to be nice */
void *ret;
if(oy->data) if(oy->data)
oy->data=_ogg_realloc(oy->data,newsize); ret=_ogg_realloc(oy->data,newsize);
else else
oy->data=_ogg_malloc(newsize); ret=_ogg_malloc(newsize);
if(!ret){
ogg_sync_clear(oy);
return NULL;
}
oy->data=ret;
oy->storage=newsize; oy->storage=newsize;
} }
@ -528,7 +640,8 @@ char *ogg_sync_buffer(ogg_sync_state *oy, long size){
} }
int ogg_sync_wrote(ogg_sync_state *oy, long bytes){ int ogg_sync_wrote(ogg_sync_state *oy, long bytes){
if(oy->fill+bytes>oy->storage)return(-1); if(ogg_sync_check(oy))return -1;
if(oy->fill+bytes>oy->storage)return -1;
oy->fill+=bytes; oy->fill+=bytes;
return(0); return(0);
} }
@ -548,6 +661,8 @@ long ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og){
unsigned char *next; unsigned char *next;
long bytes=oy->fill-oy->returned; long bytes=oy->fill-oy->returned;
if(ogg_sync_check(oy))return 0;
if(oy->headerbytes==0){ if(oy->headerbytes==0){
int headerbytes,i; int headerbytes,i;
if(bytes<27)return(0); /* not enough for a header */ if(bytes<27)return(0); /* not enough for a header */
@ -624,12 +739,12 @@ long ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og){
if(!next) if(!next)
next=oy->data+oy->fill; next=oy->data+oy->fill;
oy->returned=next-oy->data; oy->returned=(int)(next-oy->data);
return(-(next-page)); return((long)-(next-page));
} }
/* sync the stream and get a page. Keep trying until we find a page. /* sync the stream and get a page. Keep trying until we find a page.
Supress 'sync errors' after reporting the first. Suppress 'sync errors' after reporting the first.
return values: return values:
-1) recapture (hole in data) -1) recapture (hole in data)
@ -641,6 +756,8 @@ long ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og){
int ogg_sync_pageout(ogg_sync_state *oy, ogg_page *og){ int ogg_sync_pageout(ogg_sync_state *oy, ogg_page *og){
if(ogg_sync_check(oy))return 0;
/* all we need to do is verify a page at the head of the stream /* all we need to do is verify a page at the head of the stream
buffer. If it doesn't verify, we look for the next potential buffer. If it doesn't verify, we look for the next potential
frame */ frame */
@ -685,6 +802,8 @@ int ogg_stream_pagein(ogg_stream_state *os, ogg_page *og){
long pageno=ogg_page_pageno(og); long pageno=ogg_page_pageno(og);
int segments=header[26]; int segments=header[26];
if(ogg_stream_check(os)) return -1;
/* clean up 'returned data' */ /* clean up 'returned data' */
{ {
long lr=os->lacing_returned; long lr=os->lacing_returned;
@ -716,7 +835,7 @@ int ogg_stream_pagein(ogg_stream_state *os, ogg_page *og){
if(serialno!=os->serialno)return(-1); if(serialno!=os->serialno)return(-1);
if(version>0)return(-1); if(version>0)return(-1);
_os_lacing_expand(os,segments+1); if(_os_lacing_expand(os,segments+1)) return -1;
/* are we in sequence? */ /* are we in sequence? */
if(pageno!=os->pageno){ if(pageno!=os->pageno){
@ -753,7 +872,7 @@ int ogg_stream_pagein(ogg_stream_state *os, ogg_page *og){
} }
if(bodysize){ if(bodysize){
_os_body_expand(os,bodysize); if(_os_body_expand(os,bodysize)) return -1;
memcpy(os->body_data+os->body_fill,body,bodysize); memcpy(os->body_data+os->body_fill,body,bodysize);
os->body_fill+=bodysize; os->body_fill+=bodysize;
} }
@ -798,6 +917,8 @@ int ogg_stream_pagein(ogg_stream_state *os, ogg_page *og){
/* clear things to an initial state. Good to call, eg, before seeking */ /* clear things to an initial state. Good to call, eg, before seeking */
int ogg_sync_reset(ogg_sync_state *oy){ int ogg_sync_reset(ogg_sync_state *oy){
if(ogg_sync_check(oy))return -1;
oy->fill=0; oy->fill=0;
oy->returned=0; oy->returned=0;
oy->unsynced=0; oy->unsynced=0;
@ -807,6 +928,8 @@ int ogg_sync_reset(ogg_sync_state *oy){
} }
int ogg_stream_reset(ogg_stream_state *os){ int ogg_stream_reset(ogg_stream_state *os){
if(ogg_stream_check(os)) return -1;
os->body_fill=0; os->body_fill=0;
os->body_returned=0; os->body_returned=0;
@ -826,6 +949,7 @@ int ogg_stream_reset(ogg_stream_state *os){
} }
int ogg_stream_reset_serialno(ogg_stream_state *os,int serialno){ int ogg_stream_reset_serialno(ogg_stream_state *os,int serialno){
if(ogg_stream_check(os)) return -1;
ogg_stream_reset(os); ogg_stream_reset(os);
os->serialno=serialno; os->serialno=serialno;
return(0); return(0);
@ -856,7 +980,7 @@ static int _packetout(ogg_stream_state *os,ogg_packet *op,int adv){
/* Gather the whole packet. We'll have no holes or a partial packet */ /* Gather the whole packet. We'll have no holes or a partial packet */
{ {
int size=os->lacing_vals[ptr]&0xff; int size=os->lacing_vals[ptr]&0xff;
int bytes=size; long bytes=size;
int eos=os->lacing_vals[ptr]&0x200; /* last packet of the stream? */ int eos=os->lacing_vals[ptr]&0x200; /* last packet of the stream? */
int bos=os->lacing_vals[ptr]&0x100; /* first packet of the stream? */ int bos=os->lacing_vals[ptr]&0x100; /* first packet of the stream? */
@ -886,10 +1010,12 @@ static int _packetout(ogg_stream_state *os,ogg_packet *op,int adv){
} }
int ogg_stream_packetout(ogg_stream_state *os,ogg_packet *op){ int ogg_stream_packetout(ogg_stream_state *os,ogg_packet *op){
if(ogg_stream_check(os)) return 0;
return _packetout(os,op,1); return _packetout(os,op,1);
} }
int ogg_stream_packetpeek(ogg_stream_state *os,ogg_packet *op){ int ogg_stream_packetpeek(ogg_stream_state *os,ogg_packet *op){
if(ogg_stream_check(os)) return 0;
return _packetout(os,op,0); return _packetout(os,op,0);
} }
@ -904,17 +1030,17 @@ void ogg_packet_clear(ogg_packet *op) {
ogg_stream_state os_en, os_de; ogg_stream_state os_en, os_de;
ogg_sync_state oy; ogg_sync_state oy;
void checkpacket(ogg_packet *op,int len, int no, int pos){ void checkpacket(ogg_packet *op,long len, int no, long pos){
long j; long j;
static int sequence=0; static int sequence=0;
static int lastno=0; static int lastno=0;
if(op->bytes!=len){ if(op->bytes!=len){
fprintf(stderr,"incorrect packet length!\n"); fprintf(stderr,"incorrect packet length (%ld != %ld)!\n",op->bytes,len);
exit(1); exit(1);
} }
if(op->granulepos!=pos){ if(op->granulepos!=pos){
fprintf(stderr,"incorrect packet position!\n"); fprintf(stderr,"incorrect packet granpos (%ld != %ld)!\n",(long)op->granulepos,pos);
exit(1); exit(1);
} }
@ -1081,19 +1207,73 @@ const int head1_4[] = {0x4f,0x67,0x67,0x53,0,0x02,
const int head2_4[] = {0x4f,0x67,0x67,0x53,0,0x00, const int head2_4[] = {0x4f,0x67,0x67,0x53,0,0x00,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0x01,0x02,0x03,0x04,1,0,0,0, 0x01,0x02,0x03,0x04,1,0,0,0,
0x54,0x05,0x51,0xc8, 0xf8,0x3c,0x19,0x79,
17, 255,
255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255}; 255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255};
const int head3_4[] = {0x4f,0x67,0x67,0x53,0,0x05, const int head3_4[] = {0x4f,0x67,0x67,0x53,0,0x05,
0x07,0x0c,0x00,0x00,0x00,0x00,0x00,0x00, 0x07,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,
0x01,0x02,0x03,0x04,2,0,0,0, 0x01,0x02,0x03,0x04,2,0,0,0,
0xc8,0xc3,0xcb,0xed, 0x38,0xe6,0xb6,0x28,
5, 6,
10,255,4,255,0}; 255,220,255,4,255,0};
/* spill expansion test */
const int head1_4b[] = {0x4f,0x67,0x67,0x53,0,0x02,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x01,0x02,0x03,0x04,0,0,0,0,
0xff,0x7b,0x23,0x17,
1,
0};
const int head2_4b[] = {0x4f,0x67,0x67,0x53,0,0x00,
0x07,0x10,0x00,0x00,0x00,0x00,0x00,0x00,
0x01,0x02,0x03,0x04,1,0,0,0,
0xce,0x8f,0x17,0x1a,
23,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,10,255,4,255,0,0};
const int head3_4b[] = {0x4f,0x67,0x67,0x53,0,0x04,
0x07,0x14,0x00,0x00,0x00,0x00,0x00,0x00,
0x01,0x02,0x03,0x04,2,0,0,0,
0x9b,0xb2,0x50,0xa1,
1,
0};
/* page with the 255 segment limit */ /* page with the 255 segment limit */
const int head1_5[] = {0x4f,0x67,0x67,0x53,0,0x02, const int head1_5[] = {0x4f,0x67,0x67,0x53,0,0x02,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
@ -1159,25 +1339,86 @@ const int head1_6[] = {0x4f,0x67,0x67,0x53,0,0x02,
const int head2_6[] = {0x4f,0x67,0x67,0x53,0,0x00, const int head2_6[] = {0x4f,0x67,0x67,0x53,0,0x00,
0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00, 0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
0x01,0x02,0x03,0x04,1,0,0,0, 0x01,0x02,0x03,0x04,1,0,0,0,
0x3c,0xd9,0x4d,0x3f, 0x68,0x22,0x7c,0x3d,
17, 255,
100,255,255,255,255,255,255,255,255, 100,
255,255,255,255,255,255,255,255}; 255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255};
const int head3_6[] = {0x4f,0x67,0x67,0x53,0,0x01, const int head3_6[] = {0x4f,0x67,0x67,0x53,0,0x01,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0x01,0x02,0x03,0x04,2,0,0,0, 0x01,0x02,0x03,0x04,2,0,0,0,
0x01,0xd2,0xe5,0xe5, 0xf4,0x87,0xba,0xf3,
17, 255,
255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255}; 255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255};
const int head4_6[] = {0x4f,0x67,0x67,0x53,0,0x05, const int head4_6[] = {0x4f,0x67,0x67,0x53,0,0x05,
0x07,0x10,0x00,0x00,0x00,0x00,0x00,0x00, 0x07,0x10,0x00,0x00,0x00,0x00,0x00,0x00,
0x01,0x02,0x03,0x04,3,0,0,0, 0x01,0x02,0x03,0x04,3,0,0,0,
0xef,0xdd,0x88,0xde, 0xf7,0x2f,0x6c,0x60,
7, 5,
255,255,75,255,4,255,0}; 254,255,4,255,0};
/* packet that overspans over an entire page */ /* packet that overspans over an entire page */
const int head1_7[] = {0x4f,0x67,0x67,0x53,0,0x02, const int head1_7[] = {0x4f,0x67,0x67,0x53,0,0x02,
@ -1190,16 +1431,48 @@ const int head1_7[] = {0x4f,0x67,0x67,0x53,0,0x02,
const int head2_7[] = {0x4f,0x67,0x67,0x53,0,0x00, const int head2_7[] = {0x4f,0x67,0x67,0x53,0,0x00,
0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00, 0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
0x01,0x02,0x03,0x04,1,0,0,0, 0x01,0x02,0x03,0x04,1,0,0,0,
0x3c,0xd9,0x4d,0x3f, 0x68,0x22,0x7c,0x3d,
17, 255,
100,255,255,255,255,255,255,255,255, 100,
255,255,255,255,255,255,255,255}; 255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,
255,255,255,255,255,255};
const int head3_7[] = {0x4f,0x67,0x67,0x53,0,0x05, const int head3_7[] = {0x4f,0x67,0x67,0x53,0,0x05,
0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00, 0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00,
0x01,0x02,0x03,0x04,2,0,0,0, 0x01,0x02,0x03,0x04,2,0,0,0,
0xd4,0xe0,0x60,0xe5, 0xd4,0xe0,0x60,0xe5,
1,0}; 1,
0};
void test_pack(const int *pl, const int **headers, int byteskip, void test_pack(const int *pl, const int **headers, int byteskip,
int pageskip, int packetskip){ int pageskip, int packetskip){
@ -1294,7 +1567,7 @@ void test_pack(const int *pl, const int **headers, int byteskip,
if(ret<0)continue; if(ret<0)continue;
/* got a page. Happy happy. Verify that it's good. */ /* got a page. Happy happy. Verify that it's good. */
fprintf(stderr,"(%ld), ",pageout); fprintf(stderr,"(%d), ",pageout);
check_page(data+deptr,headers[pageout],&og_de); check_page(data+deptr,headers[pageout],&og_de);
deptr+=og_de.body_len; deptr+=og_de.body_len;
@ -1426,14 +1699,24 @@ int main(void){
} }
{ {
/* continuing packet test */ /* continuing packet test; with page spill expansion, we have to
const int packets[]={0,4345,259,255,-1}; overflow the lacing table. */
const int packets[]={0,65500,259,255,-1};
const int *headret[]={head1_4,head2_4,head3_4,NULL}; const int *headret[]={head1_4,head2_4,head3_4,NULL};
fprintf(stderr,"testing single packet page span... "); fprintf(stderr,"testing single packet page span... ");
test_pack(packets,headret,0,0,0); test_pack(packets,headret,0,0,0);
} }
{
/* spill expand packet test */
const int packets[]={0,4345,259,255,0,0,-1};
const int *headret[]={head1_4b,head2_4b,head3_4b,NULL};
fprintf(stderr,"testing page spill expansion... ");
test_pack(packets,headret,0,0,0);
}
/* page with the 255 segment limit */ /* page with the 255 segment limit */
{ {
@ -1477,7 +1760,7 @@ int main(void){
{ {
/* packet that overspans over an entire page */ /* packet that overspans over an entire page */
const int packets[]={0,100,9000,259,255,-1}; const int packets[]={0,100,130049,259,255,-1};
const int *headret[]={head1_6,head2_6,head3_6,head4_6,NULL}; const int *headret[]={head1_6,head2_6,head3_6,head4_6,NULL};
fprintf(stderr,"testing very large packets... "); fprintf(stderr,"testing very large packets... ");
@ -1487,7 +1770,7 @@ int main(void){
{ {
/* test for the libogg 1.1.1 resync in large continuation bug /* test for the libogg 1.1.1 resync in large continuation bug
found by Josh Coalson) */ found by Josh Coalson) */
const int packets[]={0,100,9000,259,255,-1}; const int packets[]={0,100,130049,259,255,-1};
const int *headret[]={head1_6,head2_6,head3_6,head4_6,NULL}; const int *headret[]={head1_6,head2_6,head3_6,head4_6,NULL};
fprintf(stderr,"testing continuation resync in very large packets... "); fprintf(stderr,"testing continuation resync in very large packets... ");
@ -1496,7 +1779,7 @@ int main(void){
{ {
/* term only page. why not? */ /* term only page. why not? */
const int packets[]={0,100,4080,-1}; const int packets[]={0,100,64770,-1};
const int *headret[]={head1_7,head2_7,head3_7,NULL}; const int *headret[]={head1_7,head2_7,head3_7,NULL};
fprintf(stderr,"testing zero data page (1 nil packet)... "); fprintf(stderr,"testing zero data page (1 nil packet)... ");
@ -1508,7 +1791,7 @@ int main(void){
{ {
/* build a bunch of pages for testing */ /* build a bunch of pages for testing */
unsigned char *data=_ogg_malloc(1024*1024); unsigned char *data=_ogg_malloc(1024*1024);
int pl[]={0,100,4079,2956,2057,76,34,912,0,234,1000,1000,1000,300,-1}; int pl[]={0, 1,1,98,4079, 1,1,2954,2057, 76,34,912,0,234,1000,1000, 1000,300,-1};
int inptr=0,i,j; int inptr=0,i,j;
ogg_page og[5]; ogg_page og[5];
@ -1569,17 +1852,21 @@ int main(void){
if(ogg_stream_packetout(&os_de,&test)!=1)error(); if(ogg_stream_packetout(&os_de,&test)!=1)error();
checkpacket(&test,0,0,0); checkpacket(&test,0,0,0);
if(ogg_stream_packetout(&os_de,&test)!=1)error(); if(ogg_stream_packetout(&os_de,&test)!=1)error();
checkpacket(&test,100,1,-1); checkpacket(&test,1,1,-1);
if(ogg_stream_packetout(&os_de,&test)!=1)error(); if(ogg_stream_packetout(&os_de,&test)!=1)error();
checkpacket(&test,4079,2,3000); checkpacket(&test,1,2,-1);
if(ogg_stream_packetout(&os_de,&test)!=1)error();
checkpacket(&test,98,3,-1);
if(ogg_stream_packetout(&os_de,&test)!=1)error();
checkpacket(&test,4079,4,5000);
if(ogg_stream_packetout(&os_de,&test)!=-1){ if(ogg_stream_packetout(&os_de,&test)!=-1){
fprintf(stderr,"Error: loss of page did not return error\n"); fprintf(stderr,"Error: loss of page did not return error\n");
exit(1); exit(1);
} }
if(ogg_stream_packetout(&os_de,&test)!=1)error(); if(ogg_stream_packetout(&os_de,&test)!=1)error();
checkpacket(&test,76,5,-1); checkpacket(&test,76,9,-1);
if(ogg_stream_packetout(&os_de,&test)!=1)error(); if(ogg_stream_packetout(&os_de,&test)!=1)error();
checkpacket(&test,34,6,-1); checkpacket(&test,34,10,-1);
fprintf(stderr,"ok.\n"); fprintf(stderr,"ok.\n");
} }
@ -1616,17 +1903,27 @@ int main(void){
if(ogg_stream_packetout(&os_de,&test)!=1)error(); if(ogg_stream_packetout(&os_de,&test)!=1)error();
checkpacket(&test,0,0,0); checkpacket(&test,0,0,0);
if(ogg_stream_packetout(&os_de,&test)!=1)error(); if(ogg_stream_packetout(&os_de,&test)!=1)error();
checkpacket(&test,100,1,-1); checkpacket(&test,1,1,-1);
if(ogg_stream_packetout(&os_de,&test)!=1)error(); if(ogg_stream_packetout(&os_de,&test)!=1)error();
checkpacket(&test,4079,2,3000); checkpacket(&test,1,2,-1);
if(ogg_stream_packetout(&os_de,&test)!=1)error(); if(ogg_stream_packetout(&os_de,&test)!=1)error();
checkpacket(&test,2956,3,4000); checkpacket(&test,98,3,-1);
if(ogg_stream_packetout(&os_de,&test)!=1)error();
checkpacket(&test,4079,4,5000);
if(ogg_stream_packetout(&os_de,&test)!=1)error();
checkpacket(&test,1,5,-1);
if(ogg_stream_packetout(&os_de,&test)!=1)error();
checkpacket(&test,1,6,-1);
if(ogg_stream_packetout(&os_de,&test)!=1)error();
checkpacket(&test,2954,7,-1);
if(ogg_stream_packetout(&os_de,&test)!=1)error();
checkpacket(&test,2057,8,9000);
if(ogg_stream_packetout(&os_de,&test)!=-1){ if(ogg_stream_packetout(&os_de,&test)!=-1){
fprintf(stderr,"Error: loss of page did not return error\n"); fprintf(stderr,"Error: loss of page did not return error\n");
exit(1); exit(1);
} }
if(ogg_stream_packetout(&os_de,&test)!=1)error(); if(ogg_stream_packetout(&os_de,&test)!=1)error();
checkpacket(&test,300,13,14000); checkpacket(&test,300,17,18000);
fprintf(stderr,"ok.\n"); fprintf(stderr,"ok.\n");
} }
@ -1794,7 +2091,3 @@ int main(void){
} }
#endif #endif