From e9cfa6cd267786f8fd97ef2aeb88941c98c8aacf Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 1 May 2013 16:07:20 -0400 Subject: [PATCH] add remote streaming capabilities --- .../Playback/BaseStreamingService.cs | 38 +++++++++++++++++-- .../Playback/Hls/BaseHlsService.cs | 3 +- .../Playback/Progressive/VideoService.cs | 7 ++-- .../MediaInfo/IMediaEncoder.cs | 6 ++- .../MediaInfo/MediaEncoderHelpers.cs | 8 ++++ .../MediaEncoder/MediaEncoder.cs | 23 +++++++++-- 6 files changed, 73 insertions(+), 12 deletions(-) diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 30700ad4c9..f09b9f6844 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -166,6 +166,11 @@ namespace MediaBrowser.Api.Playback { var args = string.Empty; + if (state.Item.LocationType == LocationType.Remote) + { + return string.Empty; + } + if (state.VideoStream != null) { args += string.Format("-map 0:{0}", state.VideoStream.Index); @@ -179,6 +184,7 @@ namespace MediaBrowser.Api.Playback { args += string.Format(" -map 0:{0}", state.AudioStream.Index); } + else { args += " -map -0:a"; @@ -268,8 +274,20 @@ namespace MediaBrowser.Api.Playback // Need to perform calculations manually // Try to account for bad media info - var currentHeight = state.VideoStream.Height ?? request.MaxHeight ?? request.Height ?? 0; - var currentWidth = state.VideoStream.Width ?? request.MaxWidth ?? request.Width ?? 0; + var currentHeight = request.MaxHeight ?? request.Height ?? 0; + var currentWidth = request.MaxWidth ?? request.Width ?? 0; + + if (state.VideoStream != null) + { + if (state.VideoStream.Height.HasValue) + { + currentHeight = state.VideoStream.Height.Value; + } + if (state.VideoStream.Width.HasValue) + { + currentWidth = state.VideoStream.Width.Value; + } + } var outputSize = DrawingUtils.Resize(currentWidth, currentHeight, request.Width, request.Height, request.MaxWidth, request.MaxHeight); @@ -603,6 +621,21 @@ namespace MediaBrowser.Api.Playback } } + /// + /// Gets the user agent param. + /// + /// The item. + /// System.String. + protected string GetUserAgentParam(BaseItem item) + { + if (item.Path.IndexOf("apple.com", StringComparison.OrdinalIgnoreCase) != -1) + { + return "-user-agent \"QuickTime/7.6.2\""; + } + + return string.Empty; + } + /// /// Processes the exited. /// @@ -704,7 +737,6 @@ namespace MediaBrowser.Api.Playback state.AudioStream = GetMediaStream(media.MediaStreams, null, MediaStreamType.Audio, true); } - return state; } diff --git a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs index 235eea7ecf..a4fc6600a8 100644 --- a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs @@ -194,8 +194,9 @@ namespace MediaBrowser.Api.Playback.Hls var probeSize = GetProbeSizeArgument(state.Item); - return string.Format("{0} {1} -i {2}{3} -threads 0 {4} {5} {6} -f ssegment -segment_list_flags +live -segment_time 10 -segment_list \"{7}\" \"{8}\"", + return string.Format("{0} {1} {2} -i {3}{4} -threads 0 {5} {6} {7} -f ssegment -segment_list_flags +live -segment_time 10 -segment_list \"{8}\" \"{9}\"", probeSize, + GetUserAgentParam(state.Item), GetFastSeekCommandLineParameter(state.Request), GetInputArgument(state.Item, state.IsoMount), GetSlowSeekCommandLineParameter(state.Request), diff --git a/MediaBrowser.Api/Playback/Progressive/VideoService.cs b/MediaBrowser.Api/Playback/Progressive/VideoService.cs index eb04570ed0..78362ff816 100644 --- a/MediaBrowser.Api/Playback/Progressive/VideoService.cs +++ b/MediaBrowser.Api/Playback/Progressive/VideoService.cs @@ -108,10 +108,11 @@ namespace MediaBrowser.Api.Playback.Progressive format = " -f mp4 -movflags frag_keyframe+empty_moov"; } - var threads = videoCodec.Equals("libvpx", StringComparison.OrdinalIgnoreCase) ? 2 : 0; + var threads = 0; - return string.Format("{0} {1} -i {2}{3}{4} {5} {6} -threads {7} {8}{9} \"{10}\"", + return string.Format("{0} {1} {2} -i {3}{4}{5} {6} {7} -threads {8} {9}{10} \"{11}\"", probeSize, + GetUserAgentParam(state.Item), GetFastSeekCommandLineParameter(state.Request), GetInputArgument(video, state.IsoMount), GetSlowSeekCommandLineParameter(state.Request), @@ -139,7 +140,7 @@ namespace MediaBrowser.Api.Playback.Progressive // See if we can save come cpu cycles by avoiding encoding if (codec.Equals("copy", StringComparison.OrdinalIgnoreCase)) { - return IsH264(state.VideoStream) ? args + " -bsf h264_mp4toannexb" : args; + return state.VideoStream != null && IsH264(state.VideoStream) ? args + " -bsf h264_mp4toannexb" : args; } const string keyFrameArg = " -force_key_frames expr:if(isnan(prev_forced_t),gte(t,0),gte(t,prev_forced_t+2))"; diff --git a/MediaBrowser.Common/MediaInfo/IMediaEncoder.cs b/MediaBrowser.Common/MediaInfo/IMediaEncoder.cs index 6d606e6847..84eded043c 100644 --- a/MediaBrowser.Common/MediaInfo/IMediaEncoder.cs +++ b/MediaBrowser.Common/MediaInfo/IMediaEncoder.cs @@ -99,6 +99,10 @@ namespace MediaBrowser.Common.MediaInfo /// /// The DVD /// - Dvd + Dvd, + /// + /// The URL + /// + Url } } diff --git a/MediaBrowser.Controller/Providers/MediaInfo/MediaEncoderHelpers.cs b/MediaBrowser.Controller/Providers/MediaInfo/MediaEncoderHelpers.cs index 14372553b4..7ea2a339a8 100644 --- a/MediaBrowser.Controller/Providers/MediaInfo/MediaEncoderHelpers.cs +++ b/MediaBrowser.Controller/Providers/MediaInfo/MediaEncoderHelpers.cs @@ -47,6 +47,14 @@ namespace MediaBrowser.Controller.Providers.MediaInfo } } break; + case VideoType.VideoFile: + { + if (video.LocationType == LocationType.Remote) + { + type = InputType.Url; + } + break; + } } return inputPath; diff --git a/MediaBrowser.Server.Implementations/MediaEncoder/MediaEncoder.cs b/MediaBrowser.Server.Implementations/MediaEncoder/MediaEncoder.cs index 3d4da1e15f..d02031fe6b 100644 --- a/MediaBrowser.Server.Implementations/MediaEncoder/MediaEncoder.cs +++ b/MediaBrowser.Server.Implementations/MediaEncoder/MediaEncoder.cs @@ -310,6 +310,9 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder case InputType.Bluray: inputPath = GetBlurayInputArgument(inputFiles[0]); break; + case InputType.Url: + inputPath = GetHttpInputArgument(inputFiles); + break; default: throw new ArgumentException("Unrecognized InputType"); } @@ -317,6 +320,18 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder return inputPath; } + /// + /// Gets the HTTP input argument. + /// + /// The input files. + /// System.String. + private string GetHttpInputArgument(string[] inputFiles) + { + var url = inputFiles[0]; + + return string.Format("\"{0}\"", url); + } + /// /// Gets the probe size argument. /// @@ -1005,7 +1020,7 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder /// /// The path. /// System.String. - public string GetFileInputArgument(string path) + private string GetFileInputArgument(string path) { return string.Format("file:\"{0}\"", path); } @@ -1015,7 +1030,7 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder /// /// The playable stream files. /// System.String. - public string GetConcatInputArgument(string[] playableStreamFiles) + private string GetConcatInputArgument(string[] playableStreamFiles) { // Get all streams // If there's more than one we'll need to use the concat command @@ -1027,7 +1042,7 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder } // Determine the input path for video files - return string.Format("file:\"{0}\"", playableStreamFiles[0]); + return GetFileInputArgument(playableStreamFiles[0]); } /// @@ -1035,7 +1050,7 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder /// /// The bluray root. /// System.String. - public string GetBlurayInputArgument(string blurayRoot) + private string GetBlurayInputArgument(string blurayRoot) { return string.Format("bluray:\"{0}\"", blurayRoot); }