diff options
Diffstat (limited to 'MediaBrowser.Api/ApiEntryPoint.cs')
| -rw-r--r-- | MediaBrowser.Api/ApiEntryPoint.cs | 187 |
1 files changed, 142 insertions, 45 deletions
diff --git a/MediaBrowser.Api/ApiEntryPoint.cs b/MediaBrowser.Api/ApiEntryPoint.cs index 08ac5671d..e91dd1a9b 100644 --- a/MediaBrowser.Api/ApiEntryPoint.cs +++ b/MediaBrowser.Api/ApiEntryPoint.cs @@ -151,7 +151,7 @@ namespace MediaBrowser.Api { lock (_activeTranscodingJobs) { - var job = new TranscodingJob + var job = new TranscodingJob(Logger) { Type = type, Path = path, @@ -284,28 +284,72 @@ namespace MediaBrowser.Api { job.ActiveRequestCount++; - job.DisposeKillTimer(); + if (string.IsNullOrWhiteSpace(job.PlaySessionId) || job.Type == TranscodingJobType.Progressive) + { + job.StopKillTimer(); + } } - + public void OnTranscodeEndRequest(TranscodingJob job) { job.ActiveRequestCount--; + Logger.Debug("OnTranscodeEndRequest job.ActiveRequestCount={0}", job.ActiveRequestCount); + if (job.ActiveRequestCount <= 0) + { + PingTimer(job, false); + } + } + internal void PingTranscodingJob(string playSessionId) + { + if (string.IsNullOrEmpty(playSessionId)) + { + throw new ArgumentNullException("playSessionId"); + } + + Logger.Debug("PingTranscodingJob PlaySessionId={0}", playSessionId); + + var jobs = new List<TranscodingJob>(); - if (job.ActiveRequestCount == 0) + lock (_activeTranscodingJobs) { - // TODO: Lower this hls timeout - var timerDuration = job.Type == TranscodingJobType.Progressive ? - 1000 : - 7200000; + // This is really only needed for HLS. + // Progressive streams can stop on their own reliably + jobs = jobs.Where(j => string.Equals(playSessionId, j.PlaySessionId, StringComparison.OrdinalIgnoreCase)).ToList(); + } - if (job.KillTimer == null) - { - job.KillTimer = new Timer(OnTranscodeKillTimerStopped, job, timerDuration, Timeout.Infinite); - } - else - { - job.KillTimer.Change(timerDuration, Timeout.Infinite); - } + foreach (var job in jobs) + { + PingTimer(job, true); + } + } + + private void PingTimer(TranscodingJob job, bool isProgressCheckIn) + { + if (job.HasExited) + { + job.StopKillTimer(); + return; + } + + // TODO: Lower this hls timeout + var timerDuration = job.Type == TranscodingJobType.Progressive ? + 1000 : + 1800000; + + // We can really reduce the timeout for apps that are using the newer api + if (!string.IsNullOrWhiteSpace(job.PlaySessionId) && job.Type != TranscodingJobType.Progressive) + { + timerDuration = 20000; + } + + // Don't start the timer for playback checkins with progressive streaming + if (job.Type != TranscodingJobType.Progressive || !isProgressCheckIn) + { + job.StartKillTimer(timerDuration, OnTranscodeKillTimerStopped); + } + else + { + job.ChangeKillTimerIfStarted(timerDuration); } } @@ -317,6 +361,8 @@ namespace MediaBrowser.Api { var job = (TranscodingJob)state; + Logger.Debug("Transcoding kill timer stopped for JobId {0} PlaySessionId {1}. Killing transcoding", job.Id, job.PlaySessionId); + KillTranscodingJob(job, path => true); } @@ -329,19 +375,14 @@ namespace MediaBrowser.Api /// <returns>Task.</returns> internal void KillTranscodingJobs(string deviceId, string playSessionId, Func<string, bool> deleteFiles) { - if (string.IsNullOrEmpty(deviceId)) - { - throw new ArgumentNullException("deviceId"); - } - KillTranscodingJobs(j => { - if (string.Equals(deviceId, j.DeviceId, StringComparison.OrdinalIgnoreCase)) + if (!string.IsNullOrWhiteSpace(playSessionId)) { - return string.IsNullOrWhiteSpace(playSessionId) || string.Equals(playSessionId, j.PlaySessionId, StringComparison.OrdinalIgnoreCase); + return string.Equals(playSessionId, j.PlaySessionId, StringComparison.OrdinalIgnoreCase); } - return false; + return string.Equals(deviceId, j.DeviceId, StringComparison.OrdinalIgnoreCase); }, deleteFiles); } @@ -381,6 +422,10 @@ namespace MediaBrowser.Api /// <param name="delete">The delete.</param> private void KillTranscodingJob(TranscodingJob job, Func<string, bool> delete) { + job.DisposeKillTimer(); + + Logger.Debug("KillTranscodingJob - JobId {0} PlaySessionId {1}. Killing transcoding", job.Id, job.PlaySessionId); + lock (_activeTranscodingJobs) { _activeTranscodingJobs.Remove(job); @@ -389,34 +434,23 @@ namespace MediaBrowser.Api { job.CancellationTokenSource.Cancel(); } - - job.DisposeKillTimer(); } lock (job.ProcessLock) { - var process = job.Process; - - var hasExited = true; - - try + if (job.TranscodingThrottler != null) { - hasExited = process.HasExited; - } - catch (Exception ex) - { - Logger.ErrorException("Error determining if ffmpeg process has exited for {0}", ex, job.Path); + job.TranscodingThrottler.Stop(); } + var process = job.Process; + + var hasExited = job.HasExited; + if (!hasExited) { try { - if (job.TranscodingThrottler != null) - { - job.TranscodingThrottler.Stop(); - } - Logger.Info("Killing ffmpeg process for {0}", job.Path); //process.Kill(); @@ -558,6 +592,7 @@ namespace MediaBrowser.Api /// </summary> /// <value>The process.</value> public Process Process { get; set; } + public ILogger Logger { get; private set; } /// <summary> /// Gets or sets the active request count. /// </summary> @@ -567,7 +602,7 @@ namespace MediaBrowser.Api /// Gets or sets the kill timer. /// </summary> /// <value>The kill timer.</value> - public Timer KillTimer { get; set; } + private Timer KillTimer { get; set; } public string DeviceId { get; set; } @@ -590,12 +625,74 @@ namespace MediaBrowser.Api public TranscodingThrottler TranscodingThrottler { get; set; } + private readonly object _timerLock = new object(); + + public TranscodingJob(ILogger logger) + { + Logger = logger; + } + + public void StopKillTimer() + { + lock (_timerLock) + { + if (KillTimer != null) + { + KillTimer.Change(Timeout.Infinite, Timeout.Infinite); + } + } + } + public void DisposeKillTimer() { - if (KillTimer != null) + lock (_timerLock) + { + if (KillTimer != null) + { + KillTimer.Dispose(); + KillTimer = null; + } + } + } + + public void StartKillTimer(int intervalMs, TimerCallback callback) + { + CheckHasExited(); + + lock (_timerLock) + { + if (KillTimer == null) + { + Logger.Debug("Starting kill timer at {0}ms. JobId {1} PlaySessionId {2}", intervalMs, Id, PlaySessionId); + KillTimer = new Timer(callback, this, intervalMs, Timeout.Infinite); + } + else + { + Logger.Debug("Changing kill timer to {0}ms. JobId {1} PlaySessionId {2}", intervalMs, Id, PlaySessionId); + KillTimer.Change(intervalMs, Timeout.Infinite); + } + } + } + + public void ChangeKillTimerIfStarted(int intervalMs) + { + CheckHasExited(); + + lock (_timerLock) + { + if (KillTimer != null) + { + Logger.Debug("Changing kill timer to {0}ms. JobId {1} PlaySessionId {2}", intervalMs, Id, PlaySessionId); + KillTimer.Change(intervalMs, Timeout.Infinite); + } + } + } + + private void CheckHasExited() + { + if (HasExited) { - KillTimer.Dispose(); - KillTimer = null; + throw new ObjectDisposedException("Job"); } } } |
