diff --git a/Emby.Drawing/ImageProcessor.cs b/Emby.Drawing/ImageProcessor.cs index 231bfa2b47..3e5dca9b7f 100644 --- a/Emby.Drawing/ImageProcessor.cs +++ b/Emby.Drawing/ImageProcessor.cs @@ -1,5 +1,4 @@ -using Emby.Drawing.Common; -using MediaBrowser.Common.Extensions; +using MediaBrowser.Common.Extensions; using MediaBrowser.Common.IO; using MediaBrowser.Controller; using MediaBrowser.Controller.Drawing; @@ -17,6 +16,7 @@ using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; +using Emby.Drawing.Common; namespace Emby.Drawing { @@ -215,12 +215,12 @@ namespace Emby.Drawing { CheckDisposed(); - if (!File.Exists(cacheFilePath)) + if (!_fileSystem.FileExists(cacheFilePath)) { var newWidth = Convert.ToInt32(newSize.Width); var newHeight = Convert.ToInt32(newSize.Height); - Directory.CreateDirectory(Path.GetDirectoryName(cacheFilePath)); + _fileSystem.CreateDirectory(Path.GetDirectoryName(cacheFilePath)); await _imageProcessingSemaphore.WaitAsync().ConfigureAwait(false); @@ -270,7 +270,7 @@ namespace Emby.Drawing await semaphore.WaitAsync().ConfigureAwait(false); // Check again in case of contention - if (File.Exists(croppedImagePath)) + if (_fileSystem.FileExists(croppedImagePath)) { semaphore.Release(); return GetResult(croppedImagePath); @@ -280,7 +280,7 @@ namespace Emby.Drawing try { - Directory.CreateDirectory(Path.GetDirectoryName(croppedImagePath)); + _fileSystem.CreateDirectory(Path.GetDirectoryName(croppedImagePath)); await _imageProcessingSemaphore.WaitAsync().ConfigureAwait(false); imageProcessingLockTaken = true; @@ -366,7 +366,7 @@ namespace Emby.Drawing /// ImageSize. public ImageSize GetImageSize(string path) { - return GetImageSize(path, File.GetLastWriteTimeUtc(path), false); + return GetImageSize(path, _fileSystem.GetLastWriteTimeUtc(path), false); } public ImageSize GetImageSize(ItemImageInfo info) @@ -399,6 +399,8 @@ namespace Emby.Drawing { size = GetImageSizeInternal(path, allowSlowMethod); + StartSaveImageSizeTimer(); + _cachedImagedSizes.AddOrUpdate(cacheHash, size, (keyName, oldValue) => size); } @@ -413,28 +415,26 @@ namespace Emby.Drawing /// ImageSize. private ImageSize GetImageSizeInternal(string path, bool allowSlowMethod) { - ImageSize size; - try { - size = ImageHeader.GetDimensions(path, _logger, _fileSystem); + using (var file = TagLib.File.Create(path)) + { + var image = file as TagLib.Image.File; + + var properties = image.Properties; + + return new ImageSize + { + Height = properties.PhotoHeight, + Width = properties.PhotoWidth + }; + } } catch { - if (!allowSlowMethod) - { - throw; - } - //_logger.Info("Failed to read image header for {0}. Doing it the slow way.", path); - - CheckDisposed(); - - size = _imageEncoder.GetImageSize(path); } - StartSaveImageSizeTimer(); - - return size; + return ImageHeader.GetDimensions(path, _logger, _fileSystem); } private readonly Timer _saveImageSizeTimer; @@ -452,7 +452,7 @@ namespace Emby.Drawing try { var path = ImageSizeFile; - Directory.CreateDirectory(Path.GetDirectoryName(path)); + _fileSystem.CreateDirectory(Path.GetDirectoryName(path)); _jsonSerializer.SerializeToFile(_cachedImagedSizes, path); } catch (Exception ex) @@ -624,7 +624,7 @@ namespace Emby.Drawing await semaphore.WaitAsync().ConfigureAwait(false); // Check again in case of contention - if (File.Exists(enhancedImagePath)) + if (_fileSystem.FileExists(enhancedImagePath)) { semaphore.Release(); return enhancedImagePath; @@ -634,7 +634,7 @@ namespace Emby.Drawing try { - Directory.CreateDirectory(Path.GetDirectoryName(enhancedImagePath)); + _fileSystem.CreateDirectory(Path.GetDirectoryName(enhancedImagePath)); await _imageProcessingSemaphore.WaitAsync().ConfigureAwait(false); @@ -819,4 +819,4 @@ namespace Emby.Drawing } } } -} +} \ No newline at end of file diff --git a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs index e4f00e2a08..a9a9610a97 100644 --- a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs @@ -23,7 +23,8 @@ namespace MediaBrowser.Api.Playback.Hls /// public abstract class BaseHlsService : BaseStreamingService { - protected BaseHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IZipClient zipClient, IJsonSerializer jsonSerializer) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, dlnaManager, subtitleEncoder, deviceManager, mediaSourceManager, zipClient, jsonSerializer) + protected BaseHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IZipClient zipClient, IJsonSerializer jsonSerializer) + : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, dlnaManager, subtitleEncoder, deviceManager, mediaSourceManager, zipClient, jsonSerializer) { } @@ -90,12 +91,12 @@ namespace MediaBrowser.Api.Playback.Hls TranscodingJob job = null; var playlist = state.OutputFilePath; - if (!File.Exists(playlist)) + if (!FileSystem.FileExists(playlist)) { await ApiEntryPoint.Instance.TranscodingStartLock.WaitAsync(cancellationTokenSource.Token).ConfigureAwait(false); try { - if (!File.Exists(playlist)) + if (!FileSystem.FileExists(playlist)) { // If the playlist doesn't already exist, startup ffmpeg try @@ -150,7 +151,7 @@ namespace MediaBrowser.Api.Playback.Hls { ApiEntryPoint.Instance.OnTranscodeEndRequest(job); } - + return ResultFactory.GetResult(playlistText, MimeTypes.GetMimeType("playlist.m3u8"), new Dictionary()); } @@ -317,4 +318,4 @@ namespace MediaBrowser.Api.Playback.Hls return false; } } -} +} \ No newline at end of file diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs index 7b2844cd4b..cb49e65c7e 100644 --- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs @@ -165,7 +165,7 @@ namespace MediaBrowser.Api.Playback.Hls TranscodingJob job = null; - if (File.Exists(segmentPath)) + if (FileSystem.FileExists(segmentPath)) { job = ApiEntryPoint.Instance.OnTranscodeBeginRequest(playlistPath, TranscodingJobType); return await GetSegmentResult(state, playlistPath, segmentPath, requestedIndex, job, cancellationToken).ConfigureAwait(false); @@ -174,7 +174,7 @@ namespace MediaBrowser.Api.Playback.Hls await ApiEntryPoint.Instance.TranscodingStartLock.WaitAsync(cancellationTokenSource.Token).ConfigureAwait(false); try { - if (File.Exists(segmentPath)) + if (FileSystem.FileExists(segmentPath)) { job = ApiEntryPoint.Instance.OnTranscodeBeginRequest(playlistPath, TranscodingJobType); return await GetSegmentResult(state, playlistPath, segmentPath, requestedIndex, job, cancellationToken).ConfigureAwait(false); @@ -386,8 +386,7 @@ namespace MediaBrowser.Api.Playback.Hls try { - return new DirectoryInfo(folder) - .EnumerateFiles("*", SearchOption.TopDirectoryOnly) + return fileSystem.GetFiles(folder) .Where(i => string.Equals(i.Extension, segmentExtension, StringComparison.OrdinalIgnoreCase) && Path.GetFileNameWithoutExtension(i.Name).StartsWith(filePrefix, StringComparison.OrdinalIgnoreCase)) .OrderByDescending(fileSystem.GetLastWriteTimeUtc) .FirstOrDefault(); @@ -432,7 +431,7 @@ namespace MediaBrowser.Api.Playback.Hls CancellationToken cancellationToken) { // If all transcoding has completed, just return immediately - if (transcodingJob != null && transcodingJob.HasExited && File.Exists(segmentPath)) + if (transcodingJob != null && transcodingJob.HasExited && FileSystem.FileExists(segmentPath)) { return GetSegmentResult(state, segmentPath, segmentIndex, transcodingJob); } @@ -452,7 +451,7 @@ namespace MediaBrowser.Api.Playback.Hls // If it appears in the playlist, it's done if (text.IndexOf(segmentFilename, StringComparison.OrdinalIgnoreCase) != -1) { - if (File.Exists(segmentPath)) + if (FileSystem.FileExists(segmentPath)) { return GetSegmentResult(state, segmentPath, segmentIndex, transcodingJob); } @@ -989,4 +988,4 @@ namespace MediaBrowser.Api.Playback.Hls return base.CanStreamCopyVideo(request, videoStream); } } -} +} \ No newline at end of file diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 4fcc71f975..6f25d4b6e6 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -97,6 +97,22 @@ namespace MediaBrowser.MediaEncoding.Encoder FFMpegPath = ffMpegPath; } + public void SetAvailableEncoders(List list) + { + + } + + private List _decoders = new List(); + public void SetAvailableDecoders(List list) + { + _decoders = list.ToList(); + } + + public bool SupportsDecoder(string decoder) + { + return _decoders.Contains(decoder, StringComparer.OrdinalIgnoreCase); + } + /// /// Gets the encoder path. /// @@ -330,7 +346,7 @@ namespace MediaBrowser.MediaEncoding.Encoder EnableRaisingEvents = true }; - _logger.Debug("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments); + _logger.Info("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments); using (process) { @@ -356,7 +372,7 @@ namespace MediaBrowser.MediaEncoding.Encoder process.WaitForExit(); - _logger.Debug("Keyframe extraction took {0} seconds", (DateTime.UtcNow - start).TotalSeconds); + _logger.Info("Keyframe extraction took {0} seconds", (DateTime.UtcNow - start).TotalSeconds); //_logger.Debug("Found keyframes {0}", string.Join(",", lines.ToArray())); return lines; } @@ -483,9 +499,6 @@ namespace MediaBrowser.MediaEncoding.Encoder } } - // TODO: Output in webp for smaller sizes - // -f image2 -f webp - // Use ffmpeg to sample 100 (we can drop this if required using thumbnail=50 for 50 frames) frames and pick the best thumbnail. Have a fall back just in case. var args = useIFrame ? string.Format("-i {0} -threads 1 -v quiet -vframes 1 -vf \"{2},thumbnail=30\" -f image2 \"{1}\"", inputPath, "-", vf) : string.Format("-i {0} -threads 1 -v quiet -vframes 1 -vf \"{2}\" -f image2 \"{1}\"", inputPath, "-", vf); @@ -605,7 +618,7 @@ namespace MediaBrowser.MediaEncoding.Encoder vf += string.Format(",scale=min(iw\\,{0}):trunc(ow/dar/2)*2", maxWidthParam); } - Directory.CreateDirectory(targetDirectory); + FileSystem.CreateDirectory(targetDirectory); var outputPath = Path.Combine(targetDirectory, filenamePrefix + "%05d.jpg"); var args = string.Format("-i {0} -threads 1 -v quiet -vf \"{2}\" -f image2 \"{1}\"", inputArgument, outputPath, vf); @@ -879,4 +892,4 @@ namespace MediaBrowser.MediaEncoding.Encoder } } } -} +} \ No newline at end of file diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs index 87b5e4fd71..4ec6886117 100644 --- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs +++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs @@ -44,12 +44,6 @@ namespace MediaBrowser.Model.Configuration /// true if [use HTTPS]; otherwise, false. public bool EnableHttps { get; set; } - /// - /// Gets or sets a value indicating whether [enable user specific user views]. - /// - /// true if [enable user specific user views]; otherwise, false. - public bool EnableUserSpecificUserViews { get; set; } - /// /// Gets or sets the value pointing to the file system where the ssl certiifcate is located.. /// @@ -103,7 +97,13 @@ namespace MediaBrowser.Model.Configuration /// /// true if [disable startup scan]; otherwise, false. public bool DisableStartupScan { get; set; } - + + /// + /// Gets or sets a value indicating whether [enable user views]. + /// + /// true if [enable user views]; otherwise, false. + public bool EnableUserViews { get; set; } + /// /// Gets or sets a value indicating whether [enable library metadata sub folder]. /// @@ -223,7 +223,7 @@ namespace MediaBrowser.Model.Configuration public bool EnableWindowsShortcuts { get; set; } public bool EnableVideoFrameByFrameAnalysis { get; set; } - + /// /// Initializes a new instance of the class. /// @@ -274,11 +274,7 @@ namespace MediaBrowser.Model.Configuration InsecureApps9 = new[] { - "Chromecast", - "iOS", "Unknown app", - "iPad", - "iPhone", "Windows Phone" }; @@ -581,4 +577,4 @@ namespace MediaBrowser.Model.Configuration }; } } -} +} \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Devices/DeviceManager.cs b/MediaBrowser.Server.Implementations/Devices/DeviceManager.cs index 0173f27847..548a2222a9 100644 --- a/MediaBrowser.Server.Implementations/Devices/DeviceManager.cs +++ b/MediaBrowser.Server.Implementations/Devices/DeviceManager.cs @@ -157,7 +157,7 @@ namespace MediaBrowser.Server.Implementations.Devices _libraryMonitor.ReportFileSystemChangeBeginning(path); - Directory.CreateDirectory(Path.GetDirectoryName(path)); + _fileSystem.CreateDirectory(Path.GetDirectoryName(path)); try { @@ -290,4 +290,4 @@ namespace MediaBrowser.Server.Implementations.Devices return config.GetConfiguration("devices"); } } -} +} \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs b/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs index 63067bf5a5..8ef7e94c20 100644 --- a/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs +++ b/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs @@ -15,6 +15,7 @@ using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Common.IO; namespace MediaBrowser.Server.Implementations.Library { @@ -24,17 +25,19 @@ namespace MediaBrowser.Server.Implementations.Library private readonly IUserManager _userManager; private readonly ILibraryManager _libraryManager; private readonly IJsonSerializer _jsonSerializer; + private readonly IFileSystem _fileSystem; private IMediaSourceProvider[] _providers; private readonly ILogger _logger; - public MediaSourceManager(IItemRepository itemRepo, IUserManager userManager, ILibraryManager libraryManager, ILogger logger, IJsonSerializer jsonSerializer) + public MediaSourceManager(IItemRepository itemRepo, IUserManager userManager, ILibraryManager libraryManager, ILogger logger, IJsonSerializer jsonSerializer, IFileSystem fileSystem) { _itemRepo = itemRepo; _userManager = userManager; _libraryManager = libraryManager; _logger = logger; _jsonSerializer = jsonSerializer; + _fileSystem = fileSystem; } public void AddParts(IEnumerable providers) @@ -170,7 +173,7 @@ namespace MediaBrowser.Server.Implementations.Library if (source.Protocol == MediaProtocol.File) { // TODO: Path substitution - if (!File.Exists(source.Path)) + if (!_fileSystem.FileExists(source.Path)) { source.SupportsDirectStream = false; } @@ -582,4 +585,4 @@ namespace MediaBrowser.Server.Implementations.Library public MediaSourceInfo MediaSource; } } -} +} \ No newline at end of file