forked from len0rd/rockbox
libtremor:
Merge in upstream revision 17375. This removes tremor's internal ogg code and now uses libogg instead so a bunch of changes are just adjusting to the new api. Also brings in improvements to vorbisfile which fixes FS#10484. Disabled a lot of unused code in the libogg files and moved some small functions into the ogg.h header so they can be inlined. Some small tweaks to fix warnings. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@28742 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
1f64b7fb1f
commit
67efbc1387
8 changed files with 3153 additions and 1504 deletions
File diff suppressed because it is too large
Load diff
|
|
@ -279,7 +279,7 @@ static long decode_packed_block(codebook *book, oggpack_buffer *b,
|
|||
long *bufend = buf + n;
|
||||
|
||||
while (bufptr<bufend) {
|
||||
if (b->headend > 8) {
|
||||
if(b->endbyte < b->storage - 8) {
|
||||
ogg_uint32_t *ptr;
|
||||
unsigned long bit, bitend;
|
||||
unsigned long adr;
|
||||
|
|
@ -292,10 +292,10 @@ static long decode_packed_block(codebook *book, oggpack_buffer *b,
|
|||
const ogg_uint32_t *book_codelist = book->codelist;
|
||||
const char *book_dec_codelengths = book->dec_codelengths;
|
||||
|
||||
adr = (unsigned long)b->headptr;
|
||||
bit = (adr&3)*8+b->headbit;
|
||||
adr = (unsigned long)b->ptr;
|
||||
bit = (adr&3)*8+b->endbit;
|
||||
ptr = (ogg_uint32_t*)(adr&~3);
|
||||
bitend = ((adr&3)+b->headend)*8;
|
||||
bitend = ((adr&3)+(b->storage-b->endbyte))*8;
|
||||
while (bufptr<bufend){
|
||||
if (UNLIKELY(cachesize<book_dec_maxlength)) {
|
||||
if (bit-cachesize+32>=bitend)
|
||||
|
|
@ -323,11 +323,11 @@ static long decode_packed_block(codebook *book, oggpack_buffer *b,
|
|||
cache >>= l;
|
||||
}
|
||||
|
||||
adr=(unsigned long)b->headptr;
|
||||
adr=(unsigned long)b->ptr;
|
||||
bit-=(adr&3)*8+cachesize;
|
||||
b->headend-=(bit/8);
|
||||
b->headptr+=bit/8;
|
||||
b->headbit=bit%8;
|
||||
b->endbyte+=bit/8;
|
||||
b->ptr+=bit/8;
|
||||
b->endbit=bit&7;
|
||||
} else {
|
||||
long r = decode_packed_entry_number(book, b);
|
||||
if (r == -1) return bufptr-buf;
|
||||
|
|
@ -337,7 +337,6 @@ static long decode_packed_block(codebook *book, oggpack_buffer *b,
|
|||
return n;
|
||||
}
|
||||
|
||||
|
||||
/* Decode side is specced and easier, because we don't need to find
|
||||
matches using different criteria; we simply read and map. There are
|
||||
two things we need to do 'depending':
|
||||
|
|
@ -570,3 +569,4 @@ long vorbis_book_decodevv_add(codebook *book,ogg_int32_t **a,
|
|||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -240,7 +240,7 @@ int vorbis_synthesis_idheader(ogg_packet *op){
|
|||
char buffer[6];
|
||||
|
||||
if(op){
|
||||
oggpack_readinit(&opb,op->packet);
|
||||
oggpack_readinit(&opb,op->packet,op->bytes);
|
||||
|
||||
if(!op->b_o_s)
|
||||
return(0); /* Not the initial packet */
|
||||
|
|
@ -268,7 +268,7 @@ int vorbis_synthesis_headerin(vorbis_info *vi,vorbis_comment *vc,ogg_packet *op)
|
|||
oggpack_buffer opb;
|
||||
|
||||
if(op){
|
||||
oggpack_readinit(&opb,op->packet);
|
||||
oggpack_readinit(&opb,op->packet,op->bytes);
|
||||
|
||||
/* Which of the three types of header is this? */
|
||||
/* Also verify header-ness, vorbis */
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ typedef struct OggVorbis_File {
|
|||
int seekable;
|
||||
ogg_int64_t offset;
|
||||
ogg_int64_t end;
|
||||
ogg_sync_state *oy;
|
||||
ogg_sync_state oy;
|
||||
|
||||
/* If the FILE handle isn't seekable (eg, a pipe), only the current
|
||||
stream appears */
|
||||
|
|
@ -77,7 +77,7 @@ typedef struct OggVorbis_File {
|
|||
ogg_int64_t bittrack;
|
||||
ogg_int64_t samptrack;
|
||||
|
||||
ogg_stream_state *os; /* take physical pages, weld into a logical
|
||||
ogg_stream_state os; /* take physical pages, weld into a logical
|
||||
stream of packets */
|
||||
vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */
|
||||
vorbis_block vb; /* local working space for packet->PCM decode */
|
||||
|
|
@ -87,13 +87,11 @@ typedef struct OggVorbis_File {
|
|||
} OggVorbis_File;
|
||||
|
||||
extern int ov_clear(OggVorbis_File *vf);
|
||||
//extern int ov_open(FILE *f,OggVorbis_File *vf,char *initial,long ibytes);
|
||||
extern int ov_open_callbacks(void *datasource, OggVorbis_File *vf,
|
||||
char *initial, long ibytes, ov_callbacks callbacks);
|
||||
const char *initial, long ibytes, ov_callbacks callbacks);
|
||||
|
||||
//extern int ov_test(FILE *f,OggVorbis_File *vf,char *initial,long ibytes);
|
||||
extern int ov_test_callbacks(void *datasource, OggVorbis_File *vf,
|
||||
char *initial, long ibytes, ov_callbacks callbacks);
|
||||
const char *initial, long ibytes, ov_callbacks callbacks);
|
||||
extern int ov_test_open(OggVorbis_File *vf);
|
||||
|
||||
extern long ov_bitrate(OggVorbis_File *vf,int i);
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. *
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2003 *
|
||||
* BY THE Xiph.Org FOUNDATION http://www.xiph.org/ *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2007 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: subsumed libogg includes
|
||||
function: toplevel libogg include
|
||||
last mod: $Id$
|
||||
|
||||
********************************************************************/
|
||||
#ifndef _OGG_H
|
||||
|
|
@ -21,241 +21,238 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
#include "os_types.h"
|
||||
|
||||
typedef struct ogg_buffer_state{
|
||||
struct ogg_buffer *unused_buffers;
|
||||
struct ogg_reference *unused_references;
|
||||
int outstanding;
|
||||
int shutdown;
|
||||
} ogg_buffer_state;
|
||||
extern const unsigned long mask[] ICONST_ATTR;
|
||||
|
||||
typedef struct ogg_buffer {
|
||||
unsigned char *data;
|
||||
long size;
|
||||
int refcount;
|
||||
typedef struct {
|
||||
void *iov_base;
|
||||
size_t iov_len;
|
||||
} ogg_iovec_t;
|
||||
|
||||
union {
|
||||
ogg_buffer_state *owner;
|
||||
struct ogg_buffer *next;
|
||||
} ptr;
|
||||
} ogg_buffer;
|
||||
typedef struct {
|
||||
long endbyte;
|
||||
int endbit;
|
||||
|
||||
typedef struct ogg_reference {
|
||||
ogg_buffer *buffer;
|
||||
long begin;
|
||||
long length;
|
||||
|
||||
struct ogg_reference *next;
|
||||
} ogg_reference;
|
||||
|
||||
typedef struct oggpack_buffer {
|
||||
int headbit;
|
||||
unsigned char *headptr;
|
||||
long headend;
|
||||
|
||||
/* memory management */
|
||||
ogg_reference *head;
|
||||
ogg_reference *tail;
|
||||
|
||||
/* render the byte/bit counter API constant time */
|
||||
long count; /* doesn't count the tail */
|
||||
unsigned char *buffer;
|
||||
unsigned char *ptr;
|
||||
long storage;
|
||||
} oggpack_buffer;
|
||||
|
||||
typedef struct oggbyte_buffer {
|
||||
ogg_reference *baseref;
|
||||
/* ogg_page is used to encapsulate the data in one Ogg bitstream page *****/
|
||||
|
||||
ogg_reference *ref;
|
||||
unsigned char *ptr;
|
||||
long pos;
|
||||
long end;
|
||||
} oggbyte_buffer;
|
||||
typedef struct {
|
||||
unsigned char *header;
|
||||
long header_len;
|
||||
unsigned char *body;
|
||||
long body_len;
|
||||
} ogg_page;
|
||||
|
||||
typedef struct ogg_sync_state {
|
||||
/* decode memory management pool */
|
||||
ogg_buffer_state *bufferpool;
|
||||
/* ogg_stream_state contains the current encode/decode state of a logical
|
||||
Ogg bitstream **********************************************************/
|
||||
|
||||
/* stream buffers */
|
||||
ogg_reference *fifo_head;
|
||||
ogg_reference *fifo_tail;
|
||||
long fifo_fill;
|
||||
typedef struct {
|
||||
unsigned char *body_data; /* bytes from packet bodies */
|
||||
long body_storage; /* storage elements allocated */
|
||||
long body_fill; /* elements stored; fill mark */
|
||||
long body_returned; /* elements of fill returned */
|
||||
|
||||
/* stream sync management */
|
||||
int unsynced;
|
||||
int headerbytes;
|
||||
int bodybytes;
|
||||
|
||||
} ogg_sync_state;
|
||||
int *lacing_vals; /* The values that will go to the segment table */
|
||||
ogg_int64_t *granule_vals; /* granulepos values for headers. Not compact
|
||||
this way, but it is simple coupled to the
|
||||
lacing fifo */
|
||||
long lacing_storage;
|
||||
long lacing_fill;
|
||||
long lacing_packet;
|
||||
long lacing_returned;
|
||||
|
||||
typedef struct ogg_stream_state {
|
||||
ogg_reference *header_head;
|
||||
ogg_reference *header_tail;
|
||||
ogg_reference *body_head;
|
||||
ogg_reference *body_tail;
|
||||
|
||||
int e_o_s; /* set when we have buffered the last
|
||||
packet in the logical bitstream */
|
||||
#if 0
|
||||
unsigned char header[282]; /* working space for header encode */
|
||||
int header_fill;
|
||||
#endif
|
||||
int e_o_s; /* set when we have buffered the last packet in the
|
||||
logical bitstream */
|
||||
int b_o_s; /* set after we've written the initial page
|
||||
of a logical bitstream */
|
||||
long serialno;
|
||||
ogg_uint32_t serialno;
|
||||
long pageno;
|
||||
ogg_int64_t packetno; /* sequence number for decode; the framing
|
||||
knows where there's a hole in the data,
|
||||
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 */
|
||||
ogg_int64_t granulepos;
|
||||
|
||||
int lacing_fill;
|
||||
ogg_uint32_t body_fill;
|
||||
|
||||
/* decode-side state data */
|
||||
int holeflag;
|
||||
int spanflag;
|
||||
int clearflag;
|
||||
int laceptr;
|
||||
ogg_uint32_t body_fill_next;
|
||||
|
||||
} ogg_stream_state;
|
||||
|
||||
/* ogg_packet is used to encapsulate the data and metadata belonging
|
||||
to a single raw Ogg/Vorbis packet *************************************/
|
||||
|
||||
typedef struct {
|
||||
ogg_reference *packet;
|
||||
unsigned char *packet;
|
||||
long bytes;
|
||||
long b_o_s;
|
||||
long e_o_s;
|
||||
|
||||
ogg_int64_t granulepos;
|
||||
|
||||
ogg_int64_t packetno; /* sequence number for decode; the framing
|
||||
knows where there's a hole in the data,
|
||||
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 */
|
||||
} ogg_packet;
|
||||
|
||||
typedef struct {
|
||||
ogg_reference *header;
|
||||
int header_len;
|
||||
ogg_reference *body;
|
||||
long body_len;
|
||||
} ogg_page;
|
||||
unsigned char *data;
|
||||
int storage;
|
||||
int fill;
|
||||
int returned;
|
||||
|
||||
int unsynced;
|
||||
int headerbytes;
|
||||
int bodybytes;
|
||||
} ogg_sync_state;
|
||||
|
||||
/* Ogg BITSTREAM PRIMITIVES: bitstream ************************/
|
||||
/*
|
||||
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_writealign(oggpack_buffer *b);
|
||||
extern void oggpack_writecopy(oggpack_buffer *b,void *source,long bits);
|
||||
extern void oggpack_reset(oggpack_buffer *b);
|
||||
extern void oggpack_writeclear(oggpack_buffer *b); */
|
||||
extern void oggpack_readinit(oggpack_buffer *b,unsigned char *buf,int bytes);
|
||||
/* extern void oggpack_write(oggpack_buffer *b,unsigned long value,int bits); */
|
||||
|
||||
extern void oggpack_readinit(oggpack_buffer *b,ogg_reference *r);
|
||||
extern long oggpack_look_full(oggpack_buffer *b,int bits);
|
||||
extern long oggpack_read(oggpack_buffer *b,register int bits);
|
||||
//extern long oggpack_look(oggpack_buffer *b,int bits);
|
||||
static inline long oggpack_look(oggpack_buffer *b,int bits){
|
||||
unsigned long ret;
|
||||
unsigned long m;
|
||||
|
||||
/* Inline a few, often called functions */
|
||||
if(bits<0 || bits>32) return -1;
|
||||
m=mask[bits];
|
||||
bits+=b->endbit;
|
||||
|
||||
/* mark read process as having run off the end */
|
||||
static inline void _adv_halt(oggpack_buffer *b){
|
||||
b->headptr=b->head->buffer->data+b->head->begin+b->head->length;
|
||||
b->headend=-1;
|
||||
b->headbit=0;
|
||||
}
|
||||
|
||||
/* spans forward, skipping as many bytes as headend is negative; if
|
||||
headend is zero, simply finds next byte. If we're up to the end
|
||||
of the buffer, leaves headend at zero. If we've read past the end,
|
||||
halt the decode process. */
|
||||
static inline void _span(oggpack_buffer *b){
|
||||
while(b->headend<1){
|
||||
if(b->head->next){
|
||||
b->count+=b->head->length;
|
||||
b->head=b->head->next;
|
||||
b->headptr=b->head->buffer->data+b->head->begin-b->headend;
|
||||
b->headend+=b->head->length;
|
||||
}else{
|
||||
/* we've either met the end of decode, or gone past it. halt
|
||||
only if we're past */
|
||||
if(b->headend<0 || b->headbit)
|
||||
/* read has fallen off the end */
|
||||
_adv_halt(b);
|
||||
|
||||
break;
|
||||
if(b->endbyte >= b->storage-4){
|
||||
/* not the main path */
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* limited to 32 at a time */
|
||||
static inline void oggpack_adv(oggpack_buffer *b,int bits){
|
||||
bits+=b->headbit;
|
||||
b->headbit=bits&7;
|
||||
b->headptr+=bits/8;
|
||||
if((b->headend-=((unsigned)bits)/8)<1)_span(b);
|
||||
}
|
||||
|
||||
static inline long oggpack_look(oggpack_buffer *b, int bits){
|
||||
if(bits+b->headbit < b->headend<<3){
|
||||
extern const unsigned long oggpack_mask[];
|
||||
unsigned long m=oggpack_mask[bits];
|
||||
unsigned long ret=-1;
|
||||
|
||||
bits+=b->headbit;
|
||||
ret=b->headptr[0]>>b->headbit;
|
||||
ret=b->ptr[0]>>b->endbit;
|
||||
if(bits>8){
|
||||
ret|=b->headptr[1]<<(8-b->headbit);
|
||||
ret|=b->ptr[1]<<(8-b->endbit);
|
||||
if(bits>16){
|
||||
ret|=b->headptr[2]<<(16-b->headbit);
|
||||
ret|=b->ptr[2]<<(16-b->endbit);
|
||||
if(bits>24){
|
||||
ret|=b->headptr[3]<<(24-b->headbit);
|
||||
if(bits>32 && b->headbit)
|
||||
ret|=b->headptr[4]<<(32-b->headbit);
|
||||
ret|=b->ptr[3]<<(24-b->endbit);
|
||||
if(bits>32 && b->endbit)
|
||||
ret|=b->ptr[4]<<(32-b->endbit);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret&m;
|
||||
}else{
|
||||
return oggpack_look_full(b, bits);
|
||||
}
|
||||
return(m&ret);
|
||||
}
|
||||
|
||||
extern long oggpack_look1(oggpack_buffer *b);
|
||||
|
||||
//extern void oggpack_adv(oggpack_buffer *b,int bits);
|
||||
static inline void oggpack_adv(oggpack_buffer *b,int bits){
|
||||
bits+=b->endbit;
|
||||
|
||||
if(b->endbyte > b->storage-((bits+7)>>3)) goto overflow;
|
||||
|
||||
b->ptr+=bits/8;
|
||||
b->endbyte+=bits/8;
|
||||
b->endbit=bits&7;
|
||||
return;
|
||||
|
||||
overflow:
|
||||
b->ptr=NULL;
|
||||
b->endbyte=b->storage;
|
||||
b->endbit=1;
|
||||
}
|
||||
|
||||
extern void oggpack_adv1(oggpack_buffer *b);
|
||||
extern long oggpack_read(oggpack_buffer *b,int bits);
|
||||
extern long oggpack_read1(oggpack_buffer *b);
|
||||
#if 0
|
||||
extern long oggpack_bytes(oggpack_buffer *b);
|
||||
extern long oggpack_bits(oggpack_buffer *b);
|
||||
extern unsigned char *oggpack_get_buffer(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_writealign(oggpack_buffer *b);
|
||||
extern void oggpackB_writecopy(oggpack_buffer *b,void *source,long bits);
|
||||
extern void oggpackB_reset(oggpack_buffer *b);
|
||||
extern void oggpackB_writeclear(oggpack_buffer *b);
|
||||
extern void oggpackB_readinit(oggpack_buffer *b,unsigned char *buf,int bytes);
|
||||
extern void oggpackB_write(oggpack_buffer *b,unsigned long value,int bits);
|
||||
extern long oggpackB_look(oggpack_buffer *b,int bits);
|
||||
extern long oggpackB_look1(oggpack_buffer *b);
|
||||
extern void oggpackB_adv(oggpack_buffer *b,int bits);
|
||||
extern void oggpackB_adv1(oggpack_buffer *b);
|
||||
extern long oggpackB_read(oggpack_buffer *b,int bits);
|
||||
extern long oggpackB_read1(oggpack_buffer *b);
|
||||
extern long oggpackB_bytes(oggpack_buffer *b);
|
||||
extern long oggpackB_bits(oggpack_buffer *b);
|
||||
extern unsigned char *oggpackB_get_buffer(oggpack_buffer *b);
|
||||
# endif
|
||||
/* Ogg BITSTREAM PRIMITIVES: encoding **************************/
|
||||
#if 0
|
||||
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_fill(ogg_stream_state *os, ogg_page *og, int nfill);
|
||||
extern int ogg_stream_flush(ogg_stream_state *os, ogg_page *og);
|
||||
#endif
|
||||
/* Ogg BITSTREAM PRIMITIVES: decoding **************************/
|
||||
|
||||
extern ogg_sync_state *ogg_sync_create(void);
|
||||
extern int ogg_sync_destroy(ogg_sync_state *oy);
|
||||
extern int ogg_sync_init(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_destroy(ogg_sync_state *oy);
|
||||
extern int ogg_sync_check(ogg_sync_state *oy);
|
||||
|
||||
extern unsigned char *ogg_sync_bufferin(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 long ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og);
|
||||
extern int ogg_sync_pageout(ogg_sync_state *oy, ogg_page *og);
|
||||
extern int ogg_stream_pagein(ogg_stream_state *os, ogg_page *og);
|
||||
extern int ogg_stream_packetout(ogg_stream_state *os,ogg_packet *op);
|
||||
extern int ogg_stream_packetpeek(ogg_stream_state *os,ogg_packet *op);
|
||||
|
||||
/* Ogg BITSTREAM PRIMITIVES: general ***************************/
|
||||
|
||||
extern ogg_stream_state *ogg_stream_create(int serialno);
|
||||
extern int ogg_stream_destroy(ogg_stream_state *os);
|
||||
extern int ogg_stream_init(ogg_stream_state *os,int serialno);
|
||||
extern int ogg_stream_clear(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_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_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_continued(ogg_page *og);
|
||||
extern int ogg_page_bos(ogg_page *og);
|
||||
extern int ogg_page_eos(ogg_page *og);
|
||||
extern ogg_int64_t ogg_page_granulepos(ogg_page *og);
|
||||
extern ogg_uint32_t ogg_page_serialno(ogg_page *og);
|
||||
extern ogg_uint32_t ogg_page_pageno(ogg_page *og);
|
||||
extern int ogg_page_getbuffer(ogg_page *og, unsigned char **buffer);
|
||||
extern int ogg_page_version(const ogg_page *og);
|
||||
extern int ogg_page_continued(const ogg_page *og);
|
||||
extern int ogg_page_bos(const ogg_page *og);
|
||||
extern int ogg_page_eos(const ogg_page *og);
|
||||
extern ogg_int64_t ogg_page_granulepos(const ogg_page *og);
|
||||
extern ogg_uint32_t ogg_page_serialno(const ogg_page *og);
|
||||
extern long ogg_page_pageno(const ogg_page *og);
|
||||
extern int ogg_page_packets(const ogg_page *og);
|
||||
|
||||
extern int ogg_packet_release(ogg_packet *op);
|
||||
extern int ogg_page_release(ogg_page *og);
|
||||
|
||||
extern void ogg_page_dup(ogg_page *d, ogg_page *s);
|
||||
|
||||
/* Ogg BITSTREAM PRIMITIVES: return codes ***************************/
|
||||
|
||||
#define OGG_SUCCESS 0
|
||||
|
||||
#define OGG_HOLE -10
|
||||
#define OGG_SPAN -11
|
||||
#define OGG_EVERSION -12
|
||||
#define OGG_ESERIAL -13
|
||||
#define OGG_EINVAL -14
|
||||
#define OGG_EEOS -15
|
||||
extern void ogg_packet_clear(ogg_packet *op);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ static inline int _vorbis_synthesis1(vorbis_block *vb,ogg_packet *op,int decodep
|
|||
|
||||
/* first things first. Make sure decode is ready */
|
||||
_vorbis_block_ripcord(vb);
|
||||
oggpack_readinit(opb,op->packet);
|
||||
oggpack_readinit(opb,op->packet,op->bytes);
|
||||
|
||||
/* Check the packet type */
|
||||
if(oggpack_read(opb,1)!=0){
|
||||
|
|
@ -102,6 +102,8 @@ int vorbis_synthesis(vorbis_block *vb,ogg_packet *op){
|
|||
return _vorbis_synthesis1(vb,op,1);
|
||||
}
|
||||
|
||||
/* used to track pcm position without actually performing decode.
|
||||
Useful for sequential 'fast forward' */
|
||||
int vorbis_synthesis_trackonly(vorbis_block *vb,ogg_packet *op){
|
||||
return _vorbis_synthesis1(vb,op,0);
|
||||
}
|
||||
|
|
@ -111,7 +113,7 @@ long vorbis_packet_blocksize(vorbis_info *vi,ogg_packet *op){
|
|||
oggpack_buffer opb;
|
||||
int mode;
|
||||
|
||||
oggpack_readinit(&opb,op->packet);
|
||||
oggpack_readinit(&opb,op->packet,op->bytes);
|
||||
|
||||
/* Check the packet type */
|
||||
if(oggpack_read(&opb,1)!=0){
|
||||
|
|
|
|||
|
|
@ -61,10 +61,11 @@
|
|||
|
||||
/* read a little more data from the file/pipe into the ogg_sync framer */
|
||||
static long _get_data(OggVorbis_File *vf){
|
||||
if(!(vf->callbacks.read_func))return(-1);
|
||||
if(vf->datasource){
|
||||
char *buffer=(char *)ogg_sync_bufferin(vf->oy,CHUNKSIZE);
|
||||
char *buffer=ogg_sync_buffer(&vf->oy,CHUNKSIZE);
|
||||
long bytes=(vf->callbacks.read_func)(buffer,1,CHUNKSIZE,vf->datasource);
|
||||
if(bytes>0)ogg_sync_wrote(vf->oy,bytes);
|
||||
if(bytes>0)ogg_sync_wrote(&vf->oy,bytes);
|
||||
return(bytes);
|
||||
}else
|
||||
return(0);
|
||||
|
|
@ -77,7 +78,7 @@ static int _seek_helper(OggVorbis_File *vf,ogg_int64_t offset){
|
|||
(vf->callbacks.seek_func)(vf->datasource, offset, SEEK_SET) == -1)
|
||||
return OV_EREAD;
|
||||
vf->offset=offset;
|
||||
ogg_sync_reset(vf->oy);
|
||||
ogg_sync_reset(&vf->oy);
|
||||
}else{
|
||||
/* shouldn't happen unless someone writes a broken callback */
|
||||
return OV_EFAULT;
|
||||
|
|
@ -96,9 +97,7 @@ static int _seek_helper(OggVorbis_File *vf,ogg_int64_t offset){
|
|||
n) search for a new page beginning for n bytes
|
||||
|
||||
return: <0) did not find a page (OV_FALSE, OV_EOF, OV_EREAD)
|
||||
n) found a page at absolute offset n
|
||||
|
||||
produces a refcounted page */
|
||||
n) found a page at absolute offset n */
|
||||
|
||||
static ogg_int64_t _get_next_page(OggVorbis_File *vf,ogg_page *og,
|
||||
ogg_int64_t boundary){
|
||||
|
|
@ -107,7 +106,7 @@ static ogg_int64_t _get_next_page(OggVorbis_File *vf,ogg_page *og,
|
|||
long more;
|
||||
|
||||
if(boundary>0 && vf->offset>=boundary)return(OV_FALSE);
|
||||
more=ogg_sync_pageseek(vf->oy,og);
|
||||
more=ogg_sync_pageseek(&vf->oy,og);
|
||||
|
||||
if(more<0){
|
||||
/* skipped n bytes */
|
||||
|
|
@ -137,8 +136,7 @@ static ogg_int64_t _get_next_page(OggVorbis_File *vf,ogg_page *og,
|
|||
position. Much dirtier than the above as Ogg doesn't have any
|
||||
backward search linkage. no 'readp' as it will certainly have to
|
||||
read. */
|
||||
/* returns offset or OV_EREAD, OV_FAULT and produces a refcounted page */
|
||||
|
||||
/* returns offset or OV_EREAD, OV_FAULT */
|
||||
static ogg_int64_t _get_prev_page(OggVorbis_File *vf,ogg_page *og){
|
||||
ogg_int64_t begin=vf->offset;
|
||||
ogg_int64_t end=begin;
|
||||
|
|
@ -154,6 +152,7 @@ static ogg_int64_t _get_prev_page(OggVorbis_File *vf,ogg_page *og){
|
|||
if(ret)return(ret);
|
||||
|
||||
while(vf->offset<end){
|
||||
memset(og,0,sizeof(*og));
|
||||
ret=_get_next_page(vf,og,end-vf->offset);
|
||||
if(ret==OV_EREAD)return(OV_EREAD);
|
||||
if(ret<0){
|
||||
|
|
@ -168,7 +167,6 @@ static ogg_int64_t _get_prev_page(OggVorbis_File *vf,ogg_page *og){
|
|||
holding the last page. In multiplexed (or noncompliant streams),
|
||||
we will probably have to re-read the last page we saw */
|
||||
if(og->header_len==0){
|
||||
ogg_page_release(og);
|
||||
ret=_seek_helper(vf,offset);
|
||||
if(ret)return(ret);
|
||||
|
||||
|
|
@ -219,14 +217,14 @@ static int _lookup_page_serialno(ogg_page *og, ogg_uint32_t *serialno_list, int
|
|||
static ogg_int64_t _get_prev_page_serial(OggVorbis_File *vf,
|
||||
ogg_uint32_t *serial_list, int serial_n,
|
||||
int *serialno, ogg_int64_t *granpos){
|
||||
ogg_page og={0,0,0,0};
|
||||
ogg_page og;
|
||||
ogg_int64_t begin=vf->offset;
|
||||
ogg_int64_t end=begin;
|
||||
ogg_int64_t ret;
|
||||
|
||||
ogg_int64_t prefoffset=-1;
|
||||
ogg_int64_t offset=-1;
|
||||
ogg_uint32_t ret_serialno=-1;
|
||||
ogg_int64_t ret_serialno=-1;
|
||||
ogg_int64_t ret_gran=-1;
|
||||
|
||||
while(offset==-1){
|
||||
|
|
@ -241,13 +239,11 @@ static ogg_int64_t _get_prev_page_serial(OggVorbis_File *vf,
|
|||
ret=_get_next_page(vf,&og,end-vf->offset);
|
||||
if(ret==OV_EREAD)return(OV_EREAD);
|
||||
if(ret<0){
|
||||
ogg_page_release(&og);
|
||||
break;
|
||||
}else{
|
||||
ret_serialno=ogg_page_serialno(&og);
|
||||
ret_gran=ogg_page_granulepos(&og);
|
||||
offset=ret;
|
||||
ogg_page_release(&og);
|
||||
|
||||
if(ret_serialno == (ogg_uint32_t) *serialno){
|
||||
prefoffset=ret;
|
||||
|
|
@ -276,23 +272,18 @@ static ogg_int64_t _get_prev_page_serial(OggVorbis_File *vf,
|
|||
|
||||
/* uses the local ogg_stream storage in vf; this is important for
|
||||
non-streaming input sources */
|
||||
/* consumes the page that's passed in (if any) */
|
||||
|
||||
static int _fetch_headers(OggVorbis_File *vf,
|
||||
vorbis_info *vi,
|
||||
vorbis_comment *vc,
|
||||
ogg_uint32_t **serialno_list,
|
||||
int *serialno_n,
|
||||
static int _fetch_headers(OggVorbis_File *vf,vorbis_info *vi,vorbis_comment *vc,
|
||||
ogg_uint32_t **serialno_list, int *serialno_n,
|
||||
ogg_page *og_ptr){
|
||||
ogg_page og={0,0,0,0};
|
||||
ogg_packet op={0,0,0,0,0,0};
|
||||
ogg_page og;
|
||||
ogg_packet op;
|
||||
int i,ret;
|
||||
int allbos=0;
|
||||
|
||||
if(!og_ptr){
|
||||
ogg_int64_t llret=_get_next_page(vf,&og,CHUNKSIZE);
|
||||
if(llret==OV_EREAD)return(OV_EREAD);
|
||||
if(llret<0)return OV_ENOTVORBIS;
|
||||
if(llret<0)return(OV_ENOTVORBIS);
|
||||
og_ptr=&og;
|
||||
}
|
||||
|
||||
|
|
@ -320,10 +311,10 @@ static int _fetch_headers(OggVorbis_File *vf,
|
|||
if(vf->ready_state<STREAMSET){
|
||||
/* we don't have a vorbis stream in this link yet, so begin
|
||||
prospective stream setup. We need a stream to get packets */
|
||||
ogg_stream_reset_serialno(vf->os,ogg_page_serialno(og_ptr));
|
||||
ogg_stream_pagein(vf->os,og_ptr);
|
||||
ogg_stream_reset_serialno(&vf->os,ogg_page_serialno(og_ptr));
|
||||
ogg_stream_pagein(&vf->os,og_ptr);
|
||||
|
||||
if(ogg_stream_packetout(vf->os,&op) > 0 &&
|
||||
if(ogg_stream_packetout(&vf->os,&op) > 0 &&
|
||||
vorbis_synthesis_idheader(&op)){
|
||||
/* vorbis header; continue setup */
|
||||
vf->ready_state=STREAMSET;
|
||||
|
|
@ -348,8 +339,8 @@ static int _fetch_headers(OggVorbis_File *vf,
|
|||
|
||||
/* if this page also belongs to our vorbis stream, submit it and break */
|
||||
if(vf->ready_state==STREAMSET &&
|
||||
(ogg_uint32_t) vf->os->serialno == ogg_page_serialno(og_ptr)){
|
||||
ogg_stream_pagein(vf->os,og_ptr);
|
||||
vf->os.serialno == ogg_page_serialno(og_ptr)){
|
||||
ogg_stream_pagein(&vf->os,og_ptr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -367,7 +358,7 @@ static int _fetch_headers(OggVorbis_File *vf,
|
|||
|
||||
while(i<2){ /* get a packet loop */
|
||||
|
||||
int result=ogg_stream_packetout(vf->os,&op);
|
||||
int result=ogg_stream_packetout(&vf->os,&op);
|
||||
if(result==0)break;
|
||||
if(result==-1){
|
||||
ret=OV_EBADHEADER;
|
||||
|
|
@ -387,8 +378,8 @@ static int _fetch_headers(OggVorbis_File *vf,
|
|||
}
|
||||
|
||||
/* if this page belongs to the correct stream, go parse it */
|
||||
if((ogg_uint32_t) vf->os->serialno == ogg_page_serialno(og_ptr)){
|
||||
ogg_stream_pagein(vf->os,og_ptr);
|
||||
if(vf->os.serialno == ogg_page_serialno(og_ptr)){
|
||||
ogg_stream_pagein(&vf->os,og_ptr);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -406,15 +397,10 @@ static int _fetch_headers(OggVorbis_File *vf,
|
|||
}
|
||||
}
|
||||
|
||||
ogg_packet_release(&op);
|
||||
ogg_page_release(&og);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bail_header:
|
||||
ogg_packet_release(&op);
|
||||
ogg_page_release(&og);
|
||||
vorbis_info_clear(vi);
|
||||
vorbis_comment_clear(vc);
|
||||
vf->ready_state=OPENED;
|
||||
|
|
@ -427,25 +413,23 @@ static int _fetch_headers(OggVorbis_File *vf,
|
|||
audio, however this is only called during stream parsing upon
|
||||
seekable open. */
|
||||
static ogg_int64_t _initial_pcmoffset(OggVorbis_File *vf, vorbis_info *vi){
|
||||
ogg_page og={0,0,0,0};
|
||||
ogg_int64_t accumulated=0,pos;
|
||||
ogg_page og;
|
||||
ogg_int64_t accumulated=0;
|
||||
long lastblock=-1;
|
||||
int result;
|
||||
int serialno = vf->os->serialno;
|
||||
ogg_uint32_t serialno = vf->os.serialno;
|
||||
|
||||
while(1){
|
||||
ogg_packet op={0,0,0,0,0,0};
|
||||
|
||||
ogg_packet op;
|
||||
if(_get_next_page(vf,&og,-1)<0)
|
||||
break; /* should not be possible unless the file is truncated/mangled */
|
||||
|
||||
if(ogg_page_bos(&og)) break;
|
||||
if(ogg_page_serialno(&og)!=(ogg_uint32_t) serialno) continue;
|
||||
pos=ogg_page_granulepos(&og);
|
||||
if(ogg_page_serialno(&og)!= serialno) continue;
|
||||
|
||||
/* count blocksizes of all frames in the page */
|
||||
ogg_stream_pagein(vf->os,&og);
|
||||
while((result=ogg_stream_packetout(vf->os,&op))){
|
||||
ogg_stream_pagein(&vf->os,&og);
|
||||
while((result=ogg_stream_packetout(&vf->os,&op))){
|
||||
if(result>0){ /* ignore holes */
|
||||
long thisblock=vorbis_packet_blocksize(vi,&op);
|
||||
if(lastblock!=-1)
|
||||
|
|
@ -453,11 +437,10 @@ static ogg_int64_t _initial_pcmoffset(OggVorbis_File *vf, vorbis_info *vi){
|
|||
lastblock=thisblock;
|
||||
}
|
||||
}
|
||||
ogg_packet_release(&op);
|
||||
|
||||
if(pos!=-1){
|
||||
if(ogg_page_granulepos(&og)!=-1){
|
||||
/* pcm offset of last packet on the first audio page */
|
||||
accumulated= pos-accumulated;
|
||||
accumulated= ogg_page_granulepos(&og)-accumulated;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -466,11 +449,9 @@ static ogg_int64_t _initial_pcmoffset(OggVorbis_File *vf, vorbis_info *vi){
|
|||
the beginning, a normal occurrence; set the offset to zero */
|
||||
if(accumulated<0)accumulated=0;
|
||||
|
||||
ogg_page_release(&og);
|
||||
return accumulated;
|
||||
}
|
||||
|
||||
|
||||
/* finds each bitstream link one at a time using a bisection search
|
||||
(has to begin by knowing the offset of the lb's initial page).
|
||||
Recurses for each link so it can alloc the link storage after
|
||||
|
|
@ -484,14 +465,14 @@ static int _bisect_forward_serialno(OggVorbis_File *vf,
|
|||
ogg_uint32_t *currentno_list,
|
||||
int currentnos,
|
||||
long m){
|
||||
|
||||
ogg_int64_t pcmoffset;
|
||||
ogg_int64_t dataoffset=searched;
|
||||
ogg_int64_t endsearched=end;
|
||||
ogg_int64_t next=end;
|
||||
ogg_int64_t searchgran=-1;
|
||||
ogg_page og;
|
||||
ogg_int64_t ret,last;
|
||||
int serialno = vf->os->serialno;
|
||||
int serialno = vf->os.serialno;
|
||||
|
||||
/* invariants:
|
||||
we have the headers and serialnos for the link beginning at 'begin'
|
||||
|
|
@ -538,7 +519,6 @@ static int _bisect_forward_serialno(OggVorbis_File *vf,
|
|||
/* the below guards against garbage seperating the last and
|
||||
first pages of two links. */
|
||||
while(searched<endsearched){
|
||||
ogg_page og={0,0,0,0};
|
||||
ogg_int64_t bisect;
|
||||
|
||||
if(endsearched-searched<CHUNKSIZE){
|
||||
|
|
@ -547,8 +527,10 @@ static int _bisect_forward_serialno(OggVorbis_File *vf,
|
|||
bisect=(searched+endsearched)/2;
|
||||
}
|
||||
|
||||
if(bisect != vf->offset){
|
||||
ret=_seek_helper(vf,bisect);
|
||||
if(ret)return(ret);
|
||||
}
|
||||
|
||||
last=_get_next_page(vf,&og,-1);
|
||||
if(last==OV_EREAD)return(OV_EREAD);
|
||||
|
|
@ -556,9 +538,8 @@ static int _bisect_forward_serialno(OggVorbis_File *vf,
|
|||
endsearched=bisect;
|
||||
if(last>=0)next=last;
|
||||
}else{
|
||||
searched=last+og.header_len+og.body_len;
|
||||
searched=vf->offset;
|
||||
}
|
||||
ogg_page_release(&og);
|
||||
}
|
||||
|
||||
/* Bisection point found */
|
||||
|
|
@ -580,7 +561,7 @@ static int _bisect_forward_serialno(OggVorbis_File *vf,
|
|||
|
||||
ret=_fetch_headers(vf,&vi,&vc,&next_serialno_list,&next_serialnos,NULL);
|
||||
if(ret)return(ret);
|
||||
serialno = vf->os->serialno;
|
||||
serialno = vf->os.serialno;
|
||||
dataoffset = vf->offset;
|
||||
|
||||
/* this will consume a page, however the next bistection always
|
||||
|
|
@ -627,8 +608,8 @@ static int _make_decode_ready(OggVorbis_File *vf){
|
|||
|
||||
static int _open_seekable2(OggVorbis_File *vf){
|
||||
ogg_int64_t dataoffset=vf->dataoffsets[0],end,endgran=-1;
|
||||
int endserial=vf->os->serialno;
|
||||
int serialno=vf->os->serialno;
|
||||
int endserial=vf->os.serialno;
|
||||
int serialno=vf->os.serialno;
|
||||
|
||||
/* we're partially open and have a first link header state in
|
||||
storage in vf */
|
||||
|
|
@ -684,40 +665,36 @@ static void _decode_clear(OggVorbis_File *vf){
|
|||
1) got a packet
|
||||
*/
|
||||
|
||||
STATICIRAM_NOT_MDCT int _fetch_and_process_packet(OggVorbis_File *vf,
|
||||
int readp,
|
||||
int spanp) ICODE_ATTR_TREMOR_NOT_MDCT;
|
||||
STATICIRAM_NOT_MDCT int _fetch_and_process_packet(OggVorbis_File *vf,
|
||||
static int _fetch_and_process_packet(OggVorbis_File *vf,
|
||||
ogg_packet *op_in,
|
||||
int readp,
|
||||
int spanp){
|
||||
ogg_page og={0,0,0,0};
|
||||
ogg_packet op={0,0,0,0,0,0};
|
||||
int ret=0;
|
||||
ogg_page og;
|
||||
|
||||
/* handle one packet. Try to fetch it from current stream state */
|
||||
/* extract packets from page */
|
||||
while(1){
|
||||
|
||||
if(vf->ready_state==STREAMSET){
|
||||
ret=_make_decode_ready(vf);
|
||||
if(ret<0) goto cleanup;
|
||||
int ret=_make_decode_ready(vf);
|
||||
if(ret<0)return ret;
|
||||
}
|
||||
|
||||
/* process a packet if we can. If the machine isn't loaded,
|
||||
neither is a page */
|
||||
if(vf->ready_state==INITSET){
|
||||
while(1) {
|
||||
int result=ogg_stream_packetout(vf->os,&op);
|
||||
ogg_packet op;
|
||||
ogg_packet *op_ptr=(op_in?op_in:&op);
|
||||
int result=ogg_stream_packetout(&vf->os,op_ptr);
|
||||
ogg_int64_t granulepos;
|
||||
|
||||
if(result==-1){
|
||||
ret=OV_HOLE; /* hole in the data. */
|
||||
goto cleanup;
|
||||
}
|
||||
op_in=NULL;
|
||||
if(result==-1)return(OV_HOLE); /* hole in the data. */
|
||||
if(result>0){
|
||||
/* got a packet. process it */
|
||||
granulepos=op.granulepos;
|
||||
if(!vorbis_synthesis(&vf->vb,&op)){ /* lazy check for lazy
|
||||
granulepos=op_ptr->granulepos;
|
||||
if(!vorbis_synthesis(&vf->vb,op_ptr)){ /* lazy check for lazy
|
||||
header handling. The
|
||||
header packets aren't
|
||||
audio, so if/when we
|
||||
|
|
@ -730,18 +707,15 @@ STATICIRAM_NOT_MDCT int _fetch_and_process_packet(OggVorbis_File *vf,
|
|||
int oldsamples=vorbis_synthesis_pcmout(&vf->vd,NULL);
|
||||
/* for proper use of libvorbis within libvorbisfile,
|
||||
oldsamples will always be zero. */
|
||||
if(oldsamples){
|
||||
ret=OV_EFAULT;
|
||||
goto cleanup;
|
||||
}
|
||||
if(oldsamples)return(OV_EFAULT);
|
||||
|
||||
vorbis_synthesis_blockin(&vf->vd,&vf->vb);
|
||||
vf->samptrack+=vorbis_synthesis_pcmout(&vf->vd,NULL)-oldsamples;
|
||||
vf->bittrack+=op.bytes*8;
|
||||
vf->bittrack+=op_ptr->bytes*8;
|
||||
}
|
||||
|
||||
/* update the pcm offset. */
|
||||
if(granulepos!=-1 && !op.e_o_s){
|
||||
if(granulepos!=-1 && !op_ptr->e_o_s){
|
||||
int link=(vf->seekable?vf->current_link:0);
|
||||
int i,samples;
|
||||
|
||||
|
|
@ -755,7 +729,7 @@ STATICIRAM_NOT_MDCT int _fetch_and_process_packet(OggVorbis_File *vf,
|
|||
granulepos declares the last frame in the stream, and the
|
||||
last packet of the last page may be a partial frame.
|
||||
So, we need a previous granulepos from an in-sequence page
|
||||
to have a reference point. Thus the !op.e_o_s clause
|
||||
to have a reference point. Thus the !op_ptr->e_o_s clause
|
||||
above */
|
||||
|
||||
if(vf->seekable && link>0)
|
||||
|
|
@ -772,8 +746,7 @@ STATICIRAM_NOT_MDCT int _fetch_and_process_packet(OggVorbis_File *vf,
|
|||
granulepos+=vf->pcmlengths[i*2+1];
|
||||
vf->pcm_offset=granulepos;
|
||||
}
|
||||
ret=1;
|
||||
goto cleanup;
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -782,7 +755,7 @@ STATICIRAM_NOT_MDCT int _fetch_and_process_packet(OggVorbis_File *vf,
|
|||
}
|
||||
|
||||
if(vf->ready_state>=OPENED){
|
||||
ogg_int64_t lret;
|
||||
ogg_int64_t ret;
|
||||
|
||||
while(1){
|
||||
/* the loop is not strictly necessary, but there's no sense in
|
||||
|
|
@ -791,13 +764,9 @@ STATICIRAM_NOT_MDCT int _fetch_and_process_packet(OggVorbis_File *vf,
|
|||
part of a different logical bitstream; keep reading until
|
||||
we get one with the correct serialno */
|
||||
|
||||
if(!readp){
|
||||
ret=0;
|
||||
goto cleanup;
|
||||
}
|
||||
if((lret=_get_next_page(vf,&og,-1))<0){
|
||||
ret=OV_EOF; /* eof. leave unitialized */
|
||||
goto cleanup;
|
||||
if(!readp)return(0);
|
||||
if((ret=_get_next_page(vf,&og,-1))<0){
|
||||
return(OV_EOF); /* eof. leave unitialized */
|
||||
}
|
||||
|
||||
/* bitrate tracking; add the header's bytes here, the body bytes
|
||||
|
|
@ -813,10 +782,8 @@ STATICIRAM_NOT_MDCT int _fetch_and_process_packet(OggVorbis_File *vf,
|
|||
|
||||
if(ogg_page_bos(&og)){
|
||||
/* boundary case */
|
||||
if(!spanp){
|
||||
ret=OV_EOF;
|
||||
goto cleanup;
|
||||
}
|
||||
if(!spanp)
|
||||
return(OV_EOF);
|
||||
|
||||
_decode_clear(vf);
|
||||
|
||||
|
|
@ -830,6 +797,7 @@ STATICIRAM_NOT_MDCT int _fetch_and_process_packet(OggVorbis_File *vf,
|
|||
continue; /* possibility #2 */
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -851,14 +819,14 @@ STATICIRAM_NOT_MDCT int _fetch_and_process_packet(OggVorbis_File *vf,
|
|||
|
||||
if(vf->ready_state<STREAMSET){
|
||||
if(vf->seekable){
|
||||
long serialno=ogg_page_serialno(&og);
|
||||
ogg_uint32_t serialno = ogg_page_serialno(&og);
|
||||
|
||||
/* match the serialno to bitstream section. We use this rather than
|
||||
offset positions to avoid problems near logical bitstream
|
||||
boundaries */
|
||||
|
||||
for(link=0;link<vf->links;link++)
|
||||
if(vf->serialnos[link]==(ogg_uint32_t) serialno)break;
|
||||
if(vf->serialnos[link]==serialno)break;
|
||||
|
||||
if(link==vf->links) continue; /* not the desired Vorbis
|
||||
bitstream section; keep
|
||||
|
|
@ -867,7 +835,7 @@ STATICIRAM_NOT_MDCT int _fetch_and_process_packet(OggVorbis_File *vf,
|
|||
vf->current_serialno=serialno;
|
||||
vf->current_link=link;
|
||||
|
||||
ogg_stream_reset_serialno(vf->os,vf->current_serialno);
|
||||
ogg_stream_reset_serialno(&vf->os,vf->current_serialno);
|
||||
vf->ready_state=STREAMSET;
|
||||
|
||||
}else{
|
||||
|
|
@ -875,8 +843,8 @@ STATICIRAM_NOT_MDCT int _fetch_and_process_packet(OggVorbis_File *vf,
|
|||
/* fetch the three header packets, build the info struct */
|
||||
|
||||
int ret=_fetch_headers(vf,vf->vi,vf->vc,NULL,NULL,&og);
|
||||
if(ret) goto cleanup;
|
||||
vf->current_serialno=vf->os->serialno;
|
||||
if(ret)return(ret);
|
||||
vf->current_serialno=vf->os.serialno;
|
||||
vf->current_link++;
|
||||
link=0;
|
||||
}
|
||||
|
|
@ -885,17 +853,14 @@ STATICIRAM_NOT_MDCT int _fetch_and_process_packet(OggVorbis_File *vf,
|
|||
|
||||
/* the buffered page is the data we want, and we're ready for it;
|
||||
add it to the stream state */
|
||||
ogg_stream_pagein(vf->os,&og);
|
||||
ogg_stream_pagein(&vf->os,&og);
|
||||
|
||||
}
|
||||
cleanup:
|
||||
ogg_packet_release(&op);
|
||||
ogg_page_release(&og);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int _ov_open1(void *f,OggVorbis_File *vf,char *initial,
|
||||
static int _ov_open1(void *f,OggVorbis_File *vf,const char *initial,
|
||||
long ibytes, ov_callbacks callbacks){
|
||||
int offsettest=(f?callbacks.seek_func(f,0,SEEK_CUR):-1);
|
||||
int offsettest=((f && callbacks.seek_func)?callbacks.seek_func(f,0,SEEK_CUR):-1);
|
||||
ogg_uint32_t *serialno_list=NULL;
|
||||
int serialno_list_size=0;
|
||||
int ret;
|
||||
|
|
@ -905,16 +870,16 @@ static int _ov_open1(void *f,OggVorbis_File *vf,char *initial,
|
|||
vf->callbacks = callbacks;
|
||||
|
||||
/* init the framing state */
|
||||
vf->oy=ogg_sync_create();
|
||||
ogg_sync_init(&vf->oy);
|
||||
|
||||
/* perhaps some data was previously read into a buffer for testing
|
||||
against other stream types. Allow initialization from this
|
||||
previously read data (especially as we may be reading from a
|
||||
non-seekable stream) */
|
||||
if(initial){
|
||||
unsigned char *buffer=ogg_sync_bufferin(vf->oy,ibytes);
|
||||
char *buffer=ogg_sync_buffer(&vf->oy,ibytes);
|
||||
memcpy(buffer,initial,ibytes);
|
||||
ogg_sync_wrote(vf->oy,ibytes);
|
||||
ogg_sync_wrote(&vf->oy,ibytes);
|
||||
}
|
||||
|
||||
/* can we seek? Stevens suggests the seek test was portable */
|
||||
|
|
@ -925,7 +890,7 @@ static int _ov_open1(void *f,OggVorbis_File *vf,char *initial,
|
|||
vf->links=1;
|
||||
vf->vi=_ogg_calloc(vf->links,sizeof(*vf->vi));
|
||||
vf->vc=_ogg_calloc(vf->links,sizeof(*vf->vc));
|
||||
vf->os=ogg_stream_create(-1); /* fill in the serialno later */
|
||||
ogg_stream_init(&vf->os,-1); /* fill in the serialno later */
|
||||
|
||||
/* Fetch all BOS pages, store the vorbis header and all seen serial
|
||||
numbers, load subsequent vorbis setup headers */
|
||||
|
|
@ -945,7 +910,7 @@ static int _ov_open1(void *f,OggVorbis_File *vf,char *initial,
|
|||
vf->dataoffsets=_ogg_calloc(1,sizeof(*vf->dataoffsets));
|
||||
vf->offsets[0]=0;
|
||||
vf->dataoffsets[0]=vf->offset;
|
||||
vf->current_serialno=vf->os->serialno;
|
||||
vf->current_serialno=vf->os.serialno;
|
||||
|
||||
vf->ready_state=PARTOPEN;
|
||||
}
|
||||
|
|
@ -954,7 +919,7 @@ static int _ov_open1(void *f,OggVorbis_File *vf,char *initial,
|
|||
}
|
||||
|
||||
static int _ov_open2(OggVorbis_File *vf){
|
||||
if(vf->ready_state < OPENED)
|
||||
if(vf->ready_state != PARTOPEN) return OV_EINVAL;
|
||||
vf->ready_state=OPENED;
|
||||
if(vf->seekable){
|
||||
int ret=_open_seekable2(vf);
|
||||
|
|
@ -963,7 +928,9 @@ static int _ov_open2(OggVorbis_File *vf){
|
|||
ov_clear(vf);
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
}else
|
||||
vf->ready_state=STREAMSET;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -973,7 +940,7 @@ int ov_clear(OggVorbis_File *vf){
|
|||
if(vf){
|
||||
vorbis_block_clear(&vf->vb);
|
||||
vorbis_dsp_clear(&vf->vd);
|
||||
ogg_stream_destroy(vf->os);
|
||||
ogg_stream_clear(&vf->os);
|
||||
|
||||
if(vf->vi && vf->links){
|
||||
int i;
|
||||
|
|
@ -988,8 +955,7 @@ int ov_clear(OggVorbis_File *vf){
|
|||
if(vf->pcmlengths)_ogg_free(vf->pcmlengths);
|
||||
if(vf->serialnos)_ogg_free(vf->serialnos);
|
||||
if(vf->offsets)_ogg_free(vf->offsets);
|
||||
ogg_sync_destroy(vf->oy);
|
||||
|
||||
ogg_sync_clear(&vf->oy);
|
||||
if(vf->datasource && vf->callbacks.close_func)
|
||||
(vf->callbacks.close_func)(vf->datasource);
|
||||
memset(vf,0,sizeof(*vf));
|
||||
|
|
@ -1008,8 +974,8 @@ int ov_clear(OggVorbis_File *vf){
|
|||
0) OK
|
||||
*/
|
||||
|
||||
int ov_open_callbacks(void *f,OggVorbis_File *vf,char *initial,long ibytes,
|
||||
ov_callbacks callbacks){
|
||||
int ov_open_callbacks(void *f,OggVorbis_File *vf,
|
||||
const char *initial,long ibytes,ov_callbacks callbacks){
|
||||
#if defined(CPU_COLDFIRE)
|
||||
/* this seems to be the closest we get to an init function, let's init emac
|
||||
here. rounding is disabled because of MULT31_SHIFT15, which will be
|
||||
|
|
@ -1067,9 +1033,7 @@ ogg_int64_t ov_time_total(OggVorbis_File *vf,int i){
|
|||
returns zero on success, nonzero on failure */
|
||||
|
||||
int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos){
|
||||
ogg_stream_state *work_os=NULL;
|
||||
ogg_page og={0,0,0,0};
|
||||
ogg_packet op={0,0,0,0,0,0};
|
||||
ogg_stream_state work_os;
|
||||
int ret;
|
||||
|
||||
if(vf->ready_state<OPENED)return(OV_EINVAL);
|
||||
|
|
@ -1078,12 +1042,18 @@ int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos){
|
|||
|
||||
if(pos<0 || pos>vf->end)return(OV_EINVAL);
|
||||
|
||||
/* is the seek position outside our current link [if any]? */
|
||||
if(vf->ready_state>=STREAMSET){
|
||||
if(pos<vf->offsets[vf->current_link] || pos>=vf->offsets[vf->current_link+1])
|
||||
_decode_clear(vf); /* clear out stream state */
|
||||
}
|
||||
|
||||
/* don't yet clear out decoding machine (if it's initialized), in
|
||||
the case we're in the same link. Restart the decode lapping, and
|
||||
let _fetch_and_process_packet deal with a potential bitstream
|
||||
boundary */
|
||||
vf->pcm_offset=-1;
|
||||
ogg_stream_reset_serialno(vf->os,
|
||||
ogg_stream_reset_serialno(&vf->os,
|
||||
vf->current_serialno); /* must set serialno */
|
||||
vorbis_synthesis_restart(&vf->vd);
|
||||
|
||||
|
|
@ -1106,37 +1076,43 @@ int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos){
|
|||
*/
|
||||
|
||||
{
|
||||
ogg_page og;
|
||||
ogg_packet op;
|
||||
int lastblock=0;
|
||||
int accblock=0;
|
||||
int thisblock;
|
||||
int thisblock=0;
|
||||
int lastflag=0;
|
||||
int firstflag=0;
|
||||
ogg_int64_t pagepos=-1;
|
||||
|
||||
work_os=ogg_stream_create(vf->current_serialno); /* get the memory ready */
|
||||
ogg_stream_init(&work_os,vf->current_serialno); /* get the memory ready */
|
||||
ogg_stream_reset(&work_os); /* eliminate the spurious OV_HOLE
|
||||
return from not necessarily
|
||||
starting from the beginning */
|
||||
|
||||
while(1){
|
||||
if(vf->ready_state>=STREAMSET){
|
||||
/* snarf/scan a packet if we can */
|
||||
int result=ogg_stream_packetout(work_os,&op);
|
||||
int result=ogg_stream_packetout(&work_os,&op);
|
||||
|
||||
if(result>0){
|
||||
|
||||
if(vf->vi[vf->current_link].codec_setup){
|
||||
thisblock=vorbis_packet_blocksize(vf->vi+vf->current_link,&op);
|
||||
if(thisblock<0){
|
||||
ogg_stream_packetout(vf->os,NULL);
|
||||
ogg_stream_packetout(&vf->os,NULL);
|
||||
thisblock=0;
|
||||
}else{
|
||||
|
||||
/* We can't get a guaranteed correct pcm position out of the
|
||||
last page in a stream because it might have a 'short'
|
||||
granpos, which can only be detected in the presence of a
|
||||
preceeding page. However, if the last page is also the first
|
||||
preceding page. However, if the last page is also the first
|
||||
page, the granpos rules of a first page take precedence. Not
|
||||
only that, but for first==last, the EOS page must be treated
|
||||
as if its a normal first page for the stream to open/play. */
|
||||
if(lastflag && !firstflag)
|
||||
ogg_stream_packetout(vf->os,NULL);
|
||||
ogg_stream_packetout(&vf->os,NULL);
|
||||
else
|
||||
if(lastblock)accblock+=(lastblock+thisblock)>>2;
|
||||
}
|
||||
|
|
@ -1155,7 +1131,7 @@ int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos){
|
|||
lastblock=thisblock;
|
||||
continue;
|
||||
}else
|
||||
ogg_stream_packetout(vf->os,NULL);
|
||||
ogg_stream_packetout(&vf->os,NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1174,6 +1150,7 @@ int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos){
|
|||
/* has our decoding just traversed a bitstream boundary? */
|
||||
if(vf->ready_state>=STREAMSET){
|
||||
if(vf->current_serialno!=ogg_page_serialno(&og)){
|
||||
|
||||
/* two possibilities:
|
||||
1) our decoding just traversed a bitstream boundary
|
||||
2) another stream is multiplexed into this logical section? */
|
||||
|
|
@ -1181,53 +1158,45 @@ int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos){
|
|||
if(ogg_page_bos(&og)){
|
||||
/* we traversed */
|
||||
_decode_clear(vf); /* clear out stream state */
|
||||
ogg_stream_destroy(work_os);
|
||||
ogg_stream_clear(&work_os);
|
||||
} /* else, do nothing; next loop will scoop another page */
|
||||
}
|
||||
}
|
||||
|
||||
if(vf->ready_state<STREAMSET){
|
||||
int link;
|
||||
long serialno = ogg_page_serialno(&og);
|
||||
ogg_uint32_t serialno = ogg_page_serialno(&og);
|
||||
|
||||
for(link=0;link<vf->links;link++)
|
||||
if(vf->serialnos[link]==vf->current_serialno)break;
|
||||
if(vf->serialnos[link]==serialno)break;
|
||||
|
||||
if(link==vf->links) continue; /* not the desired Vorbis
|
||||
bitstream section; keep
|
||||
trying */
|
||||
vf->current_link=link;
|
||||
vf->current_serialno=serialno;
|
||||
ogg_stream_reset_serialno(vf->os,vf->current_serialno);
|
||||
ogg_stream_reset_serialno(work_os,vf->current_serialno);
|
||||
ogg_stream_reset_serialno(&vf->os,serialno);
|
||||
ogg_stream_reset_serialno(&work_os,serialno);
|
||||
vf->ready_state=STREAMSET;
|
||||
firstflag=(pagepos<=vf->dataoffsets[link]);
|
||||
}
|
||||
|
||||
{
|
||||
ogg_page dup;
|
||||
ogg_page_dup(&dup,&og);
|
||||
ogg_stream_pagein(&vf->os,&og);
|
||||
ogg_stream_pagein(&work_os,&og);
|
||||
lastflag=ogg_page_eos(&og);
|
||||
ogg_stream_pagein(vf->os,&og);
|
||||
ogg_stream_pagein(work_os,&dup);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
ogg_packet_release(&op);
|
||||
ogg_page_release(&og);
|
||||
ogg_stream_destroy(work_os);
|
||||
ogg_stream_clear(&work_os);
|
||||
vf->bittrack=0;
|
||||
vf->samptrack=0;
|
||||
return(0);
|
||||
|
||||
seek_error:
|
||||
ogg_packet_release(&op);
|
||||
ogg_page_release(&og);
|
||||
|
||||
/* dump the machine so we're in a known state */
|
||||
vf->pcm_offset=-1;
|
||||
ogg_stream_destroy(work_os);
|
||||
ogg_stream_clear(&work_os);
|
||||
_decode_clear(vf);
|
||||
return OV_EBADLINK;
|
||||
}
|
||||
|
|
@ -1235,18 +1204,17 @@ int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos){
|
|||
/* Page granularity seek (faster than sample granularity because we
|
||||
don't do the last bit of decode to find a specific sample).
|
||||
|
||||
Seek to the last [granule marked] page preceeding the specified pos
|
||||
Seek to the last [granule marked] page preceding the specified pos
|
||||
location, such that decoding past the returned point will quickly
|
||||
arrive at the requested position. */
|
||||
int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
|
||||
int link=-1;
|
||||
ogg_int64_t result=0;
|
||||
ogg_int64_t total=ov_pcm_total(vf,-1);
|
||||
ogg_page og={0,0,0,0};
|
||||
ogg_packet op={0,0,0,0,0,0};
|
||||
|
||||
if(vf->ready_state<OPENED)return(OV_EINVAL);
|
||||
if(!vf->seekable)return(OV_ENOSEEK);
|
||||
|
||||
if(pos<0 || pos>total)return(OV_EINVAL);
|
||||
|
||||
/* which bitstream section does this pcm offset occur in? */
|
||||
|
|
@ -1256,7 +1224,7 @@ int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
|
|||
}
|
||||
|
||||
/* search within the logical bitstream for the page with the highest
|
||||
pcm_pos preceeding (or equal to) pos. There is a danger here;
|
||||
pcm_pos preceding (or equal to) pos. There is a danger here;
|
||||
missing pages or incorrect frame number information in the
|
||||
bitstream could make our task impossible. Account for that (it
|
||||
would be an error condition) */
|
||||
|
|
@ -1270,6 +1238,7 @@ int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
|
|||
ogg_int64_t target=pos-total+begintime;
|
||||
ogg_int64_t best=begin;
|
||||
|
||||
ogg_page og;
|
||||
while(begin<end){
|
||||
ogg_int64_t bisect;
|
||||
|
||||
|
|
@ -1279,11 +1248,14 @@ int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
|
|||
/* take a (pretty decent) guess. */
|
||||
bisect=begin +
|
||||
(target-begintime)*(end-begin)/(endtime-begintime) - CHUNKSIZE;
|
||||
if(bisect<=begin)
|
||||
bisect=begin+1;
|
||||
if(bisect<begin+CHUNKSIZE)
|
||||
bisect=begin;
|
||||
}
|
||||
|
||||
_seek_helper(vf,bisect);
|
||||
if(bisect!=vf->offset){
|
||||
result=_seek_helper(vf,bisect);
|
||||
if(result) goto seek_error;
|
||||
}
|
||||
|
||||
while(begin<end){
|
||||
result=_get_next_page(vf,&og,end-vf->offset);
|
||||
|
|
@ -1295,11 +1267,18 @@ int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
|
|||
if(bisect==0) goto seek_error;
|
||||
bisect-=CHUNKSIZE;
|
||||
if(bisect<=begin)bisect=begin+1;
|
||||
_seek_helper(vf,bisect);
|
||||
result=_seek_helper(vf,bisect);
|
||||
if(result) goto seek_error;
|
||||
}
|
||||
}else{
|
||||
ogg_int64_t granulepos=ogg_page_granulepos(&og);
|
||||
ogg_int64_t granulepos;
|
||||
|
||||
if(ogg_page_serialno(&og)!=vf->serialnos[link])
|
||||
continue;
|
||||
|
||||
granulepos=ogg_page_granulepos(&og);
|
||||
if(granulepos==-1)continue;
|
||||
|
||||
if(granulepos<target){
|
||||
best=result; /* raw offset of packet with granulepos */
|
||||
begin=vf->offset; /* raw offset of next page */
|
||||
|
|
@ -1315,9 +1294,10 @@ int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
|
|||
end=result;
|
||||
bisect-=CHUNKSIZE; /* an endless loop otherwise. */
|
||||
if(bisect<=begin)bisect=begin+1;
|
||||
_seek_helper(vf,bisect);
|
||||
result=_seek_helper(vf,bisect);
|
||||
if(result) goto seek_error;
|
||||
}else{
|
||||
end=result;
|
||||
end=bisect;
|
||||
endtime=granulepos;
|
||||
break;
|
||||
}
|
||||
|
|
@ -1328,8 +1308,10 @@ int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
|
|||
}
|
||||
|
||||
/* found our page. seek to it, update pcm offset. Easier case than
|
||||
raw_seek, don't keep packets preceeding granulepos. */
|
||||
raw_seek, don't keep packets preceding granulepos. */
|
||||
{
|
||||
ogg_page og;
|
||||
ogg_packet op;
|
||||
|
||||
/* seek */
|
||||
result=_seek_helper(vf,best);
|
||||
|
|
@ -1343,22 +1325,22 @@ int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
|
|||
_decode_clear(vf);
|
||||
|
||||
vf->current_link=link;
|
||||
vf->current_serialno=ogg_page_serialno(&og);
|
||||
vf->current_serialno=vf->serialnos[link];
|
||||
vf->ready_state=STREAMSET;
|
||||
|
||||
}else{
|
||||
vorbis_synthesis_restart(&vf->vd);
|
||||
}
|
||||
|
||||
ogg_stream_reset_serialno(vf->os,vf->current_serialno);
|
||||
ogg_stream_pagein(vf->os,&og);
|
||||
ogg_stream_reset_serialno(&vf->os,vf->current_serialno);
|
||||
ogg_stream_pagein(&vf->os,&og);
|
||||
|
||||
/* pull out all but last packet; the one with granulepos */
|
||||
while(1){
|
||||
result=ogg_stream_packetpeek(vf->os,&op);
|
||||
result=ogg_stream_packetpeek(&vf->os,&op);
|
||||
if(result==0){
|
||||
/* !!! the packet finishing this page originated on a
|
||||
preceeding page. Keep fetching previous pages until we
|
||||
preceding page. Keep fetching previous pages until we
|
||||
get one with a granulepos or without the 'continued' flag
|
||||
set. Then just use raw_seek for simplicity. */
|
||||
|
||||
|
|
@ -1386,7 +1368,7 @@ int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
|
|||
vf->pcm_offset+=total;
|
||||
break;
|
||||
}else
|
||||
result=ogg_stream_packetout(vf->os,NULL);
|
||||
result=ogg_stream_packetout(&vf->os,NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1398,16 +1380,9 @@ int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
|
|||
}
|
||||
vf->bittrack=0;
|
||||
vf->samptrack=0;
|
||||
|
||||
ogg_page_release(&og);
|
||||
ogg_packet_release(&op);
|
||||
return(0);
|
||||
|
||||
seek_error:
|
||||
|
||||
ogg_page_release(&og);
|
||||
ogg_packet_release(&op);
|
||||
|
||||
/* dump machine so we're in a known state */
|
||||
vf->pcm_offset=-1;
|
||||
_decode_clear(vf);
|
||||
|
|
@ -1418,23 +1393,23 @@ int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
|
|||
returns zero on success, nonzero on failure */
|
||||
|
||||
int ov_pcm_seek(OggVorbis_File *vf,ogg_int64_t pos){
|
||||
ogg_packet op={0,0,0,0,0,0};
|
||||
ogg_page og={0,0,0,0};
|
||||
int thisblock,lastblock=0;
|
||||
int ret=ov_pcm_seek_page(vf,pos);
|
||||
if(ret<0)return(ret);
|
||||
_make_decode_ready(vf);
|
||||
if((ret=_make_decode_ready(vf)))return ret;
|
||||
|
||||
/* discard leading packets we don't need for the lapping of the
|
||||
position we want; don't decode them */
|
||||
|
||||
while(1){
|
||||
ogg_packet op;
|
||||
ogg_page og;
|
||||
|
||||
int ret=ogg_stream_packetpeek(vf->os,&op);
|
||||
int ret=ogg_stream_packetpeek(&vf->os,&op);
|
||||
if(ret>0){
|
||||
thisblock=vorbis_packet_blocksize(vf->vi+vf->current_link,&op);
|
||||
if(thisblock<0){
|
||||
ogg_stream_packetout(vf->os,NULL);
|
||||
ogg_stream_packetout(&vf->os,NULL);
|
||||
continue; /* non audio packet */
|
||||
}
|
||||
if(lastblock)vf->pcm_offset+=(lastblock+thisblock)>>2;
|
||||
|
|
@ -1443,7 +1418,7 @@ int ov_pcm_seek(OggVorbis_File *vf,ogg_int64_t pos){
|
|||
vorbis_info_blocksize(vf->vi,1))>>2)>=pos)break;
|
||||
|
||||
/* remove the packet from packet queue and track its granulepos */
|
||||
ogg_stream_packetout(vf->os,NULL);
|
||||
ogg_stream_packetout(&vf->os,NULL);
|
||||
vorbis_synthesis_trackonly(&vf->vb,&op); /* set up a vb with
|
||||
only tracking, no
|
||||
pcm_decode */
|
||||
|
|
@ -1481,17 +1456,13 @@ int ov_pcm_seek(OggVorbis_File *vf,ogg_int64_t pos){
|
|||
|
||||
vf->ready_state=STREAMSET;
|
||||
vf->current_serialno=ogg_page_serialno(&og);
|
||||
ogg_stream_reset_serialno(vf->os,serialno);
|
||||
ogg_stream_reset_serialno(&vf->os,serialno);
|
||||
ret=_make_decode_ready(vf);
|
||||
if(ret){
|
||||
ogg_page_release(&og);
|
||||
ogg_packet_release(&op);
|
||||
return ret;
|
||||
}
|
||||
if(ret)return ret;
|
||||
lastblock=0;
|
||||
}
|
||||
|
||||
ogg_stream_pagein(vf->os,&og);
|
||||
ogg_stream_pagein(&vf->os,&og);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1508,12 +1479,9 @@ int ov_pcm_seek(OggVorbis_File *vf,ogg_int64_t pos){
|
|||
vf->pcm_offset+=samples;
|
||||
|
||||
if(samples<target)
|
||||
if(_fetch_and_process_packet(vf,1,1)<=0)
|
||||
if(_fetch_and_process_packet(vf,NULL,1,1)<=0)
|
||||
vf->pcm_offset=ov_pcm_total(vf,-1); /* eof */
|
||||
}
|
||||
|
||||
ogg_page_release(&og);
|
||||
ogg_packet_release(&op);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1634,9 +1602,12 @@ long ov_read_fixed(OggVorbis_File *vf,ogg_int32_t ***pcm_channels,int length,
|
|||
|
||||
/* suck in another packet */
|
||||
{
|
||||
int ret=_fetch_and_process_packet(vf,1,1);
|
||||
if(ret==OV_EOF)return(0);
|
||||
if(ret<=0)return(ret);
|
||||
int ret=_fetch_and_process_packet(vf,NULL,1,1);
|
||||
if(ret==OV_EOF)
|
||||
return(0);
|
||||
if(ret<=0)
|
||||
return(ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue