Use config values

This commit is contained in:
nicknsy 2023-02-25 15:59:46 -08:00 committed by Nick
parent d448cc18ea
commit 6744e712d3
6 changed files with 89 additions and 40 deletions

View file

@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Model.Configuration;
@ -145,10 +146,12 @@ namespace MediaBrowser.Controller.MediaEncoding
/// <param name="container">Video container type.</param>
/// <param name="mediaSource">Media source information.</param>
/// <param name="imageStream">Media stream information.</param>
/// <param name="interval">The interval.</param>
/// <param name="maxWidth">The maximum width.</param>
/// <param name="interval">The interval.</param>
/// <param name="allowHwAccel">Allow for hardware acceleration.</param>
/// <param name="allowHwEncode">Allow for hardware encoding. allowHwAccel must also be true.</param>
/// <param name="threads">The input/output thread count for ffmpeg.</param>
/// <param name="qualityScale">The qscale value for ffmpeg.</param>
/// <param name="priority">The process priority for the ffmpeg process.</param>
/// <param name="encodingHelper">EncodingHelper instance.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Directory where images where extracted. A given image made before another will always be named with a lower number.</returns>
@ -157,10 +160,12 @@ namespace MediaBrowser.Controller.MediaEncoding
string container,
MediaSourceInfo mediaSource,
MediaStream imageStream,
TimeSpan interval,
int maxWidth,
TimeSpan interval,
bool allowHwAccel,
bool allowHwEncode,
int? threads,
int? qualityScale,
ProcessPriorityClass? priority,
EncodingHelper encodingHelper,
CancellationToken cancellationToken);

View file

@ -783,14 +783,17 @@ namespace MediaBrowser.MediaEncoding.Encoder
string container,
MediaSourceInfo mediaSource,
MediaStream imageStream,
TimeSpan interval,
int maxWidth,
TimeSpan interval,
bool allowHwAccel,
bool allowHwEncode,
int? threads,
int? qualityScale,
ProcessPriorityClass? priority,
EncodingHelper encodingHelper,
CancellationToken cancellationToken)
{
var options = allowHwAccel ? _configurationManager.GetEncodingOptions() : new EncodingOptions();
threads = threads ?? _threads;
// A new EncodingOptions instance must be used as to not disable HW acceleration for all of Jellyfin.
// Additionally, we must set a few fields without defaults to prevent null pointer exceptions.
@ -822,7 +825,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
if (!allowHwAccel)
{
inputArg = "-threads " + _threads + " " + inputArg; // HW accel args set a different input thread count, only set if disabled
inputArg = "-threads " + threads + " " + inputArg; // HW accel args set a different input thread count, only set if disabled
}
var filterParam = encodingHelper.GetVideoProcessingFilterParam(jobState, options, jobState.OutputVideoCodec).Trim();
@ -831,7 +834,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
throw new InvalidOperationException("EncodingHelper returned empty or invalid filter parameters.");
}
return ExtractVideoImagesOnIntervalInternal(inputArg, filterParam, interval, vidEncoder, _threads, cancellationToken);
return ExtractVideoImagesOnIntervalInternal(inputArg, filterParam, interval, vidEncoder, threads, qualityScale, priority, cancellationToken);
}
private async Task<string> ExtractVideoImagesOnIntervalInternal(
@ -839,7 +842,9 @@ namespace MediaBrowser.MediaEncoding.Encoder
string filterParam,
TimeSpan interval,
string vidEncoder,
int outputThreads,
int? outputThreads,
int? qualityScale,
ProcessPriorityClass? priority,
CancellationToken cancellationToken)
{
if (string.IsNullOrWhiteSpace(inputArg))
@ -857,10 +862,6 @@ namespace MediaBrowser.MediaEncoding.Encoder
{
filterParam = filterParam.Insert(filterParam.IndexOf("\"", StringComparison.Ordinal) + 1, fps + ",");
}
else
{
filterParam += fps + ",";
}
var targetDirectory = Path.Combine(_configurationManager.ApplicationPaths.TempDirectory, Guid.NewGuid().ToString("N"));
Directory.CreateDirectory(targetDirectory);
@ -869,11 +870,12 @@ namespace MediaBrowser.MediaEncoding.Encoder
// Final command arguments
var args = string.Format(
CultureInfo.InvariantCulture,
"-loglevel error {0} -an -sn {1} -threads {2} -c:v {3} -f {4} \"{5}\"",
"-loglevel error {0} -an -sn {1} -threads {2} -c:v {3} {4}-f {5} \"{6}\"",
inputArg,
filterParam,
outputThreads,
outputThreads.GetValueOrDefault(_threads),
vidEncoder,
qualityScale.HasValue ? "-qscale:v " + qualityScale.Value.ToString(CultureInfo.InvariantCulture) + " " : string.Empty,
"image2",
outputPath);
@ -904,6 +906,19 @@ namespace MediaBrowser.MediaEncoding.Encoder
{
StartProcess(processWrapper);
// Set process priority
if (priority.HasValue)
{
try
{
processWrapper.Process.PriorityClass = priority.Value;
}
catch (Exception ex)
{
_logger.LogDebug(ex, "Unable to set process priority to {Priority} for {Description}", priority.Value, processDescription);
}
}
// 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.
// Making the assumption that as long as new jpegs are showing up, everything is good.

View file

@ -264,5 +264,7 @@ namespace MediaBrowser.Model.Configuration
/// </summary>
/// <value>The limit for parallel image encoding.</value>
public int ParallelImageEncodingLimit { get; set; }
public TrickplayOptions TrickplayOptions { get; set; } = new TrickplayOptions();
}
}

View file

@ -22,7 +22,6 @@ namespace MediaBrowser.Providers.Trickplay
private readonly ILogger<TrickplayImagesTask> _logger;
private readonly ILibraryManager _libraryManager;
private readonly ILocalizationManager _localization;
private readonly IServerConfigurationManager _configurationManager;
private readonly ITrickplayManager _trickplayManager;
/// <summary>
@ -31,19 +30,16 @@ namespace MediaBrowser.Providers.Trickplay
/// <param name="logger">The logger.</param>
/// <param name="libraryManager">The library manager.</param>
/// <param name="localization">The localization manager.</param>
/// <param name="configurationManager">The configuration manager.</param>
/// <param name="trickplayManager">The trickplay manager.</param>
public TrickplayImagesTask(
ILogger<TrickplayImagesTask> logger,
ILibraryManager libraryManager,
ILocalizationManager localization,
IServerConfigurationManager configurationManager,
ITrickplayManager trickplayManager)
{
_libraryManager = libraryManager;
_logger = logger;
_localization = localization;
_configurationManager = configurationManager;
_trickplayManager = trickplayManager;
}
@ -77,6 +73,14 @@ namespace MediaBrowser.Providers.Trickplay
public async Task ExecuteAsync(IProgress<double> progress, CancellationToken cancellationToken)
{
// TODO: libraryoptions dont run on libraries with trickplay disabled
/* will this still get all sub-items? should recursive be true?
* from chapterimagestask
* DtoOptions = new DtoOptions(false)
{
EnableImages = false
},
SourceTypes = new SourceType[] { SourceType.Library },
*/
var items = _libraryManager.GetItemList(new InternalItemsQuery
{
MediaTypes = new[] { MediaType.Video },

View file

@ -5,11 +5,13 @@ using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Controller.Trickplay;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO;
using Microsoft.Extensions.Logging;
@ -28,6 +30,7 @@ namespace MediaBrowser.Providers.Trickplay
private readonly IFileSystem _fileSystem;
private readonly EncodingHelper _encodingHelper;
private readonly ILibraryManager _libraryManager;
private readonly IServerConfigurationManager _config;
private static readonly SemaphoreSlim _resourcePool = new(1, 1);
@ -40,13 +43,15 @@ namespace MediaBrowser.Providers.Trickplay
/// <param name="fileSystem">The file systen.</param>
/// <param name="encodingHelper">The encoding helper.</param>
/// <param name="libraryManager">The library manager.</param>
/// <param name="config">The server configuration manager.</param>
public TrickplayManager(
ILogger<TrickplayManager> logger,
IItemRepository itemRepo,
IMediaEncoder mediaEncoder,
IFileSystem fileSystem,
EncodingHelper encodingHelper,
ILibraryManager libraryManager)
ILibraryManager libraryManager,
IServerConfigurationManager config)
{
_logger = logger;
_itemRepo = itemRepo;
@ -54,6 +59,7 @@ namespace MediaBrowser.Providers.Trickplay
_fileSystem = fileSystem;
_encodingHelper = encodingHelper;
_libraryManager = libraryManager;
_config = config;
}
/// <inheritdoc />
@ -61,16 +67,27 @@ namespace MediaBrowser.Providers.Trickplay
{
_logger.LogDebug("Trickplay refresh for {ItemId} (replace existing: {Replace})", video.Id, replace);
foreach (var width in new int[] { 320 } /*todo conf*/)
var options = _config.Configuration.TrickplayOptions;
foreach (var width in options.WidthResolutions)
{
cancellationToken.ThrowIfCancellationRequested();
await RefreshTrickplayData(video, replace, width, 10000/*todo conf*/, 10/*todo conf*/, 10/*todo conf*/, true/*todo conf*/, true/*todo conf*/, cancellationToken).ConfigureAwait(false);
await RefreshTrickplayDataInternal(
video,
replace,
width,
options,
cancellationToken).ConfigureAwait(false);
}
}
private async Task RefreshTrickplayData(Video video, bool replace, int width, int interval, int tileWidth, int tileHeight, bool doHwAccel, bool doHwEncode, CancellationToken cancellationToken)
private async Task RefreshTrickplayDataInternal(
Video video,
bool replace,
int width,
TrickplayOptions options,
CancellationToken cancellationToken)
{
if (!CanGenerateTrickplay(video, interval))
if (!CanGenerateTrickplay(video, options.Interval))
{
return;
}
@ -108,10 +125,12 @@ namespace MediaBrowser.Providers.Trickplay
container,
mediaSource,
mediaStream,
TimeSpan.FromMilliseconds(interval),
width,
doHwAccel,
doHwEncode,
TimeSpan.FromMilliseconds(options.Interval),
options.EnableHwAcceleration,
options.ProcessThreads,
options.Qscale,
options.ProcessPriority,
_encodingHelper,
cancellationToken).ConfigureAwait(false);
@ -127,7 +146,7 @@ namespace MediaBrowser.Providers.Trickplay
// Create tiles
var tilesTempDir = Path.Combine(imgTempDir, Guid.NewGuid().ToString("N"));
var tilesInfo = CreateTiles(images, width, interval, tileWidth, tileHeight, 100/* todo _config.JpegQuality*/, tilesTempDir, outputDir);
var tilesInfo = CreateTiles(images, width, options, tilesTempDir, outputDir);
// Save tiles info
try
@ -166,7 +185,7 @@ namespace MediaBrowser.Providers.Trickplay
}
}
private TrickplayTilesInfo CreateTiles(List<FileSystemMetadata> images, int width, int interval, int tileWidth, int tileHeight, int quality, string workDir, string outputDir)
private TrickplayTilesInfo CreateTiles(List<FileSystemMetadata> images, int width, TrickplayOptions options, string workDir, string outputDir)
{
if (images.Count == 0)
{
@ -178,9 +197,9 @@ namespace MediaBrowser.Providers.Trickplay
var tilesInfo = new TrickplayTilesInfo
{
Width = width,
Interval = interval,
TileWidth = tileWidth,
TileHeight = tileHeight,
Interval = options.Interval,
TileWidth = options.TileWidth,
TileHeight = options.TileHeight,
TileCount = 0,
Bandwidth = 0
};
@ -244,7 +263,7 @@ namespace MediaBrowser.Providers.Trickplay
var tileGridPath = Path.Combine(workDir, $"{imgNo}.jpg");
using (var stream = File.OpenWrite(tileGridPath))
{
tileGrid.Encode(stream, SKEncodedImageFormat.Jpeg, quality);
tileGrid.Encode(stream, SKEncodedImageFormat.Jpeg, options.JpegQuality);
}
var bitrate = (int)Math.Ceiling((decimal)new FileInfo(tileGridPath).Length * 8 / tilesInfo.TileWidth / tilesInfo.TileHeight / (tilesInfo.Interval / 1000));
@ -351,7 +370,7 @@ namespace MediaBrowser.Providers.Trickplay
{
Directory.Move(source, destination);
}
catch (System.IO.IOException)
catch (IOException)
{
// Cross device move requires a copy
Directory.CreateDirectory(destination);

View file

@ -7,6 +7,7 @@ using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Controller.Trickplay;
using MediaBrowser.Model.Configuration;
using Microsoft.Extensions.Logging;
namespace MediaBrowser.Providers.Trickplay
@ -25,7 +26,7 @@ namespace MediaBrowser.Providers.Trickplay
IForcedProvider
{
private readonly ILogger<TrickplayProvider> _logger;
private readonly IServerConfigurationManager _configurationManager;
private readonly IServerConfigurationManager _config;
private readonly ITrickplayManager _trickplayManager;
private readonly ILibraryManager _libraryManager;
@ -33,17 +34,17 @@ namespace MediaBrowser.Providers.Trickplay
/// Initializes a new instance of the <see cref="TrickplayProvider"/> class.
/// </summary>
/// <param name="logger">The logger.</param>
/// <param name="configurationManager">The configuration manager.</param>
/// <param name="config">The configuration manager.</param>
/// <param name="trickplayManager">The trickplay manager.</param>
/// <param name="libraryManager">The library manager.</param>
public TrickplayProvider(
ILogger<TrickplayProvider> logger,
IServerConfigurationManager configurationManager,
IServerConfigurationManager config,
ITrickplayManager trickplayManager,
ILibraryManager libraryManager)
{
_logger = logger;
_configurationManager = configurationManager;
_config = config;
_trickplayManager = trickplayManager;
_libraryManager = libraryManager;
}
@ -110,11 +111,14 @@ namespace MediaBrowser.Providers.Trickplay
return ItemUpdateType.None;
}
// TODO: this is always blocking for metadata collection, make non-blocking option
if (true)
if (_config.Configuration.TrickplayOptions.ScanBehavior == TrickplayScanBehavior.Blocking)
{
await _trickplayManager.RefreshTrickplayData(video, replace, cancellationToken).ConfigureAwait(false);
}
else
{
_ = _trickplayManager.RefreshTrickplayData(video, replace, cancellationToken).ConfigureAwait(false);
}
// The core doesn't need to trigger any save operations over this
return ItemUpdateType.None;