diff options
| author | Luke Pulverenti <luke.pulverenti@gmail.com> | 2014-02-20 11:37:41 -0500 |
|---|---|---|
| committer | Luke Pulverenti <luke.pulverenti@gmail.com> | 2014-02-20 11:37:41 -0500 |
| commit | 888b8d619aec031f57cfd03410ccda52edcca958 (patch) | |
| tree | 143080937fb8811d107c610507a15376d6761955 /MediaBrowser.Controller | |
| parent | 160d14208809a13791e34530a3758b079d6b9638 (diff) | |
added encoding manager interface
Diffstat (limited to 'MediaBrowser.Controller')
| -rw-r--r-- | MediaBrowser.Controller/MediaBrowser.Controller.csproj | 9 | ||||
| -rw-r--r-- | MediaBrowser.Controller/MediaEncoding/ChapterImageRefreshOptions.cs | 17 | ||||
| -rw-r--r-- | MediaBrowser.Controller/MediaEncoding/IEncodingManager.cs | 33 | ||||
| -rw-r--r-- | MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs (renamed from MediaBrowser.Controller/MediaInfo/IMediaEncoder.cs) | 2 | ||||
| -rw-r--r-- | MediaBrowser.Controller/MediaEncoding/InternalMediaInfoResult.cs (renamed from MediaBrowser.Controller/MediaInfo/InternalMediaInfoResult.cs) | 6 | ||||
| -rw-r--r-- | MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs (renamed from MediaBrowser.Controller/MediaInfo/MediaEncoderHelpers.cs) | 8 | ||||
| -rw-r--r-- | MediaBrowser.Controller/MediaInfo/FFMpegManager.cs | 297 |
7 files changed, 63 insertions, 309 deletions
diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index c88164897..ab1c012a8 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -135,8 +135,10 @@ <Compile Include="LiveTv\SeriesTimerInfo.cs" /> <Compile Include="LiveTv\TimerInfo.cs" /> <Compile Include="Localization\ILocalizationManager.cs" /> - <Compile Include="MediaInfo\IMediaEncoder.cs" /> - <Compile Include="MediaInfo\InternalMediaInfoResult.cs" /> + <Compile Include="MediaEncoding\ChapterImageRefreshOptions.cs" /> + <Compile Include="MediaEncoding\IEncodingManager.cs" /> + <Compile Include="MediaEncoding\IMediaEncoder.cs" /> + <Compile Include="MediaEncoding\InternalMediaInfoResult.cs" /> <Compile Include="Net\IHasResultFactory.cs" /> <Compile Include="Net\IHttpResultFactory.cs" /> <Compile Include="Net\IHttpServer.cs" /> @@ -198,7 +200,7 @@ <Compile Include="IServerApplicationPaths.cs" /> <Compile Include="Library\SearchHintInfo.cs" /> <Compile Include="Providers\IProviderManager.cs" /> - <Compile Include="MediaInfo\MediaEncoderHelpers.cs" /> + <Compile Include="MediaEncoding\MediaEncoderHelpers.cs" /> <Compile Include="Providers\MetadataProviderPriority.cs" /> <Compile Include="Resolvers\BaseItemResolver.cs" /> <Compile Include="Resolvers\BaseVideoResolver.cs" /> @@ -209,7 +211,6 @@ <Compile Include="Localization\BaseStrings.cs" /> <Compile Include="Localization\LocalizedStringData.cs" /> <Compile Include="Localization\LocalizedStrings.cs" /> - <Compile Include="MediaInfo\FFMpegManager.cs" /> <Compile Include="Persistence\IDisplayPreferencesRepository.cs" /> <Compile Include="Persistence\IItemRepository.cs" /> <Compile Include="Persistence\IRepository.cs" /> diff --git a/MediaBrowser.Controller/MediaEncoding/ChapterImageRefreshOptions.cs b/MediaBrowser.Controller/MediaEncoding/ChapterImageRefreshOptions.cs new file mode 100644 index 000000000..e11bd6cdf --- /dev/null +++ b/MediaBrowser.Controller/MediaEncoding/ChapterImageRefreshOptions.cs @@ -0,0 +1,17 @@ +using MediaBrowser.Controller.Entities; +using MediaBrowser.Model.Entities; +using System.Collections.Generic; + +namespace MediaBrowser.Controller.MediaEncoding +{ + public class ChapterImageRefreshOptions + { + public Video Video { get; set; } + + public List<ChapterInfo> Chapters { get; set; } + + public bool SaveChapters { get; set; } + + public bool ExtractImages { get; set; } + } +} diff --git a/MediaBrowser.Controller/MediaEncoding/IEncodingManager.cs b/MediaBrowser.Controller/MediaEncoding/IEncodingManager.cs new file mode 100644 index 000000000..d1e40e3f0 --- /dev/null +++ b/MediaBrowser.Controller/MediaEncoding/IEncodingManager.cs @@ -0,0 +1,33 @@ +using System.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.Controller.MediaEncoding +{ + public interface IEncodingManager + { + /// <summary> + /// Gets the subtitle cache path. + /// </summary> + /// <param name="originalSubtitlePath">The original subtitle path.</param> + /// <param name="outputSubtitleExtension">The output subtitle extension.</param> + /// <returns>System.String.</returns> + string GetSubtitleCachePath(string originalSubtitlePath, string outputSubtitleExtension); + + /// <summary> + /// Gets the subtitle cache path. + /// </summary> + /// <param name="mediaPath">The media path.</param> + /// <param name="subtitleStreamIndex">Index of the subtitle stream.</param> + /// <param name="outputSubtitleExtension">The output subtitle extension.</param> + /// <returns>System.String.</returns> + string GetSubtitleCachePath(string mediaPath, int subtitleStreamIndex, string outputSubtitleExtension); + + /// <summary> + /// Refreshes the chapter images. + /// </summary> + /// <param name="options">The options.</param> + /// <param name="cancellationToken">The cancellation token.</param> + /// <returns>Task{System.Boolean}.</returns> + Task<bool> RefreshChapterImages(ChapterImageRefreshOptions options, CancellationToken cancellationToken); + } +} diff --git a/MediaBrowser.Controller/MediaInfo/IMediaEncoder.cs b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs index d8cad48b3..119688fa7 100644 --- a/MediaBrowser.Controller/MediaInfo/IMediaEncoder.cs +++ b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs @@ -4,7 +4,7 @@ using System.IO; using System.Threading; using System.Threading.Tasks; -namespace MediaBrowser.Controller.MediaInfo +namespace MediaBrowser.Controller.MediaEncoding { /// <summary> /// Interface IMediaEncoder diff --git a/MediaBrowser.Controller/MediaInfo/InternalMediaInfoResult.cs b/MediaBrowser.Controller/MediaEncoding/InternalMediaInfoResult.cs index 3ceec1b90..e113521ec 100644 --- a/MediaBrowser.Controller/MediaInfo/InternalMediaInfoResult.cs +++ b/MediaBrowser.Controller/MediaEncoding/InternalMediaInfoResult.cs @@ -1,7 +1,7 @@ -using System.Collections.Generic; -using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Entities; +using System.Collections.Generic; -namespace MediaBrowser.Controller.MediaInfo +namespace MediaBrowser.Controller.MediaEncoding { /// <summary> /// Class MediaInfoResult diff --git a/MediaBrowser.Controller/MediaInfo/MediaEncoderHelpers.cs b/MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs index 300071b7b..b2b9e2af3 100644 --- a/MediaBrowser.Controller/MediaInfo/MediaEncoderHelpers.cs +++ b/MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs @@ -1,12 +1,12 @@ -using System; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.IO; +using System; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.IO; -namespace MediaBrowser.Controller.MediaInfo +namespace MediaBrowser.Controller.MediaEncoding { /// <summary> /// Class MediaEncoderHelpers diff --git a/MediaBrowser.Controller/MediaInfo/FFMpegManager.cs b/MediaBrowser.Controller/MediaInfo/FFMpegManager.cs deleted file mode 100644 index e3604eb0e..000000000 --- a/MediaBrowser.Controller/MediaInfo/FFMpegManager.cs +++ /dev/null @@ -1,297 +0,0 @@ -using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.IO; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.Movies; -using MediaBrowser.Controller.Entities.TV; -using MediaBrowser.Controller.Persistence; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Logging; -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Controller.MediaInfo -{ - /// <summary> - /// Class FFMpegManager - /// </summary> - public class FFMpegManager - { - private readonly IServerConfigurationManager _config; - private readonly IMediaEncoder _encoder; - private readonly ILogger _logger; - private readonly IItemRepository _itemRepo; - - private readonly IFileSystem _fileSystem; - - public static FFMpegManager Instance { get; private set; } - - /// <summary> - /// Initializes a new instance of the <see cref="FFMpegManager" /> class. - /// </summary> - /// <param name="encoder">The encoder.</param> - /// <param name="logger">The logger.</param> - /// <param name="itemRepo">The item repo.</param> - /// <exception cref="System.ArgumentNullException">zipClient</exception> - public FFMpegManager(IMediaEncoder encoder, ILogger logger, IItemRepository itemRepo, IFileSystem fileSystem, IServerConfigurationManager config) - { - _encoder = encoder; - _logger = logger; - _itemRepo = itemRepo; - _fileSystem = fileSystem; - _config = config; - - // TODO: Remove this static instance - Instance = this; - } - - /// <summary> - /// Gets the chapter images data path. - /// </summary> - /// <value>The chapter images data path.</value> - public string ChapterImagesPath - { - get - { - return Path.Combine(_config.ApplicationPaths.DataPath, "chapter-images"); - } - } - - /// <summary> - /// Gets the subtitle cache path. - /// </summary> - /// <value>The subtitle cache path.</value> - private string SubtitleCachePath - { - get - { - return Path.Combine(_config.ApplicationPaths.CachePath, "subtitles"); - } - } - - /// <summary> - /// Determines whether [is eligible for chapter image extraction] [the specified video]. - /// </summary> - /// <param name="video">The video.</param> - /// <returns><c>true</c> if [is eligible for chapter image extraction] [the specified video]; otherwise, <c>false</c>.</returns> - private bool IsEligibleForChapterImageExtraction(Video video) - { - if (video is Movie) - { - if (!_config.Configuration.EnableMovieChapterImageExtraction) - { - return false; - } - } - else if (video is Episode) - { - if (!_config.Configuration.EnableEpisodeChapterImageExtraction) - { - return false; - } - } - else - { - if (!_config.Configuration.EnableOtherVideoChapterImageExtraction) - { - return false; - } - } - - // Can't extract images if there are no video streams - return video.DefaultVideoStreamIndex.HasValue; - } - - /// <summary> - /// The first chapter ticks - /// </summary> - private static readonly long FirstChapterTicks = TimeSpan.FromSeconds(15).Ticks; - - /// <summary> - /// Extracts the chapter images. - /// </summary> - /// <param name="video">The video.</param> - /// <param name="chapters">The chapters.</param> - /// <param name="extractImages">if set to <c>true</c> [extract images].</param> - /// <param name="saveChapters">if set to <c>true</c> [save chapters].</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - /// <exception cref="System.ArgumentNullException"></exception> - public async Task<bool> PopulateChapterImages(Video video, List<ChapterInfo> chapters, bool extractImages, bool saveChapters, CancellationToken cancellationToken) - { - if (!IsEligibleForChapterImageExtraction(video)) - { - extractImages = false; - } - - var success = true; - var changesMade = false; - - var runtimeTicks = video.RunTimeTicks ?? 0; - - var currentImages = GetSavedChapterImages(video); - - foreach (var chapter in chapters) - { - if (chapter.StartPositionTicks >= runtimeTicks) - { - _logger.Info("Stopping chapter extraction for {0} because a chapter was found with a position greater than the runtime.", video.Name); - break; - } - - var path = GetChapterImagePath(video, chapter.StartPositionTicks); - - if (!currentImages.Contains(path, StringComparer.OrdinalIgnoreCase)) - { - if (extractImages) - { - if (video.VideoType == VideoType.HdDvd || video.VideoType == VideoType.Iso) - { - continue; - } - - if (video.VideoType == VideoType.BluRay) - { - // Can only extract reliably on single file blurays - if (video.PlayableStreamFileNames == null || video.PlayableStreamFileNames.Count != 1) - { - continue; - } - } - - // Add some time for the first chapter to make sure we don't end up with a black image - var time = chapter.StartPositionTicks == 0 ? TimeSpan.FromTicks(Math.Min(FirstChapterTicks, video.RunTimeTicks ?? 0)) : TimeSpan.FromTicks(chapter.StartPositionTicks); - - InputType type; - - var inputPath = MediaEncoderHelpers.GetInputArgument(video.Path, false, video.VideoType, video.IsoType, null, video.PlayableStreamFileNames, out type); - - try - { - var parentPath = Path.GetDirectoryName(path); - - Directory.CreateDirectory(parentPath); - - using (var stream = await _encoder.ExtractImage(inputPath, type, false, video.Video3DFormat, time, cancellationToken).ConfigureAwait(false)) - { - using (var fileStream = _fileSystem.GetFileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, true)) - { - await stream.CopyToAsync(fileStream).ConfigureAwait(false); - } - } - - chapter.ImagePath = path; - changesMade = true; - } - catch - { - success = false; - break; - } - } - else if (!string.IsNullOrEmpty(chapter.ImagePath)) - { - chapter.ImagePath = null; - changesMade = true; - } - } - else if (!string.Equals(path, chapter.ImagePath, StringComparison.OrdinalIgnoreCase)) - { - chapter.ImagePath = path; - changesMade = true; - } - } - - if (saveChapters && changesMade) - { - await _itemRepo.SaveChapters(video.Id, chapters, cancellationToken).ConfigureAwait(false); - } - - DeleteDeadImages(currentImages, chapters); - - return success; - } - - private void DeleteDeadImages(IEnumerable<string> images, IEnumerable<ChapterInfo> chapters) - { - var deadImages = images - .Except(chapters.Select(i => i.ImagePath).Where(i => !string.IsNullOrEmpty(i)), StringComparer.OrdinalIgnoreCase) - .Where(i => BaseItem.SupportedImageExtensions.Contains(Path.GetExtension(i), StringComparer.OrdinalIgnoreCase)) - .ToList(); - - foreach (var image in deadImages) - { - _logger.Debug("Deleting dead chapter image {0}", image); - - try - { - File.Delete(image); - } - catch (IOException ex) - { - _logger.ErrorException("Error deleting {0}.", ex, image); - } - } - } - - private readonly CultureInfo _usCulture = new CultureInfo("en-US"); - - /// <summary> - /// Gets the subtitle cache path. - /// </summary> - /// <param name="mediaPath">The media path.</param> - /// <param name="subtitleStream">The subtitle stream.</param> - /// <param name="outputExtension">The output extension.</param> - /// <returns>System.String.</returns> - public string GetSubtitleCachePath(string mediaPath, MediaStream subtitleStream, string outputExtension) - { - var ticksParam = string.Empty; - - if (subtitleStream.IsExternal) - { - ticksParam += _fileSystem.GetLastWriteTimeUtc(subtitleStream.Path).Ticks; - } - - var date = _fileSystem.GetLastWriteTimeUtc(mediaPath); - - var filename = (mediaPath + "_" + subtitleStream.Index.ToString(_usCulture) + "_" + date.Ticks.ToString(_usCulture) + ticksParam).GetMD5() + outputExtension; - - var prefix = filename.Substring(0, 1); - - return Path.Combine(SubtitleCachePath, prefix, filename); - } - - public string GetChapterImagePath(Video video, long chapterPositionTicks) - { - var filename = video.DateModified.Ticks.ToString(_usCulture) + "_" + chapterPositionTicks.ToString(_usCulture) + ".jpg"; - - var videoId = video.Id.ToString(); - var prefix = videoId.Substring(0, 1); - - return Path.Combine(ChapterImagesPath, prefix, videoId, filename); - } - - public List<string> GetSavedChapterImages(Video video) - { - var videoId = video.Id.ToString(); - var prefix = videoId.Substring(0, 1); - - var path = Path.Combine(ChapterImagesPath, prefix, videoId); - - try - { - return Directory.EnumerateFiles(path) - .ToList(); - } - catch (DirectoryNotFoundException) - { - return new List<string>(); - } - } - } -} |
