aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Emby.Server.Implementations/ApplicationHost.cs23
-rw-r--r--Emby.Server.Implementations/ConfigurationOptions.cs9
-rw-r--r--Emby.Server.Implementations/Emby.Server.Implementations.csproj1
-rw-r--r--Emby.Server.Implementations/HttpServer/HttpListenerHost.cs2
-rw-r--r--Jellyfin.Server/Program.cs7
-rw-r--r--MediaBrowser.Api/Playback/BaseStreamingService.cs11
-rw-r--r--MediaBrowser.Api/Playback/Hls/BaseHlsService.cs34
-rw-r--r--MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs8
-rw-r--r--MediaBrowser.Api/Playback/Hls/VideoHlsService.cs66
-rw-r--r--MediaBrowser.Api/Playback/Progressive/AudioService.cs8
-rw-r--r--MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs8
-rw-r--r--MediaBrowser.Api/Playback/Progressive/VideoService.cs8
-rw-r--r--MediaBrowser.Api/Playback/UniversalAudioService.cs19
-rw-r--r--MediaBrowser.Controller/Entities/Video.cs5
-rw-r--r--MediaBrowser.Controller/Extensions/ConfigurationExtensions.cs36
-rw-r--r--MediaBrowser.Controller/MediaBrowser.Controller.csproj4
-rw-r--r--MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs31
-rw-r--r--MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs4
-rw-r--r--MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs191
-rw-r--r--MediaBrowser.MediaEncoding/Subtitles/ISubtitleWriter.cs2
-rw-r--r--MediaBrowser.MediaEncoding/Subtitles/JsonWriter.cs36
-rw-r--r--MediaBrowser.MediaEncoding/Subtitles/SrtWriter.cs17
-rw-r--r--MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs103
-rw-r--r--MediaBrowser.MediaEncoding/Subtitles/TtmlWriter.cs7
-rw-r--r--MediaBrowser.Model/Configuration/ServerConfiguration.cs1
-rw-r--r--MediaBrowser.Model/MediaInfo/SubtitleTrackInfo.cs7
-rw-r--r--MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs6
-rw-r--r--MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs2
28 files changed, 365 insertions, 291 deletions
diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs
index 8c625539a..aed0c14a2 100644
--- a/Emby.Server.Implementations/ApplicationHost.cs
+++ b/Emby.Server.Implementations/ApplicationHost.cs
@@ -841,16 +841,14 @@ namespace Emby.Server.Implementations
serviceCollection.AddSingleton(ChapterManager);
MediaEncoder = new MediaBrowser.MediaEncoding.Encoder.MediaEncoder(
- LoggerFactory,
- JsonSerializer,
- StartupOptions.FFmpegPath,
+ LoggerFactory.CreateLogger<MediaBrowser.MediaEncoding.Encoder.MediaEncoder>(),
ServerConfigurationManager,
FileSystemManager,
- () => SubtitleEncoder,
- () => MediaSourceManager,
ProcessFactory,
- 5000,
- LocalizationManager);
+ LocalizationManager,
+ () => SubtitleEncoder,
+ _configuration,
+ StartupOptions.FFmpegPath);
serviceCollection.AddSingleton(MediaEncoder);
EncodingManager = new MediaEncoder.EncodingManager(FileSystemManager, LoggerFactory, MediaEncoder, ChapterManager, LibraryManager);
@@ -867,10 +865,19 @@ namespace Emby.Server.Implementations
AuthService = new AuthService(LoggerFactory.CreateLogger<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<MediaBrowser.MediaEncoding.Subtitles.SubtitleEncoder>(),
+ ApplicationPaths,
+ FileSystemManager,
+ MediaEncoder,
+ HttpClient,
+ MediaSourceManager,
+ ProcessFactory);
serviceCollection.AddSingleton(SubtitleEncoder);
serviceCollection.AddSingleton(typeof(IResourceFileManager), typeof(ResourceFileManager));
+ serviceCollection.AddSingleton<EncodingHelper>();
_displayPreferencesRepository.Initialize();
diff --git a/Emby.Server.Implementations/ConfigurationOptions.cs b/Emby.Server.Implementations/ConfigurationOptions.cs
index 62408ee70..a55a9eb2d 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<string, string> Configuration = new Dictionary<string, string>
+ public static Dictionary<string, string> Configuration => new Dictionary<string, string>
{
- { "HttpListenerHost:DefaultRedirectPath", "web/index.html" },
- { "MusicBrainz:BaseUrl", "https://www.musicbrainz.org" }
+ { "HttpListenerHost_DefaultRedirectPath", "web/index.html" },
+ { "MusicBrainz_BaseUrl", "https://www.musicbrainz.org" },
+ { FfmpegProbeSizeKey, "1G" },
+ { FfmpegAnalyzeDurationKey, "200M" }
};
}
}
diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj
index fde4d7059..eb14bd519 100644
--- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj
+++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj
@@ -29,7 +29,6 @@
<PackageReference Include="Microsoft.AspNetCore.ResponseCompression" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.WebSockets" Version="2.2.1" />
- <PackageReference Include="Microsoft.Extensions.Logging" Version="3.0.1" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.0.1" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="3.0.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="3.0.1" />
diff --git a/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs b/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs
index 2aefc9fe5..b77c53d87 100644
--- a/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs
+++ b/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs
@@ -57,7 +57,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 5ac005b40..712990a1e 100644
--- a/Jellyfin.Server/Program.cs
+++ b/Jellyfin.Server/Program.cs
@@ -7,6 +7,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;
@@ -145,6 +146,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);
@@ -456,9 +461,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 1e9cd3313..1c83e1cbb 100644
--- a/MediaBrowser.Api/Playback/BaseStreamingService.cs
+++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs
@@ -63,8 +63,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; }
@@ -92,11 +90,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)
: base(logger, serverConfigurationManager, httpResultFactory)
{
UserManager = userManager;
@@ -105,13 +103,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;
}
/// <summary>
@@ -148,8 +145,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 8fdc6fa49..5d0dc98dd 100644
--- a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
+++ b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
@@ -34,26 +34,26 @@ namespace MediaBrowser.Api.Playback.Hls
IMediaEncoder mediaEncoder,
IFileSystem fileSystem,
IDlnaManager dlnaManager,
- ISubtitleEncoder subtitleEncoder,
IDeviceManager deviceManager,
IMediaSourceManager mediaSourceManager,
IJsonSerializer jsonSerializer,
- IAuthorizationContext authorizationContext)
- : base(
- logger,
- serverConfigurationManager,
- httpResultFactory,
- userManager,
- libraryManager,
- isoManager,
- mediaEncoder,
- fileSystem,
- dlnaManager,
- subtitleEncoder,
- deviceManager,
- mediaSourceManager,
- jsonSerializer,
- authorizationContext)
+ IAuthorizationContext authorizationContext,
+ EncodingHelper encodingHelper)
+ : base(
+ logger,
+ serverConfigurationManager,
+ httpResultFactory,
+ userManager,
+ libraryManager,
+ isoManager,
+ mediaEncoder,
+ fileSystem,
+ dlnaManager,
+ deviceManager,
+ mediaSourceManager,
+ jsonSerializer,
+ authorizationContext,
+ encodingHelper)
{
}
diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
index f09c7e9f2..43e7ea373 100644
--- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
+++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
@@ -104,12 +104,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(
logger,
serverConfigurationManager,
@@ -120,11 +120,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 6d12a1ccd..d1c53c1c1 100644
--- a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs
+++ b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs
@@ -27,6 +27,39 @@ namespace MediaBrowser.Api.Playback.Hls
[Authenticated]
public class VideoHlsService : BaseHlsService
{
+ public VideoHlsService(
+ ILogger<VideoHlsService> logger,
+ IServerConfigurationManager serverConfigurationManager,
+ IHttpResultFactory httpResultFactory,
+ IUserManager userManager,
+ ILibraryManager libraryManager,
+ IIsoManager isoManager,
+ IMediaEncoder mediaEncoder,
+ IFileSystem fileSystem,
+ IDlnaManager dlnaManager,
+ IDeviceManager deviceManager,
+ IMediaSourceManager mediaSourceManager,
+ IJsonSerializer jsonSerializer,
+ IAuthorizationContext authorizationContext,
+ EncodingHelper encodingHelper)
+ : base(
+ logger,
+ serverConfigurationManager,
+ httpResultFactory,
+ userManager,
+ libraryManager,
+ isoManager,
+ mediaEncoder,
+ fileSystem,
+ dlnaManager,
+ deviceManager,
+ mediaSourceManager,
+ jsonSerializer,
+ authorizationContext,
+ encodingHelper)
+ {
+ }
+
public Task<object> Get(GetLiveHlsStream request)
{
return ProcessRequestAsync(request, true);
@@ -136,38 +169,5 @@ namespace MediaBrowser.Api.Playback.Hls
return args;
}
-
- public VideoHlsService(
- ILogger<VideoHlsService> logger,
- IServerConfigurationManager serverConfigurationManager,
- IHttpResultFactory httpResultFactory,
- IUserManager userManager,
- ILibraryManager libraryManager,
- IIsoManager isoManager,
- IMediaEncoder mediaEncoder,
- IFileSystem fileSystem,
- IDlnaManager dlnaManager,
- ISubtitleEncoder subtitleEncoder,
- IDeviceManager deviceManager,
- IMediaSourceManager mediaSourceManager,
- IJsonSerializer jsonSerializer,
- IAuthorizationContext authorizationContext)
- : base(
- logger,
- serverConfigurationManager,
- httpResultFactory,
- 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 11527007b..8d1e3a3f2 100644
--- a/MediaBrowser.Api/Playback/Progressive/AudioService.cs
+++ b/MediaBrowser.Api/Playback/Progressive/AudioService.cs
@@ -43,11 +43,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(
logger,
serverConfigurationManager,
@@ -59,11 +59,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 4ada90d09..ed30dbba6 100644
--- a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs
+++ b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs
@@ -38,11 +38,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(
logger,
serverConfigurationManager,
@@ -53,11 +53,11 @@ namespace MediaBrowser.Api.Playback.Progressive
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 56ec86cd4..4de81655c 100644
--- a/MediaBrowser.Api/Playback/Progressive/VideoService.cs
+++ b/MediaBrowser.Api/Playback/Progressive/VideoService.cs
@@ -80,11 +80,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(
logger,
serverConfigurationManager,
@@ -96,11 +96,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 b1450e2cc..9cba9df13 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(
ILogger<UniversalAudioService> logger,
IServerConfigurationManager serverConfigurationManager,
@@ -87,11 +89,11 @@ namespace MediaBrowser.Api.Playback
IFileSystem fileSystem,
IDlnaManager dlnaManager,
IDeviceManager deviceManager,
- ISubtitleEncoder subtitleEncoder,
IMediaSourceManager mediaSourceManager,
IJsonSerializer jsonSerializer,
IAuthorizationContext authorizationContext,
- INetworkManager networkManager)
+ INetworkManager networkManager,
+ EncodingHelper encodingHelper)
: base(logger, serverConfigurationManager, httpResultFactory)
{
HttpClient = httpClient;
@@ -102,11 +104,11 @@ namespace MediaBrowser.Api.Playback
FileSystem = fileSystem;
DlnaManager = dlnaManager;
DeviceManager = deviceManager;
- SubtitleEncoder = subtitleEncoder;
MediaSourceManager = mediaSourceManager;
JsonSerializer = jsonSerializer;
AuthorizationContext = authorizationContext;
NetworkManager = networkManager;
+ _encodingHelper = encodingHelper;
}
protected IHttpClient HttpClient { get; private set; }
@@ -117,7 +119,6 @@ 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 IJsonSerializer JsonSerializer { get; private set; }
protected IAuthorizationContext AuthorizationContext { get; private set; }
@@ -287,12 +288,12 @@ namespace MediaBrowser.Api.Playback
MediaEncoder,
FileSystem,
DlnaManager,
- SubtitleEncoder,
DeviceManager,
MediaSourceManager,
JsonSerializer,
AuthorizationContext,
- NetworkManager)
+ NetworkManager,
+ _encodingHelper)
{
Request = Request
};
@@ -337,11 +338,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
/// <value>The video3 D format.</value>
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<string>();
}
- return mediaEncoder.GetPlayableStreamFileNames(Path, videoType);
+
+ throw new NotImplementedException();
}
/// <summary>
diff --git a/MediaBrowser.Controller/Extensions/ConfigurationExtensions.cs b/MediaBrowser.Controller/Extensions/ConfigurationExtensions.cs
new file mode 100644
index 000000000..4048207bd
--- /dev/null
+++ b/MediaBrowser.Controller/Extensions/ConfigurationExtensions.cs
@@ -0,0 +1,36 @@
+using Microsoft.Extensions.Configuration;
+
+namespace MediaBrowser.Controller.Extensions
+{
+ /// <summary>
+ /// Configuration extensions for <c>MediaBrowser.Controller</c>.
+ /// </summary>
+ public static class ConfigurationExtensions
+ {
+ /// <summary>
+ /// The key for the FFmpeg probe size option.
+ /// </summary>
+ public const string FfmpegProbeSizeKey = "FFmpeg_probesize";
+
+ /// <summary>
+ /// The key for the FFmpeg analyse duration option.
+ /// </summary>
+ public const string FfmpegAnalyzeDurationKey = "FFmpeg_analyzeduration";
+
+ /// <summary>
+ /// Retrieves the FFmpeg probe size from the <see cref="IConfiguration" />.
+ /// </summary>
+ /// <param name="configuration">This configuration.</param>
+ /// <returns>The FFmpeg probe size option.</returns>
+ public static string GetProbeSize(this IConfiguration configuration)
+ => configuration[FfmpegProbeSizeKey];
+
+ /// <summary>
+ /// Retrieves the FFmpeg analyse duration from the <see cref="IConfiguration" />.
+ /// </summary>
+ /// <param name="configuration">This configuration.</param>
+ /// <returns>The FFmpeg analyse duration option.</returns>
+ public static string GetAnalyzeDuration(this IConfiguration configuration)
+ => configuration[FfmpegAnalyzeDurationKey];
+ }
+}
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
@@ -8,6 +8,10 @@
</PropertyGroup>
<ItemGroup>
+ <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="3.0.0" />
+ </ItemGroup>
+
+ <ItemGroup>
<ProjectReference Include="..\MediaBrowser.Model\MediaBrowser.Model.csproj" />
<ProjectReference Include="..\MediaBrowser.Common\MediaBrowser.Common.csproj" />
</ItemGroup>
diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
index 0664bdd98..370468958 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
/// </summary>
public interface IMediaEncoder : ITranscoderSupport
{
+ /// <summary>
+ /// The location of the discovered FFmpeg tool.
+ /// </summary>
FFmpegLocation EncoderLocation { get; }
/// <summary>
@@ -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<string> 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
{
/// <summary>
- /// Gets the encoder path.
+ /// The default image extraction timeout in milliseconds.
/// </summary>
- /// <value>The encoder path.</value>
- public string EncoderPath => FFmpegPath;
-
- /// <summary>
- /// The location of the discovered FFmpeg tool.
- /// </summary>
- 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<ISubtitleEncoder> SubtitleEncoder;
- protected readonly Func<IMediaSourceManager> 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<ISubtitleEncoder> _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<ProcessWrapper> _runningProcesses = new List<ProcessWrapper>();
- private readonly ILocalizationManager _localization;
+
+ private EncodingHelper _encodingHelper;
+
+ private string _ffmpegPath;
+ private string _ffprobePath;
public MediaEncoder(
- ILoggerFactory loggerFactory,
- IJsonSerializer jsonSerializer,
- string startupOptionsFFmpegPath,
+ ILogger<MediaEncoder> logger,
IServerConfigurationManager configurationManager,
IFileSystem fileSystem,
- Func<ISubtitleEncoder> subtitleEncoder,
- Func<IMediaSourceManager> 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<ISubtitleEncoder> 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));
+
+ /// <inheritdoc />
+ public string EncoderPath => _ffmpegPath;
+
+ /// <inheritdoc />
+ public FFmpegLocation EncoderLocation { get; private set; }
+
/// <summary>
/// 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 <EncoderAppPath> takes precedence
- if (!ValidatePath(ConfigurationManager.GetConfiguration<EncodingOptions>("encoding").EncoderAppPath, FFmpegLocation.Custom))
+ if (!ValidatePath(_configurationManager.GetConfiguration<EncodingOptions>("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 <EncoderAppPathDisplay> so it appears in UI
- var config = ConfigurationManager.GetConfiguration<EncodingOptions>("encoding");
- config.EncoderAppPathDisplay = FFmpegPath ?? string.Empty;
- ConfigurationManager.SaveConfiguration("encoding", config);
+ var config = _configurationManager.GetConfiguration<EncodingOptions>("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);
}
/// <summary>
@@ -160,9 +165,9 @@ namespace MediaBrowser.MediaEncoding.Encoder
// Write the new ffmpeg path to the xml as <EncoderAppPath>
// This ensures its not lost on next startup
- var config = ConfigurationManager.GetConfiguration<EncodingOptions>("encoding");
+ var config = _configurationManager.GetConfiguration<EncodingOptions>("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<InternalMediaInfoResult>(
+ result = await JsonSerializer.DeserializeAsync<InternalMediaInfoResult>(
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<ProcessWrapper> proceses;
- lock (_runningProcesses)
+ lock (_runningProcessesLock)
{
proceses = _runningProcesses.ToList();
_runningProcesses.Clear();
@@ -827,12 +830,11 @@ namespace MediaBrowser.MediaEncoding.Encoder
return path.Replace('\\', '/').Replace(":", "\\:").Replace("'", "'\\\\\\''");
}
- /// <summary>
- /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
- /// </summary>
+ /// <inheritdoc />
public void Dispose()
{
Dispose(true);
+ GC.SuppressFinalize(this);
}
/// <summary>
@@ -852,11 +854,6 @@ namespace MediaBrowser.MediaEncoding.Encoder
throw new NotImplementedException();
}
- public string[] GetPlayableStreamFileNames(string path, VideoType videoType)
- {
- throw new NotImplementedException();
- }
-
public IEnumerable<string> 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
{
/// <summary>
- /// Interface ISubtitleWriter
+ /// Interface ISubtitleWriter.
/// </summary>
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
{
+ /// <summary>
+ /// JSON subtitle writer.
+ /// </summary>
public class JsonWriter : ISubtitleWriter
{
- private readonly IJsonSerializer _json;
-
- public JsonWriter(IJsonSerializer json)
- {
- _json = json;
- }
-
+ /// <inheritdoc />
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<SubtitleEncoder> 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<Stream> GetSubtitleStream(string path, string language, MediaProtocol protocol, bool requiresCharset, CancellationToken cancellationToken)
+ private async Task<Stream> 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
}
}
+ /// <inheritdoc />
public async Task<string> 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<byte[]> GetBytes(string path, MediaProtocol protocol, CancellationToken cancellationToken)
+ private Task<Stream> 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<Stream>(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("</tt>");
}
}
-
- 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 9de6fef61..cf6d9c2f6 100644
--- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs
+++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs
@@ -233,7 +233,6 @@ namespace MediaBrowser.Model.Configuration
LocalNetworkSubnets = Array.Empty<string>();
LocalNetworkAddresses = Array.Empty<string>();
CodecsUsed = Array.Empty<string>();
- ImageExtractionTimeoutMs = 0;
PathSubstitutions = Array.Empty<PathSubstitution>();
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<SubtitleTrackEvent> TrackEvents { get; set; }
public SubtitleTrackInfo()
{
- TrackEvents = new SubtitleTrackEvent[] { };
+ TrackEvents = Array.Empty<SubtitleTrackEvent>();
}
}
}
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();