private void SeekToTimestampInternal(double timestamp, out double newTimestamp)
        {
            var oldTimestamp = currentTimestamp;

            reader.FrameQueue.Clear();
            reader.AudioQueue.Clear();
            previousFrames.Clear();
            reader.SeekToTimestamp(timestamp);
            synchronization = null;
            while (reader.ReadNextPacket() &&
                   (reader.FrameQueue.Count == 0 ||
                    Math.Abs(reader.FrameQueue.Peek().Timestamp - oldTimestamp) < Math.Abs(reader.FrameQueue.Peek().Timestamp - timestamp)))
            {
                reader.FrameQueue.Clear();
                reader.AudioQueue.Clear();
            }

            if (TryEnsureFrameQueueNotEmpty())
            {
                currentFrame = reader.FrameQueue.Dequeue();
                newTimestamp = currentFrame.Timestamp;
            }
            else
            {
                // should never happen
                currentFrame = new MovieFrame
                {
                    RgbaData  = new byte[GraphicsHelper.AlignedSize(reader.Width, reader.Height)],
                    Timestamp = timestamp
                };
                newTimestamp = Movie.Duration;
            }
        }
 public void GoToEnd()
 {
     SeekToTimestamp(Movie.Duration);
     while (reader.ReadNextPacket())
     {
         while (reader.FrameQueue.Any())
         {
             currentFrame = reader.FrameQueue.Dequeue();
         }
     }
     State            = MoviePlaybackState.End;
     currentTimestamp = Movie.Duration;
 }
 public StandardMoviePlayback(IMovie movie)
     : base(ResourceVolatility.Volatile)
 {
     Movie        = movie;
     reader       = movie.Read();
     videoSpeed   = 1.0;
     frameImage   = new MoviePlaybackImage();
     currentFrame = new MovieFrame
     {
         RgbaData  = new byte[GraphicsHelper.AlignedSize(reader.Width, reader.Height)],
         Timestamp = 0
     };
 }
        public void OnUpdate(FrameTime frameTime)
        {
            switch (State)
            {
            case MoviePlaybackState.Stopped:
                break;

            case MoviePlaybackState.Playing:
                if (!synchronization.HasValue)
                {
                    synchronization = new Synchronization
                    {
                        RealTime            = frameTime.TotalSeconds,
                        MovieFrameTimestamp = currentTimestamp
                    };
                }

                var realTimePassed = frameTime.TotalSeconds - synchronization.Value.RealTime;
                var signedSpeed    = playingReversed ? -videoSpeed : videoSpeed;
                currentTimestamp = Math.Max(0, realTimePassed * signedSpeed + synchronization.Value.MovieFrameTimestamp);

                if (playingReversed)
                {
                    while (currentFrame.Timestamp > currentTimestamp)
                    {
                        if (previousFrames.Count == 0 && !TryFillFrameStack(currentTimestamp))
                        {
                            ReverseDirection();
                            return;
                        }
                        currentFrame = previousFrames.Pop();
                    }
                }
                else
                {
                    var continueGettingNext = true;
                    do
                    {
                        if (!TryEnsureFrameQueueNotEmpty())
                        {
                            if (currentTimestamp >= Movie.Duration)
                            {
                                State = MoviePlaybackState.End;
                            }
                            return;
                        }

                        var nextFrame = reader.FrameQueue.Peek();
                        if (nextFrame.Timestamp <= currentTimestamp)
                        {
                            currentFrame = reader.FrameQueue.Dequeue();
                        }
                        else
                        {
                            continueGettingNext = false;
                        }
                    } while (continueGettingNext);
                }
                break;

            case MoviePlaybackState.Paused:
                break;

            case MoviePlaybackState.End:
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }
            if (currentFrame.RgbaData != frameImage.RgbaData)
            {
                // todo: size to frame?
                frameImage.Update(new IntSize2(reader.Width, reader.Height), currentFrame.RgbaData);
            }
        }