From 43845b40523f91e7816f6ea9e250a93c6f648f4f Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 3 May 2013 11:08:02 -0400 Subject: extract images for small numbers of items on discovery --- .../ScheduledTasks/VideoImagesTask.cs | 184 +++++++++++++++------ 1 file changed, 138 insertions(+), 46 deletions(-) (limited to 'MediaBrowser.Server.Implementations/ScheduledTasks/VideoImagesTask.cs') diff --git a/MediaBrowser.Server.Implementations/ScheduledTasks/VideoImagesTask.cs b/MediaBrowser.Server.Implementations/ScheduledTasks/VideoImagesTask.cs index c1f3173ee..d7863c0ba 100644 --- a/MediaBrowser.Server.Implementations/ScheduledTasks/VideoImagesTask.cs +++ b/MediaBrowser.Server.Implementations/ScheduledTasks/VideoImagesTask.cs @@ -13,6 +13,8 @@ using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Model.Logging; +using MoreLinq; namespace MediaBrowser.Server.Implementations.ScheduledTasks { @@ -41,26 +43,96 @@ namespace MediaBrowser.Server.Implementations.ScheduledTasks /// private readonly IIsoManager _isoManager; + private readonly ILogger _logger; + /// /// The _locks /// private readonly ConcurrentDictionary _locks = new ConcurrentDictionary(); + private readonly List _newlyAddedItems = new List(); + + private const int NewItemDelay = 300000; + + /// + /// The current new item timer + /// + /// The new item timer. + private Timer NewItemTimer { get; set; } + /// /// Initializes a new instance of the class. /// /// The library manager. + /// The log manager. /// The media encoder. /// The iso manager. - public VideoImagesTask(ILibraryManager libraryManager, IMediaEncoder mediaEncoder, IIsoManager isoManager) + public VideoImagesTask(ILibraryManager libraryManager, ILogManager logManager, IMediaEncoder mediaEncoder, IIsoManager isoManager) { _libraryManager = libraryManager; _mediaEncoder = mediaEncoder; _isoManager = isoManager; + _logger = logManager.GetLogger(GetType().Name); ImageCache = new FileSystemRepository(Kernel.Instance.FFMpegManager.VideoImagesDataPath); + + libraryManager.ItemAdded += libraryManager_ItemAdded; + libraryManager.ItemUpdated += libraryManager_ItemAdded; + } + + /// + /// Handles the ItemAdded event of the libraryManager control. + /// + /// The source of the event. + /// The instance containing the event data. + void libraryManager_ItemAdded(object sender, ItemChangeEventArgs e) + { + lock (_newlyAddedItems) + { + _newlyAddedItems.Add(e.Item); + + if (NewItemTimer == null) + { + NewItemTimer = new Timer(NewItemTimerCallback, null, NewItemDelay, Timeout.Infinite); + } + else + { + NewItemTimer.Change(NewItemDelay, Timeout.Infinite); + } + } } + /// + /// News the item timer callback. + /// + /// The state. + private async void NewItemTimerCallback(object state) + { + List newItems; + + // Lock the list and release all resources + lock (_newlyAddedItems) + { + newItems = _newlyAddedItems.DistinctBy(i => i.Id).ToList(); + _newlyAddedItems.Clear(); + + NewItemTimer.Dispose(); + NewItemTimer = null; + } + + foreach (var item in GetItemsForExtraction(newItems.Take(5))) + { + try + { + await ExtractImage(item, CancellationToken.None).ConfigureAwait(false); + } + catch (Exception ex) + { + _logger.ErrorException("Error creating image for {0}", ex, item.Name); + } + } + } + /// /// Gets the name of the task /// @@ -96,7 +168,42 @@ namespace MediaBrowser.Server.Implementations.ScheduledTasks /// Task. public async Task Execute(CancellationToken cancellationToken, IProgress progress) { - var allItems = _libraryManager.RootFolder.RecursiveChildren.ToList(); + var items = GetItemsForExtraction(_libraryManager.RootFolder.RecursiveChildren).ToList(); + + progress.Report(0); + + var numComplete = 0; + + foreach (var item in items) + { + try + { + await ExtractImage(item, cancellationToken).ConfigureAwait(false); + } + catch + { + // Already logged at lower levels. + // Just don't let the task fail + } + + numComplete++; + double percent = numComplete; + percent /= items.Count; + + progress.Report(100 * percent); + } + + progress.Report(100); + } + + /// + /// Gets the items for extraction. + /// + /// The source items. + /// IEnumerable{BaseItem}. + private IEnumerable