/// <summary> /// Start the following reads from the selected timestamp. /// Seeks all tracks to the block before the position given in seconds. /// </summary> /// <returns>Position that was actually possible to seek to or -1 if the position didn't change.</returns> public override double Seek(double position) { long targetTime = (long)(position * sToNs / timestampScale); Cue cue = Cue.Find(cues, targetTime); int clusterId = 0; Cluster cluster; if (cue != null) { clusterId = segments[0].GetIndexByPosition(reader, MatroskaTree.Segment_Cluster, cue.Position); } if (clusterId == -1) { while (true) { cluster = GetCluster(clusterId++); if (cluster == null) { break; } if (cluster.TimeStamp > targetTime) { break; } } if (cluster == null) { return(-1); } --clusterId; } bool[] trackSet = new bool[Tracks.Length]; int tracksSet = 0; long audioTime = long.MaxValue, minTime = long.MaxValue; while (clusterId >= 0 && tracksSet != trackSet.Length) { cluster = GetCluster(clusterId); IReadOnlyList <Block> blocks = cluster.GetBlocks(reader); for (int block = blocks.Count - 1; block >= 0; --block) { long trackId = Tracks.GetIndexByID(blocks[block].Track); if (trackId == -1 || trackSet[trackId]) { continue; } long time = cluster.TimeStamp + blocks[block].TimeStamp; if (time <= targetTime) { MatroskaTrack trackData = Tracks[trackId] as MatroskaTrack; trackData.lastCluster = clusterId; trackData.lastBlock = block; if (minTime > time) { minTime = time; } if (trackData.Format.IsAudio() && audioTime > targetTime) { audioTime = time; } trackSet[trackId] = true; ++tracksSet; } } --clusterId; } if (audioTime != long.MaxValue) { return(audioTime * timestampScale * nsToS); } if (minTime != long.MaxValue) { return(minTime * timestampScale * nsToS); } return(-1); }