bool Flush(OggPage og, bool force, int fill) { int maxvals = Math.Min(LacingFill, 0xFF); if (0 == maxvals) { return(false); } // construct a page // decide how many segments to include int vals = 0; int acc = 0; long granule_pos = -1; // If this is the initial header case, the first page must only include // the initial header packet if (!BoS) // 'initial header page' case { granule_pos = 0; for (vals = 0; vals < maxvals; vals++) { if ((LacingVals[vals] & 0xFF) < 0xFF) { vals++; break; } } } else { int packets_done = 0; int packet_just_done = 0; for (vals = 0; vals < maxvals; vals++) { if (acc > fill && packet_just_done >= 4) { force = true; break; } acc += LacingVals[vals] & 0xFF; if ((LacingVals[vals] & 0xFF) < 0xFF) { granule_pos = GranuleVals[vals]; packet_just_done = ++packets_done; } else { packet_just_done = 0; } } if (0xFF == vals) { force = true; } } if (!force) { return(false); } // construct the header in temp storage Encoding.ASCII.GetBytes("OggS", 0, 4, Header, 0); // stream structure version Header[4] = 0; // continued packet flag? Header[5] = 0; if ((LacingVals[0] & 0x100) == 0) { Header[5] |= 1; } // first page flag? if (!BoS) { Header[5] |= 2; } // last page flag? if (EoS && LacingFill == vals) { Header[5] |= 4; } BoS = true; // 64 bits of PCM position LittleEndian.Pack(granule_pos, Header, 6); // 32 bits of stream serial number LittleEndian.Pack(SerialNo, Header, 14); // 32 bits of page counter (we have both counter and page header because this // val can roll over) if (-1 == PageNo) { PageNo = 0; } LittleEndian.Pack(PageNo, Header, 18); ++PageNo; int bytes = 0; // segment table Header[26] = (byte)vals; for (int i = 0; i < vals; ++i) { bytes += Header[i + 27] = (byte)LacingVals[i]; } // set pointers in the ogg_page struct og.Header = Header; og.HeaderLength = HeaderFill = vals + 27; og.Body = BodyData; og.BodyStart = BodyReturned; og.BodyLength = bytes; // advance the lacing data and set the body_returned pointer LacingFill -= vals; Array.Copy(LacingVals, vals, LacingVals, 0, LacingFill); Array.Copy(GranuleVals, vals, GranuleVals, 0, LacingFill); BodyReturned += bytes; // calculate the checksum og.SetChecksum(); return(true); }
public bool PageOut(OggPage page) { bool force = EoS && (LacingFill > 0) || (LacingFill > 0 && !BoS); return(Flush(page, force, 0x1000)); }