diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs
index 9a83aba88b..a63aca11b3 100644
--- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs
+++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs
@@ -120,6 +120,15 @@ namespace MediaBrowser.MediaEncoding.Subtitles
bool preserveOriginalTimestamps,
CancellationToken cancellationToken)
{
+ if (string.IsNullOrWhiteSpace(itemId))
+ {
+ throw new ArgumentNullException("itemId");
+ }
+ if (string.IsNullOrWhiteSpace(mediaSourceId))
+ {
+ throw new ArgumentNullException("mediaSourceId");
+ }
+
var subtitle = await GetSubtitleStream(itemId, mediaSourceId, subtitleStreamIndex, cancellationToken)
.ConfigureAwait(false);
@@ -141,10 +150,19 @@ namespace MediaBrowser.MediaEncoding.Subtitles
int subtitleStreamIndex,
CancellationToken cancellationToken)
{
+ if (string.IsNullOrWhiteSpace(itemId))
+ {
+ throw new ArgumentNullException("itemId");
+ }
+ if (string.IsNullOrWhiteSpace(mediaSourceId))
+ {
+ throw new ArgumentNullException("mediaSourceId");
+ }
+
var mediaSources = await _mediaSourceManager.GetPlayackMediaSources(itemId, null, false, new[] { MediaType.Audio, MediaType.Video }, cancellationToken).ConfigureAwait(false);
var mediaSource = mediaSources
- .First(i => string.Equals(i.Id, mediaSourceId));
+ .First(i => string.Equals(i.Id, mediaSourceId, StringComparison.OrdinalIgnoreCase));
var subtitleStream = mediaSource.MediaStreams
.First(i => i.Type == MediaStreamType.Subtitle && i.Index == subtitleStreamIndex);
@@ -609,7 +627,8 @@ namespace MediaBrowser.MediaEncoding.Subtitles
throw;
}
- process.StandardError.BaseStream.CopyToAsync(logFileStream);
+ // Important - don't await the log task or we won't be able to kill ffmpeg when the user stops playback
+ Task.Run(() => StartStreamingLog(process.StandardError.BaseStream, logFileStream));
var ranToCompletion = process.WaitForExit(300000);
@@ -686,6 +705,33 @@ namespace MediaBrowser.MediaEncoding.Subtitles
}
}
+ private async Task StartStreamingLog(Stream source, Stream target)
+ {
+ try
+ {
+ using (var reader = new StreamReader(source))
+ {
+ while (!reader.EndOfStream)
+ {
+ var line = await reader.ReadLineAsync().ConfigureAwait(false);
+
+ var bytes = Encoding.UTF8.GetBytes(Environment.NewLine + line);
+
+ await target.WriteAsync(bytes, 0, bytes.Length).ConfigureAwait(false);
+ await target.FlushAsync().ConfigureAwait(false);
+ }
+ }
+ }
+ catch (ObjectDisposedException)
+ {
+ // Don't spam the log. This doesn't seem to throw in windows, but sometimes under linux
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error reading ffmpeg log", ex);
+ }
+ }
+
///
/// Sets the ass font.
///
diff --git a/MediaBrowser.Server.Implementations/Persistence/CleanDatabaseScheduledTask.cs b/MediaBrowser.Server.Implementations/Persistence/CleanDatabaseScheduledTask.cs
index c321e5f015..b11a3e4968 100644
--- a/MediaBrowser.Server.Implementations/Persistence/CleanDatabaseScheduledTask.cs
+++ b/MediaBrowser.Server.Implementations/Persistence/CleanDatabaseScheduledTask.cs
@@ -142,77 +142,52 @@ namespace MediaBrowser.Server.Implementations.Persistence
}
}
- private Task UpdateToLatestSchema(CancellationToken cancellationToken, IProgress progress)
+ private async Task UpdateToLatestSchema(CancellationToken cancellationToken, IProgress progress)
{
- return UpdateToLatestSchema(0, 0, null, cancellationToken, progress);
- }
-
- private async Task UpdateToLatestSchema(int queryStartIndex, int progressStartIndex, int? totalRecordCount, CancellationToken cancellationToken, IProgress progress)
- {
- IEnumerable items;
- int numItemsToSave;
- var pageSize = 1000;
-
- if (totalRecordCount.HasValue)
- {
- var list = _libraryManager.GetItemList(new InternalItemsQuery
- {
- IsCurrentSchema = false,
- ExcludeItemTypes = new[] { typeof(LiveTvProgram).Name },
- StartIndex = queryStartIndex,
- Limit = pageSize
-
- }).ToList();
-
- items = list;
- numItemsToSave = list.Count;
- }
- else
+ var itemIds = _libraryManager.GetItemIds(new InternalItemsQuery
{
- var itemsResult = _libraryManager.GetItemsResult(new InternalItemsQuery
- {
- IsCurrentSchema = false,
- ExcludeItemTypes = new[] { typeof(LiveTvProgram).Name },
- StartIndex = queryStartIndex,
- Limit = pageSize
- });
-
- totalRecordCount = itemsResult.TotalRecordCount;
- items = itemsResult.Items;
- numItemsToSave = itemsResult.Items.Length;
- }
+ IsCurrentSchema = false,
+ ExcludeItemTypes = new[] { typeof(LiveTvProgram).Name }
+ });
- var numItems = totalRecordCount.Value;
+ var numComplete = 0;
+ var numItems = itemIds.Count;
_logger.Debug("Upgrading schema for {0} items", numItems);
- if (numItemsToSave > 0)
+ foreach (var itemId in itemIds)
{
- try
- {
- await _itemRepo.SaveItems(items, cancellationToken).ConfigureAwait(false);
- }
- catch (OperationCanceledException)
- {
- throw;
- }
- catch (Exception ex)
+ cancellationToken.ThrowIfCancellationRequested();
+
+ if (itemId != Guid.Empty)
{
- _logger.ErrorException("Error saving item", ex);
+ // Somehow some invalid data got into the db. It probably predates the boundary checking
+ var item = _libraryManager.GetItemById(itemId);
+
+ if (item != null)
+ {
+ try
+ {
+ await _itemRepo.SaveItem(item, cancellationToken).ConfigureAwait(false);
+ }
+ catch (OperationCanceledException)
+ {
+ throw;
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error saving item", ex);
+ }
+ }
}
- progressStartIndex += pageSize;
- double percent = progressStartIndex;
+ numComplete++;
+ double percent = numComplete;
percent /= numItems;
progress.Report(percent * 100);
-
- var newStartIndex = queryStartIndex + (pageSize - numItemsToSave);
- await UpdateToLatestSchema(newStartIndex, progressStartIndex, totalRecordCount, cancellationToken, progress).ConfigureAwait(false);
- }
- else
- {
- progress.Report(100);
}
+
+ progress.Report(100);
}
private async Task CleanDeadItems(CancellationToken cancellationToken, IProgress progress)