📄 framing.c
字号:
if(next){
/* possible capture in this segment */
long bytes=next-now;
oy->fifo_tail=ogg_buffer_pretruncate(oy->fifo_tail,bytes);
ret-=bytes;
break;
}else{
/* no capture. advance to next segment */
long bytes=oy->fifo_tail->length;
ret-=bytes;
oy->fifo_tail=ogg_buffer_pretruncate(oy->fifo_tail,bytes);
}
}
if(!oy->fifo_tail)oy->fifo_head=0;
oy->fifo_fill+=ret;
sync_out:
return ret;
}
/* sync the stream and get a page. Keep trying until we find a page.
Supress 'sync errors' after reporting the first.
return values:
OGG_HOLE) recapture (hole in data)
0) need more data
1) page returned
Returns pointers into buffered data; invalidated by next call to
_stream, _clear, _init, or _buffer */
int ogg_sync_pageout(ogg_sync_state *oy, ogg_page *og){
/* 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
frame */
while(1){
long ret=ogg_sync_pageseek(oy,og);
if(ret>0){
/* have a page */
return 1;
}
if(ret==0){
/* need more data */
return 0;
}
/* head did not start a synced page... skipped some bytes */
if(!oy->unsynced){
oy->unsynced=1;
return OGG_HOLE;
}
/* loop. keep looking */
}
}
/* clear things to an initial state. Good to call, eg, before seeking */
int ogg_sync_reset(ogg_sync_state *oy){
ogg_buffer_release(oy->fifo_tail);
oy->fifo_tail=0;
oy->fifo_head=0;
oy->fifo_fill=0;
oy->unsynced=0;
oy->headerbytes=0;
oy->bodybytes=0;
return OGG_SUCCESS;
}
ogg_stream_state *ogg_stream_create(int serialno){
ogg_stream_state *os=_ogg_calloc(1,sizeof(*os));
os->serialno=serialno;
os->pageno=-1;
return os;
}
int ogg_stream_destroy(ogg_stream_state *os){
if(os){
ogg_buffer_release(os->header_tail);
ogg_buffer_release(os->body_tail);
memset(os,0,sizeof(*os));
_ogg_free(os);
}
return OGG_SUCCESS;
}
#define FINFLAG 0x80000000UL
#define FINMASK 0x7fffffffUL
static void _next_lace(oggbyte_buffer *ob,ogg_stream_state *os){
/* search ahead one lace */
os->body_fill_next=0;
while(os->laceptr<os->lacing_fill){
int val=oggbyte_read1(ob,27+os->laceptr++);
os->body_fill_next+=val;
if(val<255){
os->body_fill_next|=FINFLAG;
os->clearflag=1;
break;
}
}
}
static void _span_queued_page(ogg_stream_state *os){
while( !(os->body_fill&FINFLAG) ){
if(!os->header_tail)break;
/* first flush out preceeding page header (if any). Body is
flushed as it's consumed, so that's not done here. */
if(os->lacing_fill>=0)
os->header_tail=ogg_buffer_pretruncate(os->header_tail,
os->lacing_fill+27);
os->lacing_fill=0;
os->laceptr=0;
os->clearflag=0;
if(!os->header_tail){
os->header_head=0;
break;
}else{
/* process/prepare next page, if any */
long pageno;
oggbyte_buffer ob;
ogg_page og; /* only for parsing header values */
og.header=os->header_tail; /* only for parsing header values */
pageno=ogg_page_pageno(&og);
oggbyte_init(&ob,os->header_tail);
os->lacing_fill=oggbyte_read1(&ob,26);
/* are we in sequence? */
if(pageno!=os->pageno){
if(os->pageno==-1) /* indicates seek or reset */
os->holeflag=1; /* set for internal use */
else
os->holeflag=2; /* set for external reporting */
os->body_tail=ogg_buffer_pretruncate(os->body_tail,
os->body_fill);
if(os->body_tail==0)os->body_head=0;
os->body_fill=0;
}
if(ogg_page_continued(&og)){
if(os->body_fill==0){
/* continued packet, but no preceeding data to continue */
/* dump the first partial packet on the page */
_next_lace(&ob,os);
os->body_tail=
ogg_buffer_pretruncate(os->body_tail,os->body_fill_next&FINMASK);
if(os->body_tail==0)os->body_head=0;
/* set span flag */
if(!os->spanflag && !os->holeflag)os->spanflag=2;
}
}else{
if(os->body_fill>0){
/* preceeding data to continue, but not a continued page */
/* dump body_fill */
os->body_tail=ogg_buffer_pretruncate(os->body_tail,
os->body_fill);
if(os->body_tail==0)os->body_head=0;
os->body_fill=0;
/* set espan flag */
if(!os->spanflag && !os->holeflag)os->spanflag=2;
}
}
if(os->laceptr<os->lacing_fill){
os->granulepos=ogg_page_granulepos(&og);
/* get current packet size & flag */
_next_lace(&ob,os);
os->body_fill+=os->body_fill_next; /* addition handles the flag fine;
unsigned on purpose */
/* ...and next packet size & flag */
_next_lace(&ob,os);
}
os->pageno=pageno+1;
os->e_o_s=ogg_page_eos(&og);
os->b_o_s=ogg_page_bos(&og);
}
}
}
/* add the incoming page to the stream state; we decompose the page
into packet segments here as well. */
int ogg_stream_pagein(ogg_stream_state *os, ogg_page *og){
int serialno=ogg_page_serialno(og);
int version=ogg_page_version(og);
/* check the serial number */
if(serialno!=os->serialno){
ogg_page_release(og);
return OGG_ESERIAL;
}
if(version>0){
ogg_page_release(og);
return OGG_EVERSION;
}
/* add to fifos */
if(!os->body_tail){
os->body_tail=og->body;
os->body_head=ogg_buffer_walk(og->body);
}else{
os->body_head=ogg_buffer_cat(os->body_head,og->body);
}
if(!os->header_tail){
os->header_tail=og->header;
os->header_head=ogg_buffer_walk(og->header);
os->lacing_fill=-27;
}else{
os->header_head=ogg_buffer_cat(os->header_head,og->header);
}
memset(og,0,sizeof(*og));
return OGG_SUCCESS;
}
int ogg_stream_reset(ogg_stream_state *os){
ogg_buffer_release(os->header_tail);
ogg_buffer_release(os->body_tail);
os->header_tail=os->header_head=0;
os->body_tail=os->body_head=0;
os->e_o_s=0;
os->b_o_s=0;
os->pageno=-1;
os->packetno=0;
os->granulepos=0;
os->body_fill=0;
os->lacing_fill=0;
os->holeflag=0;
os->spanflag=0;
os->clearflag=0;
os->laceptr=0;
os->body_fill_next=0;
return OGG_SUCCESS;
}
int ogg_stream_reset_serialno(ogg_stream_state *os,int serialno){
ogg_stream_reset(os);
os->serialno=serialno;
return OGG_SUCCESS;
}
static int _packetout(ogg_stream_state *os,ogg_packet *op,int adv){
ogg_packet_release(op);
_span_queued_page(os);
if(os->holeflag){
int temp=os->holeflag;
if(os->clearflag)
os->holeflag=0;
else
os->holeflag=1;
if(temp==2){
os->packetno++;
return OGG_HOLE;
}
}
if(os->spanflag){
int temp=os->spanflag;
if(os->clearflag)
os->spanflag=0;
else
os->spanflag=1;
if(temp==2){
os->packetno++;
return OGG_SPAN;
}
}
if(!(os->body_fill&FINFLAG)) return 0;
if(!op && !adv)return 1; /* just using peek as an inexpensive way
to ask if there's a whole packet
waiting */
if(op){
op->b_o_s=os->b_o_s;
if(os->e_o_s && os->body_fill_next==0)
op->e_o_s=os->e_o_s;
else
op->e_o_s=0;
if( (os->body_fill&FINFLAG) && !(os->body_fill_next&FINFLAG) )
op->granulepos=os->granulepos;
else
op->granulepos=-1;
op->packetno=os->packetno;
}
if(adv){
oggbyte_buffer ob;
oggbyte_init(&ob,os->header_tail);
/* split the body contents off */
if(op){
op->packet=ogg_buffer_split(&os->body_tail,&os->body_head,
os->body_fill&FINMASK);
op->bytes=os->body_fill&FINMASK;
}else{
os->body_tail=ogg_buffer_pretruncate(os->body_tail,
os->body_fill&FINMASK);
if(os->body_tail==0)os->body_head=0;
}
/* update lacing pointers */
os->body_fill=os->body_fill_next;
_next_lace(&ob,os);
}else{
if(op){
op->packet=ogg_buffer_sub(os->body_tail,0,os->body_fill&FINMASK);
op->bytes=os->body_fill&FINMASK;
}
}
if(adv){
os->packetno++;
os->b_o_s=0;
}
return 1;
}
int ogg_stream_packetout(ogg_stream_state *os,ogg_packet *op){
return _packetout(os,op,1);
}
int ogg_stream_packetpeek(ogg_stream_state *os,ogg_packet *op){
return _packetout(os,op,0);
}
int ogg_packet_release(ogg_packet *op) {
if(op){
ogg_buffer_release(op->packet);
memset(op, 0, sizeof(*op));
}
return OGG_SUCCESS;
}
int ogg_page_release(ogg_page *og) {
if(og){
ogg_buffer_release(og->header);
ogg_buffer_release(og->body);
memset(og, 0, sizeof(*og));
}
return OGG_SUCCESS;
}
void ogg_page_dup(ogg_page *dup,ogg_page *orig){
dup->header_len=orig->header_len;
dup->body_len=orig->body_len;
dup->header=ogg_buffer_dup(orig->header);
dup->body=ogg_buffer_dup(orig->body);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -