diff --git a/MediaBrowser.Controller/MediaInfo/IMediaEncoder.cs b/MediaBrowser.Controller/MediaInfo/IMediaEncoder.cs index 8e0d696c90..0564c06131 100644 --- a/MediaBrowser.Controller/MediaInfo/IMediaEncoder.cs +++ b/MediaBrowser.Controller/MediaInfo/IMediaEncoder.cs @@ -61,9 +61,10 @@ namespace MediaBrowser.Controller.MediaInfo /// /// The input files. /// The type. + /// if set to true [is audio]. /// The cancellation token. /// Task. - Task GetMediaInfo(string[] inputFiles, InputType type, CancellationToken cancellationToken); + Task GetMediaInfo(string[] inputFiles, InputType type, bool isAudio, CancellationToken cancellationToken); /// /// Gets the probe size argument. diff --git a/MediaBrowser.Providers/MediaInfo/BaseFFProbeProvider.cs b/MediaBrowser.Providers/MediaInfo/BaseFFProbeProvider.cs index 95cbb3e4e0..e897eb1eb1 100644 --- a/MediaBrowser.Providers/MediaInfo/BaseFFProbeProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/BaseFFProbeProvider.cs @@ -1,5 +1,6 @@ using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.MediaInfo; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; @@ -117,7 +118,7 @@ namespace MediaBrowser.Providers.MediaInfo inputPath = MediaEncoderHelpers.GetInputArgument(video.Path, video.LocationType == LocationType.Remote, video.VideoType, video.IsoType, isoMount, video.PlayableStreamFileNames, out type); } - return await MediaEncoder.GetMediaInfo(inputPath, type, cancellationToken).ConfigureAwait(false); + return await MediaEncoder.GetMediaInfo(inputPath, type, item is Audio, cancellationToken).ConfigureAwait(false); } /// diff --git a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs index e9a94c3ad6..1a77985e40 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs @@ -255,13 +255,15 @@ namespace MediaBrowser.Server.Implementations.HttpServer { LogHttpRequest(context, index); - if (context.Request.IsWebSocketRequest) + var request = context.Request; + + if (request.IsWebSocketRequest) { ProcessWebSocketRequest(context); return; } - var localPath = context.Request.Url.LocalPath; + var localPath = request.Url.LocalPath; if (string.Equals(localPath, "/mediabrowser/", StringComparison.OrdinalIgnoreCase)) { @@ -288,8 +290,8 @@ namespace MediaBrowser.Server.Implementations.HttpServer return; } - var url = context.Request.Url.ToString(); - var endPoint = context.Request.RemoteEndPoint; + var url = request.Url.ToString(); + var endPoint = request.RemoteEndPoint; await ProcessRequestAsync(context).ConfigureAwait(false); diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs index 54bc874daf..2d91222c11 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs @@ -206,38 +206,58 @@ namespace MediaBrowser.Server.Implementations.LiveTv return await GetRecording(recording, service.Name, cancellationToken).ConfigureAwait(false); } + private readonly SemaphoreSlim _liveStreamSemaphore = new SemaphoreSlim(1, 1); + public async Task GetRecordingStream(string id, CancellationToken cancellationToken) { - var service = ActiveService; + await _liveStreamSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false); - var recordings = await service.GetRecordingsAsync(cancellationToken).ConfigureAwait(false); - - var recording = recordings.First(i => _tvDtoService.GetInternalRecordingId(service.Name, i.Id) == new Guid(id)); - - var result = await service.GetRecordingStream(recording.Id, cancellationToken).ConfigureAwait(false); - - if (!string.IsNullOrEmpty(result.Id)) + try { - _openStreams.AddOrUpdate(result.Id, result, (key, info) => result); - } + var service = ActiveService; - return result; + var recordings = await service.GetRecordingsAsync(cancellationToken).ConfigureAwait(false); + + var recording = recordings.First(i => _tvDtoService.GetInternalRecordingId(service.Name, i.Id) == new Guid(id)); + + var result = await service.GetRecordingStream(recording.Id, cancellationToken).ConfigureAwait(false); + + if (!string.IsNullOrEmpty(result.Id)) + { + _openStreams.AddOrUpdate(result.Id, result, (key, info) => result); + } + + return result; + } + finally + { + _liveStreamSemaphore.Release(); + } } public async Task GetChannelStream(string id, CancellationToken cancellationToken) { - var service = ActiveService; + await _liveStreamSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false); - var channel = GetInternalChannel(id); - - var result = await service.GetChannelStream(channel.ChannelInfo.Id, cancellationToken).ConfigureAwait(false); - - if (!string.IsNullOrEmpty(result.Id)) + try { - _openStreams.AddOrUpdate(result.Id, result, (key, info) => result); - } + var service = ActiveService; - return result; + var channel = GetInternalChannel(id); + + var result = await service.GetChannelStream(channel.ChannelInfo.Id, cancellationToken).ConfigureAwait(false); + + if (!string.IsNullOrEmpty(result.Id)) + { + _openStreams.AddOrUpdate(result.Id, result, (key, info) => result); + } + + return result; + } + finally + { + _liveStreamSemaphore.Release(); + } } private async Task GetChannel(ChannelInfo channelInfo, string serviceName, CancellationToken cancellationToken) @@ -1243,9 +1263,18 @@ namespace MediaBrowser.Server.Implementations.LiveTv }; } - public Task CloseLiveStream(string id, CancellationToken cancellationToken) + public async Task CloseLiveStream(string id, CancellationToken cancellationToken) { - return ActiveService.CloseLiveStream(id, cancellationToken); + await _liveStreamSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false); + + try + { + await ActiveService.CloseLiveStream(id, cancellationToken).ConfigureAwait(false); + } + finally + { + _liveStreamSemaphore.Release(); + } } public GuideInfo GetGuideInfo() diff --git a/MediaBrowser.Server.Implementations/MediaEncoder/MediaEncoder.cs b/MediaBrowser.Server.Implementations/MediaEncoder/MediaEncoder.cs index b09ff623e7..eecb6aae42 100644 --- a/MediaBrowser.Server.Implementations/MediaEncoder/MediaEncoder.cs +++ b/MediaBrowser.Server.Implementations/MediaEncoder/MediaEncoder.cs @@ -102,12 +102,13 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder /// /// The input files. /// The type. + /// if set to true [is audio]. /// The cancellation token. /// Task. - public Task GetMediaInfo(string[] inputFiles, InputType type, + public Task GetMediaInfo(string[] inputFiles, InputType type, bool isAudio, CancellationToken cancellationToken) { - return GetMediaInfoInternal(GetInputArgument(inputFiles, type), type != InputType.File, + return GetMediaInfoInternal(GetInputArgument(inputFiles, type), !isAudio, GetProbeSizeArgument(type), cancellationToken); } @@ -177,27 +178,27 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder CancellationToken cancellationToken) { var process = new Process + { + StartInfo = new ProcessStartInfo { - StartInfo = new ProcessStartInfo - { - CreateNoWindow = true, - UseShellExecute = false, + CreateNoWindow = true, + UseShellExecute = false, - // Must consume both or ffmpeg may hang due to deadlocks. See comments below. - RedirectStandardOutput = true, - RedirectStandardError = true, - FileName = FFProbePath, - Arguments = - string.Format( - "{0} -i {1} -threads 0 -v info -print_format json -show_streams -show_format", - probeSizeArgument, inputPath).Trim(), + // Must consume both or ffmpeg may hang due to deadlocks. See comments below. + RedirectStandardOutput = true, + RedirectStandardError = true, + FileName = FFProbePath, + Arguments = + string.Format( + "{0} -i {1} -threads 0 -v info -print_format json -show_streams -show_format", + probeSizeArgument, inputPath).Trim(), - WindowStyle = ProcessWindowStyle.Hidden, - ErrorDialog = false - }, + WindowStyle = ProcessWindowStyle.Hidden, + ErrorDialog = false + }, - EnableRaisingEvents = true - }; + EnableRaisingEvents = true + }; _logger.Debug("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments);