diff options
42 files changed, 319 insertions, 316 deletions
diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index f52505c04..6f4b6323d 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -298,7 +298,8 @@ namespace MediaBrowser.Api.Playback // Since transcoding of folder rips is expiremental anyway, it's not worth adding additional variables such as this. if (state.VideoType == VideoType.VideoFile) { - var hwType = ApiEntryPoint.Instance.GetEncodingOptions().HardwareAccelerationType; + var encodingOptions = ApiEntryPoint.Instance.GetEncodingOptions(); + var hwType = encodingOptions.HardwareAccelerationType; if (string.Equals(hwType, "qsv", StringComparison.OrdinalIgnoreCase) || string.Equals(hwType, "h264_qsv", StringComparison.OrdinalIgnoreCase)) @@ -314,6 +315,10 @@ namespace MediaBrowser.Api.Playback { return GetAvailableEncoder("h264_omx", defaultEncoder); } + if (string.Equals(hwType, "vaapi", StringComparison.OrdinalIgnoreCase) && !string.IsNullOrWhiteSpace(encodingOptions.VaapiDevice)) + { + return GetAvailableEncoder("h264_vaapi", defaultEncoder); + } } return defaultEncoder; @@ -427,7 +432,8 @@ namespace MediaBrowser.Api.Playback if (!string.IsNullOrEmpty(state.VideoRequest.Profile)) { - if (!string.Equals(videoCodec, "h264_omx", StringComparison.OrdinalIgnoreCase)) + if (!string.Equals(videoCodec, "h264_omx", StringComparison.OrdinalIgnoreCase) && + !string.Equals(videoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase)) { // not supported by h264_omx param += " -profile:v " + state.VideoRequest.Profile; @@ -482,7 +488,8 @@ namespace MediaBrowser.Api.Playback if (!string.Equals(videoCodec, "h264_omx", StringComparison.OrdinalIgnoreCase) && !string.Equals(videoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase) && - !string.Equals(videoCodec, "h264_nvenc", StringComparison.OrdinalIgnoreCase)) + !string.Equals(videoCodec, "h264_nvenc", StringComparison.OrdinalIgnoreCase) && + !string.Equals(videoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase)) { param = "-pix_fmt yuv420p " + param; } @@ -548,59 +555,97 @@ namespace MediaBrowser.Api.Playback var filters = new List<string>(); - if (state.DeInterlace) + if (string.Equals(outputVideoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase)) + { + filters.Add("format=nv12|vaapi"); + filters.Add("hwupload"); + } + else if (state.DeInterlace && !string.Equals(outputVideoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase)) { filters.Add("yadif=0:-1:0"); } - // If fixed dimensions were supplied - if (request.Width.HasValue && request.Height.HasValue) + if (string.Equals(outputVideoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase)) { - var widthParam = request.Width.Value.ToString(UsCulture); - var heightParam = request.Height.Value.ToString(UsCulture); + // Work around vaapi's reduced scaling features + var scaler = "scale_vaapi"; - filters.Add(string.Format("scale=trunc({0}/2)*2:trunc({1}/2)*2", widthParam, heightParam)); - } + // Given the input dimensions (inputWidth, inputHeight), determine the output dimensions + // (outputWidth, outputHeight). The user may request precise output dimensions or maximum + // output dimensions. Output dimensions are guaranteed to be even. + decimal inputWidth = Convert.ToDecimal(state.VideoStream.Width); + decimal inputHeight = Convert.ToDecimal(state.VideoStream.Height); + decimal outputWidth = request.Width.HasValue ? Convert.ToDecimal(request.Width.Value) : inputWidth; + decimal outputHeight = request.Height.HasValue ? Convert.ToDecimal(request.Height.Value) : inputHeight; + decimal maximumWidth = request.MaxWidth.HasValue ? Convert.ToDecimal(request.MaxWidth.Value) : outputWidth; + decimal maximumHeight = request.MaxHeight.HasValue ? Convert.ToDecimal(request.MaxHeight.Value) : outputHeight; - // If Max dimensions were supplied, for width selects lowest even number between input width and width req size and selects lowest even number from in width*display aspect and requested size - else if (request.MaxWidth.HasValue && request.MaxHeight.HasValue) - { - var maxWidthParam = request.MaxWidth.Value.ToString(UsCulture); - var maxHeightParam = request.MaxHeight.Value.ToString(UsCulture); + if (outputWidth > maximumWidth || outputHeight > maximumHeight) + { + var scale = Math.Min(maximumWidth / outputWidth, maximumHeight / outputHeight); + outputWidth = Math.Min(maximumWidth, Math.Truncate(outputWidth * scale)); + outputHeight = Math.Min(maximumHeight, Math.Truncate(outputHeight * scale)); + } - filters.Add(string.Format("scale=trunc(min(max(iw\\,ih*dar)\\,min({0}\\,{1}*dar))/2)*2:trunc(min(max(iw/dar\\,ih)\\,min({0}/dar\\,{1}))/2)*2", maxWidthParam, maxHeightParam)); - } + outputWidth = 2 * Math.Truncate(outputWidth / 2); + outputHeight = 2 * Math.Truncate(outputHeight / 2); - // If a fixed width was requested - else if (request.Width.HasValue) + if (outputWidth != inputWidth || outputHeight != inputHeight) + { + filters.Add(string.Format("{0}=w={1}:h={2}", scaler, outputWidth.ToString(UsCulture), outputHeight.ToString(UsCulture))); + } + } + else { - var widthParam = request.Width.Value.ToString(UsCulture); + // If fixed dimensions were supplied + if (request.Width.HasValue && request.Height.HasValue) + { + var widthParam = request.Width.Value.ToString(UsCulture); + var heightParam = request.Height.Value.ToString(UsCulture); - filters.Add(string.Format("scale={0}:trunc(ow/a/2)*2", widthParam)); - } + filters.Add(string.Format("scale=trunc({0}/2)*2:trunc({1}/2)*2", widthParam, heightParam)); + } - // If a fixed height was requested - else if (request.Height.HasValue) - { - var heightParam = request.Height.Value.ToString(UsCulture); + // If Max dimensions were supplied, for width selects lowest even number between input width and width req size and selects lowest even number from in width*display aspect and requested size + else if (request.MaxWidth.HasValue && request.MaxHeight.HasValue) + { + var maxWidthParam = request.MaxWidth.Value.ToString(UsCulture); + var maxHeightParam = request.MaxHeight.Value.ToString(UsCulture); - filters.Add(string.Format("scale=trunc(oh*a/2)*2:{0}", heightParam)); - } + filters.Add(string.Format("scale=trunc(min(max(iw\\,ih*dar)\\,min({0}\\,{1}*dar))/2)*2:trunc(min(max(iw/dar\\,ih)\\,min({0}/dar\\,{1}))/2)*2", maxWidthParam, maxHeightParam)); + } - // If a max width was requested - else if (request.MaxWidth.HasValue) - { - var maxWidthParam = request.MaxWidth.Value.ToString(UsCulture); + // If a fixed width was requested + else if (request.Width.HasValue) + { + var widthParam = request.Width.Value.ToString(UsCulture); - filters.Add(string.Format("scale=trunc(min(max(iw\\,ih*dar)\\,{0})/2)*2:trunc(ow/dar/2)*2", maxWidthParam)); - } + filters.Add(string.Format("scale={0}:trunc(ow/a/2)*2", widthParam)); + } - // If a max height was requested - else if (request.MaxHeight.HasValue) - { - var maxHeightParam = request.MaxHeight.Value.ToString(UsCulture); + // If a fixed height was requested + else if (request.Height.HasValue) + { + var heightParam = request.Height.Value.ToString(UsCulture); - filters.Add(string.Format("scale=trunc(oh*a/2)*2:min(ih\\,{0})", maxHeightParam)); + filters.Add(string.Format("scale=trunc(oh*a/2)*2:{0}", heightParam)); + } + + // If a max width was requested + else if (request.MaxWidth.HasValue) + { + var maxWidthParam = request.MaxWidth.Value.ToString(UsCulture); + + filters.Add(string.Format("scale=trunc(min(max(iw\\,ih*dar)\\,{0})/2)*2:trunc(ow/dar/2)*2", maxWidthParam)); + } + + // If a max height was requested + else if (request.MaxHeight.HasValue) + { + var maxHeightParam = request.MaxHeight.Value.ToString(UsCulture); + + filters.Add(string.Format("scale=trunc(oh*a/2)*2:min(ih\\,{0})", maxHeightParam)); + } } var output = string.Empty; @@ -935,6 +980,17 @@ namespace MediaBrowser.Api.Playback } } + if (state.VideoRequest != null) + { + var encodingOptions = ApiEntryPoint.Instance.GetEncodingOptions(); + if (GetVideoEncoder(state).IndexOf("vaapi", StringComparison.OrdinalIgnoreCase) != -1) + { + arg = "-hwaccel vaapi -hwaccel_output_format vaapi -vaapi_device " + encodingOptions.VaapiDevice + " " + arg; + } + } + + arg += string.Format(" -ss {0}", MediaEncoder.GetTimeParameter(TimeSpan.FromSeconds(1).Ticks)); + return arg.Trim(); } @@ -1590,13 +1646,6 @@ namespace MediaBrowser.Api.Playback } else if (i == 25) { - if (videoRequest != null) - { - videoRequest.ForceLiveStream = string.Equals("true", val, StringComparison.OrdinalIgnoreCase); - } - } - else if (i == 26) - { if (!string.IsNullOrWhiteSpace(val) && videoRequest != null) { SubtitleDeliveryMethod method; @@ -1606,18 +1655,18 @@ namespace MediaBrowser.Api.Playback } } } - else if (i == 27) + else if (i == 26) { request.TranscodingMaxAudioChannels = int.Parse(val, UsCulture); } - else if (i == 28) + else if (i == 27) { if (videoRequest != null) { videoRequest.EnableSubtitlesInManifest = string.Equals("true", val, StringComparison.OrdinalIgnoreCase); } } - else if (i == 29) + else if (i == 28) { request.Tag = val; } @@ -2218,7 +2267,6 @@ namespace MediaBrowser.Api.Playback if (state.VideoRequest != null) { state.VideoRequest.CopyTimestamps = transcodingProfile.CopyTimestamps; - state.VideoRequest.ForceLiveStream = transcodingProfile.ForceLiveStream; state.VideoRequest.EnableSubtitlesInManifest = transcodingProfile.EnableSubtitlesInManifest; } } @@ -2244,7 +2292,7 @@ namespace MediaBrowser.Api.Playback return Task.FromResult(true); } - if (!string.Equals(MediaEncoder.EncoderLocationType, "Default", StringComparison.OrdinalIgnoreCase)) + if (!MediaEncoder.IsDefaultEncoderPath) { return Task.FromResult(true); } diff --git a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs index 4ec14c96c..a0ac96b9d 100644 --- a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs @@ -281,11 +281,6 @@ namespace MediaBrowser.Api.Playback.Hls { var isLiveStream = (state.RunTimeTicks ?? 0) == 0; - if (state.VideoRequest.ForceLiveStream) - { - return true; - } - return isLiveStream; } } diff --git a/MediaBrowser.Api/Playback/StreamRequest.cs b/MediaBrowser.Api/Playback/StreamRequest.cs index e1a577f52..8cdf846ed 100644 --- a/MediaBrowser.Api/Playback/StreamRequest.cs +++ b/MediaBrowser.Api/Playback/StreamRequest.cs @@ -193,8 +193,6 @@ namespace MediaBrowser.Api.Playback [ApiMember(Name = "CopyTimestamps", Description = "Whether or not to copy timestamps when transcoding with an offset. Defaults to false.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")] public bool CopyTimestamps { get; set; } - public bool ForceLiveStream { get; set; } - public bool EnableSubtitlesInManifest { get; set; } public VideoStreamRequest() diff --git a/MediaBrowser.Api/Sync/SyncHelper.cs b/MediaBrowser.Api/Sync/SyncHelper.cs index 2f857000c..60df2bb1e 100644 --- a/MediaBrowser.Api/Sync/SyncHelper.cs +++ b/MediaBrowser.Api/Sync/SyncHelper.cs @@ -24,6 +24,19 @@ namespace MediaBrowser.Api.Sync } break; } + if (item.IsAudio) + { + options.Add(SyncJobOption.Quality); + options.Add(SyncJobOption.Profile); + break; + } + if (item.IsMusicGenre || item.IsArtist|| item.IsType("musicalbum")) + { + options.Add(SyncJobOption.Quality); + options.Add(SyncJobOption.Profile); + options.Add(SyncJobOption.ItemLimit); + break; + } if (item.IsFolderItem && !item.IsMusicGenre && !item.IsArtist && !item.IsType("musicalbum") && !item.IsGameGenre) { options.Add(SyncJobOption.Quality); diff --git a/MediaBrowser.Api/Sync/SyncService.cs b/MediaBrowser.Api/Sync/SyncService.cs index b9544d71b..821591dc4 100644 --- a/MediaBrowser.Api/Sync/SyncService.cs +++ b/MediaBrowser.Api/Sync/SyncService.cs @@ -291,7 +291,8 @@ namespace MediaBrowser.Api.Sync { Fields = new List<ItemFields> { - ItemFields.SyncInfo + ItemFields.SyncInfo, + ItemFields.BasicSyncInfo } }; diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index cbbb9a89a..984374a49 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -281,6 +281,20 @@ namespace MediaBrowser.Controller.Entities } } + public Task UpdateIsOffline(bool newValue) + { + var item = this; + + if (item.IsOffline != newValue) + { + item.IsOffline = newValue; + // this is creating too many repeated db updates + //return item.UpdateToRepository(ItemUpdateType.None, CancellationToken.None); + } + + return Task.FromResult(true); + } + /// <summary> /// Gets or sets the type of the location. /// </summary> @@ -290,10 +304,10 @@ namespace MediaBrowser.Controller.Entities { get { - if (IsOffline) - { - return LocationType.Offline; - } + //if (IsOffline) + //{ + // return LocationType.Offline; + //} if (string.IsNullOrWhiteSpace(Path)) { diff --git a/MediaBrowser.Controller/Entities/CollectionFolder.cs b/MediaBrowser.Controller/Entities/CollectionFolder.cs index e120f2e23..597ecf973 100644 --- a/MediaBrowser.Controller/Entities/CollectionFolder.cs +++ b/MediaBrowser.Controller/Entities/CollectionFolder.cs @@ -106,6 +106,7 @@ namespace MediaBrowser.Controller.Entities { LibraryOptions[path] = options; + options.SchemaVersion = 1; XmlSerializer.SerializeToFile(options, GetLibraryOptionsPath(path)); } } diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index b5c76c0eb..bea648a3d 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -375,7 +375,7 @@ namespace MediaBrowser.Controller.Entities if (currentChildren.TryGetValue(child.Id, out currentChild) && IsValidFromResolver(currentChild, child)) { - await UpdateIsOffline(currentChild, false).ConfigureAwait(false); + await currentChild.UpdateIsOffline(false).ConfigureAwait(false); validChildren.Add(currentChild); continue; @@ -404,7 +404,7 @@ namespace MediaBrowser.Controller.Entities else if (!string.IsNullOrEmpty(item.Path) && IsPathOffline(item.Path)) { - await UpdateIsOffline(item, true).ConfigureAwait(false); + await item.UpdateIsOffline(true).ConfigureAwait(false); } else { @@ -461,17 +461,6 @@ namespace MediaBrowser.Controller.Entities progress.Report(100); } - private Task UpdateIsOffline(BaseItem item, bool newValue) - { - if (item.IsOffline != newValue) - { - item.IsOffline = newValue; - return item.UpdateToRepository(ItemUpdateType.None, CancellationToken.None); - } - - return Task.FromResult(true); - } - private async Task RefreshMetadataRecursive(MetadataRefreshOptions refreshOptions, bool recursive, IProgress<double> progress, CancellationToken cancellationToken) { var children = ActualChildren.ToList(); diff --git a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs index 1fef8bead..7fdbf020c 100644 --- a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs +++ b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs @@ -134,5 +134,6 @@ namespace MediaBrowser.Controller.MediaEncoding Task UpdateEncoderPath(string path, string pathType); bool SupportsEncoder(string encoder); + bool IsDefaultEncoderPath { get; } } } diff --git a/MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs b/MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs index 66a9fa60b..96a3753e1 100644 --- a/MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs +++ b/MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs @@ -36,8 +36,13 @@ namespace MediaBrowser.Controller.MediaEncoding return new[] {videoPath}; } - public static List<string> GetPlayableStreamFiles(IFileSystem fileSystem, string rootPath, IEnumerable<string> filenames) + private static List<string> GetPlayableStreamFiles(IFileSystem fileSystem, string rootPath, List<string> filenames) { + if (filenames.Count == 0) + { + return new List<string>(); + } + var allFiles = fileSystem .GetFilePaths(rootPath, true) .ToList(); diff --git a/MediaBrowser.Dlna/Profiles/DefaultProfile.cs b/MediaBrowser.Dlna/Profiles/DefaultProfile.cs index e4f6d337f..5f60e8306 100644 --- a/MediaBrowser.Dlna/Profiles/DefaultProfile.cs +++ b/MediaBrowser.Dlna/Profiles/DefaultProfile.cs @@ -33,7 +33,6 @@ namespace MediaBrowser.Dlna.Profiles MaxStreamingBitrate = 20000000; MaxStaticBitrate = 20000000; MusicStreamingTranscodingBitrate = 192000; - MusicSyncBitrate = 192000; EnableAlbumArtInDidl = false; diff --git a/MediaBrowser.Dlna/Profiles/KodiProfile.cs b/MediaBrowser.Dlna/Profiles/KodiProfile.cs index 184923b70..5e1ac5760 100644 --- a/MediaBrowser.Dlna/Profiles/KodiProfile.cs +++ b/MediaBrowser.Dlna/Profiles/KodiProfile.cs @@ -11,9 +11,7 @@ namespace MediaBrowser.Dlna.Profiles Name = "Kodi"; MaxStreamingBitrate = 100000000; - MaxStaticBitrate = 100000000; MusicStreamingTranscodingBitrate = 1280000; - MusicSyncBitrate = 1280000; TimelineOffsetSeconds = 5; diff --git a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs index 32cd950af..aaa5593b4 100644 --- a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs @@ -680,7 +680,8 @@ namespace MediaBrowser.MediaEncoding.Encoder if (!string.IsNullOrEmpty(state.Options.Profile)) { - if (!string.Equals(videoCodec, "h264_omx", StringComparison.OrdinalIgnoreCase)) + if (!string.Equals(videoCodec, "h264_omx", StringComparison.OrdinalIgnoreCase) && + !string.Equals(videoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase)) { // not supported by h264_omx param += " -profile:v " + state.Options.Profile; @@ -737,7 +738,8 @@ namespace MediaBrowser.MediaEncoding.Encoder if (!string.Equals(videoCodec, "h264_omx", StringComparison.OrdinalIgnoreCase) && !string.Equals(videoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase) && - !string.Equals(videoCodec, "h264_nvenc", StringComparison.OrdinalIgnoreCase)) + !string.Equals(videoCodec, "h264_nvenc", StringComparison.OrdinalIgnoreCase) && + !string.Equals(videoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase)) { param = "-pix_fmt yuv420p " + param; } @@ -887,66 +889,96 @@ namespace MediaBrowser.MediaEncoding.Encoder var filters = new List<string>(); - if (state.DeInterlace) + if (string.Equals(outputVideoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase)) + { + filters.Add("format=nv12|vaapi"); + filters.Add("hwupload"); + } + else if (state.DeInterlace && !string.Equals(outputVideoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase)) { filters.Add("yadif=0:-1:0"); } - // If fixed dimensions were supplied - if (request.Width.HasValue && request.Height.HasValue) + if (string.Equals(outputVideoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase)) { - var widthParam = request.Width.Value.ToString(UsCulture); - var heightParam = request.Height.Value.ToString(UsCulture); + // Work around vaapi's reduced scaling features + var scaler = "scale_vaapi"; - filters.Add(string.Format("scale=trunc({0}/2)*2:trunc({1}/2)*2", widthParam, heightParam)); - } + // Given the input dimensions (inputWidth, inputHeight), determine the output dimensions + // (outputWidth, outputHeight). The user may request precise output dimensions or maximum + // output dimensions. Output dimensions are guaranteed to be even. + decimal inputWidth = Convert.ToDecimal(state.VideoStream.Width); + decimal inputHeight = Convert.ToDecimal(state.VideoStream.Height); + decimal outputWidth = request.Width.HasValue ? Convert.ToDecimal(request.Width.Value) : inputWidth; + decimal outputHeight = request.Height.HasValue ? Convert.ToDecimal(request.Height.Value) : inputHeight; + decimal maximumWidth = request.MaxWidth.HasValue ? Convert.ToDecimal(request.MaxWidth.Value) : outputWidth; + decimal maximumHeight = request.MaxHeight.HasValue ? Convert.ToDecimal(request.MaxHeight.Value) : outputHeight; - // If Max dimensions were supplied, for width selects lowest even number between input width and width req size and selects lowest even number from in width*display aspect and requested size - else if (request.MaxWidth.HasValue && request.MaxHeight.HasValue) - { - var maxWidthParam = request.MaxWidth.Value.ToString(UsCulture); - var maxHeightParam = request.MaxHeight.Value.ToString(UsCulture); + if (outputWidth > maximumWidth || outputHeight > maximumHeight) + { + var scale = Math.Min(maximumWidth / outputWidth, maximumHeight / outputHeight); + outputWidth = Math.Min(maximumWidth, Math.Truncate(outputWidth * scale)); + outputHeight = Math.Min(maximumHeight, Math.Truncate(outputHeight * scale)); + } - filters.Add(string.Format("scale=trunc(min(max(iw\\,ih*dar)\\,min({0}\\,{1}*dar))/2)*2:trunc(min(max(iw/dar\\,ih)\\,min({0}/dar\\,{1}))/2)*2", maxWidthParam, maxHeightParam)); - } + outputWidth = 2 * Math.Truncate(outputWidth / 2); + outputHeight = 2 * Math.Truncate(outputHeight / 2); - // If a fixed width was requested - else if (request.Width.HasValue) + if (outputWidth != inputWidth || outputHeight != inputHeight) + { + filters.Add(string.Format("{0}=w={1}:h={2}", scaler, outputWidth.ToString(UsCulture), outputHeight.ToString(UsCulture))); + } + } + else { - var widthParam = request.Width.Value.ToString(UsCulture); + // If fixed dimensions were supplied + if (request.Width.HasValue && request.Height.HasValue) + { + var widthParam = request.Width.Value.ToString(UsCulture); + var heightParam = request.Height.Value.ToString(UsCulture); - filters.Add(string.Format("scale={0}:trunc(ow/a/2)*2", widthParam)); - } + filters.Add(string.Format("scale=trunc({0}/2)*2:trunc({1}/2)*2", widthParam, heightParam)); + } - // If a fixed height was requested - else if (request.Height.HasValue) - { - var heightParam = request.Height.Value.ToString(UsCulture); + // If Max dimensions were supplied, for width selects lowest even number between input width and width req size and selects lowest even number from in width*display aspect and requested size + else if (request.MaxWidth.HasValue && request.MaxHeight.HasValue) + { + var maxWidthParam = request.MaxWidth.Value.ToString(UsCulture); + var maxHeightParam = request.MaxHeight.Value.ToString(UsCulture); - filters.Add(string.Format("scale=trunc(oh*a/2)*2:{0}", heightParam)); - } + filters.Add(string.Format("scale=trunc(min(max(iw\\,ih*dar)\\,min({0}\\,{1}*dar))/2)*2:trunc(min(max(iw/dar\\,ih)\\,min({0}/dar\\,{1}))/2)*2", maxWidthParam, maxHeightParam)); + } - // If a max width was requested - else if (request.MaxWidth.HasValue) - { - var maxWidthParam = request.MaxWidth.Value.ToString(UsCulture); + // If a fixed width was requested + else if (request.Width.HasValue) + { + var widthParam = request.Width.Value.ToString(UsCulture); - filters.Add(string.Format("scale=trunc(min(max(iw\\,ih*dar)\\,{0})/2)*2:trunc(ow/dar/2)*2", maxWidthParam)); - } + filters.Add(string.Format("scale={0}:trunc(ow/a/2)*2", widthParam)); + } - // If a max height was requested - else if (request.MaxHeight.HasValue) - { - var maxHeightParam = request.MaxHeight.Value.ToString(UsCulture); + // If a fixed height was requested + else if (request.Height.HasValue) + { + var heightParam = request.Height.Value.ToString(UsCulture); - filters.Add(string.Format("scale=trunc(oh*a/2)*2:min(ih\\,{0})", maxHeightParam)); - } + filters.Add(string.Format("scale=trunc(oh*a/2)*2:{0}", heightParam)); + } - if (string.Equals(outputVideoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase)) - { - if (filters.Count > 1) + // If a max width was requested + else if (request.MaxWidth.HasValue) + { + var maxWidthParam = request.MaxWidth.Value.ToString(UsCulture); + + filters.Add(string.Format("scale=trunc(min(max(iw\\,ih*dar)\\,{0})/2)*2:trunc(ow/dar/2)*2", maxWidthParam)); + } + + // If a max height was requested + else if (request.MaxHeight.HasValue) { - //filters[filters.Count - 1] += ":flags=fast_bilinear"; + var maxHeightParam = request.MaxHeight.Value.ToString(UsCulture); + + filters.Add(string.Format("scale=trunc(oh*a/2)*2:min(ih\\,{0})", maxHeightParam)); } } diff --git a/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs b/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs index ba7b14950..c72532669 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs @@ -586,6 +586,10 @@ namespace MediaBrowser.MediaEncoding.Encoder { return GetAvailableEncoder(mediaEncoder, "h264_omx", defaultEncoder); } + if (string.Equals(hwType, "vaapi", StringComparison.OrdinalIgnoreCase) && !string.IsNullOrWhiteSpace(options.VaapiDevice)) + { + return GetAvailableEncoder(mediaEncoder, "h264_vaapi", defaultEncoder); + } } return defaultEncoder; diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index f488be11a..ad84ffee8 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -123,20 +123,20 @@ namespace MediaBrowser.MediaEncoding.Encoder return "System"; } - if (IsDefaultPath(FFMpegPath)) - { - return "Default"; - } - return "Custom"; } } - private bool IsDefaultPath(string path) + public bool IsDefaultEncoderPath { - var parentPath = Path.Combine(ConfigurationManager.ApplicationPaths.ProgramDataPath, "ffmpeg", "20160410"); + get + { + var path = FFMpegPath; + + var parentPath = Path.Combine(ConfigurationManager.ApplicationPaths.ProgramDataPath, "ffmpeg", "20160410"); - return FileSystem.ContainsSubPath(parentPath, path); + return FileSystem.ContainsSubPath(parentPath, path); + } } private bool IsSystemInstalledPath(string path) diff --git a/MediaBrowser.Model/Configuration/EncodingOptions.cs b/MediaBrowser.Model/Configuration/EncodingOptions.cs index 91d28a296..3c03dc12a 100644 --- a/MediaBrowser.Model/Configuration/EncodingOptions.cs +++ b/MediaBrowser.Model/Configuration/EncodingOptions.cs @@ -10,6 +10,7 @@ namespace MediaBrowser.Model.Configuration public int ThrottleDelaySeconds { get; set; } public string HardwareAccelerationType { get; set; } public string EncoderAppPath { get; set; } + public string VaapiDevice { get; set; } public EncodingOptions() { @@ -17,6 +18,7 @@ namespace MediaBrowser.Model.Configuration EnableThrottling = true; ThrottleDelaySeconds = 180; EncodingThreadCount = -1; + VaapiDevice = "/dev/dri/card0"; } } } diff --git a/MediaBrowser.Model/Configuration/LibraryOptions.cs b/MediaBrowser.Model/Configuration/LibraryOptions.cs index e15df37c1..3fe694553 100644 --- a/MediaBrowser.Model/Configuration/LibraryOptions.cs +++ b/MediaBrowser.Model/Configuration/LibraryOptions.cs @@ -4,10 +4,13 @@ { public bool EnableArchiveMediaFiles { get; set; } public bool EnablePhotos { get; set; } + public bool EnableRealtimeMonitor { get; set; } + public int SchemaVersion { get; set; } public LibraryOptions() { EnablePhotos = true; + EnableRealtimeMonitor = true; } } } diff --git a/MediaBrowser.Model/Configuration/UserConfiguration.cs b/MediaBrowser.Model/Configuration/UserConfiguration.cs index 69dc23b21..313c5243c 100644 --- a/MediaBrowser.Model/Configuration/UserConfiguration.cs +++ b/MediaBrowser.Model/Configuration/UserConfiguration.cs @@ -27,8 +27,6 @@ namespace MediaBrowser.Model.Configuration public bool DisplayMissingEpisodes { get; set; } public bool DisplayUnairedEpisodes { get; set; } - public bool GroupMoviesIntoBoxSets { get; set; } - public string[] ExcludeFoldersFromGrouping { get; set; } public string[] GroupedFolders { get; set; } @@ -48,7 +46,6 @@ namespace MediaBrowser.Model.Configuration public bool RememberAudioSelections { get; set; } public bool RememberSubtitleSelections { get; set; } public bool EnableNextEpisodeAutoPlay { get; set; } - public bool DisplayFoldersView { get; set; } /// <summary> /// Initializes a new instance of the <see cref="UserConfiguration" /> class. diff --git a/MediaBrowser.Model/Dlna/AudioOptions.cs b/MediaBrowser.Model/Dlna/AudioOptions.cs index c208e8ab0..f3b6df861 100644 --- a/MediaBrowser.Model/Dlna/AudioOptions.cs +++ b/MediaBrowser.Model/Dlna/AudioOptions.cs @@ -59,7 +59,7 @@ namespace MediaBrowser.Model.Dlna /// Gets the maximum bitrate. /// </summary> /// <returns>System.Nullable<System.Int32>.</returns> - public int? GetMaxBitrate() + public int? GetMaxBitrate(bool isAudio) { if (MaxBitrate.HasValue) { @@ -70,6 +70,10 @@ namespace MediaBrowser.Model.Dlna { if (Context == EncodingContext.Static) { + if (isAudio && Profile.MaxStaticMusicBitrate.HasValue) + { + return Profile.MaxStaticMusicBitrate; + } return Profile.MaxStaticBitrate; } diff --git a/MediaBrowser.Model/Dlna/DeviceProfile.cs b/MediaBrowser.Model/Dlna/DeviceProfile.cs index 423928f62..d6a322322 100644 --- a/MediaBrowser.Model/Dlna/DeviceProfile.cs +++ b/MediaBrowser.Model/Dlna/DeviceProfile.cs @@ -55,7 +55,7 @@ namespace MediaBrowser.Model.Dlna public int? MaxStaticBitrate { get; set; } public int? MusicStreamingTranscodingBitrate { get; set; } - public int? MusicSyncBitrate { get; set; } + public int? MaxStaticMusicBitrate { get; set; } /// <summary> /// Controls the content of the X_DLNADOC element in the urn:schemas-dlna-org:device-1-0 namespace. @@ -115,7 +115,6 @@ namespace MediaBrowser.Model.Dlna MaxStreamingBitrate = 8000000; MaxStaticBitrate = 8000000; MusicStreamingTranscodingBitrate = 128000; - MusicSyncBitrate = 128000; } public List<string> GetSupportedMediaTypes() diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index 0710417c8..d042125b9 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -55,7 +55,7 @@ namespace MediaBrowser.Model.Dlna stream.DeviceProfileId = options.Profile.Id; } - return GetOptimalStream(streams, options.GetMaxBitrate()); + return GetOptimalStream(streams, options.GetMaxBitrate(true)); } public StreamInfo BuildVideoItem(VideoOptions options) @@ -88,7 +88,7 @@ namespace MediaBrowser.Model.Dlna stream.DeviceProfileId = options.Profile.Id; } - return GetOptimalStream(streams, options.GetMaxBitrate()); + return GetOptimalStream(streams, options.GetMaxBitrate(false)); } private StreamInfo GetOptimalStream(List<StreamInfo> streams, int? maxBitrate) @@ -275,24 +275,32 @@ namespace MediaBrowser.Model.Dlna playlistItem.MaxAudioChannels = Math.Min(options.MaxAudioChannels.Value, currentValue); } - int configuredBitrate = options.AudioTranscodingBitrate ?? - (options.Context == EncodingContext.Static ? options.Profile.MusicSyncBitrate : options.Profile.MusicStreamingTranscodingBitrate) ?? + int transcodingBitrate = options.AudioTranscodingBitrate ?? + options.Profile.MusicStreamingTranscodingBitrate ?? 128000; - playlistItem.AudioBitrate = Math.Min(configuredBitrate, playlistItem.AudioBitrate ?? configuredBitrate); + int? configuredBitrate = options.GetMaxBitrate(true); + + if (configuredBitrate.HasValue) + { + transcodingBitrate = Math.Min(configuredBitrate.Value, transcodingBitrate); + } + + playlistItem.AudioBitrate = Math.Min(transcodingBitrate, playlistItem.AudioBitrate ?? transcodingBitrate); + } return playlistItem; } - private int? GetBitrateForDirectPlayCheck(MediaSourceInfo item, AudioOptions options) + private int? GetBitrateForDirectPlayCheck(MediaSourceInfo item, AudioOptions options, bool isAudio) { if (item.Protocol == MediaProtocol.File) { return options.Profile.MaxStaticBitrate; } - return options.GetMaxBitrate(); + return options.GetMaxBitrate(isAudio); } private List<PlayMethod> GetAudioDirectPlayMethods(MediaSourceInfo item, MediaStream audioStream, AudioOptions options) @@ -312,7 +320,7 @@ namespace MediaBrowser.Model.Dlna if (directPlayProfile != null) { // While options takes the network and other factors into account. Only applies to direct stream - if (item.SupportsDirectStream && IsAudioEligibleForDirectPlay(item, options.GetMaxBitrate()) && options.EnableDirectStream) + if (item.SupportsDirectStream && IsAudioEligibleForDirectPlay(item, options.GetMaxBitrate(true)) && options.EnableDirectStream) { playMethods.Add(PlayMethod.DirectStream); } @@ -320,7 +328,7 @@ namespace MediaBrowser.Model.Dlna // The profile describes what the device supports // If device requirements are satisfied then allow both direct stream and direct play if (item.SupportsDirectPlay && - IsAudioEligibleForDirectPlay(item, GetBitrateForDirectPlayCheck(item, options)) && options.EnableDirectPlay) + IsAudioEligibleForDirectPlay(item, GetBitrateForDirectPlayCheck(item, options, true)) && options.EnableDirectPlay) { playMethods.Add(PlayMethod.DirectPlay); } @@ -403,8 +411,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 && (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)); + bool isEligibleForDirectPlay = options.EnableDirectPlay && (options.ForceDirectPlay || IsEligibleForDirectPlay(item, GetBitrateForDirectPlayCheck(item, options, true), subtitleStream, options, PlayMethod.DirectPlay)); + bool isEligibleForDirectStream = options.EnableDirectStream && (options.ForceDirectStream || IsEligibleForDirectPlay(item, options.GetMaxBitrate(false), subtitleStream, options, PlayMethod.DirectStream)); _logger.Info("Profile: {0}, Path: {1}, isEligibleForDirectPlay: {2}, isEligibleForDirectStream: {3}", options.Profile.Name ?? "Unknown Profile", @@ -469,7 +477,6 @@ namespace MediaBrowser.Model.Dlna playlistItem.VideoCodec = transcodingProfile.VideoCodec; playlistItem.CopyTimestamps = transcodingProfile.CopyTimestamps; - playlistItem.ForceLiveStream = transcodingProfile.ForceLiveStream; playlistItem.EnableSubtitlesInManifest = transcodingProfile.EnableSubtitlesInManifest; if (!string.IsNullOrEmpty(transcodingProfile.MaxAudioChannels)) @@ -570,10 +577,10 @@ namespace MediaBrowser.Model.Dlna playlistItem.MaxAudioChannels = Math.Min(options.MaxAudioChannels.Value, currentValue); } - int audioBitrate = GetAudioBitrate(playlistItem.SubProtocol, options.GetMaxBitrate(), playlistItem.TargetAudioChannels, playlistItem.TargetAudioCodec, audioStream); + int audioBitrate = GetAudioBitrate(playlistItem.SubProtocol, options.GetMaxBitrate(false), playlistItem.TargetAudioChannels, playlistItem.TargetAudioCodec, audioStream); playlistItem.AudioBitrate = Math.Min(playlistItem.AudioBitrate ?? audioBitrate, audioBitrate); - int? maxBitrateSetting = options.GetMaxBitrate(); + int? maxBitrateSetting = options.GetMaxBitrate(false); // Honor max rate if (maxBitrateSetting.HasValue) { @@ -595,19 +602,16 @@ namespace MediaBrowser.Model.Dlna private int GetAudioBitrate(string subProtocol, int? maxTotalBitrate, int? targetAudioChannels, string targetAudioCodec, MediaStream audioStream) { - var defaultBitrate = 128000; - if (StringHelper.EqualsIgnoreCase(targetAudioCodec, "ac3")) - { - defaultBitrate = 192000; - } - if (!string.IsNullOrEmpty(targetAudioCodec) && audioStream != null && StringHelper.EqualsIgnoreCase(audioStream.Codec, targetAudioCodec)) + var defaultBitrate = audioStream.BitRate ?? 192000; + // Reduce the bitrate if we're downmixing + if (targetAudioChannels.HasValue && audioStream != null && audioStream.Channels.HasValue && targetAudioChannels.Value < audioStream.Channels.Value) { - defaultBitrate = audioStream.BitRate ?? defaultBitrate; + defaultBitrate = StringHelper.EqualsIgnoreCase(targetAudioCodec, "ac3") ? 192000 : 128000; } if (targetAudioChannels.HasValue) { - if (targetAudioChannels.Value >= 5 && (maxTotalBitrate ?? 0) >= 1500000) + if (targetAudioChannels.Value >= 5 && (maxTotalBitrate ?? 0) >= 1200000) { if (StringHelper.EqualsIgnoreCase(targetAudioCodec, "ac3")) { diff --git a/MediaBrowser.Model/Dlna/StreamInfo.cs b/MediaBrowser.Model/Dlna/StreamInfo.cs index 02239aa48..ac024f00b 100644 --- a/MediaBrowser.Model/Dlna/StreamInfo.cs +++ b/MediaBrowser.Model/Dlna/StreamInfo.cs @@ -36,7 +36,6 @@ namespace MediaBrowser.Model.Dlna public string VideoProfile { get; set; } public bool CopyTimestamps { get; set; } - public bool ForceLiveStream { get; set; } public bool EnableSubtitlesInManifest { get; set; } public string[] AudioCodecs { get; set; } @@ -216,7 +215,7 @@ namespace MediaBrowser.Model.Dlna list.Add(new NameValuePair("MaxWidth", item.MaxWidth.HasValue ? StringHelper.ToStringCultureInvariant(item.MaxWidth.Value) : string.Empty)); list.Add(new NameValuePair("MaxHeight", item.MaxHeight.HasValue ? StringHelper.ToStringCultureInvariant(item.MaxHeight.Value) : string.Empty)); - if (StringHelper.EqualsIgnoreCase(item.SubProtocol, "hls") && !item.ForceLiveStream) + if (StringHelper.EqualsIgnoreCase(item.SubProtocol, "hls")) { list.Add(new NameValuePair("StartTimeTicks", string.Empty)); } @@ -246,7 +245,6 @@ namespace MediaBrowser.Model.Dlna } list.Add(new NameValuePair("CopyTimestamps", item.CopyTimestamps.ToString().ToLower())); - list.Add(new NameValuePair("ForceLiveStream", item.ForceLiveStream.ToString().ToLower())); list.Add(new NameValuePair("SubtitleMethod", item.SubtitleStreamIndex.HasValue && item.SubtitleDeliveryMethod != SubtitleDeliveryMethod.External ? item.SubtitleDeliveryMethod.ToString() : string.Empty)); list.Add(new NameValuePair("TranscodingMaxAudioChannels", item.TranscodingMaxAudioChannels.HasValue ? StringHelper.ToStringCultureInvariant(item.TranscodingMaxAudioChannels.Value) : string.Empty)); diff --git a/MediaBrowser.Model/Dlna/TranscodingProfile.cs b/MediaBrowser.Model/Dlna/TranscodingProfile.cs index 19caf85eb..beb83b053 100644 --- a/MediaBrowser.Model/Dlna/TranscodingProfile.cs +++ b/MediaBrowser.Model/Dlna/TranscodingProfile.cs @@ -35,9 +35,6 @@ namespace MediaBrowser.Model.Dlna [XmlAttribute("context")] public EncodingContext Context { get; set; } - [XmlAttribute("forceLiveStream")] - public bool ForceLiveStream { get; set; } - [XmlAttribute("enableSubtitlesInManifest")] public bool EnableSubtitlesInManifest { get; set; } diff --git a/MediaBrowser.Model/Net/MimeTypes.cs b/MediaBrowser.Model/Net/MimeTypes.cs index a13814538..8bf0703be 100644 --- a/MediaBrowser.Model/Net/MimeTypes.cs +++ b/MediaBrowser.Model/Net/MimeTypes.cs @@ -241,7 +241,7 @@ namespace MediaBrowser.Model.Net } if (StringHelper.EqualsIgnoreCase(ext, ".opus")) { - return "audio/opus"; + return "audio/ogg"; } // Playlists diff --git a/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs b/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs index 6c7918988..027341ee6 100644 --- a/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs @@ -167,10 +167,13 @@ namespace MediaBrowser.Providers.MediaInfo public bool HasChanged(IHasMetadata item, IDirectoryService directoryService) { - var file = directoryService.GetFile(item.Path); - if (file != null && file.LastWriteTimeUtc != item.DateModified) + if (item.EnableRefreshOnDateModifiedChange && !string.IsNullOrWhiteSpace(item.Path) && item.LocationType == LocationType.FileSystem) { - return true; + var file = directoryService.GetFile(item.Path); + if (file != null && file.LastWriteTimeUtc != item.DateModified) + { + return true; + } } return false; diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs b/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs index 0df8b6c4b..d255110fb 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs @@ -171,7 +171,7 @@ namespace MediaBrowser.Providers.MediaInfo public bool HasChanged(IHasMetadata item, IDirectoryService directoryService) { - if (item.EnableRefreshOnDateModifiedChange && !string.IsNullOrWhiteSpace(item.Path)) + if (item.EnableRefreshOnDateModifiedChange && !string.IsNullOrWhiteSpace(item.Path) && item.LocationType == LocationType.FileSystem) { var file = directoryService.GetFile(item.Path); if (file != null && file.LastWriteTimeUtc != item.DateModified) diff --git a/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs b/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs index 280e92beb..2ad02da2e 100644 --- a/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs @@ -194,7 +194,7 @@ namespace MediaBrowser.Providers.MediaInfo public bool HasChanged(IHasMetadata item, IDirectoryService directoryService) { - if (item.EnableRefreshOnDateModifiedChange) + if (item.EnableRefreshOnDateModifiedChange && !string.IsNullOrWhiteSpace(item.Path) && item.LocationType == LocationType.FileSystem) { var file = directoryService.GetFile(item.Path); if (file != null && file.LastWriteTimeUtc != item.DateModified) diff --git a/MediaBrowser.Providers/Photos/PhotoProvider.cs b/MediaBrowser.Providers/Photos/PhotoProvider.cs index 619b72636..c48c3d09b 100644 --- a/MediaBrowser.Providers/Photos/PhotoProvider.cs +++ b/MediaBrowser.Providers/Photos/PhotoProvider.cs @@ -154,10 +154,13 @@ namespace MediaBrowser.Providers.Photos public bool HasChanged(IHasMetadata item, IDirectoryService directoryService) { - var file = directoryService.GetFile(item.Path); - if (file != null && file.LastWriteTimeUtc != item.DateModified) + if (item.EnableRefreshOnDateModifiedChange && !string.IsNullOrWhiteSpace(item.Path) && item.LocationType == LocationType.FileSystem) { - return true; + var file = directoryService.GetFile(item.Path); + if (file != null && file.LastWriteTimeUtc != item.DateModified) + { + return true; + } } return false; diff --git a/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs b/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs index ea9e58ee4..7ed4dc71e 100644 --- a/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs +++ b/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs @@ -172,27 +172,29 @@ namespace MediaBrowser.Server.Implementations.IO } } - public void Start() + private bool IsLibraryMonitorEnabaled(BaseItem item) { - if (EnableLibraryMonitor) + var options = LibraryManager.GetLibraryOptions(item); + + if (options != null && options.SchemaVersion >= 1) { - StartInternal(); + return options.EnableRealtimeMonitor; } + + return EnableLibraryMonitor; } - /// <summary> - /// Starts this instance. - /// </summary> - private void StartInternal() + public void Start() { LibraryManager.ItemAdded += LibraryManager_ItemAdded; LibraryManager.ItemRemoved += LibraryManager_ItemRemoved; - var pathsToWatch = new List<string> { LibraryManager.RootFolder.Path }; + var pathsToWatch = new List<string> { }; var paths = LibraryManager .RootFolder .Children + .Where(IsLibraryMonitorEnabaled) .OfType<Folder>() .SelectMany(f => f.PhysicalLocations) .Distinct(StringComparer.OrdinalIgnoreCase) @@ -213,6 +215,14 @@ namespace MediaBrowser.Server.Implementations.IO } } + private void StartWatching(BaseItem item) + { + if (IsLibraryMonitorEnabaled(item)) + { + StartWatchingPath(item.Path); + } + } + /// <summary> /// Handles the ItemRemoved event of the LibraryManager control. /// </summary> @@ -235,7 +245,7 @@ namespace MediaBrowser.Server.Implementations.IO { if (e.Item.GetParent() is AggregateFolder) { - StartWatchingPath(e.Item.Path); + StartWatching(e.Item); } } @@ -382,14 +392,6 @@ namespace MediaBrowser.Server.Implementations.IO Logger.ErrorException("Error in Directory watcher for: " + dw.Path, ex); DisposeWatcher(dw); - - if (ConfigurationManager.Configuration.EnableLibraryMonitor == AutoOnOff.Auto) - { - Logger.Info("Disabling realtime monitor to prevent future instability"); - - ConfigurationManager.Configuration.EnableLibraryMonitor = AutoOnOff.Disabled; - Stop(); - } } /// <summary> @@ -420,8 +422,8 @@ namespace MediaBrowser.Server.Implementations.IO var filename = Path.GetFileName(path); - var monitorPath = !string.IsNullOrEmpty(filename) && - !_alwaysIgnoreFiles.Contains(filename, StringComparer.OrdinalIgnoreCase) && + var monitorPath = !string.IsNullOrEmpty(filename) && + !_alwaysIgnoreFiles.Contains(filename, StringComparer.OrdinalIgnoreCase) && !_alwaysIgnoreExtensions.Contains(Path.GetExtension(path) ?? string.Empty, StringComparer.OrdinalIgnoreCase); // Ignore certain files diff --git a/MediaBrowser.Server.Implementations/MediaEncoder/EncodingManager.cs b/MediaBrowser.Server.Implementations/MediaEncoder/EncodingManager.cs index 7f709d084..46ba7d2e7 100644 --- a/MediaBrowser.Server.Implementations/MediaEncoder/EncodingManager.cs +++ b/MediaBrowser.Server.Implementations/MediaEncoder/EncodingManager.cs @@ -123,7 +123,7 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder { if (extractImages) { - if (video.VideoType == VideoType.HdDvd || video.VideoType == VideoType.Iso || video.VideoType == VideoType.BluRay) + if (video.VideoType == VideoType.HdDvd || video.VideoType == VideoType.Iso || video.VideoType == VideoType.BluRay || video.VideoType == VideoType.Dvd) { continue; } diff --git a/MediaBrowser.Server.Implementations/Persistence/CleanDatabaseScheduledTask.cs b/MediaBrowser.Server.Implementations/Persistence/CleanDatabaseScheduledTask.cs index bf2afb5ac..c1394ee1c 100644 --- a/MediaBrowser.Server.Implementations/Persistence/CleanDatabaseScheduledTask.cs +++ b/MediaBrowser.Server.Implementations/Persistence/CleanDatabaseScheduledTask.cs @@ -313,8 +313,7 @@ namespace MediaBrowser.Server.Implementations.Persistence if (Folder.IsPathOffline(path)) { - libraryItem.IsOffline = true; - await libraryItem.UpdateToRepository(ItemUpdateType.None, cancellationToken).ConfigureAwait(false); + await libraryItem.UpdateIsOffline(true).ConfigureAwait(false); continue; } diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index b9befb531..5c94d589d 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -211,7 +211,6 @@ namespace MediaBrowser.Server.Implementations.Persistence _connection.AddColumn(Logger, "TypedBaseItems", "ProductionYear", "INT"); _connection.AddColumn(Logger, "TypedBaseItems", "ParentId", "GUID"); _connection.AddColumn(Logger, "TypedBaseItems", "Genres", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "ParentalRatingValue", "INT"); _connection.AddColumn(Logger, "TypedBaseItems", "SchemaVersion", "INT"); _connection.AddColumn(Logger, "TypedBaseItems", "SortName", "Text"); _connection.AddColumn(Logger, "TypedBaseItems", "RunTimeTicks", "BIGINT"); @@ -488,7 +487,6 @@ namespace MediaBrowser.Server.Implementations.Persistence "ProductionYear", "ParentId", "Genres", - "ParentalRatingValue", "InheritedParentalRatingValue", "SchemaVersion", "SortName", @@ -795,7 +793,6 @@ namespace MediaBrowser.Server.Implementations.Persistence } _saveItemCommand.GetParameter(index++).Value = string.Join("|", item.Genres.ToArray()); - _saveItemCommand.GetParameter(index++).Value = item.GetParentalRatingValue() ?? 0; _saveItemCommand.GetParameter(index++).Value = item.GetInheritedParentalRatingValue() ?? 0; _saveItemCommand.GetParameter(index++).Value = LatestSchemaVersion; diff --git a/MediaBrowser.Server.Implementations/Sync/AppSyncProvider.cs b/MediaBrowser.Server.Implementations/Sync/AppSyncProvider.cs index 03485012f..408ec717e 100644 --- a/MediaBrowser.Server.Implementations/Sync/AppSyncProvider.cs +++ b/MediaBrowser.Server.Implementations/Sync/AppSyncProvider.cs @@ -85,6 +85,11 @@ namespace MediaBrowser.Server.Implementations.Sync { Name = "Low", Id = "low" + }, + new SyncQualityOption + { + Name = "Custom", + Id = "custom" } }; } diff --git a/MediaBrowser.Server.Mono/Native/BaseMonoApp.cs b/MediaBrowser.Server.Mono/Native/BaseMonoApp.cs index 4011fa3de..faf3ba37e 100644 --- a/MediaBrowser.Server.Mono/Native/BaseMonoApp.cs +++ b/MediaBrowser.Server.Mono/Native/BaseMonoApp.cs @@ -132,7 +132,7 @@ namespace MediaBrowser.Server.Mono.Native { get { - return Environment.OperatingSystem != Startup.Common.OperatingSystem.Osx; + return Environment.OperatingSystem != Startup.Common.OperatingSystem.Osx; } } @@ -187,7 +187,7 @@ namespace MediaBrowser.Server.Mono.Native { info.SystemArchitecture = Architecture.X64; } - else + else { info.SystemArchitecture = Architecture.X86; } @@ -273,32 +273,11 @@ namespace MediaBrowser.Server.Mono.Native break; } - info.DownloadUrls = GetDownloadUrls(environment); + // No version available - user requirement + info.DownloadUrls = new string[] { }; return info; } - - private static string[] GetDownloadUrls(NativeEnvironment environment) - { - switch (environment.OperatingSystem) - { - case OperatingSystem.Linux: - - switch (environment.SystemArchitecture) - { - case Architecture.X64: - return new[] - { - "https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/linux/ffmpeg-git-20160215-64bit-static.7z" - }; - } - break; - } - - // No version available - return new string[] { }; - } - } public class NullPowerManagement : IPowerManagement diff --git a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs index 8516e54ee..9c5015b0e 100644 --- a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs +++ b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs @@ -386,8 +386,6 @@ namespace MediaBrowser.Server.Startup.Common new MovieDbEpisodeProviderMigration(ServerConfigurationManager), new DbMigration(ServerConfigurationManager, TaskManager), new UpdateLevelMigration(ServerConfigurationManager, this, HttpClient, JsonSerializer, _releaseAssetFilename), - new FolderViewSettingMigration(ServerConfigurationManager, UserManager), - new CollectionGroupingMigration(ServerConfigurationManager, UserManager), new CollectionsViewMigration(ServerConfigurationManager, UserManager) }; diff --git a/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj b/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj index 979a3a357..5ee7d49e8 100644 --- a/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj +++ b/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj @@ -70,9 +70,7 @@ <Compile Include="FFMpeg\FFMpegInfo.cs" /> <Compile Include="INativeApp.cs" /> <Compile Include="MbLinkShortcutHandler.cs" /> - <Compile Include="Migrations\CollectionGroupingMigration.cs" /> <Compile Include="Migrations\CollectionsViewMigration.cs" /> - <Compile Include="Migrations\FolderViewSettingMigration.cs" /> <Compile Include="Migrations\IVersionMigration.cs" /> <Compile Include="Migrations\DbMigration.cs" /> <Compile Include="Migrations\MovieDbEpisodeProviderMigration.cs" /> diff --git a/MediaBrowser.Server.Startup.Common/Migrations/CollectionGroupingMigration.cs b/MediaBrowser.Server.Startup.Common/Migrations/CollectionGroupingMigration.cs deleted file mode 100644 index 5041c49b8..000000000 --- a/MediaBrowser.Server.Startup.Common/Migrations/CollectionGroupingMigration.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System.Linq; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Library; - -namespace MediaBrowser.Server.Startup.Common.Migrations -{ - public class CollectionGroupingMigration : IVersionMigration - { - private readonly IServerConfigurationManager _config; - private readonly IUserManager _userManager; - - public CollectionGroupingMigration(IServerConfigurationManager config, IUserManager userManager) - { - _config = config; - _userManager = userManager; - } - - public void Run() - { - var migrationKey = this.GetType().Name; - var migrationKeyList = _config.Configuration.Migrations.ToList(); - - if (!migrationKeyList.Contains(migrationKey)) - { - if (_config.Configuration.IsStartupWizardCompleted) - { - if (_userManager.Users.Any(i => i.Configuration.GroupMoviesIntoBoxSets)) - { - _config.Configuration.EnableGroupingIntoCollections = true; - } - } - - migrationKeyList.Add(migrationKey); - _config.Configuration.Migrations = migrationKeyList.ToArray(); - _config.SaveConfiguration(); - } - - } - } -} diff --git a/MediaBrowser.Server.Startup.Common/Migrations/FolderViewSettingMigration.cs b/MediaBrowser.Server.Startup.Common/Migrations/FolderViewSettingMigration.cs deleted file mode 100644 index 12054864b..000000000 --- a/MediaBrowser.Server.Startup.Common/Migrations/FolderViewSettingMigration.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System.Linq; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Library; - -namespace MediaBrowser.Server.Startup.Common.Migrations -{ - public class FolderViewSettingMigration : IVersionMigration - { - private readonly IServerConfigurationManager _config; - private readonly IUserManager _userManager; - - public FolderViewSettingMigration(IServerConfigurationManager config, IUserManager userManager) - { - _config = config; - _userManager = userManager; - } - - public void Run() - { - var migrationKey = this.GetType().Name; - var migrationKeyList = _config.Configuration.Migrations.ToList(); - - if (!migrationKeyList.Contains(migrationKey)) - { - if (_config.Configuration.IsStartupWizardCompleted) - { - if (_userManager.Users.Any(i => i.Configuration.DisplayFoldersView)) - { - _config.Configuration.EnableFolderView = true; - } - } - - migrationKeyList.Add(migrationKey); - _config.Configuration.Migrations = migrationKeyList.ToArray(); - _config.SaveConfiguration(); - } - - } - } -} diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj index b2eb34526..5b66c27f4 100644 --- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj +++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj @@ -1001,9 +1001,6 @@ <Content Include="dashboard-ui\scripts\livetvsuggested.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\scripts\sync.js">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
<Content Include="dashboard-ui\scripts\tvupcoming.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
diff --git a/Nuget/MediaBrowser.Common.Internal.nuspec b/Nuget/MediaBrowser.Common.Internal.nuspec index e96a77e64..d1c4c0b44 100644 --- a/Nuget/MediaBrowser.Common.Internal.nuspec +++ b/Nuget/MediaBrowser.Common.Internal.nuspec @@ -2,7 +2,7 @@ <package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd"> <metadata> <id>MediaBrowser.Common.Internal</id> - <version>3.0.654</version> + <version>3.0.655</version> <title>MediaBrowser.Common.Internal</title> <authors>Luke</authors> <owners>ebr,Luke,scottisafool</owners> @@ -12,7 +12,7 @@ <description>Contains common components shared by Emby Theater and Emby Server. Not intended for plugin developer consumption.</description> <copyright>Copyright © Emby 2013</copyright> <dependencies> - <dependency id="MediaBrowser.Common" version="3.0.654" /> + <dependency id="MediaBrowser.Common" version="3.0.655" /> <dependency id="NLog" version="4.3.6" /> <dependency id="SimpleInjector" version="3.2.0" /> </dependencies> diff --git a/Nuget/MediaBrowser.Common.nuspec b/Nuget/MediaBrowser.Common.nuspec index ada11fd45..ffee84de2 100644 --- a/Nuget/MediaBrowser.Common.nuspec +++ b/Nuget/MediaBrowser.Common.nuspec @@ -2,7 +2,7 @@ <package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd"> <metadata> <id>MediaBrowser.Common</id> - <version>3.0.654</version> + <version>3.0.655</version> <title>MediaBrowser.Common</title> <authors>Emby Team</authors> <owners>ebr,Luke,scottisafool</owners> diff --git a/Nuget/MediaBrowser.Server.Core.nuspec b/Nuget/MediaBrowser.Server.Core.nuspec index f4a79f454..73c51ca35 100644 --- a/Nuget/MediaBrowser.Server.Core.nuspec +++ b/Nuget/MediaBrowser.Server.Core.nuspec @@ -2,7 +2,7 @@ <package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"> <metadata> <id>MediaBrowser.Server.Core</id> - <version>3.0.654</version> + <version>3.0.655</version> <title>Media Browser.Server.Core</title> <authors>Emby Team</authors> <owners>ebr,Luke,scottisafool</owners> @@ -12,7 +12,7 @@ <description>Contains core components required to build plugins for Emby Server.</description> <copyright>Copyright © Emby 2013</copyright> <dependencies> - <dependency id="MediaBrowser.Common" version="3.0.654" /> + <dependency id="MediaBrowser.Common" version="3.0.655" /> <dependency id="Interfaces.IO" version="1.0.0.5" /> </dependencies> </metadata> |
