public int pageseek(Page og) { int page = returned; int next; int bytes = fill - returned; if (headerbytes == 0) { int _headerbytes, i; if (bytes < 27) { return(0); // not enough for a header } /* verify capture pattern */ //!!!!!!!!!!! if (data[page] != 'O' || data[page + 1] != 'g' || data[page + 2] != 'g' || data[page + 3] != 'S') { headerbytes = 0; bodybytes = 0; // search for possible capture next = 0; for (int ii = 0; ii < bytes - 1; ii++) { if (data[page + 1 + ii] == 'O') { next = page + 1 + ii; break; } } //next=memchr(page+1,'O',bytes-1); if (next == 0) { next = fill; } returned = next; return(-(next - page)); } _headerbytes = (data[page + 26] & 0xff) + 27; if (bytes < _headerbytes) { return(0); // not enough for header + seg table } // count up body length in the segment table for (i = 0; i < (data[page + 26] & 0xff); i++) { bodybytes += (data[page + 27 + i] & 0xff); } headerbytes = _headerbytes; } if (bodybytes + headerbytes > bytes) { return(0); } // The whole test page is buffered. Verify the checksum lock (chksum) { // Grab the checksum bytes, set the header field to zero Array.Copy(data, page + 22, chksum, 0, 4); data[page + 22] = 0; data[page + 23] = 0; data[page + 24] = 0; data[page + 25] = 0; // set up a temp page struct and recompute the checksum Page log = pageseek_p; log.header_base = data; log.header = page; log.header_len = headerbytes; log.body_base = data; log.body = page + headerbytes; log.body_len = bodybytes; log.checksum(); // Compare if (chksum[0] != data[page + 22] || chksum[1] != data[page + 23] || chksum[2] != data[page + 24] || chksum[3] != data[page + 25]) { // D'oh. Mismatch! Corrupt page (or miscapture and not a page at all) // replace the computed checksum with the one actually read in Array.Copy(chksum, 0, data, page + 22, 4); // Bad checksum. Lose sync */ headerbytes = 0; bodybytes = 0; // search for possible capture next = 0; for (int ii = 0; ii < bytes - 1; ii++) { if (data[page + 1 + ii] == 'O') { next = page + 1 + ii; break; } } //next=memchr(page+1,'O',bytes-1); if (next == 0) { next = fill; } returned = next; return(-(next - page)); } } // yes, have a whole page all ready to go { page = returned; if (og != null) { og.header_base = data; og.header = page; og.header_len = headerbytes; og.body_base = data; og.body = page + headerbytes; og.body_len = bodybytes; } unsynced = 0; returned += (bytes = headerbytes + bodybytes); headerbytes = 0; bodybytes = 0; return(bytes); } }
/* 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 gurantee that all packets have flushed. Only a return value of 0 from ogg_stream_flush indicates all packet data is flushed into pages. ogg_stream_page 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 need to flush an undersized page in the middle of a stream for some reason. */ public int flush(Page og) { //System.out.println(this+" ---body_returned: "+body_returned); int i; int vals=0; int maxvals=(lacing_fill>255?255:lacing_fill); int bytes=0; int acc=0; long granule_pos=granule_vals[0]; if(maxvals==0)return(0); /* construct a page */ /* decide how many segments to include */ /* If this is the initial header case, the first page must only include the initial header packet */ if(b_o_s==0) { /* 'initial header page' case */ granule_pos=0; for(vals=0;vals<maxvals;vals++) { if((lacing_vals[vals]&0x0ff)<255) { vals++; break; } } } else { for(vals=0;vals<maxvals;vals++) { if(acc>4096)break; acc+=(lacing_vals[vals]&0x0ff); granule_pos=granule_vals[vals]; } } /* construct the header in temp storage */ String oggs_str = "OggS"; Encoding AE = Encoding.UTF8; byte[] oggs_byt = AE.GetBytes(oggs_str); Array.Copy(oggs_byt, 0, header, 0, oggs_byt.Length); /* stream structure version */ header[4]=0x00; /* continued packet flag? */ header[5]=0x00; if((lacing_vals[0]&0x100)==0)header[5]|=0x01; /* first page flag? */ if(b_o_s==0) header[5]|=0x02; /* last page flag? */ if(e_o_s!=0 && lacing_fill==vals) header[5]|=0x04; b_o_s=1; /* 64 bits of PCM position */ for(i=6;i<14;i++) { header[i]=(byte)granule_pos; granule_pos>>=8; } /* 32 bits of stream serial number */ { int _serialno=serialno; for(i=14;i<18;i++) { header[i]=(byte)_serialno; _serialno>>=8; } } /* 32 bits of page counter (we have both counter and page header because this val can roll over) */ if(pageno==-1)pageno=0; /* because someone called stream_reset; this would be a strange thing to do in an encode stream, but it has plausible uses */ { int _pageno=pageno++; for(i=18;i<22;i++) { header[i]=(byte)_pageno; _pageno>>=8; } } /* zero for computation; filled in later */ header[22]=0; header[23]=0; header[24]=0; header[25]=0; /* segment table */ header[26]=(byte)vals; for(i=0;i<vals;i++) { header[i+27]=(byte)lacing_vals[i]; bytes+=(header[i+27]&0xff); } /* set pointers in the ogg_page struct */ og.header_base=header; og.header=0; og.header_len=header_fill=vals+27; og.body_base=body_data; og.body=body_returned; og.body_len=bytes; /* advance the lacing data and set the body_returned pointer */ lacing_fill-=vals; Array.Copy(lacing_vals, vals, lacing_vals, 0, lacing_fill*4); Array.Copy(granule_vals, vals, granule_vals, 0, lacing_fill*8); body_returned+=bytes; /* calculate the checksum */ og.checksum(); /* done */ 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 gurantee that all packets have flushed. * Only a return value of 0 from ogg_stream_flush indicates all packet * data is flushed into pages. * * ogg_stream_page 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 need to flush an undersized * page in the middle of a stream for some reason. */ public int flush(Page og) { //System.out.println(this+" ---body_returned: "+body_returned); int i; int vals = 0; int maxvals = (lacing_fill > 255?255:lacing_fill); int bytes = 0; int acc = 0; long granule_pos = granule_vals[0]; if (maxvals == 0) { return(0); } /* construct a page */ /* decide how many segments to include */ /* If this is the initial header case, the first page must only include * the initial header packet */ if (b_o_s == 0) { /* 'initial header page' case */ granule_pos = 0; for (vals = 0; vals < maxvals; vals++) { if ((lacing_vals[vals] & 0x0ff) < 255) { vals++; break; } } } else { for (vals = 0; vals < maxvals; vals++) { if (acc > 4096) { break; } acc += (lacing_vals[vals] & 0x0ff); granule_pos = granule_vals[vals]; } } /* construct the header in temp storage */ String oggs_str = "OggS"; Encoding AE = Encoding.UTF8; byte[] oggs_byt = AE.GetBytes(oggs_str); Array.Copy(oggs_byt, 0, header, 0, oggs_byt.Length); /* stream structure version */ header[4] = 0x00; /* continued packet flag? */ header[5] = 0x00; if ((lacing_vals[0] & 0x100) == 0) { header[5] |= 0x01; } /* first page flag? */ if (b_o_s == 0) { header[5] |= 0x02; } /* last page flag? */ if (e_o_s != 0 && lacing_fill == vals) { header[5] |= 0x04; } b_o_s = 1; /* 64 bits of PCM position */ for (i = 6; i < 14; i++) { header[i] = (byte)granule_pos; granule_pos >>= 8; } /* 32 bits of stream serial number */ { int _serialno = serialno; for (i = 14; i < 18; i++) { header[i] = (byte)_serialno; _serialno >>= 8; } } /* 32 bits of page counter (we have both counter and page header * because this val can roll over) */ if (pageno == -1) { pageno = 0; /* because someone called * stream_reset; this would be a * strange thing to do in an * encode stream, but it has * plausible uses */ } { int _pageno = pageno++; for (i = 18; i < 22; i++) { header[i] = (byte)_pageno; _pageno >>= 8; } } /* zero for computation; filled in later */ header[22] = 0; header[23] = 0; header[24] = 0; header[25] = 0; /* segment table */ header[26] = (byte)vals; for (i = 0; i < vals; i++) { header[i + 27] = (byte)lacing_vals[i]; bytes += (header[i + 27] & 0xff); } /* set pointers in the ogg_page struct */ og.header_base = header; og.header = 0; og.header_len = header_fill = vals + 27; og.body_base = body_data; og.body = body_returned; og.body_len = bytes; /* advance the lacing data and set the body_returned pointer */ lacing_fill -= vals; Array.Copy(lacing_vals, vals, lacing_vals, 0, lacing_fill * 4); Array.Copy(granule_vals, vals, granule_vals, 0, lacing_fill * 8); body_returned += bytes; /* calculate the checksum */ og.checksum(); /* done */ return(1); }