From e69f7b757f8f3782d4a0b85a641f36005301aaae Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 19 Jun 2016 23:34:47 -0400 Subject: [PATCH 1/7] add userdata index --- .../Dto/DtoService.cs | 58 ++++++++----------- .../Library/LibraryManager.cs | 48 ++------------- .../Persistence/SqliteItemRepository.cs | 4 +- 3 files changed, 33 insertions(+), 77 deletions(-) diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs index 388dfd515d..a4cf90e5b0 100644 --- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs +++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs @@ -1276,26 +1276,22 @@ namespace MediaBrowser.Server.Implementations.Dto { dto.Artists = hasArtist.Artists; - dto.ArtistItems = hasArtist - .Artists + var artistItems = _libraryManager.GetArtists(new InternalItemsQuery + { + EnableTotalRecordCount = false, + ItemIds = new[] { item.Id.ToString("N") } + }); + + dto.ArtistItems = artistItems.Items .Select(i => { - try + var artist = i.Item1; + return new NameIdPair { - var artist = _libraryManager.GetArtist(i); - return new NameIdPair - { - Name = artist.Name, - Id = artist.Id.ToString("N") - }; - } - catch (Exception ex) - { - _logger.ErrorException("Error getting artist", ex); - return null; - } + Name = artist.Name, + Id = artist.Id.ToString("N") + }; }) - .Where(i => i != null) .ToList(); } @@ -1304,26 +1300,22 @@ namespace MediaBrowser.Server.Implementations.Dto { dto.AlbumArtist = hasAlbumArtist.AlbumArtists.FirstOrDefault(); - dto.AlbumArtists = hasAlbumArtist - .AlbumArtists + var artistItems = _libraryManager.GetAlbumArtists(new InternalItemsQuery + { + EnableTotalRecordCount = false, + ItemIds = new[] { item.Id.ToString("N") } + }); + + dto.ArtistItems = artistItems.Items .Select(i => { - try + var artist = i.Item1; + return new NameIdPair { - var artist = _libraryManager.GetArtist(i); - return new NameIdPair - { - Name = artist.Name, - Id = artist.Id.ToString("N") - }; - } - catch (Exception ex) - { - _logger.ErrorException("Error getting album artist", ex); - return null; - } + Name = artist.Name, + Id = artist.Id.ToString("N") + }; }) - .Where(i => i != null) .ToList(); } @@ -1604,7 +1596,7 @@ namespace MediaBrowser.Server.Implementations.Dto { IsFolder = false, Recursive = true, - ExcludeLocationTypes = new[] {LocationType.Virtual}, + ExcludeLocationTypes = new[] { LocationType.Virtual }, User = user }).ConfigureAwait(false); diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs index aabe704c7a..af00481001 100644 --- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs +++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs @@ -944,9 +944,7 @@ namespace MediaBrowser.Server.Implementations.Library private T CreateItemByName(string path, string name) where T : BaseItem, new() { - var isArtist = typeof(T) == typeof(MusicArtist); - - if (isArtist) + if (typeof(T) == typeof(MusicArtist)) { var existing = GetItemList(new InternalItemsQuery { @@ -1277,11 +1275,6 @@ namespace MediaBrowser.Server.Implementations.Library return item; } - private bool EnableCaching - { - get { return false; } - } - public IEnumerable GetItemList(InternalItemsQuery query) { if (query.User != null) @@ -1289,14 +1282,7 @@ namespace MediaBrowser.Server.Implementations.Library AddUserToQuery(query, query.User); } - if (!EnableCaching) - { - return ItemRepository.GetItemList(query); - } - - var result = ItemRepository.GetItemIdsList(query); - - return result.Select(GetItemById).Where(i => i != null); + return ItemRepository.GetItemList(query); } public QueryResult QueryItems(InternalItemsQuery query) @@ -1426,12 +1412,7 @@ namespace MediaBrowser.Server.Implementations.Library SetTopParentIdsOrAncestors(query, parents); - if (!EnableCaching) - { - return ItemRepository.GetItemList(query); - } - - return GetItemIds(query).Select(GetItemById).Where(i => i != null); + return ItemRepository.GetItemList(query); } public QueryResult GetItemsResult(InternalItemsQuery query) @@ -1453,31 +1434,12 @@ namespace MediaBrowser.Server.Implementations.Library if (query.EnableTotalRecordCount) { - if (!EnableCaching) - { - return ItemRepository.GetItems(query); - } - - var initialResult = ItemRepository.GetItemIds(query); - - return new QueryResult - { - TotalRecordCount = initialResult.TotalRecordCount, - Items = initialResult.Items.Select(GetItemById).Where(i => i != null).ToArray() - }; - } - - if (!EnableCaching) - { - return new QueryResult - { - Items = ItemRepository.GetItemList(query).ToArray() - }; + return ItemRepository.GetItems(query); } return new QueryResult { - Items = ItemRepository.GetItemIdsList(query).Select(GetItemById).Where(i => i != null).ToArray() + Items = ItemRepository.GetItemList(query).ToArray() }; } diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index e8b39a1fe3..5dae246572 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -155,8 +155,9 @@ namespace MediaBrowser.Server.Implementations.Persistence "create index if not exists idx_AncestorIds1 on AncestorIds(AncestorId)", "create index if not exists idx_AncestorIds2 on AncestorIds(AncestorIdText)", - "create table if not exists UserDataKeys (ItemId GUID, UserDataKey TEXT, PRIMARY KEY (ItemId, UserDataKey))", + "create table if not exists UserDataKeys (ItemId GUID, UserDataKey TEXT Priority INT, PRIMARY KEY (ItemId, UserDataKey))", "create index if not exists idx_UserDataKeys1 on UserDataKeys(ItemId)", + "create index if not exists idx_UserDataKeys2 on UserDataKeys(ItemId,Priority)", "create table if not exists ItemValues (ItemId GUID, Type INT, Value TEXT, CleanValue TEXT)", "create index if not exists idx_ItemValues on ItemValues(ItemId)", @@ -270,6 +271,7 @@ namespace MediaBrowser.Server.Implementations.Persistence { "create index if not exists idx_PresentationUniqueKey on TypedBaseItems(PresentationUniqueKey)", "create index if not exists idx_GuidType on TypedBaseItems(Guid,Type)", + "create index if not exists idx_CleanNameType on TypedBaseItems(CleanName,Type)", "create index if not exists idx_Type on TypedBaseItems(Type)", "create index if not exists idx_TopParentId on TypedBaseItems(TopParentId)", "create index if not exists idx_TypeTopParentId on TypedBaseItems(Type,TopParentId)", From 624ac450c283fb6acc23f40a98e7e0212b909a34 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 20 Jun 2016 00:14:47 -0400 Subject: [PATCH 2/7] update indexes --- .../LiveTv/LiveTvManager.cs | 18 ++++++++++++++---- .../Persistence/SqliteItemRepository.cs | 5 ++++- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs index 9f80877f63..29c4a43d38 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs @@ -140,10 +140,13 @@ namespace MediaBrowser.Server.Implementations.LiveTv { var user = string.IsNullOrEmpty(query.UserId) ? null : _userManager.GetUserById(query.UserId); + var topFolder = await GetInternalLiveTvFolder(cancellationToken).ConfigureAwait(false); + var channels = _libraryManager.GetItemList(new InternalItemsQuery { IncludeItemTypes = new[] { typeof(LiveTvChannel).Name }, - SortBy = new[] { ItemSortBy.SortName } + SortBy = new[] { ItemSortBy.SortName }, + TopParentIds = new[] { topFolder.Id.ToString("N") } }).Cast(); @@ -891,6 +894,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv { var user = string.IsNullOrEmpty(query.UserId) ? null : _userManager.GetUserById(query.UserId); + var topFolder = await GetInternalLiveTvFolder(cancellationToken).ConfigureAwait(false); + var internalQuery = new InternalItemsQuery(user) { IncludeItemTypes = new[] { typeof(LiveTvProgram).Name }, @@ -907,7 +912,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv Limit = query.Limit, SortBy = query.SortBy, SortOrder = query.SortOrder ?? SortOrder.Ascending, - EnableTotalRecordCount = query.EnableTotalRecordCount + EnableTotalRecordCount = query.EnableTotalRecordCount, + TopParentIds = new[] { topFolder.Id.ToString("N") } }; if (query.HasAired.HasValue) @@ -939,6 +945,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv { var user = _userManager.GetUserById(query.UserId); + var topFolder = await GetInternalLiveTvFolder(cancellationToken).ConfigureAwait(false); + var internalQuery = new InternalItemsQuery(user) { IncludeItemTypes = new[] { typeof(LiveTvProgram).Name }, @@ -947,7 +955,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv IsSports = query.IsSports, IsKids = query.IsKids, EnableTotalRecordCount = query.EnableTotalRecordCount, - SortBy = new[] { ItemSortBy.StartDate } + SortBy = new[] { ItemSortBy.StartDate }, + TopParentIds = new[] { topFolder.Id.ToString("N") } }; if (query.Limit.HasValue) @@ -1905,7 +1914,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv MaxStartDate = now, MinEndDate = now, Limit = channelIds.Length, - SortBy = new[] { "StartDate" } + SortBy = new[] { "StartDate" }, + TopParentIds = new[] { GetInternalLiveTvFolder(CancellationToken.None).Result.Id.ToString("N") } }, new string[] { }).ToList(); diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index 5dae246572..80de2b7ce9 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -278,7 +278,10 @@ namespace MediaBrowser.Server.Implementations.Persistence "create index if not exists idx_TypeTopParentId2 on TypedBaseItems(TopParentId,MediaType,IsVirtualItem)", "create index if not exists idx_TypeTopParentId3 on TypedBaseItems(TopParentId,IsFolder,IsVirtualItem)", "create index if not exists idx_TypeTopParentId4 on TypedBaseItems(TopParentId,Type,IsVirtualItem)", - "create index if not exists idx_TypeTopParentId5 on TypedBaseItems(TopParentId,IsVirtualItem)" + "create index if not exists idx_TypeTopParentId5 on TypedBaseItems(TopParentId,IsVirtualItem)", + "create index if not exists idx_TypeTopParentId6 on TypedBaseItems(TopParentId,Type,IsVirtualItem,PresentationUniqueKey)", + "create index if not exists idx_TypeTopParentId7 on TypedBaseItems(TopParentId,MediaType,IsVirtualItem,PresentationUniqueKey)", + "create index if not exists idx_TypeTopParentId8 on TypedBaseItems(TopParentId,IsFolder,IsVirtualItem,PresentationUniqueKey)" }; _connection.RunQueries(postQueries, Logger); From b0b0649280bdc01df94a6ef23ad5e502ad039a6d Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 20 Jun 2016 00:56:06 -0400 Subject: [PATCH 3/7] update indexes --- .../Library/LibraryManager.cs | 2 +- .../Persistence/SqliteItemRepository.cs | 14 ++++++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs index af00481001..883864156c 100644 --- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs +++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs @@ -1461,7 +1461,7 @@ namespace MediaBrowser.Server.Implementations.Library return true; } - _logger.Debug("Query requires ancestor query due to type: " + i.GetType().Name); + //_logger.Debug("Query requires ancestor query due to type: " + i.GetType().Name); return false; })) diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index 80de2b7ce9..ed5a64b8c8 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -156,12 +156,13 @@ namespace MediaBrowser.Server.Implementations.Persistence "create index if not exists idx_AncestorIds2 on AncestorIds(AncestorIdText)", "create table if not exists UserDataKeys (ItemId GUID, UserDataKey TEXT Priority INT, PRIMARY KEY (ItemId, UserDataKey))", - "create index if not exists idx_UserDataKeys1 on UserDataKeys(ItemId)", + //"create index if not exists idx_UserDataKeys1 on UserDataKeys(ItemId)", "create index if not exists idx_UserDataKeys2 on UserDataKeys(ItemId,Priority)", "create table if not exists ItemValues (ItemId GUID, Type INT, Value TEXT, CleanValue TEXT)", - "create index if not exists idx_ItemValues on ItemValues(ItemId)", + //"create index if not exists idx_ItemValues on ItemValues(ItemId)", "create index if not exists idx_ItemValues2 on ItemValues(ItemId,Type)", + "create index if not exists idx_ItemValues3 on ItemValues(ItemId,Type,CleanValue)", "create table if not exists ProviderIds (ItemId GUID, Name TEXT, Value TEXT, PRIMARY KEY (ItemId, Name))", "create index if not exists Idx_ProviderIds on ProviderIds(ItemId)", @@ -170,11 +171,10 @@ namespace MediaBrowser.Server.Implementations.Persistence "create index if not exists idx_Images on Images(ItemId)", "create table if not exists People (ItemId GUID, Name TEXT NOT NULL, Role TEXT, PersonType TEXT, SortOrder int, ListOrder int)", - "create index if not exists idxPeopleItemId on People(ItemId)", + "create index if not exists idxPeopleItemId1 on People(ItemId,ListOrder)", "create index if not exists idxPeopleName on People(Name)", "create table if not exists "+ChaptersTableName+" (ItemId GUID, ChapterIndex INT, StartPositionTicks BIGINT, Name TEXT, ImagePath TEXT, PRIMARY KEY (ItemId, ChapterIndex))", - "create index if not exists idx_"+ChaptersTableName+"1 on "+ChaptersTableName+"(ItemId)", createMediaStreamsTableCommand, "create index if not exists idx_mediastreams1 on mediastreams(ItemId)", @@ -275,11 +275,17 @@ namespace MediaBrowser.Server.Implementations.Persistence "create index if not exists idx_Type on TypedBaseItems(Type)", "create index if not exists idx_TopParentId on TypedBaseItems(TopParentId)", "create index if not exists idx_TypeTopParentId on TypedBaseItems(Type,TopParentId)", + + // used by movie suggestions + "create index if not exists idx_TypeTopParentIdGroup on TypedBaseItems(Type,TopParentId,PresentationUniqueKey)", "create index if not exists idx_TypeTopParentId2 on TypedBaseItems(TopParentId,MediaType,IsVirtualItem)", "create index if not exists idx_TypeTopParentId3 on TypedBaseItems(TopParentId,IsFolder,IsVirtualItem)", "create index if not exists idx_TypeTopParentId4 on TypedBaseItems(TopParentId,Type,IsVirtualItem)", "create index if not exists idx_TypeTopParentId5 on TypedBaseItems(TopParentId,IsVirtualItem)", "create index if not exists idx_TypeTopParentId6 on TypedBaseItems(TopParentId,Type,IsVirtualItem,PresentationUniqueKey)", + + // latest items + "create index if not exists idx_TypeTopParentId9 on TypedBaseItems(TopParentId,Type,IsVirtualItem,PresentationUniqueKey,DateCreated)", "create index if not exists idx_TypeTopParentId7 on TypedBaseItems(TopParentId,MediaType,IsVirtualItem,PresentationUniqueKey)", "create index if not exists idx_TypeTopParentId8 on TypedBaseItems(TopParentId,IsFolder,IsVirtualItem,PresentationUniqueKey)" }; From 6e9f8fb2d1a878369ee36b2e9ebfe7a54954183f Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 20 Jun 2016 02:19:28 -0400 Subject: [PATCH 4/7] allow customization of ffmpeg path --- .../MediaEncoding/IMediaEncoder.cs | 2 + .../Encoder/MediaEncoder.cs | 71 +++++++++++++++++++ .../Configuration/EncodingOptions.cs | 1 + MediaBrowser.Model/System/SystemInfo.cs | 2 + .../ApplicationHost.cs | 30 +++++--- .../FFMpeg/FFmpegValidator.cs | 9 +-- 6 files changed, 100 insertions(+), 15 deletions(-) diff --git a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs index 7c3959f6e8..023af7d1ad 100644 --- a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs +++ b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs @@ -134,5 +134,7 @@ namespace MediaBrowser.Controller.MediaEncoding /// The path. /// System.String. string EscapeSubtitleFilterPath(string path); + + void Init(); } } diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 399fdead9c..dafc63cfbd 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -21,6 +21,8 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; using CommonIO; +using MediaBrowser.Model.Configuration; +using MediaBrowser.Common.Configuration; namespace MediaBrowser.MediaEncoding.Encoder { @@ -77,6 +79,7 @@ namespace MediaBrowser.MediaEncoding.Encoder protected readonly Func MediaSourceManager; private readonly List _runningProcesses = new List(); + private readonly bool _hasExternalEncoder; public MediaEncoder(ILogger logger, IJsonSerializer jsonSerializer, string ffMpegPath, string ffProbePath, string version, IServerConfigurationManager configurationManager, IFileSystem fileSystem, ILiveTvManager liveTvManager, IIsoManager isoManager, ILibraryManager libraryManager, IChannelManager channelManager, ISessionManager sessionManager, Func subtitleEncoder, Func mediaSourceManager) { @@ -94,6 +97,74 @@ namespace MediaBrowser.MediaEncoding.Encoder MediaSourceManager = mediaSourceManager; FFProbePath = ffProbePath; FFMpegPath = ffMpegPath; + + _hasExternalEncoder = !string.IsNullOrWhiteSpace(ffMpegPath); + } + + public void Init() + { + ConfigureEncoderPaths(); + } + + private void ConfigureEncoderPaths() + { + if (_hasExternalEncoder) + { + LogPaths(); + return; + } + + var appPath = GetEncodingOptions().EncoderAppPath; + appPath = "C:\\dev\\Emby.dev\\ProgramData-Server\\ffmpeg"; + + if (Directory.Exists(appPath)) + { + SetPathsFromDirectory(appPath); + } + + else if (File.Exists(appPath)) + { + FFMpegPath = appPath; + + SetProbePathFromEncoderPath(appPath); + } + + LogPaths(); + } + + private void SetPathsFromDirectory(string path) + { + // Since we can't predict the file extension, first try directly within the folder + // If that doesn't pan out, then do a recursive search + var files = Directory.GetFiles(path); + + FFMpegPath = files.FirstOrDefault(i => string.Equals(Path.GetFileNameWithoutExtension(i), "ffmpeg", StringComparison.OrdinalIgnoreCase)); + FFProbePath = files.FirstOrDefault(i => string.Equals(Path.GetFileNameWithoutExtension(i), "ffprobe", StringComparison.OrdinalIgnoreCase)); + + if (string.IsNullOrWhiteSpace(FFMpegPath) || !File.Exists(FFMpegPath)) + { + files = Directory.GetFiles(path, "*", SearchOption.AllDirectories); + + FFMpegPath = files.FirstOrDefault(i => string.Equals(Path.GetFileNameWithoutExtension(i), "ffmpeg", StringComparison.OrdinalIgnoreCase)); + SetProbePathFromEncoderPath(FFMpegPath); + } + } + + private void SetProbePathFromEncoderPath(string appPath) + { + FFProbePath = Directory.GetFiles(Path.GetDirectoryName(appPath)) + .FirstOrDefault(i => string.Equals(Path.GetFileNameWithoutExtension(i), "ffprobe", StringComparison.OrdinalIgnoreCase)); + } + + private void LogPaths() + { + _logger.Info("FFMpeg: {0}", FFMpegPath ?? "not found"); + _logger.Info("FFProbe: {0}", FFProbePath ?? "not found"); + } + + private EncodingOptions GetEncodingOptions() + { + return ConfigurationManager.GetConfiguration("encoding"); } private List _encoders = new List(); diff --git a/MediaBrowser.Model/Configuration/EncodingOptions.cs b/MediaBrowser.Model/Configuration/EncodingOptions.cs index d33cf55775..91d28a2969 100644 --- a/MediaBrowser.Model/Configuration/EncodingOptions.cs +++ b/MediaBrowser.Model/Configuration/EncodingOptions.cs @@ -9,6 +9,7 @@ namespace MediaBrowser.Model.Configuration public bool EnableThrottling { get; set; } public int ThrottleDelaySeconds { get; set; } public string HardwareAccelerationType { get; set; } + public string EncoderAppPath { get; set; } public EncodingOptions() { diff --git a/MediaBrowser.Model/System/SystemInfo.cs b/MediaBrowser.Model/System/SystemInfo.cs index 6b54a90d44..73d5961f67 100644 --- a/MediaBrowser.Model/System/SystemInfo.cs +++ b/MediaBrowser.Model/System/SystemInfo.cs @@ -152,6 +152,8 @@ namespace MediaBrowser.Model.System /// true if [supports automatic run at startup]; otherwise, false. public bool SupportsAutoRunAtStartup { get; set; } + public bool HasExternalEncoder { get; set; } + /// /// Initializes a new instance of the class. /// diff --git a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs index 7341f56cbd..c6a180db1e 100644 --- a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs +++ b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs @@ -323,6 +323,8 @@ namespace MediaBrowser.Server.Startup.Common await base.RunStartupTasks().ConfigureAwait(false); + InitMediaEncoder(); + Logger.Info("ServerId: {0}", SystemId); Logger.Info("Core startup complete"); HttpServer.GlobalResponse = null; @@ -344,6 +346,20 @@ namespace MediaBrowser.Server.Startup.Common LogManager.RemoveConsoleOutput(); } + private void InitMediaEncoder() + { + MediaEncoder.Init(); + + Task.Run(() => + { + var result = new FFmpegValidator(Logger, ApplicationPaths, FileSystemManager).Validate(MediaEncoder.EncoderPath); + + var mediaEncoder = (MediaEncoder) MediaEncoder; + mediaEncoder.SetAvailableDecoders(result.Item1); + mediaEncoder.SetAvailableEncoders(result.Item2); + }); + } + public override Task Init(IProgress progress) { HttpPort = ServerConfigurationManager.Configuration.HttpServerPortNumber; @@ -634,6 +650,8 @@ namespace MediaBrowser.Server.Startup.Common var info = await new FFMpegLoader(Logger, ApplicationPaths, HttpClient, ZipClient, FileSystemManager, NativeApp.Environment, NativeApp.GetType().Assembly, NativeApp.GetFfmpegInstallInfo()) .GetFFMpegInfo(NativeApp.Environment, _startupOptions, progress).ConfigureAwait(false); + _hasExternalEncoder = !string.IsNullOrWhiteSpace(info.EncoderPath); + var mediaEncoder = new MediaEncoder(LogManager.GetLogger("MediaEncoder"), JsonSerializer, info.EncoderPath, @@ -651,14 +669,6 @@ namespace MediaBrowser.Server.Startup.Common MediaEncoder = mediaEncoder; RegisterSingleInstance(MediaEncoder); - - Task.Run(() => - { - var result = new FFmpegValidator(Logger, ApplicationPaths, FileSystemManager).Validate(info); - - mediaEncoder.SetAvailableDecoders(result.Item1); - mediaEncoder.SetAvailableEncoders(result.Item2); - }); } /// @@ -1094,6 +1104,7 @@ namespace MediaBrowser.Server.Startup.Common } } + private bool _hasExternalEncoder; /// /// Gets the system status. /// @@ -1133,7 +1144,8 @@ namespace MediaBrowser.Server.Startup.Common SupportsRunningAsService = SupportsRunningAsService, ServerName = FriendlyName, LocalAddress = localAddress, - SupportsLibraryMonitor = SupportsLibraryMonitor + SupportsLibraryMonitor = SupportsLibraryMonitor, + HasExternalEncoder = _hasExternalEncoder }; } diff --git a/MediaBrowser.Server.Startup.Common/FFMpeg/FFmpegValidator.cs b/MediaBrowser.Server.Startup.Common/FFMpeg/FFmpegValidator.cs index 0ae021407b..d92dc1b965 100644 --- a/MediaBrowser.Server.Startup.Common/FFMpeg/FFmpegValidator.cs +++ b/MediaBrowser.Server.Startup.Common/FFMpeg/FFmpegValidator.cs @@ -21,13 +21,10 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg _fileSystem = fileSystem; } - public Tuple,List> Validate(FFMpegInfo info) + public Tuple,List> Validate(string encoderPath) { - _logger.Info("FFMpeg: {0}", info.EncoderPath); - _logger.Info("FFProbe: {0}", info.ProbePath); - - var decoders = GetDecoders(info.EncoderPath); - var encoders = GetEncoders(info.EncoderPath); + var decoders = GetDecoders(encoderPath); + var encoders = GetEncoders(encoderPath); return new Tuple, List>(decoders, encoders); } From 6cb5b2cd72abbda45218b4f463522b5807b3bf00 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 20 Jun 2016 02:30:20 -0400 Subject: [PATCH 5/7] update ffmpeg path customization --- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index dafc63cfbd..61986e3bc0 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -115,7 +115,6 @@ namespace MediaBrowser.MediaEncoding.Encoder } var appPath = GetEncodingOptions().EncoderAppPath; - appPath = "C:\\dev\\Emby.dev\\ProgramData-Server\\ffmpeg"; if (Directory.Exists(appPath)) { From fb07b4640c60d5135097d25d71cad4d2e4b6131f Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 20 Jun 2016 02:45:35 -0400 Subject: [PATCH 6/7] update ffmpeg path customization --- .../MediaEncoding/IMediaEncoder.cs | 6 --- .../Encoder/MediaEncoder.cs | 46 ++++++++++++------- .../ApplicationHost.cs | 4 +- 3 files changed, 32 insertions(+), 24 deletions(-) diff --git a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs index 023af7d1ad..c00f76f22c 100644 --- a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs +++ b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs @@ -19,12 +19,6 @@ namespace MediaBrowser.Controller.MediaEncoding /// The encoder path. string EncoderPath { get; } - /// - /// Gets the version. - /// - /// The version. - string Version { get; } - /// /// Supportses the decoder. /// diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 61986e3bc0..fc627c232a 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -66,8 +66,6 @@ namespace MediaBrowser.MediaEncoding.Encoder public string FFProbePath { get; private set; } - public string Version { get; private set; } - protected readonly IServerConfigurationManager ConfigurationManager; protected readonly IFileSystem FileSystem; protected readonly ILiveTvManager LiveTvManager; @@ -81,11 +79,10 @@ namespace MediaBrowser.MediaEncoding.Encoder private readonly List _runningProcesses = new List(); private readonly bool _hasExternalEncoder; - public MediaEncoder(ILogger logger, IJsonSerializer jsonSerializer, string ffMpegPath, string ffProbePath, string version, IServerConfigurationManager configurationManager, IFileSystem fileSystem, ILiveTvManager liveTvManager, IIsoManager isoManager, ILibraryManager libraryManager, IChannelManager channelManager, ISessionManager sessionManager, Func subtitleEncoder, Func mediaSourceManager) + public MediaEncoder(ILogger logger, IJsonSerializer jsonSerializer, string ffMpegPath, string ffProbePath, bool hasExternalEncoder, IServerConfigurationManager configurationManager, IFileSystem fileSystem, ILiveTvManager liveTvManager, IIsoManager isoManager, ILibraryManager libraryManager, IChannelManager channelManager, ISessionManager sessionManager, Func subtitleEncoder, Func mediaSourceManager) { _logger = logger; _jsonSerializer = jsonSerializer; - Version = version; ConfigurationManager = configurationManager; FileSystem = fileSystem; LiveTvManager = liveTvManager; @@ -98,34 +95,51 @@ namespace MediaBrowser.MediaEncoding.Encoder FFProbePath = ffProbePath; FFMpegPath = ffMpegPath; - _hasExternalEncoder = !string.IsNullOrWhiteSpace(ffMpegPath); + _hasExternalEncoder = hasExternalEncoder; } public void Init() { ConfigureEncoderPaths(); - } - private void ConfigureEncoderPaths() - { if (_hasExternalEncoder) { LogPaths(); return; } - var appPath = GetEncodingOptions().EncoderAppPath; - - if (Directory.Exists(appPath)) + // If the path was passed in, save it into config now. + var encodingOptions = GetEncodingOptions(); + var appPath = encodingOptions.EncoderAppPath; + if (!string.IsNullOrWhiteSpace(FFMpegPath) && !string.Equals(FFMpegPath, appPath, StringComparison.Ordinal)) { - SetPathsFromDirectory(appPath); + encodingOptions.EncoderAppPath = FFMpegPath; + ConfigurationManager.SaveConfiguration("encoding", encodingOptions); + } + } + + private void ConfigureEncoderPaths() + { + if (_hasExternalEncoder) + { + return; } - else if (File.Exists(appPath)) - { - FFMpegPath = appPath; + var appPath = GetEncodingOptions().EncoderAppPath; - SetProbePathFromEncoderPath(appPath); + if (!string.IsNullOrWhiteSpace(appPath)) + { + if (Directory.Exists(appPath)) + { + SetPathsFromDirectory(appPath); + } + + else if (File.Exists(appPath)) + { + FFMpegPath = appPath; + + SetProbePathFromEncoderPath(appPath); + } } LogPaths(); diff --git a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs index c6a180db1e..1130d3a11b 100644 --- a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs +++ b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs @@ -650,13 +650,13 @@ namespace MediaBrowser.Server.Startup.Common var info = await new FFMpegLoader(Logger, ApplicationPaths, HttpClient, ZipClient, FileSystemManager, NativeApp.Environment, NativeApp.GetType().Assembly, NativeApp.GetFfmpegInstallInfo()) .GetFFMpegInfo(NativeApp.Environment, _startupOptions, progress).ConfigureAwait(false); - _hasExternalEncoder = !string.IsNullOrWhiteSpace(info.EncoderPath); + _hasExternalEncoder = string.Equals(info.Version, "custom", StringComparison.OrdinalIgnoreCase); var mediaEncoder = new MediaEncoder(LogManager.GetLogger("MediaEncoder"), JsonSerializer, info.EncoderPath, info.ProbePath, - info.Version, + _hasExternalEncoder, ServerConfigurationManager, FileSystemManager, LiveTvManager, From 39ed3696ad783765b083b4a99fa4d7d91f0fa32c Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 20 Jun 2016 02:47:12 -0400 Subject: [PATCH 7/7] update ffmpeg path config --- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index fc627c232a..39a2338568 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -127,6 +127,11 @@ namespace MediaBrowser.MediaEncoding.Encoder var appPath = GetEncodingOptions().EncoderAppPath; + if (string.IsNullOrWhiteSpace(appPath)) + { + appPath = Path.Combine(ConfigurationManager.ApplicationPaths.ProgramDataPath, "ffmpeg"); + } + if (!string.IsNullOrWhiteSpace(appPath)) { if (Directory.Exists(appPath))