/// <summary> /// Waits for the frame extractor to be ready for playback. /// Returns true if successful, false if it timed out. /// </summary> private bool WaitForPlaybackReadyState() { var renderTime = RealtimeClock.PositionSeconds; var startTime = DateTime.UtcNow; var cycleCount = -1; FFmpegMediaFrame playbackFrame = null; while (IsCancellationPending == false) { if (DateTime.UtcNow.Subtract(startTime) > Constants.WaitForPlaybackReadyStateTimeout) { ErrorOccurredCallback(this, new MediaPlaybackException(MediaPlaybackErrorSources.WaitForPlaybackReadyState, MediaPlaybackErrorCode.WaitForPlaybackTimedOut, string.Format("Waiting for playback ready state @ {0:0.000} rimed Out in {1} cycles", renderTime, cycleCount))); return(false); } cycleCount++; // Wait for a decoding cycle. MediaFramesExtractedDone.Wait(Constants.FrameExtractorWaitMs); renderTime = RealtimeClock.PositionSeconds; playbackFrame = LeadingFramesCache.GetFrame(renderTime, CheckFrameBounds); if (IsLiveStream && LeadingFramesCache.Count > 0) { playbackFrame = LeadingFramesCache.FirstFrame; break; } if (playbackFrame != null) { break; } } // Do some additional logging System.Diagnostics.Debug.WriteLineIf( cycleCount >= 0, string.Format("WaitForPlaybackReadyState @ {0:0.000} = {1} cycles. Leading Frames: {2}, Frame Index: {3}, Frame Start: {4}", renderTime, cycleCount, LeadingFramesCache.Count, LeadingFramesCache.IndexOf(playbackFrame), (playbackFrame != null ? playbackFrame.StartTime.ToString("0.000") : "NULL"))); return(true); }
/// <summary> /// Releases all managed and unmanaged resources /// </summary> public void Dispose() { if (IsCancellationPending) { return; } this.IsCancellationPending = true; this.VideoRenderTimer.Stop(); if (this.AudioRenderer != null) { if (this.AudioRenderer.HasInitialized) { this.AudioRenderer.Stop(); } this.AudioRenderer.Dispose(); this.AudioRenderer = null; } if (MediaFrameExtractorThread != null) { MediaFrameExtractorThread.Join(); MediaFrameExtractorThread = null; } if (MediaFramesExtractedDone != null) { try { MediaFramesExtractedDone.Dispose(); MediaFramesExtractedDone = null; } finally { } } if (LeadingFramesCache != null) { LeadingFramesCache.Clear(); LeadingFramesCache = null; } if (LaggingFramesCache != null) { LaggingFramesCache.Clear(); LaggingFramesCache = null; } if (VideoCodecContext != null) { fixed(AVCodecContext **videoCodecContextRef = &VideoCodecContext) { ffmpeg.avcodec_close(VideoCodecContext); ffmpeg.avcodec_free_context(videoCodecContextRef); VideoCodecContext = null; } } if (AudioCodecContext != null) { fixed(AVCodecContext **audioCodecContextRef = &AudioCodecContext) { ffmpeg.avcodec_close(AudioCodecContext); ffmpeg.avcodec_free_context(audioCodecContextRef); AudioCodecContext = null; } } if (VideoResampler != null) { ffmpeg.sws_freeContext(VideoResampler); VideoResampler = null; } if (AudioResampler != null) { fixed(SwrContext **audioResamplerRef = &AudioResampler) { ffmpeg.swr_close(AudioResampler); ffmpeg.swr_free(audioResamplerRef); AudioResampler = null; } } if (InputFormatContext != null) { fixed(AVFormatContext **inputFormatContextRef = &InputFormatContext) { ffmpeg.avformat_close_input(inputFormatContextRef); ffmpeg.avformat_free_context(InputFormatContext); InputFormatContext = null; } } if (DecodedPictureHolder != null) { ffmpeg.av_free(DecodedPictureHolder); DecodedPictureHolder = null; } if (DecodedWaveHolder != null) { ffmpeg.av_free(DecodedWaveHolder); DecodedWaveHolder = null; } }