diff options
Diffstat (limited to 'MediaBrowser.Api/Playback/BaseStreamingService.cs')
| -rw-r--r-- | MediaBrowser.Api/Playback/BaseStreamingService.cs | 124 |
1 files changed, 88 insertions, 36 deletions
diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index a9aaab00c..612f73191 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -1,5 +1,4 @@ -using System.Text; -using MediaBrowser.Common.Extensions; +using MediaBrowser.Common.Extensions; using MediaBrowser.Common.IO; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Dlna; @@ -22,6 +21,7 @@ using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; +using System.Text; using System.Threading; using System.Threading.Tasks; @@ -937,8 +937,6 @@ namespace MediaBrowser.Api.Playback ApiEntryPoint.Instance.OnTranscodeFailedToStart(outputPath, TranscodingJobType); - state.LogFileStream.Dispose(); - throw; } @@ -1096,23 +1094,12 @@ namespace MediaBrowser.Api.Playback /// </summary> /// <param name="process">The process.</param> /// <param name="state">The state.</param> - protected async void OnFfMpegProcessExited(Process process, StreamState state) + protected void OnFfMpegProcessExited(Process process, StreamState state) { - if (state.IsoMount != null) - { - state.IsoMount.Dispose(); - state.IsoMount = null; - } - - if (state.StandardInputCancellationTokenSource != null) - { - state.StandardInputCancellationTokenSource.Cancel(); - } + state.Dispose(); var outputFilePath = GetOutputFilePath(state); - state.LogFileStream.Dispose(); - try { Logger.Info("FFMpeg exited with code {0} for {1}", process.ExitCode, outputFilePath); @@ -1121,18 +1108,6 @@ namespace MediaBrowser.Api.Playback { Logger.Info("FFMpeg exited with an error for {0}", outputFilePath); } - - if (!string.IsNullOrEmpty(state.LiveTvStreamId)) - { - try - { - await LiveTvManager.CloseLiveStream(state.LiveTvStreamId, CancellationToken.None).ConfigureAwait(false); - } - catch (Exception ex) - { - Logger.ErrorException("Error closing live tv stream", ex); - } - } } protected double? GetFramerateParam(StreamState state) @@ -1357,7 +1332,7 @@ namespace MediaBrowser.Api.Playback request.AudioCodec = InferAudioCodec(url); } - var state = new StreamState + var state = new StreamState(LiveTvManager, Logger) { Request = request, RequestedUrl = url @@ -1393,7 +1368,7 @@ namespace MediaBrowser.Api.Playback mediaUrl = streamInfo.Url; } - if (!string.IsNullOrEmpty(path) && File.Exists(path)) + if (!string.IsNullOrEmpty(path)) { state.MediaPath = path; state.IsRemote = false; @@ -1406,7 +1381,7 @@ namespace MediaBrowser.Api.Playback state.RunTimeTicks = recording.RunTimeTicks; - if (recording.RecordingInfo.Status == RecordingStatus.InProgress && !state.IsRemote) + if (recording.RecordingInfo.Status == RecordingStatus.InProgress) { await Task.Delay(1000, cancellationToken).ConfigureAwait(false); } @@ -1429,7 +1404,7 @@ namespace MediaBrowser.Api.Playback state.LiveTvStreamId = streamInfo.Id; - if (!string.IsNullOrEmpty(streamInfo.Path) && File.Exists(streamInfo.Path)) + if (!string.IsNullOrEmpty(streamInfo.Path)) { state.MediaPath = streamInfo.Path; state.IsRemote = false; @@ -1515,6 +1490,14 @@ namespace MediaBrowser.Api.Playback } } + if (state.AudioStream != null) + { + //if (CanStreamCopyAudio(request, state.AudioStream)) + //{ + // request.AudioCodec = "copy"; + //} + } + return state; } @@ -1538,7 +1521,7 @@ namespace MediaBrowser.Api.Playback } // If client is requesting a specific video profile, it must match the source - if (!string.IsNullOrEmpty(request.Profile) && !string.Equals(request.Profile, videoStream.Profile)) + if (!string.IsNullOrEmpty(request.Profile) && !string.Equals(request.Profile, videoStream.Profile, StringComparison.OrdinalIgnoreCase)) { return false; } @@ -1599,12 +1582,50 @@ namespace MediaBrowser.Api.Playback return false; } } - return false; } return SupportsAutomaticVideoStreamCopy; } + private bool CanStreamCopyAudio(StreamRequest request, MediaStream audioStream) + { + // Source and target codecs must match + if (string.IsNullOrEmpty(request.AudioCodec) || !string.Equals(request.AudioCodec, audioStream.Codec, StringComparison.OrdinalIgnoreCase)) + { + return false; + } + + // Video bitrate must fall within requested value + if (request.AudioBitRate.HasValue) + { + if (!audioStream.BitRate.HasValue || audioStream.BitRate.Value > request.AudioBitRate.Value) + { + return false; + } + } + + // Channels must fall within requested value + var channels = request.AudioChannels ?? request.MaxAudioChannels; + if (channels.HasValue) + { + if (!audioStream.Channels.HasValue || audioStream.Channels.Value > channels.Value) + { + return false; + } + } + + // Sample rate must fall within requested value + if (request.AudioSampleRate.HasValue) + { + if (!audioStream.SampleRate.HasValue || audioStream.SampleRate.Value > request.AudioSampleRate.Value) + { + return false; + } + } + + return SupportsAutomaticVideoStreamCopy; + } + protected virtual bool SupportsAutomaticVideoStreamCopy { get @@ -1722,7 +1743,21 @@ namespace MediaBrowser.Api.Playback // 0 = native, 1 = transcoded var orgCi = isStaticallyStreamed ? ";DLNA.ORG_CI=0" : ";DLNA.ORG_CI=1"; - const string dlnaflags = ";DLNA.ORG_FLAGS=01500000000000000000000000000000"; + var flagValue = DlnaFlags.DLNA_ORG_FLAG_STREAMING_TRANSFER_MODE | + DlnaFlags.DLNA_ORG_FLAG_BACKGROUND_TRANSFERT_MODE | + DlnaFlags.DLNA_ORG_FLAG_DLNA_V15; + + if (isStaticallyStreamed) + { + //flagValue = flagValue | DlnaFlags.DLNA_ORG_FLAG_BYTE_BASED_SEEK; + } + else if (state.RunTimeTicks.HasValue) + { + //flagValue = flagValue | DlnaFlags.DLNA_ORG_FLAG_TIME_BASED_SEEK; + } + + var dlnaflags = string.Format(";DLNA.ORG_FLAGS={0}000000000000000000000000", + Enum.Format(typeof(DlnaFlags), flagValue, "x")); if (!string.IsNullOrWhiteSpace(state.OrgPn)) { @@ -1772,6 +1807,23 @@ namespace MediaBrowser.Api.Playback } } + [Flags] + private enum DlnaFlags + { + DLNA_ORG_FLAG_SENDER_PACED = (1 << 31), + DLNA_ORG_FLAG_TIME_BASED_SEEK = (1 << 30), + DLNA_ORG_FLAG_BYTE_BASED_SEEK = (1 << 29), + DLNA_ORG_FLAG_PLAY_CONTAINER = (1 << 28), + DLNA_ORG_FLAG_S0_INCREASE = (1 << 27), + DLNA_ORG_FLAG_SN_INCREASE = (1 << 26), + DLNA_ORG_FLAG_RTSP_PAUSE = (1 << 25), + DLNA_ORG_FLAG_STREAMING_TRANSFER_MODE = (1 << 24), + DLNA_ORG_FLAG_INTERACTIVE_TRANSFERT_MODE = (1 << 23), + DLNA_ORG_FLAG_BACKGROUND_TRANSFERT_MODE = (1 << 22), + DLNA_ORG_FLAG_CONNECTION_STALL = (1 << 21), + DLNA_ORG_FLAG_DLNA_V15 = (1 << 20), + }; + private void AddTimeSeekResponseHeaders(StreamState state, IDictionary<string, string> responseHeaders) { var runtimeSeconds = TimeSpan.FromTicks(state.RunTimeTicks.Value).TotalSeconds.ToString(UsCulture); |
