/// <summary> /// Runs in UI thread. /// </summary> private void CalculateTimeRemaining() { // Thread safety :-) var progress = _progress; // 0.0 to 1.0 var pct = progress / 100; // Previously calculated estimate from the last tick var oldEstimate = _timeRemaining; // Fresh estimate (might be jerky) var newEstimate = TimeSpan.Zero; // The final estimate value that will actually be used var finalEstimate = oldEstimate; // Make sure progress percentage is within legal bounds (0%, 100%) if (pct > 0 && pct < 1) newEstimate = new TimeSpan((long)(RunTime.Ticks / pct) - RunTime.Ticks); // Make sure the user gets fresh calculations when the process is first started and when it's nearly finished. var criticalThreshold = TimeSpan.FromMinutes(1.25); var isCriticalPeriod = progress < .5 || progress > 95 || oldEstimate < criticalThreshold || newEstimate < criticalThreshold; // If the new estimate differs from the previous estimate by more than 2 minutes, use the new estimate. var changeThreshold = pct < 0.2 ? TimeSpan.FromMinutes(2) : TimeSpan.FromSeconds(20); var isLargeChange = Math.Abs(newEstimate.TotalSeconds - oldEstimate.TotalSeconds) > changeThreshold.TotalSeconds; // If the previous estimate was less than 1 second remaining, use the new estimate. var lowPreviousEstimate = oldEstimate.TotalMilliseconds < 1000; // Use the new estimate if (isCriticalPeriod || isLargeChange || lowPreviousEstimate) { finalEstimate = newEstimate; } // Decrement the previous estimate by roughly 1 second else { finalEstimate -= (DateTime.Now - _lastTick); } // If the estimate dips below 0, set it to 30 seconds if (finalEstimate.TotalMilliseconds < 0) finalEstimate = TimeSpan.FromSeconds(30); // Truncate (remove) milliseconds from estimate finalEstimate = TimeSpan.FromSeconds(Math.Floor(finalEstimate.TotalSeconds)); _timeRemaining = finalEstimate; _uiProgressState = new ProgressState { ProcessState = State, PercentComplete = progress, TimeElapsed = RunTime, TimeRemaining = finalEstimate }; }
private void OnProgressUpdated(FFmpeg ffmpeg, ProgressState progressState, CancellationToken cancellationToken) { var status = string.Format("Muxing to MKV with FFmpeg: {0} - {1} @ {2} fps", TimeSpan.FromMilliseconds(ffmpeg.CurOutTimeMs).ToStringMedium(), FileUtils.HumanFriendlyFileSize(ffmpeg.CurSize), ffmpeg.CurFps.ToString("0.0")); Host.ReportProgress(this, progressState.PercentComplete, status); if (cancellationToken.IsCancellationRequested) ffmpeg.Kill(); }
/// <summary> /// Runs in UI thread. /// </summary> private void CalculateTimeRemaining() { // Thread safety :-) var progress = _progress; // 0.0 to 1.0 var pct = progress / 100; // Previously calculated estimate from the last tick var oldEstimate = _timeRemaining; // Fresh estimate (might be jerky) var newEstimate = TimeSpan.Zero; // The final estimate value that will actually be used var finalEstimate = oldEstimate; // Make sure progress percentage is within legal bounds (0%, 100%) if (pct > 0 && pct < 1) { newEstimate = new TimeSpan((long)(RunTime.Ticks / pct) - RunTime.Ticks); } // Make sure the user gets fresh calculations when the process is first started and when it's nearly finished. var criticalThreshold = TimeSpan.FromMinutes(1.25); var isCriticalPeriod = progress < .5 || progress > 95 || oldEstimate < criticalThreshold || newEstimate < criticalThreshold; // If the new estimate differs from the previous estimate by more than 2 minutes, use the new estimate. var changeThreshold = pct < 0.2 ? TimeSpan.FromMinutes(2) : TimeSpan.FromSeconds(20); var isLargeChange = Math.Abs(newEstimate.TotalSeconds - oldEstimate.TotalSeconds) > changeThreshold.TotalSeconds; // If the previous estimate was less than 1 second remaining, use the new estimate. var lowPreviousEstimate = oldEstimate.TotalMilliseconds < 1000; // Use the new estimate if (isCriticalPeriod || isLargeChange || lowPreviousEstimate) { finalEstimate = newEstimate; } // Decrement the previous estimate by roughly 1 second else { finalEstimate -= (DateTime.Now - _lastTick); } // If the estimate dips below 0, set it to 30 seconds if (finalEstimate.TotalMilliseconds < 0) { finalEstimate = TimeSpan.FromSeconds(30); } // Truncate (remove) milliseconds from estimate finalEstimate = TimeSpan.FromSeconds(Math.Floor(finalEstimate.TotalSeconds)); _timeRemaining = finalEstimate; _uiProgressState = new ProgressState { ProcessState = State, PercentComplete = progress, TimeElapsed = RunTime, TimeRemaining = finalEstimate }; }