public GetFrame ( decimal renderTime, bool checkBounds ) : |
||
renderTime | decimal | The render time. |
checkBounds | bool | |
return |
/// <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; } }
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; } } }