📄 framing.c
字号:
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)); dprintf(("ogg_stream_create os %p %d bytes\n", os, 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); dprintf(("_ogg_stream_destroy free os %p\n", os)); _ogg_free(os); os = NULL; } 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 + -