📄 framing.c
字号:
oy->headerbytes=0; oy->bodybytes=0; oy->fifo_tail=ogg_buffer_pretruncate(oy->fifo_tail,1); ret--; /* search forward through fragments for possible capture */ while(oy->fifo_tail){ /* invariant: fifo_cursor points to a position in fifo_tail */ const unsigned char *now=oy->fifo_tail->buffer->data+oy->fifo_tail->begin; const unsigned char *next=memchr(now, 'O', oy->fifo_tail->length); 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); _ogg_free(os);
//memset(os,0,sizeof(*os)); } return OGG_SUCCESS;} #define FINFLAG 0x80000000UL#define FINMASK 0x7fffffffULstatic 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 + -