Ejemplo n.º 1
0
        /// <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);
        }