aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Server.Implementations/LiveTv/EmbyTV
diff options
context:
space:
mode:
authorLuke Pulverenti <luke.pulverenti@gmail.com>2016-09-29 08:55:49 -0400
committerLuke Pulverenti <luke.pulverenti@gmail.com>2016-09-29 08:55:49 -0400
commit76c7bfcb6795771cb06ef354fbf76d6e39de8948 (patch)
treeb37dfa760d21cbc36395574dfb64c28ac69e9927 /MediaBrowser.Server.Implementations/LiveTv/EmbyTV
parentf5d37ed659d88bfa00483deddbbf93c33c2e10d6 (diff)
update closing of streams
Diffstat (limited to 'MediaBrowser.Server.Implementations/LiveTv/EmbyTV')
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs16
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs143
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs39
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs1
4 files changed, 98 insertions, 101 deletions
diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs
index 0d043669af..0f8c15e719 100644
--- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs
+++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs
@@ -47,19 +47,9 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
_logger.Info("Copying recording stream to file {0}", targetFile);
- if (mediaSource.RunTimeTicks.HasValue)
- {
- // The media source already has a fixed duration
- // But add another stop 1 minute later just in case the recording gets stuck for any reason
- var durationToken = new CancellationTokenSource(duration.Add(TimeSpan.FromMinutes(1)));
- cancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, durationToken.Token).Token;
- }
- else
- {
- // The media source if infinite so we need to handle stopping ourselves
- var durationToken = new CancellationTokenSource(duration);
- cancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, durationToken.Token).Token;
- }
+ // The media source if infinite so we need to handle stopping ourselves
+ var durationToken = new CancellationTokenSource(duration);
+ cancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, durationToken.Token).Token;
await CopyUntilCancelled(response.Content, output, cancellationToken).ConfigureAwait(false);
}
diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
index f53ec3ee8a..ef19dcbc91 100644
--- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
+++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
@@ -340,22 +340,15 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
_timerProvider.Delete(timer);
}
- private List<ChannelInfo> _channelCache = null;
private async Task<IEnumerable<ChannelInfo>> GetChannelsAsync(bool enableCache, CancellationToken cancellationToken)
{
- if (enableCache && _channelCache != null)
- {
-
- return _channelCache.ToList();
- }
-
var list = new List<ChannelInfo>();
foreach (var hostInstance in _liveTvManager.TunerHosts)
{
try
{
- var channels = await hostInstance.GetChannels(cancellationToken).ConfigureAwait(false);
+ var channels = await hostInstance.GetChannels(enableCache, cancellationToken).ConfigureAwait(false);
list.AddRange(channels);
}
@@ -388,7 +381,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
}
}
- _channelCache = list.ToList();
return list;
}
@@ -400,7 +392,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
{
try
{
- var channels = await hostInstance.GetChannels(cancellationToken).ConfigureAwait(false);
+ var channels = await hostInstance.GetChannels(false, cancellationToken).ConfigureAwait(false);
list.AddRange(channels);
}
@@ -632,6 +624,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
existingTimer.Genres = updatedTimer.Genres;
existingTimer.HomePageUrl = updatedTimer.HomePageUrl;
existingTimer.IsKids = updatedTimer.IsKids;
+ existingTimer.IsNews = updatedTimer.IsNews;
existingTimer.IsMovie = updatedTimer.IsMovie;
existingTimer.IsProgramSeries = updatedTimer.IsProgramSeries;
existingTimer.IsSports = updatedTimer.IsSports;
@@ -836,33 +829,68 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
{
var result = await GetChannelStreamInternal(channelId, streamId, cancellationToken).ConfigureAwait(false);
- return result.Item1.PublicMediaSource;
+ return result.Item2;
+ }
+
+ private MediaSourceInfo CloneMediaSource(MediaSourceInfo mediaSource, int consumerId)
+ {
+ var json = _jsonSerializer.SerializeToString(mediaSource);
+ mediaSource = _jsonSerializer.DeserializeFromString<MediaSourceInfo>(json);
+
+ mediaSource.Id = consumerId.ToString(CultureInfo.InvariantCulture) + "_" + mediaSource.Id;
+
+ return mediaSource;
}
- private async Task<Tuple<LiveStream, ITunerHost>> GetChannelStreamInternal(string channelId, string streamId, CancellationToken cancellationToken)
+ private async Task<Tuple<LiveStream, MediaSourceInfo, ITunerHost>> GetChannelStreamInternal(string channelId, string streamId, CancellationToken cancellationToken)
{
_logger.Info("Streaming Channel " + channelId);
- foreach (var hostInstance in _liveTvManager.TunerHosts)
+ await _liveStreamsSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
+
+ var result = _liveStreams.Values.FirstOrDefault(i => string.Equals(i.OriginalStreamId, streamId, StringComparison.OrdinalIgnoreCase));
+
+ if (result != null)
{
- try
- {
- var result = await hostInstance.GetChannelStream(channelId, streamId, cancellationToken).ConfigureAwait(false);
+ //result.ConsumerCount++;
- await _liveStreamsSemaphore.WaitAsync().ConfigureAwait(false);
- _liveStreams[result.Id] = result;
- _liveStreamsSemaphore.Release();
+ //_logger.Info("Live stream {0} consumer count is now {1}", streamId, result.ConsumerCount);
- return new Tuple<LiveStream, ITunerHost>(result, hostInstance);
- }
- catch (FileNotFoundException)
- {
- }
- catch (Exception e)
+ //_liveStreamsSemaphore.Release();
+ //return new Tuple<LiveStream, MediaSourceInfo, ITunerHost>(result, CloneMediaSource(result.OpenedMediaSource, result.ConsumerCount - 1), result.TunerHost);
+ }
+
+ try
+ {
+ foreach (var hostInstance in _liveTvManager.TunerHosts)
{
- _logger.ErrorException("Error getting channel stream", e);
+ try
+ {
+ result = await hostInstance.GetChannelStream(channelId, streamId, cancellationToken).ConfigureAwait(false);
+
+ _liveStreams[result.OpenedMediaSource.Id] = result;
+
+ result.ConsumerCount++;
+ result.TunerHost = hostInstance;
+ result.OriginalStreamId = streamId;
+
+ _logger.Info("Returning mediasource streamId {0}, mediaSource.Id {1}, mediaSource.LiveStreamId {2}",
+ streamId, result.OpenedMediaSource.Id, result.OpenedMediaSource.LiveStreamId);
+
+ return new Tuple<LiveStream, MediaSourceInfo, ITunerHost>(result, CloneMediaSource(result.OpenedMediaSource, 0), hostInstance);
+ }
+ catch (FileNotFoundException)
+ {
+ }
+ catch (OperationCanceledException)
+ {
+ }
}
}
+ finally
+ {
+ _liveStreamsSemaphore.Release();
+ }
throw new ApplicationException("Tuner not found.");
}
@@ -896,25 +924,41 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
public async Task CloseLiveStream(string id, CancellationToken cancellationToken)
{
- await _liveStreamsSemaphore.WaitAsync().ConfigureAwait(false);
+ // Ignore the consumer id
+ id = id.Substring(id.IndexOf('_') + 1);
+
+ await _liveStreamsSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
try
{
LiveStream stream;
if (_liveStreams.TryGetValue(id, out stream))
{
- _liveStreams.Remove(id);
+ stream.ConsumerCount--;
- try
+ _logger.Info("Live stream {0} consumer count is now {1}", id, stream.ConsumerCount);
+
+ if (stream.ConsumerCount <= 0)
{
+ _liveStreams.Remove(id);
+
+ _logger.Info("Closing live stream {0}", id);
+
await stream.Close().ConfigureAwait(false);
_logger.Info("Live stream {0} closed successfully", id);
}
- catch (Exception ex)
- {
- _logger.ErrorException("Error closing live stream", ex);
- }
}
+ else
+ {
+ _logger.Warn("Live stream not found: {0}, unable to close", id);
+ }
+ }
+ catch (OperationCanceledException)
+ {
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error closing live stream", ex);
}
finally
{
@@ -1095,20 +1139,18 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
var recordPath = GetRecordingPath(timer, out seriesPath);
var recordingStatus = RecordingStatus.New;
- LiveStream liveStream = null;
+ string liveStreamId = null;
try
{
var allMediaSources =
await GetChannelStreamMediaSources(timer.ChannelId, CancellationToken.None).ConfigureAwait(false);
- var liveStreamInfo =
- await
- GetChannelStreamInternal(timer.ChannelId, allMediaSources[0].Id, CancellationToken.None)
+ var liveStreamInfo = await GetChannelStreamInternal(timer.ChannelId, allMediaSources[0].Id, CancellationToken.None)
.ConfigureAwait(false);
- liveStream = liveStreamInfo.Item1;
- var mediaStreamInfo = liveStreamInfo.Item1.PublicMediaSource;
- var tunerHost = liveStreamInfo.Item2;
+
+ var mediaStreamInfo = liveStreamInfo.Item2;
+ liveStreamId = mediaStreamInfo.Id;
// HDHR doesn't seem to release the tuner right away after first probing with ffmpeg
//await Task.Delay(3000, cancellationToken).ConfigureAwait(false);
@@ -1140,15 +1182,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
EnforceKeepUpTo(timer);
};
- var pathWithDuration = tunerHost.ApplyDuration(mediaStreamInfo.Path, duration);
-
- // If it supports supplying duration via url
- if (!string.Equals(pathWithDuration, mediaStreamInfo.Path, StringComparison.OrdinalIgnoreCase))
- {
- mediaStreamInfo.Path = pathWithDuration;
- mediaStreamInfo.RunTimeTicks = duration.Ticks;
- }
-
await recorder.Record(mediaStreamInfo, recordPath, duration, onStarted, cancellationToken)
.ConfigureAwait(false);
@@ -1166,11 +1199,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
recordingStatus = RecordingStatus.Error;
}
- if (liveStream != null)
+ if (!string.IsNullOrWhiteSpace(liveStreamId))
{
try
{
- await CloseLiveStream(liveStream.Id, CancellationToken.None).ConfigureAwait(false);
+ await CloseLiveStream(liveStreamId, CancellationToken.None).ConfigureAwait(false);
}
catch (Exception ex)
{
@@ -1251,7 +1284,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
}
}
- private readonly SemaphoreSlim _recordingDeleteSemaphore = new SemaphoreSlim(1,1);
+ private readonly SemaphoreSlim _recordingDeleteSemaphore = new SemaphoreSlim(1, 1);
private async Task DeleteLibraryItemsForTimers(List<TimerInfo> timers)
{
foreach (var timer in timers)
@@ -1295,7 +1328,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
}
catch (FileNotFoundException)
{
-
+
}
}
@@ -1492,6 +1525,10 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
{
AddGenre(timer.Genres, "Kids");
}
+ if (timer.IsNews)
+ {
+ AddGenre(timer.Genres, "News");
+ }
foreach (var genre in timer.Genres)
{
diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs
index f74a76e3f9..ce5f14f4b2 100644
--- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs
+++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs
@@ -71,38 +71,12 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
var durationToken = new CancellationTokenSource(duration);
cancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, durationToken.Token).Token;
- await RecordFromFile(mediaSource, mediaSource.Path, targetFile, false, duration, onStarted, cancellationToken).ConfigureAwait(false);
+ await RecordFromFile(mediaSource, mediaSource.Path, targetFile, duration, onStarted, cancellationToken).ConfigureAwait(false);
_logger.Info("Recording completed to file {0}", targetFile);
}
- private async void DeleteTempFile(string path)
- {
- for (var i = 0; i < 10; i++)
- {
- try
- {
- File.Delete(path);
- return;
- }
- catch (FileNotFoundException)
- {
- return;
- }
- catch (DirectoryNotFoundException)
- {
- return;
- }
- catch (Exception ex)
- {
- _logger.ErrorException("Error deleting recording temp file", ex);
- }
-
- await Task.Delay(1000).ConfigureAwait(false);
- }
- }
-
- private Task RecordFromFile(MediaSourceInfo mediaSource, string inputFile, string targetFile, bool deleteInputFileAfterCompletion, TimeSpan duration, Action onStarted, CancellationToken cancellationToken)
+ private Task RecordFromFile(MediaSourceInfo mediaSource, string inputFile, string targetFile, TimeSpan duration, Action onStarted, CancellationToken cancellationToken)
{
_targetPath = targetFile;
_fileSystem.CreateDirectory(Path.GetDirectoryName(targetFile));
@@ -143,7 +117,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
var commandLineLogMessageBytes = Encoding.UTF8.GetBytes(_json.SerializeToString(mediaSource) + Environment.NewLine + Environment.NewLine + commandLineLogMessage + Environment.NewLine + Environment.NewLine);
_logFileStream.Write(commandLineLogMessageBytes, 0, commandLineLogMessageBytes.Length);
- process.Exited += (sender, args) => OnFfMpegProcessExited(process, inputFile, deleteInputFileAfterCompletion);
+ process.Exited += (sender, args) => OnFfMpegProcessExited(process, inputFile);
process.Start();
@@ -252,7 +226,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
/// <summary>
/// Processes the exited.
/// </summary>
- private void OnFfMpegProcessExited(Process process, string inputFile, bool deleteInputFileAfterCompletion)
+ private void OnFfMpegProcessExited(Process process, string inputFile)
{
_hasExited = true;
@@ -278,11 +252,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
_logger.Error("FFMpeg recording exited with an error for {0}.", _targetPath);
_taskCompletionSource.TrySetException(new Exception(string.Format("Recording for {0} failed", _targetPath)));
}
-
- if (deleteInputFileAfterCompletion)
- {
- DeleteTempFile(inputFile);
- }
}
private void DisposeLogStream()
diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs
index f9c04abc5f..bb6935e8e7 100644
--- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs
+++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs
@@ -42,6 +42,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
timerInfo.EpisodeNumber = programInfo.EpisodeNumber;
timerInfo.IsMovie = programInfo.IsMovie;
timerInfo.IsKids = programInfo.IsKids;
+ timerInfo.IsNews = programInfo.IsNews;
timerInfo.IsSports = programInfo.IsSports;
timerInfo.ProductionYear = programInfo.ProductionYear;
timerInfo.EpisodeTitle = programInfo.EpisodeTitle;