diff options
| author | Luke Pulverenti <luke.pulverenti@gmail.com> | 2013-04-07 16:55:05 -0400 |
|---|---|---|
| committer | Luke Pulverenti <luke.pulverenti@gmail.com> | 2013-04-07 16:55:05 -0400 |
| commit | cb39f8e7b5f71dcf0de2681d953b016e29adbc54 (patch) | |
| tree | fd2ef9a2a8b284a8810ece7b6ead4df0da3d133d /MediaBrowser.Controller/Providers | |
| parent | d14c3b31ff5665b03fee07aab46532fcf3069c1a (diff) | |
extracted a media encoding interface to keep ffmpeg out of nuget packages
Diffstat (limited to 'MediaBrowser.Controller/Providers')
8 files changed, 217 insertions, 99 deletions
diff --git a/MediaBrowser.Controller/Providers/IProviderManager.cs b/MediaBrowser.Controller/Providers/IProviderManager.cs index 902ed21bcd..cb7237a9df 100644 --- a/MediaBrowser.Controller/Providers/IProviderManager.cs +++ b/MediaBrowser.Controller/Providers/IProviderManager.cs @@ -1,13 +1,12 @@ -using System.Collections.Generic; -using MediaBrowser.Controller.Entities; -using System; +using MediaBrowser.Controller.Entities; +using System.Collections.Generic; using System.IO; using System.Threading; using System.Threading.Tasks; namespace MediaBrowser.Controller.Providers { - public interface IProviderManager : IDisposable + public interface IProviderManager { /// <summary> /// Downloads the and save image. diff --git a/MediaBrowser.Controller/Providers/MediaInfo/BaseFFMpegProvider.cs b/MediaBrowser.Controller/Providers/MediaInfo/BaseFFMpegProvider.cs index 6edd28b245..9fa6363a83 100644 --- a/MediaBrowser.Controller/Providers/MediaInfo/BaseFFMpegProvider.cs +++ b/MediaBrowser.Controller/Providers/MediaInfo/BaseFFMpegProvider.cs @@ -1,4 +1,5 @@ using MediaBrowser.Common.IO; +using MediaBrowser.Common.MediaInfo; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Model.Entities; @@ -15,8 +16,11 @@ namespace MediaBrowser.Controller.Providers.MediaInfo public abstract class BaseFFMpegProvider<T> : BaseMetadataProvider where T : BaseItem { - protected BaseFFMpegProvider(ILogManager logManager, IServerConfigurationManager configurationManager) : base(logManager, configurationManager) + protected readonly IMediaEncoder MediaEncoder; + + protected BaseFFMpegProvider(ILogManager logManager, IServerConfigurationManager configurationManager, IMediaEncoder mediaEncoder) : base(logManager, configurationManager) { + MediaEncoder = mediaEncoder; } /// <summary> @@ -53,7 +57,7 @@ namespace MediaBrowser.Controller.Providers.MediaInfo { get { - return Kernel.Instance.FFMpegManager.FFMpegVersion; + return MediaEncoder.Version; } } diff --git a/MediaBrowser.Controller/Providers/MediaInfo/BaseFFProbeProvider.cs b/MediaBrowser.Controller/Providers/MediaInfo/BaseFFProbeProvider.cs index 7c977d02f7..eac10d5221 100644 --- a/MediaBrowser.Controller/Providers/MediaInfo/BaseFFProbeProvider.cs +++ b/MediaBrowser.Controller/Providers/MediaInfo/BaseFFProbeProvider.cs @@ -1,12 +1,13 @@ -using System.Globalization; -using MediaBrowser.Common.IO; +using MediaBrowser.Common.IO; +using MediaBrowser.Common.MediaInfo; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.MediaInfo; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; +using MediaBrowser.Model.Serialization; using System; using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Threading; using System.Threading.Tasks; @@ -17,13 +18,17 @@ namespace MediaBrowser.Controller.Providers.MediaInfo /// Provides a base class for extracting media information through ffprobe /// </summary> /// <typeparam name="T"></typeparam> - public abstract class BaseFFProbeProvider<T> : BaseFFMpegProvider<T>, IDisposable + public abstract class BaseFFProbeProvider<T> : BaseFFMpegProvider<T> where T : BaseItem { - protected BaseFFProbeProvider(ILogManager logManager, IServerConfigurationManager configurationManager) : base(logManager, configurationManager) + protected BaseFFProbeProvider(ILogManager logManager, IServerConfigurationManager configurationManager, IMediaEncoder mediaEncoder, IProtobufSerializer protobufSerializer) + : base(logManager, configurationManager, mediaEncoder) { + ProtobufSerializer = protobufSerializer; } + protected readonly IProtobufSerializer ProtobufSerializer; + /// <summary> /// Gets or sets the FF probe cache. /// </summary> @@ -81,11 +86,7 @@ namespace MediaBrowser.Controller.Providers.MediaInfo { OnPreFetch(myItem, isoMount); - var inputPath = isoMount == null ? - Kernel.Instance.FFMpegManager.GetInputArgument(myItem) : - Kernel.Instance.FFMpegManager.GetInputArgument((Video)item, isoMount); - - var result = await Kernel.Instance.FFMpegManager.RunFFProbe(item, inputPath, item.DateModified, FFProbeCache, cancellationToken).ConfigureAwait(false); + var result = await GetMediaInfo(item, isoMount, item.DateModified, FFProbeCache, cancellationToken).ConfigureAwait(false); cancellationToken.ThrowIfCancellationRequested(); @@ -111,6 +112,61 @@ namespace MediaBrowser.Controller.Providers.MediaInfo } /// <summary> + /// Gets the media info. + /// </summary> + /// <param name="item">The item.</param> + /// <param name="isoMount">The iso mount.</param> + /// <param name="lastDateModified">The last date modified.</param> + /// <param name="cache">The cache.</param> + /// <param name="cancellationToken">The cancellation token.</param> + /// <returns>Task{MediaInfoResult}.</returns> + /// <exception cref="System.ArgumentNullException">inputPath + /// or + /// cache</exception> + private async Task<MediaInfoResult> GetMediaInfo(BaseItem item, IIsoMount isoMount, DateTime lastDateModified, FileSystemRepository cache, CancellationToken cancellationToken) + { + if (cache == null) + { + throw new ArgumentNullException("cache"); + } + + // Put the ffmpeg version into the cache name so that it's unique per-version + // We don't want to try and deserialize data based on an old version, which could potentially fail + var resourceName = item.Id + "_" + lastDateModified.Ticks + "_" + MediaEncoder.Version; + + // Forumulate the cache file path + var cacheFilePath = cache.GetResourcePath(resourceName, ".pb"); + + cancellationToken.ThrowIfCancellationRequested(); + + // Avoid File.Exists by just trying to deserialize + try + { + return ProtobufSerializer.DeserializeFromFile<MediaInfoResult>(cacheFilePath); + } + catch (FileNotFoundException) + { + // Cache file doesn't exist + } + + var type = InputType.AudioFile; + var inputPath = isoMount == null ? new[] { item.Path } : new[] { isoMount.MountedPath }; + + var video = item as Video; + + if (video != null) + { + inputPath = MediaEncoderHelpers.GetInputArgument(video, isoMount, out type); + } + + var info = await MediaEncoder.GetMediaInfo(inputPath, type, cancellationToken).ConfigureAwait(false); + + ProtobufSerializer.SerializeToFile(info, cacheFilePath); + + return info; + } + + /// <summary> /// Gets a value indicating whether [refresh on version change]. /// </summary> /// <value><c>true</c> if [refresh on version change]; otherwise, <c>false</c>.</value> @@ -147,7 +203,7 @@ namespace MediaBrowser.Controller.Providers.MediaInfo /// Normalizes the FF probe result. /// </summary> /// <param name="result">The result.</param> - private void NormalizeFFProbeResult(FFProbeResult result) + private void NormalizeFFProbeResult(MediaInfoResult result) { if (result.format != null && result.format.tags != null) { @@ -180,7 +236,7 @@ namespace MediaBrowser.Controller.Providers.MediaInfo /// <param name="result">The result.</param> /// <param name="isoMount">The iso mount.</param> /// <returns>Task.</returns> - protected abstract void Fetch(T item, CancellationToken cancellationToken, FFProbeResult result, IIsoMount isoMount); + protected abstract void Fetch(T item, CancellationToken cancellationToken, MediaInfoResult result, IIsoMount isoMount); /// <summary> /// Converts ffprobe stream info to our MediaStream class @@ -188,7 +244,7 @@ namespace MediaBrowser.Controller.Providers.MediaInfo /// <param name="streamInfo">The stream info.</param> /// <param name="formatInfo">The format info.</param> /// <returns>MediaStream.</returns> - protected MediaStream GetMediaStream(FFProbeMediaStreamInfo streamInfo, FFProbeMediaFormatInfo formatInfo) + protected MediaStream GetMediaStream(MediaStreamInfo streamInfo, MediaFormatInfo formatInfo) { var stream = new MediaStream { @@ -360,22 +416,5 @@ namespace MediaBrowser.Controller.Providers.MediaInfo { return new Dictionary<string, string>(dict, StringComparer.OrdinalIgnoreCase); } - - /// <summary> - /// Releases unmanaged and - optionally - managed resources. - /// </summary> - /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param> - protected virtual void Dispose(bool dispose) - { - if (dispose) - { - FFProbeCache.Dispose(); - } - } - - public void Dispose() - { - Dispose(true); - } } } diff --git a/MediaBrowser.Controller/Providers/MediaInfo/FFMpegAudioImageProvider.cs b/MediaBrowser.Controller/Providers/MediaInfo/FFMpegAudioImageProvider.cs index 68e552d3c4..421b0522da 100644 --- a/MediaBrowser.Controller/Providers/MediaInfo/FFMpegAudioImageProvider.cs +++ b/MediaBrowser.Controller/Providers/MediaInfo/FFMpegAudioImageProvider.cs @@ -1,10 +1,11 @@ -using System.Collections.Concurrent; +using MediaBrowser.Common.MediaInfo; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; using System; +using System.Collections.Concurrent; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -16,8 +17,8 @@ namespace MediaBrowser.Controller.Providers.MediaInfo /// </summary> public class FFMpegAudioImageProvider : BaseFFMpegProvider<Audio> { - public FFMpegAudioImageProvider(ILogManager logManager, IServerConfigurationManager configurationManager) - : base(logManager, configurationManager) + public FFMpegAudioImageProvider(ILogManager logManager, IServerConfigurationManager configurationManager, IMediaEncoder mediaEncoder) + : base(logManager, configurationManager, mediaEncoder) { } @@ -94,12 +95,11 @@ namespace MediaBrowser.Controller.Providers.MediaInfo { try { - var imageSucceeded = await Kernel.Instance.FFMpegManager.ExtractAudioImage(audio.Path, path, cancellationToken).ConfigureAwait(false); - - if (!imageSucceeded) - { - success = ProviderRefreshStatus.Failure; - } + await MediaEncoder.ExtractImage(new[] { audio.Path }, InputType.AudioFile, null, path, cancellationToken).ConfigureAwait(false); + } + catch + { + success = ProviderRefreshStatus.Failure; } finally { diff --git a/MediaBrowser.Controller/Providers/MediaInfo/FFMpegVideoImageProvider.cs b/MediaBrowser.Controller/Providers/MediaInfo/FFMpegVideoImageProvider.cs index bc851a0cba..a29dbb0432 100644 --- a/MediaBrowser.Controller/Providers/MediaInfo/FFMpegVideoImageProvider.cs +++ b/MediaBrowser.Controller/Providers/MediaInfo/FFMpegVideoImageProvider.cs @@ -1,10 +1,11 @@ -using System.Linq; -using MediaBrowser.Common.IO; +using MediaBrowser.Common.IO; +using MediaBrowser.Common.MediaInfo; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; using System; +using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -26,12 +27,12 @@ namespace MediaBrowser.Controller.Providers.MediaInfo /// <param name="isoManager">The iso manager.</param> /// <param name="logManager">The log manager.</param> /// <param name="configurationManager">The configuration manager.</param> - public FfMpegVideoImageProvider(IIsoManager isoManager, ILogManager logManager, IServerConfigurationManager configurationManager) - : base(logManager, configurationManager) + public FfMpegVideoImageProvider(IIsoManager isoManager, ILogManager logManager, IServerConfigurationManager configurationManager, IMediaEncoder mediaEncoder) + : base(logManager, configurationManager, mediaEncoder) { _isoManager = isoManager; - } - + } + /// <summary> /// Gets the priority. /// </summary> @@ -57,7 +58,7 @@ namespace MediaBrowser.Controller.Providers.MediaInfo if (video != null) { - if (video.VideoType == VideoType.Iso && video.IsoType.HasValue && _isoManager.CanMount(item.Path)) + if (video.VideoType == VideoType.Iso && _isoManager.CanMount(item.Path)) { return true; } @@ -139,25 +140,23 @@ namespace MediaBrowser.Controller.Providers.MediaInfo { // If we know the duration, grab it from 10% into the video. Otherwise just 10 seconds in. // Always use 10 seconds for dvd because our duration could be out of whack - var imageOffset = video.VideoType != VideoType.Dvd && video.RunTimeTicks.HasValue && video.RunTimeTicks.Value > 0 - ? TimeSpan.FromTicks(Convert.ToInt64(video.RunTimeTicks.Value * .1)) - : TimeSpan.FromSeconds(10); + var imageOffset = video.VideoType != VideoType.Dvd && video.RunTimeTicks.HasValue && + video.RunTimeTicks.Value > 0 + ? TimeSpan.FromTicks(Convert.ToInt64(video.RunTimeTicks.Value * .1)) + : TimeSpan.FromSeconds(10); - var inputPath = isoMount == null ? - Kernel.Instance.FFMpegManager.GetInputArgument(video) : - Kernel.Instance.FFMpegManager.GetInputArgument(video, isoMount); + InputType type; - var success = await Kernel.Instance.FFMpegManager.ExtractImage(inputPath, imageOffset, path, cancellationToken).ConfigureAwait(false); + var inputPath = MediaEncoderHelpers.GetInputArgument(video, isoMount, out type); - if (success) - { - video.PrimaryImagePath = path; - SetLastRefreshed(video, DateTime.UtcNow); - } - else - { - SetLastRefreshed(video, DateTime.UtcNow, ProviderRefreshStatus.Failure); - } + await MediaEncoder.ExtractImage(inputPath, type, imageOffset, path, cancellationToken).ConfigureAwait(false); + + video.PrimaryImagePath = path; + SetLastRefreshed(video, DateTime.UtcNow); + } + catch + { + SetLastRefreshed(video, DateTime.UtcNow, ProviderRefreshStatus.Failure); } finally { diff --git a/MediaBrowser.Controller/Providers/MediaInfo/FFProbeAudioInfoProvider.cs b/MediaBrowser.Controller/Providers/MediaInfo/FFProbeAudioInfoProvider.cs index 8390a0ceeb..e767d51965 100644 --- a/MediaBrowser.Controller/Providers/MediaInfo/FFProbeAudioInfoProvider.cs +++ b/MediaBrowser.Controller/Providers/MediaInfo/FFProbeAudioInfoProvider.cs @@ -1,15 +1,15 @@ using MediaBrowser.Common.IO; +using MediaBrowser.Common.MediaInfo; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Controller.MediaInfo; using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Logging; +using MediaBrowser.Model.Serialization; using System; using System.Collections.Generic; using System.Linq; using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Model.Logging; namespace MediaBrowser.Controller.Providers.MediaInfo { @@ -18,7 +18,8 @@ namespace MediaBrowser.Controller.Providers.MediaInfo /// </summary> public class FFProbeAudioInfoProvider : BaseFFProbeProvider<Audio> { - public FFProbeAudioInfoProvider(ILogManager logManager, IServerConfigurationManager configurationManager) : base(logManager, configurationManager) + public FFProbeAudioInfoProvider(ILogManager logManager, IServerConfigurationManager configurationManager, IMediaEncoder mediaEncoder, IProtobufSerializer protobufSerializer) + : base(logManager, configurationManager, mediaEncoder, protobufSerializer) { } @@ -42,7 +43,7 @@ namespace MediaBrowser.Controller.Providers.MediaInfo /// <param name="data">The data.</param> /// <param name="isoMount">The iso mount.</param> /// <returns>Task.</returns> - protected override void Fetch(Audio audio, CancellationToken cancellationToken, FFProbeResult data, IIsoMount isoMount) + protected override void Fetch(Audio audio, CancellationToken cancellationToken, MediaInfoResult data, IIsoMount isoMount) { if (data.streams == null) { diff --git a/MediaBrowser.Controller/Providers/MediaInfo/FFProbeVideoInfoProvider.cs b/MediaBrowser.Controller/Providers/MediaInfo/FFProbeVideoInfoProvider.cs index a2a9fa0d14..07b71576b6 100644 --- a/MediaBrowser.Controller/Providers/MediaInfo/FFProbeVideoInfoProvider.cs +++ b/MediaBrowser.Controller/Providers/MediaInfo/FFProbeVideoInfoProvider.cs @@ -1,8 +1,8 @@ using MediaBrowser.Common.IO; +using MediaBrowser.Common.MediaInfo; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Movies; -using MediaBrowser.Controller.MediaInfo; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; using MediaBrowser.Model.MediaInfo; @@ -21,8 +21,8 @@ namespace MediaBrowser.Controller.Providers.MediaInfo /// </summary> public class FFProbeVideoInfoProvider : BaseFFProbeProvider<Video> { - public FFProbeVideoInfoProvider(IIsoManager isoManager, IBlurayExaminer blurayExaminer, IProtobufSerializer protobufSerializer, ILogManager logManager, IServerConfigurationManager configurationManager) - : base(logManager, configurationManager) + public FFProbeVideoInfoProvider(IIsoManager isoManager, IBlurayExaminer blurayExaminer, IProtobufSerializer protobufSerializer, ILogManager logManager, IServerConfigurationManager configurationManager, IMediaEncoder mediaEncoder) + : base(logManager, configurationManager, mediaEncoder, protobufSerializer) { if (isoManager == null) { @@ -39,7 +39,6 @@ namespace MediaBrowser.Controller.Providers.MediaInfo _blurayExaminer = blurayExaminer; _isoManager = isoManager; - _protobufSerializer = protobufSerializer; BdInfoCache = new FileSystemRepository(Path.Combine(ConfigurationManager.ApplicationPaths.CachePath, "bdinfo")); } @@ -62,11 +61,6 @@ namespace MediaBrowser.Controller.Providers.MediaInfo private readonly IIsoManager _isoManager; /// <summary> - /// The _protobuf serializer - /// </summary> - private readonly IProtobufSerializer _protobufSerializer; - - /// <summary> /// Returns true or false indicating if the provider should refresh when the contents of it's directory changes /// </summary> /// <value><c>true</c> if [refresh on file system stamp change]; otherwise, <c>false</c>.</value> @@ -187,7 +181,7 @@ namespace MediaBrowser.Controller.Providers.MediaInfo /// <param name="data">The data.</param> /// <param name="isoMount">The iso mount.</param> /// <returns>Task.</returns> - protected override void Fetch(Video video, CancellationToken cancellationToken, FFProbeResult data, IIsoMount isoMount) + protected override void Fetch(Video video, CancellationToken cancellationToken, MediaInfoResult data, IIsoMount isoMount) { if (data.format != null) { @@ -335,13 +329,13 @@ namespace MediaBrowser.Controller.Providers.MediaInfo try { - result = _protobufSerializer.DeserializeFromFile<BlurayDiscInfo>(cacheFile); + result = ProtobufSerializer.DeserializeFromFile<BlurayDiscInfo>(cacheFile); } catch (FileNotFoundException) { result = GetBDInfo(inputPath); - _protobufSerializer.SerializeToFile(result, cacheFile); + ProtobufSerializer.SerializeToFile(result, cacheFile); } cancellationToken.ThrowIfCancellationRequested(); @@ -422,19 +416,5 @@ namespace MediaBrowser.Controller.Providers.MediaInfo { return _blurayExaminer.GetDiscInfo(path); } - - /// <summary> - /// Releases unmanaged and - optionally - managed resources. - /// </summary> - /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param> - protected override void Dispose(bool dispose) - { - if (dispose) - { - BdInfoCache.Dispose(); - } - - base.Dispose(dispose); - } } } diff --git a/MediaBrowser.Controller/Providers/MediaInfo/MediaEncoderHelpers.cs b/MediaBrowser.Controller/Providers/MediaInfo/MediaEncoderHelpers.cs new file mode 100644 index 0000000000..14372553b4 --- /dev/null +++ b/MediaBrowser.Controller/Providers/MediaInfo/MediaEncoderHelpers.cs @@ -0,0 +1,96 @@ +using MediaBrowser.Common.IO; +using MediaBrowser.Common.MediaInfo; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Model.Entities; + +namespace MediaBrowser.Controller.Providers.MediaInfo +{ + /// <summary> + /// Class MediaEncoderHelpers + /// </summary> + public static class MediaEncoderHelpers + { + /// <summary> + /// Gets the input argument. + /// </summary> + /// <param name="video">The video.</param> + /// <param name="isoMount">The iso mount.</param> + /// <param name="type">The type.</param> + /// <returns>System.String[][].</returns> + public static string[] GetInputArgument(Video video, IIsoMount isoMount, out InputType type) + { + var inputPath = isoMount == null ? new[] { video.Path } : new[] { isoMount.MountedPath }; + + type = InputType.VideoFile; + + switch (video.VideoType) + { + case VideoType.BluRay: + type = InputType.Bluray; + break; + case VideoType.Dvd: + type = InputType.Dvd; + inputPath = video.GetPlayableStreamFiles(inputPath[0]).ToArray(); + break; + case VideoType.Iso: + if (video.IsoType.HasValue) + { + switch (video.IsoType.Value) + { + case IsoType.BluRay: + type = InputType.Bluray; + break; + case IsoType.Dvd: + type = InputType.Dvd; + inputPath = video.GetPlayableStreamFiles(inputPath[0]).ToArray(); + break; + } + } + break; + } + + return inputPath; + } + + /// <summary> + /// Gets the type of the input. + /// </summary> + /// <param name="item">The item.</param> + /// <returns>InputType.</returns> + public static InputType GetInputType(BaseItem item) + { + var type = InputType.AudioFile; + + var video = item as Video; + + if (video != null) + { + switch (video.VideoType) + { + case VideoType.BluRay: + type = InputType.Bluray; + break; + case VideoType.Dvd: + type = InputType.Dvd; + break; + case VideoType.Iso: + if (video.IsoType.HasValue) + { + switch (video.IsoType.Value) + { + case IsoType.BluRay: + type = InputType.Bluray; + break; + case IsoType.Dvd: + type = InputType.Dvd; + break; + } + } + break; + } + } + + return type; + } + } +} |
