public bool TryReadPage(out OggPage page) { OggReadPageResult result; do { result = ReadPageInternal(out page); } while (result == OggReadPageResult.Repeat); return result == OggReadPageResult.Success; }
private OggReadPageResult ReadPageInternal(out OggPage page) { page = null; if (headerBytes == 0) { if (filled < 27) return OggReadPageResult.NeedMoreData; if (data[0] != 'O' || data[1] != 'g' || data[2] != 'g' || data[3] != 'S') { return Resynchronize(); } int hbytes = data[26] + 27; if (filled < hbytes) return OggReadPageResult.NeedMoreData; headerBytes = hbytes; for (int i = 0; i < (int)data[26]; ++i) { bodyBytes += data[27 + i]; } } if (headerBytes + bodyBytes <= filled) { // Check the CRC. // Have to temporarily zero out the CRC field first, though. byte crc0, crc1, crc2, crc3; crc0 = data[22]; crc1 = data[23]; crc2 = data[24]; crc3 = data[25]; data[22] = 0; data[23] = 0; data[24] = 0; data[25] = 0; uint actualCrc = OggCrc32.Compute(data, 0, headerBytes + bodyBytes); data[22] = crc0; data[23] = crc1; data[24] = crc2; data[25] = crc3; if (crc0 != (byte)(actualCrc & 0xFF) || crc1 != (byte)((actualCrc >> 8) & 0xFF) || crc2 != (byte)((actualCrc >> 16) & 0xFF) || crc3 != (byte)((actualCrc >> 24) & 0xFF)) { Console.WriteLine("CRC fail!"); return Resynchronize(); } page = new OggPage(); byte headerType = data[5]; page.Continuation = (headerType & 0x1) != 0; page.BeginningOfStream = (headerType & 0x2) != 0; page.EndOfStream = (headerType & 0x4) != 0; page.GranulePosition = BitConverter.ToUInt64(data, 6); page.BitstreamSerialNumber = BitConverter.ToUInt32(data, 14); page.PageSequenceNumber = BitConverter.ToUInt32(data, 18); // TODO: Copy page bytes // TODO: Return the page somehow /*Console.WriteLine("---------------------------------"); Console.WriteLine("Header Bytes: {0}", headerBytes); Console.WriteLine("Body Bytes: {0}", bodyBytes); Console.WriteLine("Incomplete: {0}", data[headerBytes - 1] == 255); Console.WriteLine("Continuation: {0}", page.Continuation); Console.WriteLine("BeginningOfStream: {0}", page.BeginningOfStream); Console.WriteLine("EndOfStream: {0}", page.EndOfStream); Console.WriteLine("GranulePosition: {0}", page.GranulePosition); Console.WriteLine("BitstreamSerialNumber: {0}", page.BitstreamSerialNumber); Console.WriteLine("PageSequenceNumber: {0}", page.PageSequenceNumber); Console.WriteLine("CRC: {0:X8}", actualCrc); Console.WriteLine(); Console.WriteLine("Segment count: {0}", data[26]); Console.WriteLine("Segment table:"); Util.DumpBytes(data, 27, headerBytes - 27); Console.WriteLine(); Console.WriteLine("Body:"); Util.DumpBytes(data, headerBytes, bodyBytes);*/ // TODO: Share buffers instead int numSegments = headerBytes - 27; page.SegmentTable = new byte[numSegments]; Array.Copy(data, 27, page.SegmentTable, 0, numSegments); page.Data = new byte[bodyBytes]; Array.Copy(data, headerBytes, page.Data, 0, bodyBytes); TrimFront(headerBytes + bodyBytes); headerBytes = 0; bodyBytes = 0; return OggReadPageResult.Success; } else return OggReadPageResult.NeedMoreData; }