GetFrame() public method

Gets a frame at the given render time.
public GetFrame ( decimal renderTime, bool checkBounds ) : FFmpegMediaFrame
renderTime decimal The render time.
checkBounds bool
return FFmpegMediaFrame
Ejemplo n.º 1
0
        /// <summary>
        /// Renders the video image. This method is called on a Dispatcher timer.
        /// It is responsible for rendering the decoded video image continuously.
        /// It also avoids rendering the same image again.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
        private void RenderVideoImage(object sender, EventArgs e)
        {
            MediaFramesExtractedDone.Wait(Constants.FrameExtractorWaitMs);
            var renderTime = RealtimeClock.PositionSeconds;

            try
            {
                var videoFrame = VideoFramesCache.GetFrame(renderTime, false);
                if (videoFrame == null || videoFrame == LastRenderedVideoFrame)
                {
                    return;
                }
                if (videoFrame.PictureBufferPtr != IntPtr.Zero)
                {
                    VideoRenderer.Lock();
                    Helper.NativeMethods.RtlMoveMemory(VideoRenderer.BackBuffer, videoFrame.PictureBufferPtr, videoFrame.PictureBufferLength);
                    VideoRenderer.AddDirtyRect(new Int32Rect(0, 0, VideoRenderer.PixelWidth, VideoRenderer.PixelHeight));
                    VideoRenderer.Unlock();
                    LastRenderedVideoFrame = videoFrame;
                }
            }
            finally
            {
                this.Position = renderTime;
            }
        }
Ejemplo n.º 2
0
        private void InternalLoadFrames(decimal renderTime)
        {
            if (renderTime < StartTime)
            {
                renderTime = StartTime;
            }
            if (IsAtEndOfStream && LeadingFramesCache.Count > 0 && renderTime >= LeadingFramesCache.EndTime)
            {
                renderTime = LeadingFramesCache.EndTime;
            }

            // The very first thing we do is fill the buffer if it is empty
            if (this.LeadingFramesCache.IsEmpty)
            {
                this.InternalFillFramesCache(Constants.FrameExtractorFillTimeout);

                if (LeadingFramesCache.Count > 0)
                {
                    if (FirstLeadingFrameTime == null)
                    {
                        FirstLeadingFrameTime = LeadingFramesCache.FirstFrameTime;
                    }

                    if (IsLiveStream)
                    {
                        RealtimeClock.Seek(LeadingFramesCache.FirstFrameTime);
                        RealtimeClock.Play();
                        return;
                    }
                }
            }

            var renderFrame      = LeadingFramesCache.GetFrame(renderTime, CheckFrameBounds);
            var renderFrameIndex = LeadingFramesCache.IndexOf(renderFrame);
            var renderFrameFound = renderFrameIndex >= 0;

            // if we can't find the frame . . .
            if (renderFrameFound == false)
            {
                // Perform the seek operation
                this.InternalSeekInput(renderTime);
                renderTime = RealtimeClock.PositionSeconds;

                // try to find the frame now that we have stuff
                var seekFrame = LeadingFramesCache.GetFrame(renderTime, CheckFrameBounds);

                if (seekFrame != null)
                {
                    // seek is successful at this point
                    RealtimeClock.Seek(renderTime);
                    PcmAudioProvider.Clear();
                }
                else
                {
                    // got some frames but not the ones we asked for

                    if (this.LeadingFramesCache.Count > 0)
                    {
                        if (IsAtEndOfStream)
                        {
                            RealtimeClock.Seek(this.LeadingFramesCache.MiddleFrameTime);
                        }
                        else
                        {
                            if (InternalGetIsInFirstTimeSegment(renderTime))
                            {
                                RealtimeClock.Seek(renderTime);
                                ErrorOccurredCallback(this, new MediaPlaybackException(MediaPlaybackErrorSources.InternalLoadFrames, MediaPlaybackErrorCode.LoadFramesFailedInFirstSegment,
                                                                                       string.Format("Could not find frames at {0:0.000} (On first time segment). First Leading Frame occurs at {1:0.000}",
                                                                                                     renderTime, LeadingFramesCache.FirstFrameTime)));
                            }
                            else
                            {
                                RealtimeClock.Seek(this.LeadingFramesCache.LastFrameTime);
                                ErrorOccurredCallback(this, new MediaPlaybackException(MediaPlaybackErrorSources.InternalLoadFrames, MediaPlaybackErrorCode.LoadFramesFailedForCurrentPosition,
                                                                                       string.Format("Could not find frames at {0:0.000} (NOT on first segment). Last Leading Frame occurs at {1:0.000} - This should not have occurred.",
                                                                                                     renderTime, LeadingFramesCache.LastFrameTime)));
                            }
                        }
                    }
                    else
                    {
                        ErrorOccurredCallback(this, new MediaPlaybackException(MediaPlaybackErrorSources.InternalLoadFrames, MediaPlaybackErrorCode.LoadFramesFailedCritical,
                                                                               string.Format("Could not find frames at {0:0.000} and no Leading Frames exist in the cache - Critical Error.",
                                                                                             renderTime)));
                    }
                }

                return;
            }
            else
            {
                var isInLastTimeSegment  = InternalGetIsInLastTimeSegment(renderTime);
                var isInFirstTimeSegment = InternalGetIsInFirstTimeSegment(renderTime);

                // frward lookup
                if (renderFrameIndex > LeadingFramesCache.MiddleIndex)
                {
                    if (isInLastTimeSegment == false)
                    {
                        if (LeadingFramesCache.IsFull)
                        {
                            var removalCount = 1;

                            if (SpeedRatio >= Constants.DefaultSpeedRatio)
                            {
                                removalCount = (int)Math.Ceiling(SpeedRatio);
                            }

                            removalCount = Math.Min(LeadingFramesCache.Count / 4, removalCount);

                            for (var i = 1; i <= removalCount; i++)
                            {
                                LeadingFramesCache.RemoveFirst();
                            }
                        }

                        this.InternalFillFramesCache(Constants.FrameExtractorFillTimeout);
                        return;
                    }
                    else
                    {
                        if (renderFrameIndex >= LeadingFramesCache.Count - 1)
                        {
                            // All input has been processed up to the last frame now.
                            RealtimeClock.Seek(LeadingFramesCache.EndTime);
                            return;
                        }
                    }
                }

                // backward lookup
                if (renderFrameIndex <= 1 && isInFirstTimeSegment == false && IsLiveStream == false)
                {
                    InternalSeekInput(LeadingFramesCache.StartTime);
                    var frame = LeadingFramesCache.GetFrame(renderTime, CheckFrameBounds);
                    if (frame != null)
                    {
                        RealtimeClock.Seek(renderTime);
                    }
                    else
                    {
                        RealtimeClock.Seek(LeadingFramesCache.MiddleFrame != null ? LeadingFramesCache.MiddleFrame.StartTime : 0M);
                    }

                    return;
                }
            }
        }