mirror of
https://github.com/jellyfin/jellyfin.git
synced 2025-06-04 22:24:35 -04:00
fix chapter image extraction
This commit is contained in:
parent
635de736a9
commit
a639d32454
@ -1651,6 +1651,11 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
return AddImages(imageType, images.Cast<FileSystemInfo>().ToList());
|
return AddImages(imageType, images.Cast<FileSystemInfo>().ToList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool AddImages(ImageType imageType, IEnumerable<FileSystemInfo> images)
|
||||||
|
{
|
||||||
|
return AddImages(imageType, images.ToList());
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds the images.
|
/// Adds the images.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -62,7 +62,9 @@ namespace MediaBrowser.Dlna.Ssdp
|
|||||||
{
|
{
|
||||||
if (string.Equals(args.Method, "M-SEARCH", StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(args.Method, "M-SEARCH", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
TimeSpan delay = GetSearchDelay(args.Headers);
|
var headers = args.Headers;
|
||||||
|
|
||||||
|
TimeSpan delay = GetSearchDelay(headers);
|
||||||
|
|
||||||
if (_config.GetDlnaConfiguration().EnableDebugLogging)
|
if (_config.GetDlnaConfiguration().EnableDebugLogging)
|
||||||
{
|
{
|
||||||
@ -71,7 +73,11 @@ namespace MediaBrowser.Dlna.Ssdp
|
|||||||
|
|
||||||
await Task.Delay(delay).ConfigureAwait(false);
|
await Task.Delay(delay).ConfigureAwait(false);
|
||||||
|
|
||||||
RespondToSearch(args.EndPoint, args.Headers["st"]);
|
string st;
|
||||||
|
if (headers.TryGetValue("st", out st))
|
||||||
|
{
|
||||||
|
RespondToSearch(args.EndPoint, st);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EventHelper.FireEventIfNotNull(MessageReceived, this, args, _logger);
|
EventHelper.FireEventIfNotNull(MessageReceived, this, args, _logger);
|
||||||
|
@ -75,7 +75,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
|||||||
protected readonly Func<ISubtitleEncoder> SubtitleEncoder;
|
protected readonly Func<ISubtitleEncoder> SubtitleEncoder;
|
||||||
protected readonly Func<IMediaSourceManager> MediaSourceManager;
|
protected readonly Func<IMediaSourceManager> MediaSourceManager;
|
||||||
|
|
||||||
private readonly List<Process> _runningProcesses = new List<Process>();
|
private readonly List<ProcessWrapper> _runningProcesses = new List<ProcessWrapper>();
|
||||||
|
|
||||||
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, string version, IServerConfigurationManager configurationManager, IFileSystem fileSystem, ILiveTvManager liveTvManager, IIsoManager isoManager, ILibraryManager libraryManager, IChannelManager channelManager, ISessionManager sessionManager, Func<ISubtitleEncoder> subtitleEncoder, Func<IMediaSourceManager> mediaSourceManager)
|
||||||
{
|
{
|
||||||
@ -197,9 +197,11 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
|||||||
|
|
||||||
await _ffProbeResourcePool.WaitAsync(cancellationToken).ConfigureAwait(false);
|
await _ffProbeResourcePool.WaitAsync(cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
|
var processWrapper = new ProcessWrapper(process, this);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
StartProcess(process);
|
StartProcess(processWrapper);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@ -264,7 +266,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
|||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
StopProcess(process, 100, true);
|
StopProcess(processWrapper, 100, true);
|
||||||
|
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
@ -303,7 +305,9 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
|||||||
|
|
||||||
_logger.Debug("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments);
|
_logger.Debug("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments);
|
||||||
|
|
||||||
StartProcess(process);
|
var processWrapper = new ProcessWrapper(process, this);
|
||||||
|
|
||||||
|
StartProcess(processWrapper);
|
||||||
|
|
||||||
var lines = new List<int>();
|
var lines = new List<int>();
|
||||||
var outputCancellationSource = new CancellationTokenSource(4000);
|
var outputCancellationSource = new CancellationTokenSource(4000);
|
||||||
@ -325,7 +329,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
|||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
StopProcess(process, 100, true);
|
StopProcess(processWrapper, 100, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return lines;
|
return lines;
|
||||||
@ -382,23 +386,6 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
protected readonly CultureInfo UsCulture = new CultureInfo("en-US");
|
protected readonly CultureInfo UsCulture = new CultureInfo("en-US");
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Processes the exited.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="sender">The sender.</param>
|
|
||||||
/// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
|
|
||||||
private void ProcessExited(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
var process = (Process) sender;
|
|
||||||
|
|
||||||
lock (_runningProcesses)
|
|
||||||
{
|
|
||||||
_runningProcesses.Remove(process);
|
|
||||||
}
|
|
||||||
|
|
||||||
process.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task<Stream> ExtractAudioImage(string path, CancellationToken cancellationToken)
|
public Task<Stream> ExtractAudioImage(string path, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
return ExtractImage(new[] { path }, MediaProtocol.File, true, null, null, cancellationToken);
|
return ExtractImage(new[] { path }, MediaProtocol.File, true, null, null, cancellationToken);
|
||||||
@ -423,6 +410,10 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
|||||||
{
|
{
|
||||||
return await ExtractImageInternal(inputArgument, protocol, threedFormat, offset, true, resourcePool, cancellationToken).ConfigureAwait(false);
|
return await ExtractImageInternal(inputArgument, protocol, threedFormat, offset, true, resourcePool, cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
catch (ArgumentException)
|
||||||
|
{
|
||||||
|
throw;
|
||||||
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
_logger.Error("I-frame image extraction failed, will attempt standard way. Input: {0}", inputArgument);
|
_logger.Error("I-frame image extraction failed, will attempt standard way. Input: {0}", inputArgument);
|
||||||
@ -505,7 +496,9 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
|||||||
|
|
||||||
await resourcePool.WaitAsync(cancellationToken).ConfigureAwait(false);
|
await resourcePool.WaitAsync(cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
StartProcess(process);
|
var processWrapper = new ProcessWrapper(process, this);
|
||||||
|
|
||||||
|
StartProcess(processWrapper);
|
||||||
|
|
||||||
var memoryStream = new MemoryStream();
|
var memoryStream = new MemoryStream();
|
||||||
|
|
||||||
@ -521,12 +514,12 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
|||||||
|
|
||||||
if (!ranToCompletion)
|
if (!ranToCompletion)
|
||||||
{
|
{
|
||||||
StopProcess(process, 1000, false);
|
StopProcess(processWrapper, 1000, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
resourcePool.Release();
|
resourcePool.Release();
|
||||||
|
|
||||||
var exitCode = ranToCompletion ? process.ExitCode : -1;
|
var exitCode = ranToCompletion ? processWrapper.ExitCode ?? 0 : -1;
|
||||||
|
|
||||||
process.Dispose();
|
process.Dispose();
|
||||||
|
|
||||||
@ -611,9 +604,11 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
|||||||
|
|
||||||
bool ranToCompletion;
|
bool ranToCompletion;
|
||||||
|
|
||||||
|
var processWrapper = new ProcessWrapper(process, this);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
StartProcess(process);
|
StartProcess(processWrapper);
|
||||||
|
|
||||||
// Need to give ffmpeg enough time to make all the thumbnails, which could be a while,
|
// Need to give ffmpeg enough time to make all the thumbnails, which could be a while,
|
||||||
// but we still need to detect if the process hangs.
|
// but we still need to detect if the process hangs.
|
||||||
@ -637,7 +632,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
|||||||
|
|
||||||
if (!ranToCompletion)
|
if (!ranToCompletion)
|
||||||
{
|
{
|
||||||
StopProcess(process, 1000, false);
|
StopProcess(processWrapper, 1000, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
@ -645,7 +640,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
|||||||
resourcePool.Release();
|
resourcePool.Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
var exitCode = ranToCompletion ? process.ExitCode : -1;
|
var exitCode = ranToCompletion ? processWrapper.ExitCode ?? 0 : -1;
|
||||||
|
|
||||||
process.Dispose();
|
process.Dispose();
|
||||||
|
|
||||||
@ -699,18 +694,16 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
|||||||
return job.OutputFilePath;
|
return job.OutputFilePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void StartProcess(Process process)
|
private void StartProcess(ProcessWrapper process)
|
||||||
{
|
{
|
||||||
process.Exited += ProcessExited;
|
process.Process.Start();
|
||||||
|
|
||||||
process.Start();
|
|
||||||
|
|
||||||
lock (_runningProcesses)
|
lock (_runningProcesses)
|
||||||
{
|
{
|
||||||
_runningProcesses.Add(process);
|
_runningProcesses.Add(process);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private void StopProcess(Process process, int waitTimeMs, bool enableForceKill)
|
private void StopProcess(ProcessWrapper process, int waitTimeMs, bool enableForceKill)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -718,7 +711,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
process.StandardInput.WriteLine("q");
|
process.Process.StandardInput.WriteLine("q");
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
@ -727,7 +720,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (process.WaitForExit(waitTimeMs))
|
if (process.Process.WaitForExit(waitTimeMs))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -739,7 +732,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
|||||||
|
|
||||||
if (enableForceKill)
|
if (enableForceKill)
|
||||||
{
|
{
|
||||||
process.Kill();
|
process.Process .Kill();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@ -750,7 +743,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
|||||||
|
|
||||||
private void StopProcesses()
|
private void StopProcesses()
|
||||||
{
|
{
|
||||||
List<Process> proceses;
|
List<ProcessWrapper> proceses;
|
||||||
lock (_runningProcesses)
|
lock (_runningProcesses)
|
||||||
{
|
{
|
||||||
proceses = _runningProcesses.ToList();
|
proceses = _runningProcesses.ToList();
|
||||||
@ -782,5 +775,36 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
|||||||
StopProcesses();
|
StopProcesses();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class ProcessWrapper
|
||||||
|
{
|
||||||
|
public readonly Process Process;
|
||||||
|
public bool HasExited;
|
||||||
|
public int? ExitCode;
|
||||||
|
private readonly MediaEncoder _mediaEncoder;
|
||||||
|
|
||||||
|
public ProcessWrapper(Process process, MediaEncoder mediaEncoder)
|
||||||
|
{
|
||||||
|
Process = process;
|
||||||
|
this._mediaEncoder = mediaEncoder;
|
||||||
|
Process.Exited += Process_Exited;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Process_Exited(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
var process = (Process)sender;
|
||||||
|
|
||||||
|
HasExited = true;
|
||||||
|
|
||||||
|
ExitCode = process.ExitCode;
|
||||||
|
|
||||||
|
lock (_mediaEncoder._runningProcesses)
|
||||||
|
{
|
||||||
|
_mediaEncoder._runningProcesses.Remove(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
process.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Channels;
|
||||||
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
using MediaBrowser.Controller.Plugins;
|
using MediaBrowser.Controller.Plugins;
|
||||||
using MediaBrowser.Controller.Session;
|
using MediaBrowser.Controller.Session;
|
||||||
@ -69,7 +70,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
|
|||||||
/// <param name="e">The <see cref="ItemChangeEventArgs"/> instance containing the event data.</param>
|
/// <param name="e">The <see cref="ItemChangeEventArgs"/> instance containing the event data.</param>
|
||||||
void libraryManager_ItemAdded(object sender, ItemChangeEventArgs e)
|
void libraryManager_ItemAdded(object sender, ItemChangeEventArgs e)
|
||||||
{
|
{
|
||||||
if (e.Item.LocationType == LocationType.Virtual)
|
if (!FilterItem(e.Item))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -102,7 +103,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
|
|||||||
/// <param name="e">The <see cref="ItemChangeEventArgs"/> instance containing the event data.</param>
|
/// <param name="e">The <see cref="ItemChangeEventArgs"/> instance containing the event data.</param>
|
||||||
void libraryManager_ItemUpdated(object sender, ItemChangeEventArgs e)
|
void libraryManager_ItemUpdated(object sender, ItemChangeEventArgs e)
|
||||||
{
|
{
|
||||||
if (e.Item.LocationType == LocationType.Virtual)
|
if (!FilterItem(e.Item))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -130,7 +131,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
|
|||||||
/// <param name="e">The <see cref="ItemChangeEventArgs"/> instance containing the event data.</param>
|
/// <param name="e">The <see cref="ItemChangeEventArgs"/> instance containing the event data.</param>
|
||||||
void libraryManager_ItemRemoved(object sender, ItemChangeEventArgs e)
|
void libraryManager_ItemRemoved(object sender, ItemChangeEventArgs e)
|
||||||
{
|
{
|
||||||
if (e.Item.LocationType == LocationType.Virtual)
|
if (!FilterItem(e.Item))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -257,6 +258,16 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool FilterItem(BaseItem item)
|
||||||
|
{
|
||||||
|
if (item.LocationType == LocationType.Virtual)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return !(item is IChannelItem);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Translates the physical item to user library.
|
/// Translates the physical item to user library.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -151,8 +151,9 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
|
|||||||
chapter.ImagePath = path;
|
chapter.ImagePath = path;
|
||||||
changesMade = true;
|
changesMade = true;
|
||||||
}
|
}
|
||||||
catch
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
_logger.ErrorException("Error extraching chapter images for {0}", ex, string.Join(",", inputPath));
|
||||||
success = false;
|
success = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user