diff options
| author | Luke Pulverenti <luke.pulverenti@gmail.com> | 2015-02-27 12:43:06 -0500 |
|---|---|---|
| committer | Luke Pulverenti <luke.pulverenti@gmail.com> | 2015-02-27 12:43:06 -0500 |
| commit | f0594dea772a06e16bf1d5938836b4b3ec906424 (patch) | |
| tree | 034d5836915a0940ac82d92d759c5dcc93a5d188 /MediaBrowser.Api/Playback/TranscodingThrottler.cs | |
| parent | 28ffeb5121247ced3fc7d764242e41b92837f740 (diff) | |
stub out process throttle
Diffstat (limited to 'MediaBrowser.Api/Playback/TranscodingThrottler.cs')
| -rw-r--r-- | MediaBrowser.Api/Playback/TranscodingThrottler.cs | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/MediaBrowser.Api/Playback/TranscodingThrottler.cs b/MediaBrowser.Api/Playback/TranscodingThrottler.cs new file mode 100644 index 000000000..81848c017 --- /dev/null +++ b/MediaBrowser.Api/Playback/TranscodingThrottler.cs @@ -0,0 +1,157 @@ +using MediaBrowser.Model.Logging; +using System; +using System.IO; +using System.Threading; + +namespace MediaBrowser.Api.Playback +{ + public class TranscodingThrottler : IDisposable + { + private readonly TranscodingJob _job; + private readonly ILogger _logger; + private Timer _timer; + + public void Start() + { + _timer = new Timer(TimerCallback, null, 1000, 1000); + } + + private void TimerCallback(object state) + { + if (IsThrottleAllowed(_job)) + { + PauseTranscoding(); + } + else + { + UnpauseTranscoding(); + } + } + + private void PauseTranscoding() + { + _logger.Debug("Sending pause command to ffmpeg"); + _job.Process.StandardInput.WriteLine("p"); + } + + private void UnpauseTranscoding() + { + _logger.Debug("Sending unpause command to ffmpeg"); + _job.Process.StandardInput.WriteLine("u"); + } + + private readonly long _gapLengthInTicks = TimeSpan.FromMinutes(2).Ticks; + + public TranscodingThrottler(TranscodingJob job, ILogger logger) + { + _job = job; + _logger = logger; + } + + private bool IsThrottleAllowed(TranscodingJob job) + { + //var job = string.IsNullOrEmpty(request.TranscodingJobId) ? + //null : + //ApiEntryPoint.Instance.GetTranscodingJob(request.TranscodingJobId); + + //var limits = new List<long>(); + //if (state.InputBitrate.HasValue) + //{ + // // Bytes per second + // limits.Add((state.InputBitrate.Value / 8)); + //} + //if (state.InputFileSize.HasValue && state.RunTimeTicks.HasValue) + //{ + // var totalSeconds = TimeSpan.FromTicks(state.RunTimeTicks.Value).TotalSeconds; + + // if (totalSeconds > 1) + // { + // var timeBasedLimit = state.InputFileSize.Value / totalSeconds; + // limits.Add(Convert.ToInt64(timeBasedLimit)); + // } + //} + + //// Take the greater of the above to methods, just to be safe + //var throttleLimit = limits.Count > 0 ? limits.First() : 0; + + //// Pad to play it safe + //var bytesPerSecond = Convert.ToInt64(1.05 * throttleLimit); + + //// Don't even start evaluating this until at least two minutes have content have been consumed + //var targetGap = throttleLimit * 120; + + var bytesDownloaded = job.BytesDownloaded ?? 0; + var transcodingPositionTicks = job.TranscodingPositionTicks ?? 0; + var downloadPositionTicks = job.DownloadPositionTicks ?? 0; + + var path = job.Path; + + if (downloadPositionTicks > 0 && transcodingPositionTicks > 0) + { + // HLS - time-based consideration + + var targetGap = _gapLengthInTicks; + var gap = transcodingPositionTicks - downloadPositionTicks; + + if (gap < targetGap) + { + //Logger.Debug("Not throttling transcoder gap {0} target gap {1}", gap, targetGap); + return false; + } + + //Logger.Debug("Throttling transcoder gap {0} target gap {1}", gap, targetGap); + return true; + } + + if (bytesDownloaded > 0 && transcodingPositionTicks > 0) + { + // Progressive Streaming - byte-based consideration + + try + { + var bytesTranscoded = job.BytesTranscoded ?? new FileInfo(path).Length; + + // Estimate the bytes the transcoder should be ahead + double gapFactor = _gapLengthInTicks; + gapFactor /= transcodingPositionTicks; + var targetGap = bytesTranscoded * gapFactor; + + var gap = bytesTranscoded - bytesDownloaded; + + if (gap < targetGap) + { + //Logger.Debug("Not throttling transcoder gap {0} target gap {1} bytes downloaded {2}", gap, targetGap, bytesDownloaded); + return false; + } + + //Logger.Debug("Throttling transcoder gap {0} target gap {1} bytes downloaded {2}", gap, targetGap, bytesDownloaded); + return true; + } + catch + { + //Logger.Error("Error getting output size"); + } + } + else + { + //Logger.Debug("No throttle data for " + path); + } + + return false; + } + + public void Dispose() + { + DisposeTimer(); + } + + private void DisposeTimer() + { + if (_timer != null) + { + _timer.Dispose(); + _timer = null; + } + } + } +} |
