Merge branch 'beta' of https://github.com/MediaBrowser/Emby into beta

This commit is contained in:
Luke Pulverenti 2016-06-20 02:50:41 -04:00
commit 2edaff2ad3
10 changed files with 185 additions and 113 deletions

View file

@ -19,12 +19,6 @@ namespace MediaBrowser.Controller.MediaEncoding
/// <value>The encoder path.</value>
string EncoderPath { get; }
/// <summary>
/// Gets the version.
/// </summary>
/// <value>The version.</value>
string Version { get; }
/// <summary>
/// Supportses the decoder.
/// </summary>
@ -134,5 +128,7 @@ namespace MediaBrowser.Controller.MediaEncoding
/// <param name="path">The path.</param>
/// <returns>System.String.</returns>
string EscapeSubtitleFilterPath(string path);
void Init();
}
}

View file

@ -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
{
@ -64,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;
@ -77,12 +77,12 @@ namespace MediaBrowser.MediaEncoding.Encoder
protected readonly Func<IMediaSourceManager> MediaSourceManager;
private readonly List<ProcessWrapper> _runningProcesses = new List<ProcessWrapper>();
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<ISubtitleEncoder> subtitleEncoder, Func<IMediaSourceManager> 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<ISubtitleEncoder> subtitleEncoder, Func<IMediaSourceManager> mediaSourceManager)
{
_logger = logger;
_jsonSerializer = jsonSerializer;
Version = version;
ConfigurationManager = configurationManager;
FileSystem = fileSystem;
LiveTvManager = liveTvManager;
@ -94,6 +94,95 @@ namespace MediaBrowser.MediaEncoding.Encoder
MediaSourceManager = mediaSourceManager;
FFProbePath = ffProbePath;
FFMpegPath = ffMpegPath;
_hasExternalEncoder = hasExternalEncoder;
}
public void Init()
{
ConfigureEncoderPaths();
if (_hasExternalEncoder)
{
LogPaths();
return;
}
// 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))
{
encodingOptions.EncoderAppPath = FFMpegPath;
ConfigurationManager.SaveConfiguration("encoding", encodingOptions);
}
}
private void ConfigureEncoderPaths()
{
if (_hasExternalEncoder)
{
return;
}
var appPath = GetEncodingOptions().EncoderAppPath;
if (string.IsNullOrWhiteSpace(appPath))
{
appPath = Path.Combine(ConfigurationManager.ApplicationPaths.ProgramDataPath, "ffmpeg");
}
if (!string.IsNullOrWhiteSpace(appPath))
{
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<EncodingOptions>("encoding");
}
private List<string> _encoders = new List<string>();

View file

@ -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()
{

View file

@ -152,6 +152,8 @@ namespace MediaBrowser.Model.System
/// <value><c>true</c> if [supports automatic run at startup]; otherwise, <c>false</c>.</value>
public bool SupportsAutoRunAtStartup { get; set; }
public bool HasExternalEncoder { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="SystemInfo" /> class.
/// </summary>

View file

@ -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);

View file

@ -944,9 +944,7 @@ namespace MediaBrowser.Server.Implementations.Library
private T CreateItemByName<T>(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<BaseItem> 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<BaseItem> 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<BaseItem> 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<BaseItem>
{
TotalRecordCount = initialResult.TotalRecordCount,
Items = initialResult.Items.Select(GetItemById).Where(i => i != null).ToArray()
};
}
if (!EnableCaching)
{
return new QueryResult<BaseItem>
{
Items = ItemRepository.GetItemList(query).ToArray()
};
return ItemRepository.GetItems(query);
}
return new QueryResult<BaseItem>
{
Items = ItemRepository.GetItemIdsList(query).Select(GetItemById).Where(i => i != null).ToArray()
Items = ItemRepository.GetItemList(query).ToArray()
};
}
@ -1499,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;
}))

View file

@ -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<LiveTvChannel>();
@ -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();

View file

@ -155,12 +155,14 @@ 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 index if not exists idx_UserDataKeys1 on UserDataKeys(ItemId)",
"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)",
//"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)",
@ -169,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)",
@ -270,13 +271,23 @@ 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)",
// 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_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)"
};
_connection.RunQueries(postQueries, Logger);

View file

@ -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<double> progress)
{
HttpPort = ServerConfigurationManager.Configuration.HttpServerPortNumber;
@ -634,11 +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.Equals(info.Version, "custom", StringComparison.OrdinalIgnoreCase);
var mediaEncoder = new MediaEncoder(LogManager.GetLogger("MediaEncoder"),
JsonSerializer,
info.EncoderPath,
info.ProbePath,
info.Version,
_hasExternalEncoder,
ServerConfigurationManager,
FileSystemManager,
LiveTvManager,
@ -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);
});
}
/// <summary>
@ -1094,6 +1104,7 @@ namespace MediaBrowser.Server.Startup.Common
}
}
private bool _hasExternalEncoder;
/// <summary>
/// Gets the system status.
/// </summary>
@ -1133,7 +1144,8 @@ namespace MediaBrowser.Server.Startup.Common
SupportsRunningAsService = SupportsRunningAsService,
ServerName = FriendlyName,
LocalAddress = localAddress,
SupportsLibraryMonitor = SupportsLibraryMonitor
SupportsLibraryMonitor = SupportsLibraryMonitor,
HasExternalEncoder = _hasExternalEncoder
};
}

View file

@ -21,13 +21,10 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg
_fileSystem = fileSystem;
}
public Tuple<List<string>,List<string>> Validate(FFMpegInfo info)
public Tuple<List<string>,List<string>> 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<string>, List<string>>(decoders, encoders);
}