From a9a85f251e77cf1670e69733e1d7b5ab9116aaaf Mon Sep 17 00:00:00 2001 From: Andrew Mahone Date: Fri, 18 Oct 2019 07:56:53 -0400 Subject: Instantiate AttachmentExtractor in ApplicationHost. --- Emby.Server.Implementations/ApplicationHost.cs | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'Emby.Server.Implementations/ApplicationHost.cs') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 04904fc4a..bcd99ffe4 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -282,6 +282,8 @@ namespace Emby.Server.Implementations private ISubtitleEncoder SubtitleEncoder { get; set; } + private IAttachmentExtractor AttachmentExtractor { get; set; } + private ISessionManager SessionManager { get; set; } private ILiveTvManager LiveTvManager { get; set; } @@ -904,6 +906,10 @@ namespace Emby.Server.Implementations serviceCollection.AddSingleton(typeof(IResourceFileManager), typeof(ResourceFileManager)); + AttachmentExtractor = new MediaBrowser.MediaEncoding.Attachments.AttachmentExtractor(LibraryManager, LoggerFactory, ApplicationPaths, FileSystemManager, MediaEncoder, MediaSourceManager, ProcessFactory); + + serviceCollection.AddSingleton(AttachmentExtractor); + _displayPreferencesRepository.Initialize(); var userDataRepo = new SqliteUserDataRepository(LoggerFactory, ApplicationPaths); -- cgit v1.2.3 From d33e0a4e2c59783c785c992ea0c3a31596ae3058 Mon Sep 17 00:00:00 2001 From: Andrew Mahone Date: Tue, 5 Nov 2019 08:17:34 -0500 Subject: Simplify AttachmentExtractor instantiation. Co-Authored-By: Bond-009 --- Emby.Server.Implementations/ApplicationHost.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Emby.Server.Implementations/ApplicationHost.cs') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index ac37cfe07..9330d5719 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -908,7 +908,7 @@ namespace Emby.Server.Implementations AttachmentExtractor = new MediaBrowser.MediaEncoding.Attachments.AttachmentExtractor(LibraryManager, LoggerFactory, ApplicationPaths, FileSystemManager, MediaEncoder, MediaSourceManager, ProcessFactory); - serviceCollection.AddSingleton(AttachmentExtractor); + serviceCollection.AddSingleton(); _displayPreferencesRepository.Initialize(); -- cgit v1.2.3 From 79bbf09ecba6d3c2ddb0955bdbd51164a6c7a236 Mon Sep 17 00:00:00 2001 From: Andrew Mahone Date: Wed, 6 Nov 2019 08:43:49 -0500 Subject: Revert "Simplify AttachmentExtractor instantiation." This reverts commit d33e0a4e2c59783c785c992ea0c3a31596ae3058. --- Emby.Server.Implementations/ApplicationHost.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Emby.Server.Implementations/ApplicationHost.cs') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 9330d5719..ac37cfe07 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -908,7 +908,7 @@ namespace Emby.Server.Implementations AttachmentExtractor = new MediaBrowser.MediaEncoding.Attachments.AttachmentExtractor(LibraryManager, LoggerFactory, ApplicationPaths, FileSystemManager, MediaEncoder, MediaSourceManager, ProcessFactory); - serviceCollection.AddSingleton(); + serviceCollection.AddSingleton(AttachmentExtractor); _displayPreferencesRepository.Initialize(); -- cgit v1.2.3 From c6855e6a2a347db17f2b8b2f18dd89d5b47a8816 Mon Sep 17 00:00:00 2001 From: Andrew Mahone Date: Thu, 7 Nov 2019 11:53:39 -0500 Subject: Simplify AttachmentExtractor instantiation. --- Emby.Server.Implementations/ApplicationHost.cs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'Emby.Server.Implementations/ApplicationHost.cs') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index ac37cfe07..97da5b437 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -282,8 +282,6 @@ namespace Emby.Server.Implementations private ISubtitleEncoder SubtitleEncoder { get; set; } - private IAttachmentExtractor AttachmentExtractor { get; set; } - private ISessionManager SessionManager { get; set; } private ILiveTvManager LiveTvManager { get; set; } @@ -906,9 +904,7 @@ namespace Emby.Server.Implementations serviceCollection.AddSingleton(typeof(IResourceFileManager), typeof(ResourceFileManager)); - AttachmentExtractor = new MediaBrowser.MediaEncoding.Attachments.AttachmentExtractor(LibraryManager, LoggerFactory, ApplicationPaths, FileSystemManager, MediaEncoder, MediaSourceManager, ProcessFactory); - - serviceCollection.AddSingleton(AttachmentExtractor); + serviceCollection.AddSingleton(typeof(MediaBrowser.Controller.MediaEncoding.IAttachmentExtractor),typeof(MediaBrowser.MediaEncoding.Attachments.AttachmentExtractor)); _displayPreferencesRepository.Initialize(); -- cgit v1.2.3 From cc5acf37f75d2c652d9cd855ebc34a1e7d414a9f Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sat, 26 Oct 2019 22:53:53 +0200 Subject: Make probesize and analyzeduration configurable and simplify circular dependencies Makes the probesize and analyzeduration configurable with env args. (`JELLYFIN_FFmpeg_probesize` and `FFmpeg_analyzeduration`) --- Emby.Server.Implementations/ApplicationHost.cs | 23 ++- .../ConfigurationOptions.cs | 9 +- .../Emby.Server.Implementations.csproj | 1 - .../HttpServer/HttpListenerHost.cs | 2 +- Jellyfin.Server/Program.cs | 7 +- MediaBrowser.Api/Playback/BaseStreamingService.cs | 11 +- MediaBrowser.Api/Playback/Hls/BaseHlsService.cs | 56 +++--- MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs | 9 +- MediaBrowser.Api/Playback/Hls/VideoHlsService.cs | 56 +++--- .../Playback/Progressive/AudioService.cs | 8 +- .../Progressive/BaseProgressiveStreamingService.cs | 11 +- .../Playback/Progressive/VideoService.cs | 8 +- MediaBrowser.Api/Playback/UniversalAudioService.cs | 63 +++---- MediaBrowser.Controller/Entities/Video.cs | 5 +- .../Extensions/ConfigurationExtensions.cs | 36 ++++ .../MediaBrowser.Controller.csproj | 4 + .../MediaEncoding/EncodingHelper.cs | 31 +++- .../MediaEncoding/IMediaEncoder.cs | 4 +- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 191 ++++++++++----------- .../Subtitles/ISubtitleWriter.cs | 2 +- MediaBrowser.MediaEncoding/Subtitles/JsonWriter.cs | 36 ++-- MediaBrowser.MediaEncoding/Subtitles/SrtWriter.cs | 17 +- .../Subtitles/SubtitleEncoder.cs | 103 ++++++----- MediaBrowser.MediaEncoding/Subtitles/TtmlWriter.cs | 7 - .../Configuration/ServerConfiguration.cs | 1 - MediaBrowser.Model/MediaInfo/SubtitleTrackInfo.cs | 7 +- .../MediaInfo/VideoImageProvider.cs | 6 +- .../Music/MusicBrainzAlbumProvider.cs | 2 +- 28 files changed, 396 insertions(+), 320 deletions(-) create mode 100644 MediaBrowser.Controller/Extensions/ConfigurationExtensions.cs (limited to 'Emby.Server.Implementations/ApplicationHost.cs') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index bd5e973c0..1c034ca79 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -886,16 +886,14 @@ namespace Emby.Server.Implementations serviceCollection.AddSingleton(ChapterManager); MediaEncoder = new MediaBrowser.MediaEncoding.Encoder.MediaEncoder( - LoggerFactory, - JsonSerializer, - StartupOptions.FFmpegPath, + LoggerFactory.CreateLogger(), ServerConfigurationManager, FileSystemManager, - () => SubtitleEncoder, - () => MediaSourceManager, ProcessFactory, - 5000, - LocalizationManager); + LocalizationManager, + () => SubtitleEncoder, + _configuration, + StartupOptions.FFmpegPath); serviceCollection.AddSingleton(MediaEncoder); EncodingManager = new MediaEncoder.EncodingManager(FileSystemManager, LoggerFactory, MediaEncoder, ChapterManager, LibraryManager); @@ -912,10 +910,19 @@ namespace Emby.Server.Implementations AuthService = new AuthService(authContext, ServerConfigurationManager, SessionManager, NetworkManager); serviceCollection.AddSingleton(AuthService); - SubtitleEncoder = new MediaBrowser.MediaEncoding.Subtitles.SubtitleEncoder(LibraryManager, LoggerFactory, ApplicationPaths, FileSystemManager, MediaEncoder, JsonSerializer, HttpClient, MediaSourceManager, ProcessFactory); + SubtitleEncoder = new MediaBrowser.MediaEncoding.Subtitles.SubtitleEncoder( + LibraryManager, + LoggerFactory.CreateLogger(), + ApplicationPaths, + FileSystemManager, + MediaEncoder, + HttpClient, + MediaSourceManager, + ProcessFactory); serviceCollection.AddSingleton(SubtitleEncoder); serviceCollection.AddSingleton(typeof(IResourceFileManager), typeof(ResourceFileManager)); + serviceCollection.AddSingleton(); _displayPreferencesRepository.Initialize(); diff --git a/Emby.Server.Implementations/ConfigurationOptions.cs b/Emby.Server.Implementations/ConfigurationOptions.cs index 62408ee70..445a554b2 100644 --- a/Emby.Server.Implementations/ConfigurationOptions.cs +++ b/Emby.Server.Implementations/ConfigurationOptions.cs @@ -1,13 +1,16 @@ using System.Collections.Generic; +using static MediaBrowser.Controller.Extensions.ConfigurationExtensions; namespace Emby.Server.Implementations { public static class ConfigurationOptions { - public static readonly Dictionary Configuration = new Dictionary + public static Dictionary Configuration => new Dictionary { - { "HttpListenerHost:DefaultRedirectPath", "web/index.html" }, - { "MusicBrainz:BaseUrl", "https://www.musicbrainz.org" } + { "HttpListenerHost_DefaultRedirectPath", "web/index.html" }, + { "MusicBrainz_BaseUrl", "https://www.musicbrainz.org" }, + { FfmpegProbeSizeKey, "1G" }, + { FfmpegAnalyzeDuration, "200M" } }; } } diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index 214ea5aff..618f54ce7 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -28,7 +28,6 @@ - diff --git a/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs b/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs index dc1a56e27..2736339b1 100644 --- a/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs +++ b/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs @@ -56,7 +56,7 @@ namespace Emby.Server.Implementations.HttpServer _appHost = applicationHost; _logger = logger; _config = config; - _defaultRedirectPath = configuration["HttpListenerHost:DefaultRedirectPath"]; + _defaultRedirectPath = configuration["HttpListenerHost_DefaultRedirectPath"]; _baseUrlPrefix = _config.Configuration.BaseUrl; _networkManager = networkManager; _jsonSerializer = jsonSerializer; diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index bdf3689f1..c9ca79a2b 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -6,6 +6,7 @@ using System.Net; using System.Net.Security; using System.Reflection; using System.Runtime.InteropServices; +using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; @@ -133,6 +134,10 @@ namespace Jellyfin.Server ApplicationHost.LogEnvironmentInfo(_logger, appPaths); + // Make sure we have all the code pages we can get + // Ref: https://docs.microsoft.com/en-us/dotnet/api/system.text.codepagesencodingprovider.instance?view=netcore-3.0#remarks + Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); + // Increase the max http request limit // The default connection limit is 10 for ASP.NET hosted applications and 2 for all others. ServicePointManager.DefaultConnectionLimit = Math.Max(96, ServicePointManager.DefaultConnectionLimit); @@ -369,9 +374,9 @@ namespace Jellyfin.Server return new ConfigurationBuilder() .SetBasePath(appPaths.ConfigurationDirectoryPath) + .AddInMemoryCollection(ConfigurationOptions.Configuration) .AddJsonFile("logging.json", false, true) .AddEnvironmentVariables("JELLYFIN_") - .AddInMemoryCollection(ConfigurationOptions.Configuration) .Build(); } diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 4bd729aac..d554930ac 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -69,8 +69,6 @@ namespace MediaBrowser.Api.Playback protected IDeviceManager DeviceManager { get; private set; } - protected ISubtitleEncoder SubtitleEncoder { get; private set; } - protected IMediaSourceManager MediaSourceManager { get; private set; } protected IJsonSerializer JsonSerializer { get; private set; } @@ -96,11 +94,11 @@ namespace MediaBrowser.Api.Playback IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, - ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IJsonSerializer jsonSerializer, - IAuthorizationContext authorizationContext) + IAuthorizationContext authorizationContext, + EncodingHelper encodingHelper) { ServerConfigurationManager = serverConfig; UserManager = userManager; @@ -109,13 +107,12 @@ namespace MediaBrowser.Api.Playback MediaEncoder = mediaEncoder; FileSystem = fileSystem; DlnaManager = dlnaManager; - SubtitleEncoder = subtitleEncoder; DeviceManager = deviceManager; MediaSourceManager = mediaSourceManager; JsonSerializer = jsonSerializer; AuthorizationContext = authorizationContext; - EncodingHelper = new EncodingHelper(MediaEncoder, FileSystem, SubtitleEncoder); + EncodingHelper = encodingHelper; } /// @@ -152,8 +149,6 @@ namespace MediaBrowser.Api.Playback return Path.Combine(folder, filename + ext); } - protected readonly CultureInfo UsCulture = new CultureInfo("en-US"); - protected virtual string GetDefaultEncoderPreset() { return "superfast"; diff --git a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs index 27eb67ee6..390e85d08 100644 --- a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs @@ -25,6 +25,34 @@ namespace MediaBrowser.Api.Playback.Hls /// public abstract class BaseHlsService : BaseStreamingService { + public BaseHlsService( + IServerConfigurationManager serverConfig, + IUserManager userManager, + ILibraryManager libraryManager, + IIsoManager isoManager, + IMediaEncoder mediaEncoder, + IFileSystem fileSystem, + IDlnaManager dlnaManager, + IDeviceManager deviceManager, + IMediaSourceManager mediaSourceManager, + IJsonSerializer jsonSerializer, + IAuthorizationContext authorizationContext, + EncodingHelper encodingHelper) + : base(serverConfig, + userManager, + libraryManager, + isoManager, + mediaEncoder, + fileSystem, + dlnaManager, + deviceManager, + mediaSourceManager, + jsonSerializer, + authorizationContext, + encodingHelper) + { + } + /// /// Gets the audio arguments. /// @@ -313,33 +341,5 @@ namespace MediaBrowser.Api.Playback.Hls { return 0; } - - public BaseHlsService( - IServerConfigurationManager serverConfig, - IUserManager userManager, - ILibraryManager libraryManager, - IIsoManager isoManager, - IMediaEncoder mediaEncoder, - IFileSystem fileSystem, - IDlnaManager dlnaManager, - ISubtitleEncoder subtitleEncoder, - IDeviceManager deviceManager, - IMediaSourceManager mediaSourceManager, - IJsonSerializer jsonSerializer, - IAuthorizationContext authorizationContext) - : base(serverConfig, - userManager, - libraryManager, - isoManager, - mediaEncoder, - fileSystem, - dlnaManager, - subtitleEncoder, - deviceManager, - mediaSourceManager, - jsonSerializer, - authorizationContext) - { - } } } diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs index 9ecb5fe8c..60a1f6899 100644 --- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs @@ -94,7 +94,6 @@ namespace MediaBrowser.Api.Playback.Hls [Authenticated] public class DynamicHlsService : BaseHlsService { - public DynamicHlsService( IServerConfigurationManager serverConfig, IUserManager userManager, @@ -103,12 +102,12 @@ namespace MediaBrowser.Api.Playback.Hls IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, - ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IJsonSerializer jsonSerializer, IAuthorizationContext authorizationContext, - INetworkManager networkManager) + INetworkManager networkManager, + EncodingHelper encodingHelper) : base(serverConfig, userManager, libraryManager, @@ -116,11 +115,11 @@ namespace MediaBrowser.Api.Playback.Hls mediaEncoder, fileSystem, dlnaManager, - subtitleEncoder, deviceManager, mediaSourceManager, jsonSerializer, - authorizationContext) + authorizationContext, + encodingHelper) { NetworkManager = networkManager; } diff --git a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs index 4a5f4025b..cada7138c 100644 --- a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs @@ -26,6 +26,34 @@ namespace MediaBrowser.Api.Playback.Hls [Authenticated] public class VideoHlsService : BaseHlsService { + public VideoHlsService( + IServerConfigurationManager serverConfig, + IUserManager userManager, + ILibraryManager libraryManager, + IIsoManager isoManager, + IMediaEncoder mediaEncoder, + IFileSystem fileSystem, + IDlnaManager dlnaManager, + IDeviceManager deviceManager, + IMediaSourceManager mediaSourceManager, + IJsonSerializer jsonSerializer, + IAuthorizationContext authorizationContext, + EncodingHelper encodingHelper) + : base(serverConfig, + userManager, + libraryManager, + isoManager, + mediaEncoder, + fileSystem, + dlnaManager, + deviceManager, + mediaSourceManager, + jsonSerializer, + authorizationContext, + encodingHelper) + { + } + public Task Get(GetLiveHlsStream request) { return ProcessRequestAsync(request, true); @@ -135,33 +163,5 @@ namespace MediaBrowser.Api.Playback.Hls return args; } - - public VideoHlsService( - IServerConfigurationManager serverConfig, - IUserManager userManager, - ILibraryManager libraryManager, - IIsoManager isoManager, - IMediaEncoder mediaEncoder, - IFileSystem fileSystem, - IDlnaManager dlnaManager, - ISubtitleEncoder subtitleEncoder, - IDeviceManager deviceManager, - IMediaSourceManager mediaSourceManager, - IJsonSerializer jsonSerializer, - IAuthorizationContext authorizationContext) - : base(serverConfig, - userManager, - libraryManager, - isoManager, - mediaEncoder, - fileSystem, - dlnaManager, - subtitleEncoder, - deviceManager, - mediaSourceManager, - jsonSerializer, - authorizationContext) - { - } } } diff --git a/MediaBrowser.Api/Playback/Progressive/AudioService.cs b/MediaBrowser.Api/Playback/Progressive/AudioService.cs index dfe4b2b8e..5679a4e17 100644 --- a/MediaBrowser.Api/Playback/Progressive/AudioService.cs +++ b/MediaBrowser.Api/Playback/Progressive/AudioService.cs @@ -40,11 +40,11 @@ namespace MediaBrowser.Api.Playback.Progressive IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, - ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IJsonSerializer jsonSerializer, - IAuthorizationContext authorizationContext) + IAuthorizationContext authorizationContext, + EncodingHelper encodingHelper) : base(httpClient, serverConfig, userManager, @@ -53,11 +53,11 @@ namespace MediaBrowser.Api.Playback.Progressive mediaEncoder, fileSystem, dlnaManager, - subtitleEncoder, deviceManager, mediaSourceManager, jsonSerializer, - authorizationContext) + authorizationContext, + encodingHelper) { } diff --git a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs index 97c1a7a49..ee7b99c2a 100644 --- a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs +++ b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs @@ -35,23 +35,24 @@ namespace MediaBrowser.Api.Playback.Progressive IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, - ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IJsonSerializer jsonSerializer, - IAuthorizationContext authorizationContext) - : base(serverConfig, + IAuthorizationContext authorizationContext, + EncodingHelper encodingHelper) + : base( + serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, dlnaManager, - subtitleEncoder, deviceManager, mediaSourceManager, jsonSerializer, - authorizationContext) + authorizationContext, + encodingHelper) { HttpClient = httpClient; } diff --git a/MediaBrowser.Api/Playback/Progressive/VideoService.cs b/MediaBrowser.Api/Playback/Progressive/VideoService.cs index cfc8a283d..976e11b47 100644 --- a/MediaBrowser.Api/Playback/Progressive/VideoService.cs +++ b/MediaBrowser.Api/Playback/Progressive/VideoService.cs @@ -77,11 +77,11 @@ namespace MediaBrowser.Api.Playback.Progressive IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, - ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IJsonSerializer jsonSerializer, - IAuthorizationContext authorizationContext) + IAuthorizationContext authorizationContext, + EncodingHelper encodingHelper) : base(httpClient, serverConfig, userManager, @@ -90,11 +90,11 @@ namespace MediaBrowser.Api.Playback.Progressive mediaEncoder, fileSystem, dlnaManager, - subtitleEncoder, deviceManager, mediaSourceManager, jsonSerializer, - authorizationContext) + authorizationContext, + encodingHelper) { } diff --git a/MediaBrowser.Api/Playback/UniversalAudioService.cs b/MediaBrowser.Api/Playback/UniversalAudioService.cs index b3d8bfe59..70c0f4b01 100644 --- a/MediaBrowser.Api/Playback/UniversalAudioService.cs +++ b/MediaBrowser.Api/Playback/UniversalAudioService.cs @@ -9,7 +9,6 @@ using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Devices; using MediaBrowser.Controller.Dlna; -using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.Net; @@ -75,6 +74,9 @@ namespace MediaBrowser.Api.Playback [Authenticated] public class UniversalAudioService : BaseApiService { + private readonly ILoggerFactory _loggerFactory; + private readonly EncodingHelper _encodingHelper; + public UniversalAudioService( IHttpClient httpClient, IServerConfigurationManager serverConfigurationManager, @@ -85,14 +87,12 @@ namespace MediaBrowser.Api.Playback IFileSystem fileSystem, IDlnaManager dlnaManager, IDeviceManager deviceManager, - ISubtitleEncoder subtitleEncoder, IMediaSourceManager mediaSourceManager, - IZipClient zipClient, IJsonSerializer jsonSerializer, IAuthorizationContext authorizationContext, - IImageProcessor imageProcessor, INetworkManager networkManager, - ILoggerFactory loggerFactory) + ILoggerFactory loggerFactory, + EncodingHelper encodingHelper) { HttpClient = httpClient; ServerConfigurationManager = serverConfigurationManager; @@ -103,15 +103,12 @@ namespace MediaBrowser.Api.Playback FileSystem = fileSystem; DlnaManager = dlnaManager; DeviceManager = deviceManager; - SubtitleEncoder = subtitleEncoder; MediaSourceManager = mediaSourceManager; - ZipClient = zipClient; JsonSerializer = jsonSerializer; AuthorizationContext = authorizationContext; - ImageProcessor = imageProcessor; NetworkManager = networkManager; _loggerFactory = loggerFactory; - _logger = loggerFactory.CreateLogger(nameof(UniversalAudioService)); + _encodingHelper = encodingHelper; } protected IHttpClient HttpClient { get; private set; } @@ -123,15 +120,10 @@ namespace MediaBrowser.Api.Playback protected IFileSystem FileSystem { get; private set; } protected IDlnaManager DlnaManager { get; private set; } protected IDeviceManager DeviceManager { get; private set; } - protected ISubtitleEncoder SubtitleEncoder { get; private set; } protected IMediaSourceManager MediaSourceManager { get; private set; } - protected IZipClient ZipClient { get; private set; } protected IJsonSerializer JsonSerializer { get; private set; } protected IAuthorizationContext AuthorizationContext { get; private set; } - protected IImageProcessor ImageProcessor { get; private set; } protected INetworkManager NetworkManager { get; private set; } - private ILoggerFactory _loggerFactory; - private ILogger _logger; public Task Get(GetUniversalAudioStream request) { @@ -242,7 +234,17 @@ namespace MediaBrowser.Api.Playback AuthorizationContext.GetAuthorizationInfo(Request).DeviceId = request.DeviceId; - var mediaInfoService = new MediaInfoService(MediaSourceManager, DeviceManager, LibraryManager, ServerConfigurationManager, NetworkManager, MediaEncoder, UserManager, JsonSerializer, AuthorizationContext, _loggerFactory) + var mediaInfoService = new MediaInfoService( + MediaSourceManager, + DeviceManager, + LibraryManager, + ServerConfigurationManager, + NetworkManager, + MediaEncoder, + UserManager, + JsonSerializer, + AuthorizationContext, + _loggerFactory) { Request = Request }; @@ -276,19 +278,20 @@ namespace MediaBrowser.Api.Playback if (!isStatic && string.Equals(mediaSource.TranscodingSubProtocol, "hls", StringComparison.OrdinalIgnoreCase)) { - var service = new DynamicHlsService(ServerConfigurationManager, - UserManager, - LibraryManager, - IsoManager, - MediaEncoder, - FileSystem, - DlnaManager, - SubtitleEncoder, - DeviceManager, - MediaSourceManager, - JsonSerializer, - AuthorizationContext, - NetworkManager) + var service = new DynamicHlsService( + ServerConfigurationManager, + UserManager, + LibraryManager, + IsoManager, + MediaEncoder, + FileSystem, + DlnaManager, + DeviceManager, + MediaSourceManager, + JsonSerializer, + AuthorizationContext, + NetworkManager, + _encodingHelper) { Request = Request }; @@ -330,11 +333,11 @@ namespace MediaBrowser.Api.Playback MediaEncoder, FileSystem, DlnaManager, - SubtitleEncoder, DeviceManager, MediaSourceManager, JsonSerializer, - AuthorizationContext) + AuthorizationContext, + _encodingHelper) { Request = Request }; diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs index 60906bdb0..af4d227bc 100644 --- a/MediaBrowser.Controller/Entities/Video.cs +++ b/MediaBrowser.Controller/Entities/Video.cs @@ -137,7 +137,7 @@ namespace MediaBrowser.Controller.Entities /// The video3 D format. public Video3DFormat? Video3DFormat { get; set; } - public string[] GetPlayableStreamFileNames(IMediaEncoder mediaEncoder) + public string[] GetPlayableStreamFileNames() { var videoType = VideoType; @@ -153,7 +153,8 @@ namespace MediaBrowser.Controller.Entities { return Array.Empty(); } - return mediaEncoder.GetPlayableStreamFileNames(Path, videoType); + + throw new NotImplementedException(); } /// diff --git a/MediaBrowser.Controller/Extensions/ConfigurationExtensions.cs b/MediaBrowser.Controller/Extensions/ConfigurationExtensions.cs new file mode 100644 index 000000000..80a98ad5f --- /dev/null +++ b/MediaBrowser.Controller/Extensions/ConfigurationExtensions.cs @@ -0,0 +1,36 @@ +using Microsoft.Extensions.Configuration; + +namespace MediaBrowser.Controller.Extensions +{ + /// + /// Configuration extensions for MediaBrowser.Controller. + /// + public static class ConfigurationExtensions + { + /// + /// The key for the FFmpeg probe size option. + /// + public const string FfmpegProbeSizeKey = "FFmpeg_probesize"; + + /// + /// The key for the FFmpeg analyse duration option. + /// + public const string FfmpegAnalyzeDuration = "FFmpeg_analyzeduration"; + + /// + /// Retrieves the FFmpeg probe size from the . + /// + /// This configuration. + /// The FFmpeg probe size option. + public static string GetProbeSize(this IConfiguration configuration) + => configuration[FfmpegProbeSizeKey]; + + /// + /// Retrieves the FFmpeg analyse duration from the . + /// + /// This configuration. + /// The FFmpeg analyse duration option. + public static string GetAnalyzeDuration(this IConfiguration configuration) + => configuration[FfmpegAnalyzeDuration]; + } +} diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 276eb71bc..60c76ef7d 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -7,6 +7,10 @@ https://github.com/jellyfin/jellyfin + + + + diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 349e371a7..d829db44b 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -12,6 +12,7 @@ using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.IO; using MediaBrowser.Model.MediaInfo; +using Microsoft.Extensions.Configuration; namespace MediaBrowser.Controller.MediaEncoding { @@ -22,6 +23,7 @@ namespace MediaBrowser.Controller.MediaEncoding private readonly IMediaEncoder _mediaEncoder; private readonly IFileSystem _fileSystem; private readonly ISubtitleEncoder _subtitleEncoder; + private readonly IConfiguration _configuration; private static readonly string[] _videoProfiles = new[] { @@ -34,11 +36,16 @@ namespace MediaBrowser.Controller.MediaEncoding "ConstrainedHigh" }; - public EncodingHelper(IMediaEncoder mediaEncoder, IFileSystem fileSystem, ISubtitleEncoder subtitleEncoder) + public EncodingHelper( + IMediaEncoder mediaEncoder, + IFileSystem fileSystem, + ISubtitleEncoder subtitleEncoder, + IConfiguration configuration) { _mediaEncoder = mediaEncoder; _fileSystem = fileSystem; _subtitleEncoder = subtitleEncoder; + _configuration = configuration; } public string GetH264Encoder(EncodingJobInfo state, EncodingOptions encodingOptions) @@ -172,7 +179,7 @@ namespace MediaBrowser.Controller.MediaEncoding return string.Empty; } - public string GetInputFormat(string container) + public static string GetInputFormat(string container) { if (string.IsNullOrEmpty(container)) { @@ -641,7 +648,11 @@ namespace MediaBrowser.Controller.MediaEncoding if (!string.IsNullOrEmpty(state.SubtitleStream.Language)) { - var charenc = _subtitleEncoder.GetSubtitleFileCharacterSet(subtitlePath, state.SubtitleStream.Language, state.MediaSource.Protocol, CancellationToken.None).Result; + var charenc = _subtitleEncoder.GetSubtitleFileCharacterSet( + subtitlePath, + state.SubtitleStream.Language, + state.MediaSource.Protocol, + CancellationToken.None).GetAwaiter().GetResult(); if (!string.IsNullOrEmpty(charenc)) { @@ -1897,7 +1908,7 @@ namespace MediaBrowser.Controller.MediaEncoding // If transcoding from 10 bit, transform colour spaces too if (!string.IsNullOrEmpty(videoStream.PixelFormat) && videoStream.PixelFormat.IndexOf("p10", StringComparison.OrdinalIgnoreCase) != -1 - && string.Equals(outputVideoCodec,"libx264", StringComparison.OrdinalIgnoreCase)) + && string.Equals(outputVideoCodec, "libx264", StringComparison.OrdinalIgnoreCase)) { filters.Add("format=p010le"); filters.Add("format=nv12"); @@ -1946,7 +1957,9 @@ namespace MediaBrowser.Controller.MediaEncoding var output = string.Empty; - if (state.SubtitleStream != null && state.SubtitleStream.IsTextSubtitleStream && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode) + if (state.SubtitleStream != null + && state.SubtitleStream.IsTextSubtitleStream + && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode) { var subParam = GetTextSubtitleParam(state); @@ -2035,11 +2048,11 @@ namespace MediaBrowser.Controller.MediaEncoding } } - public static string GetProbeSizeArgument(int numInputFiles) - => numInputFiles > 1 ? "-probesize 1G" : ""; + public string GetProbeSizeArgument(int numInputFiles) + => numInputFiles > 1 ? "-probesize " + _configuration["FFmpeg:probesize"] : string.Empty; - public static string GetAnalyzeDurationArgument(int numInputFiles) - => numInputFiles > 1 ? "-analyzeduration 200M" : ""; + public string GetAnalyzeDurationArgument(int numInputFiles) + => numInputFiles > 1 ? "-analyzeduration " + _configuration["FFmpeg:analyzeduration"] : string.Empty; public string GetInputModifier(EncodingJobInfo state, EncodingOptions encodingOptions) { diff --git a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs index d032a849e..37f0b11a7 100644 --- a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs +++ b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs @@ -15,6 +15,9 @@ namespace MediaBrowser.Controller.MediaEncoding /// public interface IMediaEncoder : ITranscoderSupport { + /// + /// The location of the discovered FFmpeg tool. + /// FFmpegLocation EncoderLocation { get; } /// @@ -97,7 +100,6 @@ namespace MediaBrowser.Controller.MediaEncoding void UpdateEncoderPath(string path, string pathType); bool SupportsEncoder(string encoder); - string[] GetPlayableStreamFileNames(string path, VideoType videoType); IEnumerable GetPrimaryPlaylistVobFiles(string path, IIsoMount isoMount, uint? titleNumber); } } diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 04ff66991..6bcd6cd46 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -3,13 +3,13 @@ using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; +using System.Text.Json; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Library; using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.MediaEncoding.Probing; using MediaBrowser.Model.Configuration; @@ -19,9 +19,9 @@ using MediaBrowser.Model.Entities; using MediaBrowser.Model.Globalization; using MediaBrowser.Model.IO; using MediaBrowser.Model.MediaInfo; -using MediaBrowser.Model.Serialization; using MediaBrowser.Model.System; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Configuration; namespace MediaBrowser.MediaEncoding.Encoder { @@ -31,55 +31,60 @@ namespace MediaBrowser.MediaEncoding.Encoder public class MediaEncoder : IMediaEncoder, IDisposable { /// - /// Gets the encoder path. + /// The default image extraction timeout in milliseconds. /// - /// The encoder path. - public string EncoderPath => FFmpegPath; - - /// - /// The location of the discovered FFmpeg tool. - /// - public FFmpegLocation EncoderLocation { get; private set; } + internal const int DefaultImageExtractionTimeout = 5000; private readonly ILogger _logger; - private readonly IJsonSerializer _jsonSerializer; - private string FFmpegPath; - private string FFprobePath; - protected readonly IServerConfigurationManager ConfigurationManager; - protected readonly IFileSystem FileSystem; - protected readonly Func SubtitleEncoder; - protected readonly Func MediaSourceManager; + private readonly IServerConfigurationManager _configurationManager; + private readonly IFileSystem _fileSystem; private readonly IProcessFactory _processFactory; - private readonly int DefaultImageExtractionTimeoutMs; - private readonly string StartupOptionFFmpegPath; + private readonly ILocalizationManager _localization; + private readonly Func _subtitleEncoder; + private readonly IConfiguration _configuration; + private readonly string _startupOptionFFmpegPath; private readonly SemaphoreSlim _thumbnailResourcePool = new SemaphoreSlim(2, 2); + + private readonly object _runningProcessesLock = new object(); private readonly List _runningProcesses = new List(); - private readonly ILocalizationManager _localization; + + private EncodingHelper _encodingHelper; + + private string _ffmpegPath; + private string _ffprobePath; public MediaEncoder( - ILoggerFactory loggerFactory, - IJsonSerializer jsonSerializer, - string startupOptionsFFmpegPath, + ILogger logger, IServerConfigurationManager configurationManager, IFileSystem fileSystem, - Func subtitleEncoder, - Func mediaSourceManager, IProcessFactory processFactory, - int defaultImageExtractionTimeoutMs, - ILocalizationManager localization) - { - _logger = loggerFactory.CreateLogger(nameof(MediaEncoder)); - _jsonSerializer = jsonSerializer; - StartupOptionFFmpegPath = startupOptionsFFmpegPath; - ConfigurationManager = configurationManager; - FileSystem = fileSystem; - SubtitleEncoder = subtitleEncoder; + ILocalizationManager localization, + Func subtitleEncoder, + IConfiguration configuration, + string startupOptionsFFmpegPath) + { + _logger = logger; + _configurationManager = configurationManager; + _fileSystem = fileSystem; _processFactory = processFactory; - DefaultImageExtractionTimeoutMs = defaultImageExtractionTimeoutMs; _localization = localization; + _startupOptionFFmpegPath = startupOptionsFFmpegPath; + _subtitleEncoder = subtitleEncoder; + _configuration = configuration; } + private EncodingHelper EncodingHelper + => LazyInitializer.EnsureInitialized( + ref _encodingHelper, + () => new EncodingHelper(this, _fileSystem, _subtitleEncoder(), _configuration)); + + /// + public string EncoderPath => _ffmpegPath; + + /// + public FFmpegLocation EncoderLocation { get; private set; } + /// /// Run at startup or if the user removes a Custom path from transcode page. /// Sets global variables FFmpegPath. @@ -88,39 +93,39 @@ namespace MediaBrowser.MediaEncoding.Encoder public void SetFFmpegPath() { // 1) Custom path stored in config/encoding xml file under tag takes precedence - if (!ValidatePath(ConfigurationManager.GetConfiguration("encoding").EncoderAppPath, FFmpegLocation.Custom)) + if (!ValidatePath(_configurationManager.GetConfiguration("encoding").EncoderAppPath, FFmpegLocation.Custom)) { // 2) Check if the --ffmpeg CLI switch has been given - if (!ValidatePath(StartupOptionFFmpegPath, FFmpegLocation.SetByArgument)) + if (!ValidatePath(_startupOptionFFmpegPath, FFmpegLocation.SetByArgument)) { // 3) Search system $PATH environment variable for valid FFmpeg if (!ValidatePath(ExistsOnSystemPath("ffmpeg"), FFmpegLocation.System)) { EncoderLocation = FFmpegLocation.NotFound; - FFmpegPath = null; + _ffmpegPath = null; } } } // Write the FFmpeg path to the config/encoding.xml file as so it appears in UI - var config = ConfigurationManager.GetConfiguration("encoding"); - config.EncoderAppPathDisplay = FFmpegPath ?? string.Empty; - ConfigurationManager.SaveConfiguration("encoding", config); + var config = _configurationManager.GetConfiguration("encoding"); + config.EncoderAppPathDisplay = _ffmpegPath ?? string.Empty; + _configurationManager.SaveConfiguration("encoding", config); // Only if mpeg path is set, try and set path to probe - if (FFmpegPath != null) + if (_ffmpegPath != null) { // Determine a probe path from the mpeg path - FFprobePath = Regex.Replace(FFmpegPath, @"[^\/\\]+?(\.[^\/\\\n.]+)?$", @"ffprobe$1"); + _ffprobePath = Regex.Replace(_ffmpegPath, @"[^\/\\]+?(\.[^\/\\\n.]+)?$", @"ffprobe$1"); // Interrogate to understand what coders are supported - var validator = new EncoderValidator(_logger, FFmpegPath); + var validator = new EncoderValidator(_logger, _ffmpegPath); SetAvailableDecoders(validator.GetDecoders()); SetAvailableEncoders(validator.GetEncoders()); } - _logger.LogInformation("FFmpeg: {0}: {1}", EncoderLocation, FFmpegPath ?? string.Empty); + _logger.LogInformation("FFmpeg: {0}: {1}", EncoderLocation, _ffmpegPath ?? string.Empty); } /// @@ -160,9 +165,9 @@ namespace MediaBrowser.MediaEncoding.Encoder // Write the new ffmpeg path to the xml as // This ensures its not lost on next startup - var config = ConfigurationManager.GetConfiguration("encoding"); + var config = _configurationManager.GetConfiguration("encoding"); config.EncoderAppPath = newPath; - ConfigurationManager.SaveConfiguration("encoding", config); + _configurationManager.SaveConfiguration("encoding", config); // Trigger SetFFmpegPath so we validate the new path and setup probe path SetFFmpegPath(); @@ -193,7 +198,7 @@ namespace MediaBrowser.MediaEncoding.Encoder // ToDo - Enable the ffmpeg validator. At the moment any version can be used. rc = true; - FFmpegPath = path; + _ffmpegPath = path; EncoderLocation = location; } else @@ -209,7 +214,7 @@ namespace MediaBrowser.MediaEncoding.Encoder { try { - var files = FileSystem.GetFilePaths(path); + var files = _fileSystem.GetFilePaths(path); var excludeExtensions = new[] { ".c" }; @@ -304,7 +309,7 @@ namespace MediaBrowser.MediaEncoding.Encoder { var extractChapters = request.MediaType == DlnaProfileType.Video && request.ExtractChapters; - var inputFiles = MediaEncoderHelpers.GetInputArgument(FileSystem, request.MediaSource.Path, request.MountedIso, request.PlayableStreamFileNames); + var inputFiles = MediaEncoderHelpers.GetInputArgument(_fileSystem, request.MediaSource.Path, request.MountedIso, request.PlayableStreamFileNames); var probeSize = EncodingHelper.GetProbeSizeArgument(inputFiles.Length); string analyzeDuration; @@ -365,7 +370,7 @@ namespace MediaBrowser.MediaEncoding.Encoder // Must consume both or ffmpeg may hang due to deadlocks. See comments below. RedirectStandardOutput = true, - FileName = FFprobePath, + FileName = _ffprobePath, Arguments = args, @@ -383,7 +388,7 @@ namespace MediaBrowser.MediaEncoding.Encoder _logger.LogDebug("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments); } - using (var processWrapper = new ProcessWrapper(process, this, _logger)) + using (var processWrapper = new ProcessWrapper(process, this)) { _logger.LogDebug("Starting ffprobe with args {Args}", args); StartProcess(processWrapper); @@ -391,7 +396,7 @@ namespace MediaBrowser.MediaEncoding.Encoder InternalMediaInfoResult result; try { - result = await _jsonSerializer.DeserializeFromStreamAsync( + result = await JsonSerializer.DeserializeAsync( process.StandardOutput.BaseStream).ConfigureAwait(false); } catch @@ -423,7 +428,7 @@ namespace MediaBrowser.MediaEncoding.Encoder } } - return new ProbeResultNormalizer(_logger, FileSystem, _localization).GetMediaInfo(result, videoType, isAudio, primaryPath, protocol); + return new ProbeResultNormalizer(_logger, _fileSystem, _localization).GetMediaInfo(result, videoType, isAudio, primaryPath, protocol); } } @@ -486,7 +491,7 @@ namespace MediaBrowser.MediaEncoding.Encoder throw new ArgumentNullException(nameof(inputPath)); } - var tempExtractPath = Path.Combine(ConfigurationManager.ApplicationPaths.TempDirectory, Guid.NewGuid() + ".jpg"); + var tempExtractPath = Path.Combine(_configurationManager.ApplicationPaths.TempDirectory, Guid.NewGuid() + ".jpg"); Directory.CreateDirectory(Path.GetDirectoryName(tempExtractPath)); // apply some filters to thumbnail extracted below (below) crop any black lines that we made and get the correct ar then scale to width 600. @@ -545,7 +550,6 @@ namespace MediaBrowser.MediaEncoding.Encoder args = string.Format("-ss {0} ", GetTimeParameter(offset.Value)) + args; } - var encodinghelper = new EncodingHelper(this, FileSystem, SubtitleEncoder()); if (videoStream != null) { /* fix @@ -559,7 +563,7 @@ namespace MediaBrowser.MediaEncoding.Encoder if (!string.IsNullOrWhiteSpace(container)) { - var inputFormat = encodinghelper.GetInputFormat(container); + var inputFormat = EncodingHelper.GetInputFormat(container); if (!string.IsNullOrWhiteSpace(inputFormat)) { args = "-f " + inputFormat + " " + args; @@ -570,7 +574,7 @@ namespace MediaBrowser.MediaEncoding.Encoder { CreateNoWindow = true, UseShellExecute = false, - FileName = FFmpegPath, + FileName = _ffmpegPath, Arguments = args, IsHidden = true, ErrorDialog = false, @@ -579,7 +583,7 @@ namespace MediaBrowser.MediaEncoding.Encoder _logger.LogDebug("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments); - using (var processWrapper = new ProcessWrapper(process, this, _logger)) + using (var processWrapper = new ProcessWrapper(process, this)) { bool ranToCompletion; @@ -588,10 +592,10 @@ namespace MediaBrowser.MediaEncoding.Encoder { StartProcess(processWrapper); - var timeoutMs = ConfigurationManager.Configuration.ImageExtractionTimeoutMs; + var timeoutMs = _configurationManager.Configuration.ImageExtractionTimeoutMs; if (timeoutMs <= 0) { - timeoutMs = DefaultImageExtractionTimeoutMs; + timeoutMs = DefaultImageExtractionTimeout; } ranToCompletion = await process.WaitForExitAsync(timeoutMs).ConfigureAwait(false); @@ -607,7 +611,7 @@ namespace MediaBrowser.MediaEncoding.Encoder } var exitCode = ranToCompletion ? processWrapper.ExitCode ?? 0 : -1; - var file = FileSystem.GetFileInfo(tempExtractPath); + var file = _fileSystem.GetFileInfo(tempExtractPath); if (exitCode == -1 || !file.Exists || file.Length == 0) { @@ -675,7 +679,6 @@ namespace MediaBrowser.MediaEncoding.Encoder args = analyzeDurationArgument + " " + args; } - var encodinghelper = new EncodingHelper(this, FileSystem, SubtitleEncoder()); if (videoStream != null) { /* fix @@ -689,7 +692,7 @@ namespace MediaBrowser.MediaEncoding.Encoder if (!string.IsNullOrWhiteSpace(container)) { - var inputFormat = encodinghelper.GetInputFormat(container); + var inputFormat = EncodingHelper.GetInputFormat(container); if (!string.IsNullOrWhiteSpace(inputFormat)) { args = "-f " + inputFormat + " " + args; @@ -700,7 +703,7 @@ namespace MediaBrowser.MediaEncoding.Encoder { CreateNoWindow = true, UseShellExecute = false, - FileName = FFmpegPath, + FileName = _ffmpegPath, Arguments = args, IsHidden = true, ErrorDialog = false, @@ -713,7 +716,7 @@ namespace MediaBrowser.MediaEncoding.Encoder bool ranToCompletion = false; - using (var processWrapper = new ProcessWrapper(process, this, _logger)) + using (var processWrapper = new ProcessWrapper(process, this)) { try { @@ -736,10 +739,10 @@ namespace MediaBrowser.MediaEncoding.Encoder cancellationToken.ThrowIfCancellationRequested(); - var jpegCount = FileSystem.GetFilePaths(targetDirectory) + var jpegCount = _fileSystem.GetFilePaths(targetDirectory) .Count(i => string.Equals(Path.GetExtension(i), ".jpg", StringComparison.OrdinalIgnoreCase)); - isResponsive = (jpegCount > lastCount); + isResponsive = jpegCount > lastCount; lastCount = jpegCount; } @@ -770,7 +773,7 @@ namespace MediaBrowser.MediaEncoding.Encoder { process.Process.Start(); - lock (_runningProcesses) + lock (_runningProcessesLock) { _runningProcesses.Add(process); } @@ -804,7 +807,7 @@ namespace MediaBrowser.MediaEncoding.Encoder private void StopProcesses() { List proceses; - lock (_runningProcesses) + lock (_runningProcessesLock) { proceses = _runningProcesses.ToList(); _runningProcesses.Clear(); @@ -827,12 +830,11 @@ namespace MediaBrowser.MediaEncoding.Encoder return path.Replace('\\', '/').Replace(":", "\\:").Replace("'", "'\\\\\\''"); } - /// - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - /// + /// public void Dispose() { Dispose(true); + GC.SuppressFinalize(this); } /// @@ -852,11 +854,6 @@ namespace MediaBrowser.MediaEncoding.Encoder throw new NotImplementedException(); } - public string[] GetPlayableStreamFileNames(string path, VideoType videoType) - { - throw new NotImplementedException(); - } - public IEnumerable GetPrimaryPlaylistVobFiles(string path, IIsoMount isoMount, uint? titleNumber) { throw new NotImplementedException(); @@ -870,21 +867,24 @@ namespace MediaBrowser.MediaEncoding.Encoder private class ProcessWrapper : IDisposable { - public readonly IProcess Process; - public bool HasExited; - public int? ExitCode; private readonly MediaEncoder _mediaEncoder; - private readonly ILogger _logger; - public ProcessWrapper(IProcess process, MediaEncoder mediaEncoder, ILogger logger) + private bool _disposed = false; + + public ProcessWrapper(IProcess process, MediaEncoder mediaEncoder) { Process = process; _mediaEncoder = mediaEncoder; - _logger = logger; - Process.Exited += Process_Exited; + Process.Exited += OnProcessExited; } - void Process_Exited(object sender, EventArgs e) + public IProcess Process { get; } + + public bool HasExited { get; private set; } + + public int? ExitCode { get; private set; } + + void OnProcessExited(object sender, EventArgs e) { var process = (IProcess)sender; @@ -903,7 +903,7 @@ namespace MediaBrowser.MediaEncoding.Encoder private void DisposeProcess(IProcess process) { - lock (_mediaEncoder._runningProcesses) + lock (_mediaEncoder._runningProcessesLock) { _mediaEncoder._runningProcesses.Remove(this); } @@ -917,23 +917,18 @@ namespace MediaBrowser.MediaEncoding.Encoder } } - private bool _disposed; - private readonly object _syncLock = new object(); public void Dispose() { - lock (_syncLock) + if (!_disposed) { - if (!_disposed) + if (Process != null) { - if (Process != null) - { - Process.Exited -= Process_Exited; - DisposeProcess(Process); - } + Process.Exited -= OnProcessExited; + DisposeProcess(Process); } - - _disposed = true; } + + _disposed = true; } } } diff --git a/MediaBrowser.MediaEncoding/Subtitles/ISubtitleWriter.cs b/MediaBrowser.MediaEncoding/Subtitles/ISubtitleWriter.cs index 3401c2d67..dec714121 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/ISubtitleWriter.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/ISubtitleWriter.cs @@ -5,7 +5,7 @@ using MediaBrowser.Model.MediaInfo; namespace MediaBrowser.MediaEncoding.Subtitles { /// - /// Interface ISubtitleWriter + /// Interface ISubtitleWriter. /// public interface ISubtitleWriter { diff --git a/MediaBrowser.MediaEncoding/Subtitles/JsonWriter.cs b/MediaBrowser.MediaEncoding/Subtitles/JsonWriter.cs index 8995fcfe1..241ebc6df 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/JsonWriter.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/JsonWriter.cs @@ -1,27 +1,39 @@ using System.IO; -using System.Text; +using System.Text.Json; using System.Threading; using MediaBrowser.Model.MediaInfo; -using MediaBrowser.Model.Serialization; namespace MediaBrowser.MediaEncoding.Subtitles { + /// + /// JSON subtitle writer. + /// public class JsonWriter : ISubtitleWriter { - private readonly IJsonSerializer _json; - - public JsonWriter(IJsonSerializer json) - { - _json = json; - } - + /// public void Write(SubtitleTrackInfo info, Stream stream, CancellationToken cancellationToken) { - using (var writer = new StreamWriter(stream, Encoding.UTF8, 1024, true)) + using (var writer = new Utf8JsonWriter(stream)) { - var json = _json.SerializeToString(info); + var trackevents = info.TrackEvents; + writer.WriteStartArray("TrackEvents"); + + for (int i = 0; i < trackevents.Count; i++) + { + cancellationToken.ThrowIfCancellationRequested(); + + var current = trackevents[i]; + writer.WriteStartObject(); + + writer.WriteString("Id", current.Id); + writer.WriteString("Text", current.Text); + writer.WriteNumber("StartPositionTicks", current.StartPositionTicks); + writer.WriteNumber("EndPositionTicks", current.EndPositionTicks); + + writer.WriteEndObject(); + } - writer.Write(json); + writer.WriteEndObject(); } } } diff --git a/MediaBrowser.MediaEncoding/Subtitles/SrtWriter.cs b/MediaBrowser.MediaEncoding/Subtitles/SrtWriter.cs index 6f96a641e..45b317b2e 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SrtWriter.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SrtWriter.cs @@ -14,14 +14,19 @@ namespace MediaBrowser.MediaEncoding.Subtitles { using (var writer = new StreamWriter(stream, Encoding.UTF8, 1024, true)) { - var index = 1; + var trackEvents = info.TrackEvents; - foreach (var trackEvent in info.TrackEvents) + for (int i = 0; i < trackEvents.Count; i++) { cancellationToken.ThrowIfCancellationRequested(); - writer.WriteLine(index.ToString(CultureInfo.InvariantCulture)); - writer.WriteLine(@"{0:hh\:mm\:ss\,fff} --> {1:hh\:mm\:ss\,fff}", TimeSpan.FromTicks(trackEvent.StartPositionTicks), TimeSpan.FromTicks(trackEvent.EndPositionTicks)); + var trackEvent = trackEvents[i]; + + writer.WriteLine((i + 1).ToString(CultureInfo.InvariantCulture)); + writer.WriteLine( + @"{0:hh\:mm\:ss\,fff} --> {1:hh\:mm\:ss\,fff}", + TimeSpan.FromTicks(trackEvent.StartPositionTicks), + TimeSpan.FromTicks(trackEvent.EndPositionTicks)); var text = trackEvent.Text; @@ -29,9 +34,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles text = Regex.Replace(text, @"\\n", " ", RegexOptions.IgnoreCase); writer.WriteLine(text); - writer.WriteLine(string.Empty); - - index++; + writer.WriteLine(); } } } diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index d5fa76c3a..183d7566d 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -17,7 +17,6 @@ using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.IO; using MediaBrowser.Model.MediaInfo; -using MediaBrowser.Model.Serialization; using Microsoft.Extensions.Logging; using UtfUnknown; @@ -30,28 +29,25 @@ namespace MediaBrowser.MediaEncoding.Subtitles private readonly IApplicationPaths _appPaths; private readonly IFileSystem _fileSystem; private readonly IMediaEncoder _mediaEncoder; - private readonly IJsonSerializer _json; private readonly IHttpClient _httpClient; private readonly IMediaSourceManager _mediaSourceManager; private readonly IProcessFactory _processFactory; public SubtitleEncoder( ILibraryManager libraryManager, - ILoggerFactory loggerFactory, + ILogger logger, IApplicationPaths appPaths, IFileSystem fileSystem, IMediaEncoder mediaEncoder, - IJsonSerializer json, IHttpClient httpClient, IMediaSourceManager mediaSourceManager, IProcessFactory processFactory) { _libraryManager = libraryManager; - _logger = loggerFactory.CreateLogger(nameof(SubtitleEncoder)); + _logger = logger; _appPaths = appPaths; _fileSystem = fileSystem; _mediaEncoder = mediaEncoder; - _json = json; _httpClient = httpClient; _mediaSourceManager = mediaSourceManager; _processFactory = processFactory; @@ -59,7 +55,8 @@ namespace MediaBrowser.MediaEncoding.Subtitles private string SubtitleCachePath => Path.Combine(_appPaths.DataPath, "subtitles"); - private Stream ConvertSubtitles(Stream stream, + private Stream ConvertSubtitles( + Stream stream, string inputFormat, string outputFormat, long startTimeTicks, @@ -170,7 +167,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles && (mediaSource.VideoType.Value == VideoType.BluRay || mediaSource.VideoType.Value == VideoType.Dvd)) { var mediaSourceItem = (Video)_libraryManager.GetItemById(new Guid(mediaSource.Id)); - inputFiles = mediaSourceItem.GetPlayableStreamFileNames(_mediaEncoder); + inputFiles = mediaSourceItem.GetPlayableStreamFileNames(); } else { @@ -179,32 +176,27 @@ namespace MediaBrowser.MediaEncoding.Subtitles var fileInfo = await GetReadableFile(mediaSource.Path, inputFiles, mediaSource.Protocol, subtitleStream, cancellationToken).ConfigureAwait(false); - var stream = await GetSubtitleStream(fileInfo.Path, subtitleStream.Language, fileInfo.Protocol, fileInfo.IsExternal, cancellationToken).ConfigureAwait(false); + var stream = await GetSubtitleStream(fileInfo.Path, fileInfo.Protocol, fileInfo.IsExternal, cancellationToken).ConfigureAwait(false); return (stream, fileInfo.Format); } - private async Task GetSubtitleStream(string path, string language, MediaProtocol protocol, bool requiresCharset, CancellationToken cancellationToken) + private async Task GetSubtitleStream(string path, MediaProtocol protocol, bool requiresCharset, CancellationToken cancellationToken) { if (requiresCharset) { - var bytes = await GetBytes(path, protocol, cancellationToken).ConfigureAwait(false); - - var charset = CharsetDetector.DetectFromBytes(bytes).Detected?.EncodingName; - _logger.LogDebug("charset {CharSet} detected for {Path}", charset ?? "null", path); - - if (!string.IsNullOrEmpty(charset)) + using (var stream = await GetStream(path, protocol, cancellationToken).ConfigureAwait(false)) { - // Make sure we have all the code pages we can get - Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); - using (var inputStream = new MemoryStream(bytes)) - using (var reader = new StreamReader(inputStream, Encoding.GetEncoding(charset))) + var result = CharsetDetector.DetectFromStream(stream).Detected; + + if (result != null) { - var text = await reader.ReadToEndAsync().ConfigureAwait(false); + _logger.LogDebug("charset {CharSet} detected for {Path}", result.EncodingName, path); - bytes = Encoding.UTF8.GetBytes(text); + using var reader = new StreamReader(stream, result.Encoding); + var text = await reader.ReadToEndAsync().ConfigureAwait(false); - return new MemoryStream(bytes); + return new MemoryStream(Encoding.UTF8.GetBytes(text)); } } } @@ -323,7 +315,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles if (string.Equals(format, "json", StringComparison.OrdinalIgnoreCase)) { - return new JsonWriter(_json); + return new JsonWriter(); } if (string.Equals(format, SubtitleFormat.SRT, StringComparison.OrdinalIgnoreCase)) { @@ -544,7 +536,12 @@ namespace MediaBrowser.MediaEncoding.Subtitles { if (!File.Exists(outputPath)) { - await ExtractTextSubtitleInternal(_mediaEncoder.GetInputArgument(inputFiles, protocol), subtitleStreamIndex, outputCodec, outputPath, cancellationToken).ConfigureAwait(false); + await ExtractTextSubtitleInternal( + _mediaEncoder.GetInputArgument(inputFiles, protocol), + subtitleStreamIndex, + outputCodec, + outputPath, + cancellationToken).ConfigureAwait(false); } } finally @@ -572,8 +569,13 @@ namespace MediaBrowser.MediaEncoding.Subtitles Directory.CreateDirectory(Path.GetDirectoryName(outputPath)); - var processArgs = string.Format("-i {0} -map 0:{1} -an -vn -c:s {2} \"{3}\"", inputPath, - subtitleStreamIndex, outputCodec, outputPath); + var processArgs = string.Format( + CultureInfo.InvariantCulture, + "-i {0} -map 0:{1} -an -vn -c:s {2} \"{3}\"", + inputPath, + subtitleStreamIndex, + outputCodec, + outputPath); var process = _processFactory.Create(new ProcessOptions { @@ -721,41 +723,38 @@ namespace MediaBrowser.MediaEncoding.Subtitles } } + /// public async Task GetSubtitleFileCharacterSet(string path, string language, MediaProtocol protocol, CancellationToken cancellationToken) { - var bytes = await GetBytes(path, protocol, cancellationToken).ConfigureAwait(false); - - var charset = CharsetDetector.DetectFromBytes(bytes).Detected?.EncodingName; + using (var stream = await GetStream(path, protocol, cancellationToken).ConfigureAwait(false)) + { + var charset = CharsetDetector.DetectFromStream(stream).Detected?.EncodingName; - _logger.LogDebug("charset {0} detected for {Path}", charset ?? "null", path); + _logger.LogDebug("charset {0} detected for {Path}", charset ?? "null", path); - return charset; + return charset; + } } - private async Task GetBytes(string path, MediaProtocol protocol, CancellationToken cancellationToken) + private Task GetStream(string path, MediaProtocol protocol, CancellationToken cancellationToken) { - if (protocol == MediaProtocol.Http) + switch (protocol) { - var opts = new HttpRequestOptions() - { - Url = path, - CancellationToken = cancellationToken - }; - using (var file = await _httpClient.Get(opts).ConfigureAwait(false)) - using (var memoryStream = new MemoryStream()) - { - await file.CopyToAsync(memoryStream).ConfigureAwait(false); - memoryStream.Position = 0; + case MediaProtocol.Http: + var opts = new HttpRequestOptions() + { + Url = path, + CancellationToken = cancellationToken, + BufferContent = true + }; - return memoryStream.ToArray(); - } - } - if (protocol == MediaProtocol.File) - { - return File.ReadAllBytes(path); - } + return _httpClient.Get(opts); - throw new ArgumentOutOfRangeException(nameof(protocol)); + case MediaProtocol.File: + return Task.FromResult(File.OpenRead(path)); + default: + throw new ArgumentOutOfRangeException(nameof(protocol)); + } } } } diff --git a/MediaBrowser.MediaEncoding/Subtitles/TtmlWriter.cs b/MediaBrowser.MediaEncoding/Subtitles/TtmlWriter.cs index cdaf94964..4f15bac49 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/TtmlWriter.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/TtmlWriter.cs @@ -49,12 +49,5 @@ namespace MediaBrowser.MediaEncoding.Subtitles writer.WriteLine(""); } } - - private string FormatTime(long ticks) - { - var time = TimeSpan.FromTicks(ticks); - - return string.Format(@"{0:hh\:mm\:ss\,fff}", time); - } } } diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs index b8abe49e3..ede2d71ad 100644 --- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs +++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs @@ -231,7 +231,6 @@ namespace MediaBrowser.Model.Configuration LocalNetworkSubnets = Array.Empty(); LocalNetworkAddresses = Array.Empty(); CodecsUsed = Array.Empty(); - ImageExtractionTimeoutMs = 0; PathSubstitutions = Array.Empty(); IgnoreVirtualInterfaces = false; EnableSimpleArtistDetection = true; diff --git a/MediaBrowser.Model/MediaInfo/SubtitleTrackInfo.cs b/MediaBrowser.Model/MediaInfo/SubtitleTrackInfo.cs index 962f4d2fe..c382b20c9 100644 --- a/MediaBrowser.Model/MediaInfo/SubtitleTrackInfo.cs +++ b/MediaBrowser.Model/MediaInfo/SubtitleTrackInfo.cs @@ -1,12 +1,15 @@ +using System; +using System.Collections.Generic; + namespace MediaBrowser.Model.MediaInfo { public class SubtitleTrackInfo { - public SubtitleTrackEvent[] TrackEvents { get; set; } + public IReadOnlyList TrackEvents { get; set; } public SubtitleTrackInfo() { - TrackEvents = new SubtitleTrackEvent[] { }; + TrackEvents = Array.Empty(); } } } diff --git a/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs b/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs index e0b23108f..95b915b3d 100644 --- a/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs @@ -62,7 +62,11 @@ namespace MediaBrowser.Providers.MediaInfo { var protocol = item.PathProtocol ?? MediaProtocol.File; - var inputPath = MediaEncoderHelpers.GetInputArgument(_fileSystem, item.Path, null, item.GetPlayableStreamFileNames(_mediaEncoder)); + var inputPath = MediaEncoderHelpers.GetInputArgument( + _fileSystem, + item.Path, + null, + item.GetPlayableStreamFileNames()); var mediaStreams = item.GetMediaStreams(); diff --git a/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs b/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs index 8e71b625e..e9ca7938e 100644 --- a/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs +++ b/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs @@ -57,7 +57,7 @@ namespace MediaBrowser.Providers.Music _appHost = appHost; _logger = logger; - _musicBrainzBaseUrl = configuration["MusicBrainz:BaseUrl"]; + _musicBrainzBaseUrl = configuration["MusicBrainz_BaseUrl"]; // Use a stopwatch to ensure we don't exceed the MusicBrainz rate limit _stopWatchMusicBrainz.Start(); -- cgit v1.2.3 From 49330e30827eb4fc6b94cfbf6cd611e1d297920d Mon Sep 17 00:00:00 2001 From: Bond-009 Date: Mon, 30 Dec 2019 16:03:20 +0100 Subject: Fix a couple of TODOs --- Emby.Dlna/Eventing/EventManager.cs | 36 ++++++---------- Emby.Server.Implementations/ApplicationHost.cs | 3 +- .../Collections/CollectionManager.cs | 48 +++++----------------- 3 files changed, 23 insertions(+), 64 deletions(-) (limited to 'Emby.Server.Implementations/ApplicationHost.cs') diff --git a/Emby.Dlna/Eventing/EventManager.cs b/Emby.Dlna/Eventing/EventManager.cs index 4b542a820..b76a0066d 100644 --- a/Emby.Dlna/Eventing/EventManager.cs +++ b/Emby.Dlna/Eventing/EventManager.cs @@ -29,25 +29,15 @@ namespace Emby.Dlna.Eventing { var subscription = GetSubscription(subscriptionId, false); - int timeoutSeconds; + subscription.TimeoutSeconds = ParseTimeout(requestedTimeoutString) ?? 300; + int timeoutSeconds = subscription.TimeoutSeconds; + subscription.SubscriptionTime = DateTime.UtcNow; - // Remove logging for now because some devices are sending this very frequently - // TODO re-enable with dlna debug logging setting - //_logger.LogDebug("Renewing event subscription for {0} with timeout of {1} to {2}", - // subscription.NotificationType, - // timeout, - // subscription.CallbackUrl); - - if (subscription != null) - { - subscription.TimeoutSeconds = ParseTimeout(requestedTimeoutString) ?? 300; - timeoutSeconds = subscription.TimeoutSeconds; - subscription.SubscriptionTime = DateTime.UtcNow; - } - else - { - timeoutSeconds = 300; - } + _logger.LogDebug( + "Renewing event subscription for {0} with timeout of {1} to {2}", + subscription.NotificationType, + timeoutSeconds, + subscription.CallbackUrl); return GetEventSubscriptionResponse(subscriptionId, requestedTimeoutString, timeoutSeconds); } @@ -57,12 +47,10 @@ namespace Emby.Dlna.Eventing var timeout = ParseTimeout(requestedTimeoutString) ?? 300; var id = "uuid:" + Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture); - // Remove logging for now because some devices are sending this very frequently - // TODO re-enable with dlna debug logging setting - //_logger.LogDebug("Creating event subscription for {0} with timeout of {1} to {2}", - // notificationType, - // timeout, - // callbackUrl); + _logger.LogDebug("Creating event subscription for {0} with timeout of {1} to {2}", + notificationType, + timeout, + callbackUrl); _subscriptions.TryAdd(id, new EventSubscription { diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index aed0c14a2..67bc0cd2b 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -764,9 +764,8 @@ namespace Emby.Server.Implementations LibraryManager = new LibraryManager(this, LoggerFactory, TaskManager, UserManager, ServerConfigurationManager, UserDataManager, () => LibraryMonitor, FileSystemManager, () => ProviderManager, () => UserViewManager); serviceCollection.AddSingleton(LibraryManager); - // TODO wtaylor: investigate use of second music manager var musicManager = new MusicManager(LibraryManager); - serviceCollection.AddSingleton(new MusicManager(LibraryManager)); + serviceCollection.AddSingleton(musicManager); LibraryMonitor = new LibraryMonitor(LoggerFactory, LibraryManager, ServerConfigurationManager, FileSystemManager); serviceCollection.AddSingleton(LibraryMonitor); diff --git a/Emby.Server.Implementations/Collections/CollectionManager.cs b/Emby.Server.Implementations/Collections/CollectionManager.cs index 2b8a5bdc5..1d7c11989 100644 --- a/Emby.Server.Implementations/Collections/CollectionManager.cs +++ b/Emby.Server.Implementations/Collections/CollectionManager.cs @@ -31,11 +31,7 @@ namespace Emby.Server.Implementations.Collections private readonly ILogger _logger; private readonly IProviderManager _providerManager; private readonly ILocalizationManager _localizationManager; - private IApplicationPaths _appPaths; - - public event EventHandler CollectionCreated; - public event EventHandler ItemsAddedToCollection; - public event EventHandler ItemsRemovedFromCollection; + private readonly IApplicationPaths _appPaths; public CollectionManager( ILibraryManager libraryManager, @@ -55,6 +51,10 @@ namespace Emby.Server.Implementations.Collections _appPaths = appPaths; } + public event EventHandler CollectionCreated; + public event EventHandler ItemsAddedToCollection; + public event EventHandler ItemsRemovedFromCollection; + private IEnumerable FindFolders(string path) { return _libraryManager @@ -341,11 +341,11 @@ namespace Emby.Server.Implementations.Collections } } - public class CollectionManagerEntryPoint : IServerEntryPoint + public sealed class CollectionManagerEntryPoint : IServerEntryPoint { private readonly CollectionManager _collectionManager; private readonly IServerConfigurationManager _config; - private ILogger _logger; + private readonly ILogger _logger; public CollectionManagerEntryPoint(ICollectionManager collectionManager, IServerConfigurationManager config, ILogger logger) { @@ -354,6 +354,7 @@ namespace Emby.Server.Implementations.Collections _logger = logger; } + /// public async Task RunAsync() { if (!_config.Configuration.CollectionsUpgraded && _config.Configuration.IsStartupWizardCompleted) @@ -377,39 +378,10 @@ namespace Emby.Server.Implementations.Collections } } - #region IDisposable Support - private bool disposedValue = false; // To detect redundant calls - - protected virtual void Dispose(bool disposing) - { - if (!disposedValue) - { - if (disposing) - { - // TODO: dispose managed state (managed objects). - } - - // TODO: free unmanaged resources (unmanaged objects) and override a finalizer below. - // TODO: set large fields to null. - - disposedValue = true; - } - } - - // TODO: override a finalizer only if Dispose(bool disposing) above has code to free unmanaged resources. - // ~CollectionManagerEntryPoint() { - // // Do not change this code. Put cleanup code in Dispose(bool disposing) above. - // Dispose(false); - // } - - // This code added to correctly implement the disposable pattern. + /// public void Dispose() { - // Do not change this code. Put cleanup code in Dispose(bool disposing) above. - Dispose(true); - // TODO: uncomment the following line if the finalizer is overridden above. - // GC.SuppressFinalize(this); + // Nothing to dispose } - #endregion } } -- cgit v1.2.3 From 599432890311c9255cb376bbeb6f5f4f673fbf1b Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Thu, 2 Jan 2020 21:22:10 +0100 Subject: Fix baseurl (again) --- Emby.Server.Implementations/ApplicationHost.cs | 40 +++++++++++++++-------- MediaBrowser.Controller/IServerApplicationHost.cs | 8 +++-- 2 files changed, 32 insertions(+), 16 deletions(-) (limited to 'Emby.Server.Implementations/ApplicationHost.cs') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 67bc0cd2b..9b853c6d1 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -103,14 +103,11 @@ using MediaBrowser.Providers.Subtitles; using MediaBrowser.Providers.TV.TheTVDB; using MediaBrowser.WebDashboard.Api; using MediaBrowser.XbmcMetadata.Providers; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Extensions; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; -using Microsoft.OpenApi.Models; using OperatingSystem = MediaBrowser.Common.System.OperatingSystem; namespace Emby.Server.Implementations @@ -1478,7 +1475,7 @@ namespace Emby.Server.Implementations /// /// The IPv6 address. /// The IPv6 address without the scope id. - private string RemoveScopeId(string address) + private ReadOnlySpan RemoveScopeId(ReadOnlySpan address) { var index = address.IndexOf('%'); if (index == -1) @@ -1486,33 +1483,50 @@ namespace Emby.Server.Implementations return address; } - return address.Substring(0, index); + return address.Slice(0, index); } + /// public string GetLocalApiUrl(IPAddress ipAddress) { if (ipAddress.AddressFamily == AddressFamily.InterNetworkV6) { var str = RemoveScopeId(ipAddress.ToString()); + Span span = new char[str.Length + 2]; + span[0] = '['; + str.CopyTo(span.Slice(1)); + span[^1] = ']'; - return GetLocalApiUrl("[" + str + "]"); + return GetLocalApiUrl(span); } return GetLocalApiUrl(ipAddress.ToString()); } - public string GetLocalApiUrl(string host) + /// + public string GetLocalApiUrl(ReadOnlySpan host) { + var url = new StringBuilder(64); if (EnableHttps) { - return string.Format("https://{0}:{1}", - host, - HttpsPort.ToString(CultureInfo.InvariantCulture)); + url.Append("https://"); + } + else + { + url.Append("http://"); + } + + url.Append(host) + .Append(':') + .Append(HttpPort); + + string baseUrl = ServerConfigurationManager.Configuration.BaseUrl; + if (baseUrl.Length != 0) + { + url.Append('/').Append(baseUrl); } - return string.Format("http://{0}:{1}", - host, - HttpPort.ToString(CultureInfo.InvariantCulture)); + return url.ToString(); } public Task> GetLocalIpAddresses(CancellationToken cancellationToken) diff --git a/MediaBrowser.Controller/IServerApplicationHost.cs b/MediaBrowser.Controller/IServerApplicationHost.cs index b3c56bdd5..25f0905eb 100644 --- a/MediaBrowser.Controller/IServerApplicationHost.cs +++ b/MediaBrowser.Controller/IServerApplicationHost.cs @@ -71,13 +71,15 @@ namespace MediaBrowser.Controller /// /// Gets the local API URL. /// - /// The host. - /// System.String. - string GetLocalApiUrl(string host); + /// The hostname. + /// The local API URL. + string GetLocalApiUrl(ReadOnlySpan hostname); /// /// Gets the local API URL. /// + /// The IP address. + /// The local API URL. string GetLocalApiUrl(IPAddress address); void LaunchUrl(string url); -- cgit v1.2.3 From a253fa616da3fd982ca2190b69d25853893665f1 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Thu, 26 Dec 2019 23:09:00 +0100 Subject: Fix build and address comments --- Emby.Server.Implementations/ApplicationHost.cs | 2 +- .../Data/SqliteItemRepository.cs | 34 ++++---- .../Library/MediaSourceManager.cs | 9 -- Jellyfin.Api/Controllers/StartupController.cs | 1 - MediaBrowser.Api/Attachments/AttachmentService.cs | 19 ++--- .../Library/IMediaSourceManager.cs | 11 +-- .../MediaEncoding/IAttachmentExtractor.cs | 4 +- .../Attachments/AttachmentExtractor.cs | 97 +++++++++++----------- .../Encoder/EncodingUtils.cs | 2 +- 9 files changed, 82 insertions(+), 97 deletions(-) (limited to 'Emby.Server.Implementations/ApplicationHost.cs') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 7c3f59af2..c5ac27ed4 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -878,7 +878,7 @@ namespace Emby.Server.Implementations serviceCollection.AddSingleton(typeof(IResourceFileManager), typeof(ResourceFileManager)); serviceCollection.AddSingleton(); - serviceCollection.AddSingleton(typeof(MediaBrowser.Controller.MediaEncoding.IAttachmentExtractor),typeof(MediaBrowser.MediaEncoding.Attachments.AttachmentExtractor)); + serviceCollection.AddSingleton(typeof(IAttachmentExtractor), typeof(MediaBrowser.MediaEncoding.Attachments.AttachmentExtractor)); _displayPreferencesRepository.Initialize(); diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index 2206816a5..91ca8477d 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -55,8 +55,8 @@ namespace Emby.Server.Implementations.Data queryPrefixText.Append("insert into mediaattachments ("); foreach (var column in _mediaAttachmentSaveColumns) { - queryPrefixText.Append(column); - queryPrefixText.Append(','); + queryPrefixText.Append(column) + .Append(','); } queryPrefixText.Length -= 1; @@ -449,6 +449,7 @@ namespace Emby.Server.Implementations.Data "Filename", "MIMEType" }; + private static readonly string _mediaAttachmentInsertPrefix; private static string GetSaveItemCommandText() @@ -6208,7 +6209,10 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type return list; } - public void SaveMediaAttachments(Guid id, List attachments, CancellationToken cancellationToken) + public void SaveMediaAttachments( + Guid id, + List attachments, + CancellationToken cancellationToken) { CheckDisposed(); if (id == Guid.Empty) @@ -6237,24 +6241,22 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type } } - private void InsertMediaAttachments(byte[] idBlob, List attachments, IDatabaseConnection db, CancellationToken cancellationToken) + private void InsertMediaAttachments( + byte[] idBlob, + List attachments, + IDatabaseConnection db, + CancellationToken cancellationToken) { - var startIndex = 0; - var insertAtOnce = 10; + const int InsertAtOnce = 10; - while (startIndex < attachments.Count) + for (var startIndex = 0; startIndex < attachments.Count; startIndex += InsertAtOnce) { var insertText = new StringBuilder(_mediaAttachmentInsertPrefix); - var endIndex = Math.Min(attachments.Count, startIndex + insertAtOnce); + var endIndex = Math.Min(attachments.Count, startIndex + InsertAtOnce); for (var i = startIndex; i < endIndex; i++) { - if (i != startIndex) - { - insertText.Append(','); - } - var index = i.ToString(CultureInfo.InvariantCulture); insertText.Append("(@ItemId, "); @@ -6265,9 +6267,11 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type insertText.Length -= 1; - insertText.Append(")"); + insertText.Append("),"); } + insertText.Length--; + cancellationToken.ThrowIfCancellationRequested(); using (var statement = PrepareStatement(db, insertText.ToString())) @@ -6291,8 +6295,6 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type statement.Reset(); statement.MoveNext(); } - - startIndex += insertAtOnce; } } diff --git a/Emby.Server.Implementations/Library/MediaSourceManager.cs b/Emby.Server.Implementations/Library/MediaSourceManager.cs index 4eff2807c..ba1564d1f 100644 --- a/Emby.Server.Implementations/Library/MediaSourceManager.cs +++ b/Emby.Server.Implementations/Library/MediaSourceManager.cs @@ -136,15 +136,6 @@ namespace Emby.Server.Implementations.Library return _itemRepo.GetMediaAttachments(query); } - /// - public List GetMediaAttachments(string mediaSourceId) - { - return GetMediaAttachments(new MediaAttachmentQuery - { - ItemId = new Guid(mediaSourceId) - }); - } - /// public List GetMediaAttachments(Guid itemId) { diff --git a/Jellyfin.Api/Controllers/StartupController.cs b/Jellyfin.Api/Controllers/StartupController.cs index 1014c8c56..afc9b8f3d 100644 --- a/Jellyfin.Api/Controllers/StartupController.cs +++ b/Jellyfin.Api/Controllers/StartupController.cs @@ -96,7 +96,6 @@ namespace Jellyfin.Api.Controllers public StartupUserDto GetFirstUser() { var user = _userManager.Users.First(); - return new StartupUserDto { Name = user.Name, diff --git a/MediaBrowser.Api/Attachments/AttachmentService.cs b/MediaBrowser.Api/Attachments/AttachmentService.cs index 1ebfaa14b..ef09951b6 100644 --- a/MediaBrowser.Api/Attachments/AttachmentService.cs +++ b/MediaBrowser.Api/Attachments/AttachmentService.cs @@ -1,22 +1,14 @@ using System; -using System.Collections.Generic; -using System.Globalization; using System.IO; -using System.Linq; -using System.Text; using System.Threading; using System.Threading.Tasks; -using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.Net; -using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; -using MediaBrowser.Model.IO; -using MediaBrowser.Model.Providers; using MediaBrowser.Model.Services; using Microsoft.Extensions.Logging; -using MimeTypes = MediaBrowser.Model.Net.MimeTypes; namespace MediaBrowser.Api.Attachments { @@ -38,7 +30,13 @@ namespace MediaBrowser.Api.Attachments private readonly ILibraryManager _libraryManager; private readonly IAttachmentExtractor _attachmentExtractor; - public AttachmentService(ILibraryManager libraryManager, IAttachmentExtractor attachmentExtractor) + public AttachmentService( + ILogger logger, + IServerConfigurationManager serverConfigurationManager, + IHttpResultFactory httpResultFactory, + ILibraryManager libraryManager, + IAttachmentExtractor attachmentExtractor) + : base(logger, serverConfigurationManager, httpResultFactory) { _libraryManager = libraryManager; _attachmentExtractor = attachmentExtractor; @@ -46,7 +44,6 @@ namespace MediaBrowser.Api.Attachments public async Task Get(GetAttachment request) { - var item = (Video)_libraryManager.GetItemById(request.Id); var (attachment, attachmentStream) = await GetAttachment(request).ConfigureAwait(false); var mime = string.IsNullOrWhiteSpace(attachment.MIMEType) ? "application/octet-stream" : attachment.MIMEType; diff --git a/MediaBrowser.Controller/Library/IMediaSourceManager.cs b/MediaBrowser.Controller/Library/IMediaSourceManager.cs index dda8d397a..09e6fda88 100644 --- a/MediaBrowser.Controller/Library/IMediaSourceManager.cs +++ b/MediaBrowser.Controller/Library/IMediaSourceManager.cs @@ -41,21 +41,14 @@ namespace MediaBrowser.Controller.Library /// /// Gets the media attachments. /// - /// The item identifier. + /// The item identifier. /// IEnumerable<MediaAttachment>. List GetMediaAttachments(Guid itemId); /// /// Gets the media attachments. /// - /// The The media source identifier. - /// IEnumerable<MediaAttachment>. - - List GetMediaAttachments(string mediaSourceId); - /// - /// Gets the media attachments. - /// - /// The query. + /// The query. /// IEnumerable<MediaAttachment>. List GetMediaAttachments(MediaAttachmentQuery query); diff --git a/MediaBrowser.Controller/MediaEncoding/IAttachmentExtractor.cs b/MediaBrowser.Controller/MediaEncoding/IAttachmentExtractor.cs index 59c0a3f21..7c7e84de6 100644 --- a/MediaBrowser.Controller/MediaEncoding/IAttachmentExtractor.cs +++ b/MediaBrowser.Controller/MediaEncoding/IAttachmentExtractor.cs @@ -2,14 +2,14 @@ using System.IO; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Controller.Entities; -using MediaBrowser.Model.MediaInfo; using MediaBrowser.Model.Entities; namespace MediaBrowser.Controller.MediaEncoding { public interface IAttachmentExtractor { - Task<(MediaAttachment attachment, Stream stream)> GetAttachment(BaseItem item, + Task<(MediaAttachment attachment, Stream stream)> GetAttachment( + BaseItem item, string mediaSourceId, int attachmentStreamIndex, CancellationToken cancellationToken); diff --git a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs index cb22343c4..c371e8b94 100644 --- a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs +++ b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs @@ -4,44 +4,41 @@ using System.Collections.Concurrent; using System.Globalization; using System.IO; using System.Linq; -using System.Text; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.Net; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.MediaEncoding; -using MediaBrowser.Model.Diagnostics; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.IO; using MediaBrowser.Model.MediaInfo; -using MediaBrowser.Model.Serialization; using Microsoft.Extensions.Logging; -using UtfUnknown; namespace MediaBrowser.MediaEncoding.Attachments { - public class AttachmentExtractor : IAttachmentExtractor + public class AttachmentExtractor : IAttachmentExtractor, IDisposable { - private readonly ILibraryManager _libraryManager; private readonly ILogger _logger; private readonly IApplicationPaths _appPaths; private readonly IFileSystem _fileSystem; private readonly IMediaEncoder _mediaEncoder; private readonly IMediaSourceManager _mediaSourceManager; + private readonly ConcurrentDictionary _semaphoreLocks = + new ConcurrentDictionary(); + + private bool _disposed = false; + public AttachmentExtractor( - ILibraryManager libraryManager, ILogger logger, IApplicationPaths appPaths, IFileSystem fileSystem, IMediaEncoder mediaEncoder, IMediaSourceManager mediaSourceManager) { - _libraryManager = libraryManager; _logger = logger; _appPaths = appPaths; _fileSystem = fileSystem; @@ -49,8 +46,7 @@ namespace MediaBrowser.MediaEncoding.Attachments _mediaSourceManager = mediaSourceManager; } - private string AttachmentCachePath => Path.Combine(_appPaths.DataPath, "attachments"); - + /// public async Task<(MediaAttachment attachment, Stream stream)> GetAttachment(BaseItem item, string mediaSourceId, int attachmentStreamIndex, CancellationToken cancellationToken) { if (item == null) @@ -70,12 +66,14 @@ namespace MediaBrowser.MediaEncoding.Attachments { throw new ResourceNotFoundException($"MediaSource {mediaSourceId} not found"); } + var mediaAttachment = mediaSource.MediaAttachments .FirstOrDefault(i => i.Index == attachmentStreamIndex); if (mediaAttachment == null) { throw new ResourceNotFoundException($"MediaSource {mediaSourceId} has no attachment with stream index {attachmentStreamIndex}"); } + var attachmentStream = await GetAttachmentStream(mediaSource, mediaAttachment, cancellationToken) .ConfigureAwait(false); @@ -87,49 +85,32 @@ namespace MediaBrowser.MediaEncoding.Attachments MediaAttachment mediaAttachment, CancellationToken cancellationToken) { - var inputFiles = new[] { mediaSource.Path }; - var attachmentPath = await GetReadableFile(mediaSource.Path, inputFiles, mediaSource.Protocol, mediaAttachment, cancellationToken).ConfigureAwait(false); - var stream = await GetAttachmentStream(attachmentPath, cancellationToken).ConfigureAwait(false); - return stream; + var attachmentPath = await GetReadableFile(mediaSource.Path, mediaSource.Path, mediaSource.Protocol, mediaAttachment, cancellationToken).ConfigureAwait(false); + return File.OpenRead(attachmentPath); } - private async Task GetAttachmentStream( - string path, - CancellationToken cancellationToken) - { - return File.OpenRead(path); - } - - private async Task GetReadableFile( + private async Task GetReadableFile( string mediaPath, - string[] inputFiles, + string inputFile, MediaProtocol protocol, MediaAttachment mediaAttachment, CancellationToken cancellationToken) { var outputPath = GetAttachmentCachePath(mediaPath, protocol, mediaAttachment.Index); - await ExtractAttachment(inputFiles, protocol, mediaAttachment.Index, outputPath, cancellationToken) + await ExtractAttachment(inputFile, protocol, mediaAttachment.Index, outputPath, cancellationToken) .ConfigureAwait(false); return outputPath; } - private readonly ConcurrentDictionary _semaphoreLocks = - new ConcurrentDictionary(); - - private SemaphoreSlim GetLock(string filename) - { - return _semaphoreLocks.GetOrAdd(filename, key => new SemaphoreSlim(1, 1)); - } - private async Task ExtractAttachment( - string[] inputFiles, + string inputFile, MediaProtocol protocol, int attachmentStreamIndex, string outputPath, CancellationToken cancellationToken) { - var semaphore = GetLock(outputPath); + var semaphore = _semaphoreLocks.GetOrAdd(outputPath, key => new SemaphoreSlim(1, 1)); await semaphore.WaitAsync(cancellationToken).ConfigureAwait(false); @@ -137,7 +118,11 @@ namespace MediaBrowser.MediaEncoding.Attachments { if (!File.Exists(outputPath)) { - await ExtractAttachmentInternal(_mediaEncoder.GetInputArgument(inputFiles, protocol), attachmentStreamIndex, outputPath, cancellationToken).ConfigureAwait(false); + await ExtractAttachmentInternal( + _mediaEncoder.GetInputArgument(new[] { inputFile }, protocol), + attachmentStreamIndex, + outputPath, + cancellationToken).ConfigureAwait(false); } } finally @@ -186,16 +171,7 @@ namespace MediaBrowser.MediaEncoding.Attachments _logger.LogInformation("{File} {Arguments}", process.StartInfo.FileName, process.StartInfo.Arguments); - try - { - process.Start(); - } - catch (Exception ex) - { - _logger.LogError(ex, "Error starting ffmpeg"); - - throw; - } + process.Start(); var processTcs = new TaskCompletionSource(); process.EnableRaisingEvents = true; @@ -216,6 +192,7 @@ namespace MediaBrowser.MediaEncoding.Attachments _logger.LogError(ex, "Error killing attachment extraction process"); } } + var exitCode = ranToCompletion ? process.ExitCode : -1; process.Dispose(); @@ -270,9 +247,35 @@ namespace MediaBrowser.MediaEncoding.Attachments { filename = (mediaPath + attachmentStreamIndex.ToString(CultureInfo.InvariantCulture)).GetMD5().ToString("D"); } + var prefix = filename.Substring(0, 1); - return Path.Combine(AttachmentCachePath, prefix, filename); + return Path.Combine(_appPaths.DataPath, "attachments", prefix, filename); + } + + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); } + /// + /// Releases unmanaged and - optionally - managed resources. + /// + /// true to release both managed and unmanaged resources; false to release only unmanaged resources. + protected virtual void Dispose(bool disposing) + { + if (_disposed) + { + return; + } + + if (disposing) + { + + } + + _disposed = true; + } } } diff --git a/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs b/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs index d4aede572..c5da42089 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs @@ -43,7 +43,7 @@ namespace MediaBrowser.MediaEncoding.Encoder /// /// The path. /// System.String. - private static string GetFileInputArgument(string path) + public static string GetFileInputArgument(string path) { if (path.IndexOf("://") != -1) { -- cgit v1.2.3