diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index f60a106dac..ce3691095c 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -1669,7 +1669,7 @@ namespace MediaBrowser.Api.Playback RequestedUrl = url, UserAgent = Request.UserAgent }; - + //if ((Request.UserAgent ?? string.Empty).IndexOf("iphone", StringComparison.OrdinalIgnoreCase) != -1 || // (Request.UserAgent ?? string.Empty).IndexOf("ipad", StringComparison.OrdinalIgnoreCase) != -1 || // (Request.UserAgent ?? string.Empty).IndexOf("ipod", StringComparison.OrdinalIgnoreCase) != -1) @@ -1770,6 +1770,19 @@ namespace MediaBrowser.Api.Playback { state.OutputVideoCodec = "copy"; } + else + { + // If the user doesn't have access to transcoding, then force stream copy, regardless of whether it will be compatible or not + var auth = AuthorizationContext.GetAuthorizationInfo(Request); + if (!string.IsNullOrWhiteSpace(auth.UserId)) + { + var user = UserManager.GetUserById(auth.UserId); + if (!user.Policy.EnableVideoPlaybackTranscoding) + { + state.OutputVideoCodec = "copy"; + } + } + } if (state.AudioStream != null && CanStreamCopyAudio(state, state.SupportedAudioCodecs)) { diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs index f4ecf36934..e029d4e99a 100644 --- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs @@ -942,17 +942,5 @@ namespace MediaBrowser.Api.Playback.Hls { return isOutputVideo ? ".ts" : ".ts"; } - - protected override bool CanStreamCopyVideo(StreamState state) - { - var isLiveStream = IsLiveStream(state); - - //if (!isLiveStream && Request.QueryString["AllowCustomSegmenting"] != "true") - //{ - // return false; - //} - - return base.CanStreamCopyVideo(state); - } } } \ No newline at end of file diff --git a/MediaBrowser.Api/Playback/MediaInfoService.cs b/MediaBrowser.Api/Playback/MediaInfoService.cs index 2d9cc40c0a..0b989784c0 100644 --- a/MediaBrowser.Api/Playback/MediaInfoService.cs +++ b/MediaBrowser.Api/Playback/MediaInfoService.cs @@ -15,6 +15,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.MediaEncoding; namespace MediaBrowser.Api.Playback @@ -68,8 +69,9 @@ namespace MediaBrowser.Api.Playback private readonly IServerConfigurationManager _config; private readonly INetworkManager _networkManager; private readonly IMediaEncoder _mediaEncoder; + private readonly IUserManager _userManager; - public MediaInfoService(IMediaSourceManager mediaSourceManager, IDeviceManager deviceManager, ILibraryManager libraryManager, IServerConfigurationManager config, INetworkManager networkManager, IMediaEncoder mediaEncoder) + public MediaInfoService(IMediaSourceManager mediaSourceManager, IDeviceManager deviceManager, ILibraryManager libraryManager, IServerConfigurationManager config, INetworkManager networkManager, IMediaEncoder mediaEncoder, IUserManager userManager) { _mediaSourceManager = mediaSourceManager; _deviceManager = deviceManager; @@ -77,6 +79,7 @@ namespace MediaBrowser.Api.Playback _config = config; _networkManager = networkManager; _mediaEncoder = mediaEncoder; + _userManager = userManager; } public object Get(GetBitrateTestBytes request) @@ -119,7 +122,7 @@ namespace MediaBrowser.Api.Playback SetDeviceSpecificData(item, result.MediaSource, profile, authInfo, request.MaxStreamingBitrate, request.StartTimeTicks ?? 0, result.MediaSource.Id, request.AudioStreamIndex, - request.SubtitleStreamIndex, request.PlaySessionId); + request.SubtitleStreamIndex, request.PlaySessionId, request.UserId); } else { @@ -159,7 +162,7 @@ namespace MediaBrowser.Api.Playback { var mediaSourceId = request.MediaSourceId; - SetDeviceSpecificData(request.Id, info, profile, authInfo, request.MaxStreamingBitrate ?? profile.MaxStreamingBitrate, request.StartTimeTicks ?? 0, mediaSourceId, request.AudioStreamIndex, request.SubtitleStreamIndex); + SetDeviceSpecificData(request.Id, info, profile, authInfo, request.MaxStreamingBitrate ?? profile.MaxStreamingBitrate, request.StartTimeTicks ?? 0, mediaSourceId, request.AudioStreamIndex, request.SubtitleStreamIndex, request.UserId); } return ToOptimizedResult(info); @@ -221,13 +224,14 @@ namespace MediaBrowser.Api.Playback long startTimeTicks, string mediaSourceId, int? audioStreamIndex, - int? subtitleStreamIndex) + int? subtitleStreamIndex, + string userId) { var item = _libraryManager.GetItemById(itemId); foreach (var mediaSource in result.MediaSources) { - SetDeviceSpecificData(item, mediaSource, profile, auth, maxBitrate, startTimeTicks, mediaSourceId, audioStreamIndex, subtitleStreamIndex, result.PlaySessionId); + SetDeviceSpecificData(item, mediaSource, profile, auth, maxBitrate, startTimeTicks, mediaSourceId, audioStreamIndex, subtitleStreamIndex, result.PlaySessionId, userId); } SortMediaSources(result, maxBitrate); @@ -242,7 +246,8 @@ namespace MediaBrowser.Api.Playback string mediaSourceId, int? audioStreamIndex, int? subtitleStreamIndex, - string playSessionId) + string playSessionId, + string userId) { var streamBuilder = new StreamBuilder(_mediaEncoder, Logger); @@ -262,6 +267,8 @@ namespace MediaBrowser.Api.Playback options.SubtitleStreamIndex = subtitleStreamIndex; } + var user = _userManager.GetUserById(userId); + if (mediaSource.SupportsDirectPlay) { var supportsDirectStream = mediaSource.SupportsDirectStream; @@ -270,6 +277,14 @@ namespace MediaBrowser.Api.Playback mediaSource.SupportsDirectStream = true; options.MaxBitrate = maxBitrate; + if (item is Audio) + { + if (!user.Policy.EnableAudioPlaybackTranscoding) + { + options.ForceDirectPlay = true; + } + } + // The MediaSource supports direct stream, now test to see if the client supports it var streamInfo = string.Equals(item.MediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase) ? streamBuilder.BuildAudioItem(options) : @@ -293,6 +308,14 @@ namespace MediaBrowser.Api.Playback { options.MaxBitrate = GetMaxBitrate(maxBitrate); + if (item is Audio) + { + if (!user.Policy.EnableAudioPlaybackTranscoding) + { + options.ForceDirectStream = true; + } + } + // The MediaSource supports direct stream, now test to see if the client supports it var streamInfo = string.Equals(item.MediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase) ? streamBuilder.BuildAudioItem(options) : diff --git a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj index 862d95f7ee..7a9589c982 100644 --- a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj +++ b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj @@ -346,8 +346,8 @@ Dlna\HttpHeaderInfo.cs - - Dlna\ILocalPlayer.cs + + Dlna\ITranscoderSupport.cs Dlna\MediaFormatProfile.cs @@ -355,9 +355,6 @@ Dlna\MediaFormatProfileResolver.cs - - Dlna\NullLocalPlayer.cs - Dlna\PlaybackErrorCode.cs diff --git a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj index 953e5b7bef..420b536ae4 100644 --- a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj +++ b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj @@ -318,8 +318,8 @@ Dlna\HttpHeaderInfo.cs - - Dlna\ILocalPlayer.cs + + Dlna\ITranscoderSupport.cs Dlna\MediaFormatProfile.cs @@ -327,9 +327,6 @@ Dlna\MediaFormatProfileResolver.cs - - Dlna\NullLocalPlayer.cs - Dlna\PlaybackErrorCode.cs diff --git a/MediaBrowser.Model/Dlna/AudioOptions.cs b/MediaBrowser.Model/Dlna/AudioOptions.cs index 162b88c981..c208e8ab0b 100644 --- a/MediaBrowser.Model/Dlna/AudioOptions.cs +++ b/MediaBrowser.Model/Dlna/AudioOptions.cs @@ -18,6 +18,8 @@ namespace MediaBrowser.Model.Dlna public bool EnableDirectPlay { get; set; } public bool EnableDirectStream { get; set; } + public bool ForceDirectPlay { get; set; } + public bool ForceDirectStream { get; set; } public string ItemId { get; set; } public List MediaSources { get; set; } diff --git a/MediaBrowser.Model/Dlna/ILocalPlayer.cs b/MediaBrowser.Model/Dlna/ILocalPlayer.cs deleted file mode 100644 index 9de360023e..0000000000 --- a/MediaBrowser.Model/Dlna/ILocalPlayer.cs +++ /dev/null @@ -1,39 +0,0 @@ - -namespace MediaBrowser.Model.Dlna -{ - public interface ILocalPlayer - { - /// - /// Determines whether this instance [can access file] the specified path. - /// - /// The path. - /// true if this instance [can access file] the specified path; otherwise, false. - bool CanAccessFile(string path); - /// - /// Determines whether this instance [can access directory] the specified path. - /// - /// The path. - /// true if this instance [can access directory] the specified path; otherwise, false. - bool CanAccessDirectory(string path); - /// - /// Determines whether this instance [can access URL] the specified URL. - /// - /// The URL. - /// if set to true [requires custom request headers]. - /// true if this instance [can access URL] the specified URL; otherwise, false. - bool CanAccessUrl(string url, bool requiresCustomRequestHeaders); - } - - public interface ITranscoderSupport - { - bool CanEncodeToAudioCodec(string codec); - } - - public class FullTranscoderSupport : ITranscoderSupport - { - public bool CanEncodeToAudioCodec(string codec) - { - return true; - } - } -} diff --git a/MediaBrowser.Model/Dlna/ITranscoderSupport.cs b/MediaBrowser.Model/Dlna/ITranscoderSupport.cs new file mode 100644 index 0000000000..0dac234032 --- /dev/null +++ b/MediaBrowser.Model/Dlna/ITranscoderSupport.cs @@ -0,0 +1,15 @@ +namespace MediaBrowser.Model.Dlna +{ + public interface ITranscoderSupport + { + bool CanEncodeToAudioCodec(string codec); + } + + public class FullTranscoderSupport : ITranscoderSupport + { + public bool CanEncodeToAudioCodec(string codec) + { + return true; + } + } +} diff --git a/MediaBrowser.Model/Dlna/NullLocalPlayer.cs b/MediaBrowser.Model/Dlna/NullLocalPlayer.cs deleted file mode 100644 index c34b638871..0000000000 --- a/MediaBrowser.Model/Dlna/NullLocalPlayer.cs +++ /dev/null @@ -1,21 +0,0 @@ - -namespace MediaBrowser.Model.Dlna -{ - public class NullLocalPlayer : ILocalPlayer - { - public bool CanAccessFile(string path) - { - return false; - } - - public bool CanAccessDirectory(string path) - { - return false; - } - - public bool CanAccessUrl(string url, bool requiresCustomRequestHeaders) - { - return false; - } - } -} diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index 2863eba2e0..c05ca41878 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -11,29 +11,17 @@ namespace MediaBrowser.Model.Dlna { public class StreamBuilder { - private readonly ILocalPlayer _localPlayer; private readonly ILogger _logger; private readonly ITranscoderSupport _transcoderSupport; - public StreamBuilder(ILocalPlayer localPlayer, ITranscoderSupport transcoderSupport, ILogger logger) + public StreamBuilder(ITranscoderSupport transcoderSupport, ILogger logger) { _transcoderSupport = transcoderSupport; - _localPlayer = localPlayer; _logger = logger; } - public StreamBuilder(ITranscoderSupport transcoderSupport, ILogger logger) - : this(new NullLocalPlayer(), transcoderSupport, logger) - { - } - - public StreamBuilder(ILocalPlayer localPlayer, ILogger logger) - : this(localPlayer, new FullTranscoderSupport(), logger) - { - } - public StreamBuilder(ILogger logger) - : this(new NullLocalPlayer(), new FullTranscoderSupport(), logger) + : this(new FullTranscoderSupport(), logger) { } @@ -127,6 +115,20 @@ namespace MediaBrowser.Model.Dlna DeviceProfile = options.Profile }; + if (options.ForceDirectPlay) + { + playlistItem.PlayMethod = PlayMethod.DirectPlay; + playlistItem.Container = item.Container; + return playlistItem; + } + + if (options.ForceDirectStream) + { + playlistItem.PlayMethod = PlayMethod.DirectStream; + playlistItem.Container = item.Container; + return playlistItem; + } + MediaStream audioStream = item.GetDefaultAudioStream(null); List directPlayMethods = GetAudioDirectPlayMethods(item, audioStream, options); @@ -182,19 +184,7 @@ namespace MediaBrowser.Model.Dlna if (all) { - if (item.Protocol == MediaProtocol.File && - directPlayMethods.Contains(PlayMethod.DirectPlay) && - _localPlayer.CanAccessFile(item.Path)) - { - playlistItem.PlayMethod = PlayMethod.DirectPlay; - } - else if (item.Protocol == MediaProtocol.Http && - directPlayMethods.Contains(PlayMethod.DirectPlay) && - _localPlayer.CanAccessUrl(item.Path, item.RequiredHttpHeaders.Count > 0)) - { - playlistItem.PlayMethod = PlayMethod.DirectPlay; - } - else if (directPlayMethods.Contains(PlayMethod.DirectStream)) + if (directPlayMethods.Contains(PlayMethod.DirectStream)) { playlistItem.PlayMethod = PlayMethod.DirectStream; } @@ -413,8 +403,8 @@ namespace MediaBrowser.Model.Dlna MediaStream videoStream = item.VideoStream; // TODO: This doesn't accout for situation of device being able to handle media bitrate, but wifi connection not fast enough - bool isEligibleForDirectPlay = options.EnableDirectPlay && IsEligibleForDirectPlay(item, GetBitrateForDirectPlayCheck(item, options), subtitleStream, options, PlayMethod.DirectPlay); - bool isEligibleForDirectStream = options.EnableDirectStream && IsEligibleForDirectPlay(item, options.GetMaxBitrate(), subtitleStream, options, PlayMethod.DirectStream); + bool isEligibleForDirectPlay = options.EnableDirectPlay && (options.ForceDirectPlay || IsEligibleForDirectPlay(item, GetBitrateForDirectPlayCheck(item, options), subtitleStream, options, PlayMethod.DirectPlay)); + bool isEligibleForDirectStream = options.EnableDirectStream && (options.ForceDirectStream || IsEligibleForDirectPlay(item, options.GetMaxBitrate(), subtitleStream, options, PlayMethod.DirectStream)); _logger.Info("Profile: {0}, Path: {1}, isEligibleForDirectPlay: {2}, isEligibleForDirectStream: {3}", options.Profile.Name ?? "Unknown Profile", @@ -425,7 +415,7 @@ namespace MediaBrowser.Model.Dlna if (isEligibleForDirectPlay || isEligibleForDirectStream) { // See if it can be direct played - PlayMethod? directPlay = GetVideoDirectPlayProfile(options.Profile, item, videoStream, audioStream, isEligibleForDirectPlay, isEligibleForDirectStream); + PlayMethod? directPlay = GetVideoDirectPlayProfile(options, item, videoStream, audioStream, isEligibleForDirectPlay, isEligibleForDirectStream); if (directPlay != null) { @@ -645,13 +635,24 @@ namespace MediaBrowser.Model.Dlna return Math.Min(defaultBitrate, encoderAudioBitrateLimit); } - private PlayMethod? GetVideoDirectPlayProfile(DeviceProfile profile, + private PlayMethod? GetVideoDirectPlayProfile(VideoOptions options, MediaSourceInfo mediaSource, MediaStream videoStream, MediaStream audioStream, bool isEligibleForDirectPlay, bool isEligibleForDirectStream) { + DeviceProfile profile = options.Profile; + + if (options.ForceDirectPlay) + { + return PlayMethod.DirectPlay; + } + if (options.ForceDirectStream) + { + return PlayMethod.DirectStream; + } + if (videoStream == null) { _logger.Info("Profile: {0}, Cannot direct stream with no known video stream. Path: {1}", @@ -829,25 +830,6 @@ namespace MediaBrowser.Model.Dlna } } - if (isEligibleForDirectPlay && mediaSource.SupportsDirectPlay) - { - if (mediaSource.Protocol == MediaProtocol.Http) - { - if (_localPlayer.CanAccessUrl(mediaSource.Path, mediaSource.RequiredHttpHeaders.Count > 0)) - { - return PlayMethod.DirectPlay; - } - } - - else if (mediaSource.Protocol == MediaProtocol.File) - { - if (_localPlayer.CanAccessFile(mediaSource.Path)) - { - return PlayMethod.DirectPlay; - } - } - } - if (isEligibleForDirectStream && mediaSource.SupportsDirectStream) { return PlayMethod.DirectStream; diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index 931b2ebcb2..e3c1e52a53 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -118,9 +118,8 @@ - + - diff --git a/MediaBrowser.WebDashboard/Api/PackageCreator.cs b/MediaBrowser.WebDashboard/Api/PackageCreator.cs index 4c353c413e..b7b1f1dfd7 100644 --- a/MediaBrowser.WebDashboard/Api/PackageCreator.cs +++ b/MediaBrowser.WebDashboard/Api/PackageCreator.cs @@ -440,15 +440,7 @@ namespace MediaBrowser.WebDashboard.Api files.Insert(0, "cordova.js"); } - var tags = files.Select(s => - { - if (s.IndexOf("require", StringComparison.OrdinalIgnoreCase) == -1 && s.IndexOf("alameda", StringComparison.OrdinalIgnoreCase) == -1) - { - return string.Format("", s); - } - return string.Format("", s); - - }).ToArray(); + var tags = files.Select(s => string.Format("", s)).ToArray(); builder.Append(string.Join(string.Empty, tags));