public long SeekTo( long granulePos, int preRoll, GetPacketGranuleCountDelegate getPacketGranuleCount) { if (_reader == null) { throw new ObjectDisposedException(GetType().FullName); } int pageIndex = _reader.FindPage(granulePos); int packetIndex; if (granulePos == 0) { // for this, we can generically say the first packet on the first page having a non-zero granule packetIndex = 0; } else { packetIndex = FindPacket(pageIndex, ref granulePos, getPacketGranuleCount); packetIndex -= preRoll; } if (!NormalizePacketIndex(ref pageIndex, ref packetIndex)) { throw new ArgumentOutOfRangeException(nameof(granulePos)); } _lastPacket = null; _pageIndex = pageIndex; _packetIndex = packetIndex; return(granulePos); }
private int FindPacket( int pageIndex, ref long granulePos, GetPacketGranuleCountDelegate getPacketGranuleCount) { // we will only look through the current page... // if the granule isn't on the page, behavior is: // - if before: return 0 // - if after: return packetCount - (isContinued ? 2 : 1) // neither should happen because we're already looking at the correct page if (!_reader.GetPage( pageIndex, out long pageGranulePos, out bool isResync, out _, out bool isContinued, out int packetCount, out int pageOverhead)) { return(-1); } var gp = pageGranulePos; var packetIndex = packetCount - (isContinued ? 2 : 1); while (packetIndex > 0) { if (gp >= granulePos) { var packet = CreatePacket( ref pageIndex, ref packetIndex, false, pageGranulePos, isResync, isContinued, packetCount, pageOverhead); if (packet == null) { break; } gp -= getPacketGranuleCount(packet, false); } if (gp < granulePos) { granulePos = gp; return(packetIndex); } --packetIndex; } if (packetIndex == 0) { // we're likely in the right spot for the granulePos... if (pageIndex > 0 && _reader.GetPage(pageIndex - 1, out var prevGranulePos, out _, out _, out _, out _, out _)) { granulePos = prevGranulePos; return(0); } } return(-1); }