diff options
30 files changed, 132 insertions, 103 deletions
diff --git a/Dockerfile.arm b/Dockerfile.arm index 8da17ee5f..8e0ba7af5 100644 --- a/Dockerfile.arm +++ b/Dockerfile.arm @@ -38,9 +38,6 @@ RUN apt-get update \ libssl-dev \ libfontconfig1 \ libfreetype6 \ - libomxil-bellagio0 \ - libomxil-bellagio-bin \ - libraspberrypi0 \ vainfo \ libva2 \ locales \ diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs index 09ba36851..3d2b8f7f6 100644 --- a/Emby.Server.Implementations/Dto/DtoService.cs +++ b/Emby.Server.Implementations/Dto/DtoService.cs @@ -182,7 +182,7 @@ namespace Emby.Server.Implementations.Dto if (options.ContainsField(ItemFields.People)) { - AttachPeople(dto, item); + AttachPeople(dto, item, user); } if (options.ContainsField(ItemFields.PrimaryImageAspectRatio)) @@ -503,7 +503,8 @@ namespace Emby.Server.Implementations.Dto /// </summary> /// <param name="dto">The dto.</param> /// <param name="item">The item.</param> - private void AttachPeople(BaseItemDto dto, BaseItem item) + /// <param name="user">The requesting user.</param> + private void AttachPeople(BaseItemDto dto, BaseItem item, User user = null) { // Ordering by person type to ensure actors and artists are at the front. // This is taking advantage of the fact that they both begin with A @@ -560,6 +561,9 @@ namespace Emby.Server.Implementations.Dto return null; } }).Where(i => i != null) + .Where(i => user == null ? + true : + i.IsVisible(user)) .GroupBy(i => i.Name, StringComparer.OrdinalIgnoreCase) .Select(x => x.First()) .ToDictionary(i => i.Name, StringComparer.OrdinalIgnoreCase); diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index 24395a193..2792a4c7c 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -29,7 +29,7 @@ <PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="6.0.1" /> <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="6.0.0" /> <PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="6.0.0" /> - <PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.8" /> + <PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.9" /> <PackageReference Include="Mono.Nat" Version="3.0.3" /> <PackageReference Include="prometheus-net.DotNetRuntime" Version="4.2.4" /> <PackageReference Include="sharpcompress" Version="0.32.2" /> diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index 679684552..250e7619f 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -2766,7 +2766,8 @@ namespace Emby.Server.Implementations.Library public List<Person> GetPeopleItems(InternalPeopleQuery query) { - return _itemRepository.GetPeopleNames(query).Select(i => + return _itemRepository.GetPeopleNames(query) + .Select(i => { try { @@ -2777,7 +2778,12 @@ namespace Emby.Server.Implementations.Library _logger.LogError(ex, "Error getting person"); return null; } - }).Where(i => i != null).ToList(); + }) + .Where(i => i != null) + .Where(i => query.User == null ? + true : + i.IsVisible(query.User)) + .ToList(); } public List<string> GetPeopleNames(InternalPeopleQuery query) diff --git a/Emby.Server.Implementations/Localization/Core/sl-SI.json b/Emby.Server.Implementations/Localization/Core/sl-SI.json index b2d7ce11d..d845accac 100644 --- a/Emby.Server.Implementations/Localization/Core/sl-SI.json +++ b/Emby.Server.Implementations/Localization/Core/sl-SI.json @@ -90,7 +90,7 @@ "UserStartedPlayingItemWithValues": "{0} predvaja {1} na {2}", "UserStoppedPlayingItemWithValues": "{0} je nehal predvajati {1} na {2}", "ValueHasBeenAddedToLibrary": "{0} je bil dodan vaši knjižnici", - "ValueSpecialEpisodeName": "Bonus - {0}", + "ValueSpecialEpisodeName": "Posebna epizoda - {0}", "VersionNumber": "Različica {0}", "TaskDownloadMissingSubtitles": "Prenesi manjkajoče podnapise", "TaskRefreshChannelsDescription": "Osveži podatke spletnih kanalov.", diff --git a/Emby.Server.Implementations/TV/TVSeriesManager.cs b/Emby.Server.Implementations/TV/TVSeriesManager.cs index d7ab9c021..6005896ad 100644 --- a/Emby.Server.Implementations/TV/TVSeriesManager.cs +++ b/Emby.Server.Implementations/TV/TVSeriesManager.cs @@ -135,20 +135,15 @@ namespace Emby.Server.Implementations.TV return GetResult(episodes, request); } - public IEnumerable<Episode> GetNextUpEpisodes(NextUpQuery request, User user, IReadOnlyList<string> seriesKeys, DtoOptions dtoOptions) + private IEnumerable<Episode> GetNextUpEpisodes(NextUpQuery request, User user, IReadOnlyList<string> seriesKeys, DtoOptions dtoOptions) { - // Avoid implicitly captured closure - var currentUser = user; - - var allNextUp = seriesKeys - .Select(i => GetNextUp(i, currentUser, dtoOptions, false)); + var allNextUp = seriesKeys.Select(i => GetNextUp(i, user, dtoOptions, false)); if (request.EnableRewatching) { allNextUp = allNextUp.Concat( - seriesKeys.Select(i => GetNextUp(i, currentUser, dtoOptions, true)) - ) - .OrderByDescending(i => i.Item1); + seriesKeys.Select(i => GetNextUp(i, user, dtoOptions, true))) + .OrderByDescending(i => i.LastWatchedDate); } // If viewing all next up for all series, remove first episodes @@ -161,23 +156,18 @@ namespace Emby.Server.Implementations.TV { if (request.DisableFirstEpisode) { - return i.Item1 != DateTime.MinValue; + return i.LastWatchedDate != DateTime.MinValue; } - if (alwaysEnableFirstEpisode || (i.Item1 != DateTime.MinValue && i.Item1.Date >= request.NextUpDateCutoff)) + if (alwaysEnableFirstEpisode || (i.LastWatchedDate != DateTime.MinValue && i.LastWatchedDate.Date >= request.NextUpDateCutoff)) { anyFound = true; return true; } - if (!anyFound && i.Item1 == DateTime.MinValue) - { - return true; - } - - return false; + return !anyFound && i.LastWatchedDate == DateTime.MinValue; }) - .Select(i => i.Item2()) + .Select(i => i.GetEpisodeFunction()) .Where(i => i != null); } @@ -195,14 +185,14 @@ namespace Emby.Server.Implementations.TV /// Gets the next up. /// </summary> /// <returns>Task{Episode}.</returns> - private Tuple<DateTime, Func<Episode>> GetNextUp(string seriesKey, User user, DtoOptions dtoOptions, bool rewatching) + private (DateTime LastWatchedDate, Func<Episode> GetEpisodeFunction) GetNextUp(string seriesKey, User user, DtoOptions dtoOptions, bool rewatching) { var lastQuery = new InternalItemsQuery(user) { AncestorWithPresentationUniqueKey = null, SeriesPresentationUniqueKey = seriesKey, IncludeItemTypes = new[] { BaseItemKind.Episode }, - OrderBy = new[] { (ItemSortBy.SortName, SortOrder.Descending) }, + OrderBy = new[] { (ItemSortBy.ParentIndexNumber, SortOrder.Descending), (ItemSortBy.IndexNumber, SortOrder.Descending) }, IsPlayed = true, Limit = 1, ParentIndexNumberNotEquals = 0, @@ -216,24 +206,23 @@ namespace Emby.Server.Implementations.TV if (rewatching) { // find last watched by date played, not by newest episode watched - lastQuery.OrderBy = new[] { (ItemSortBy.DatePlayed, SortOrder.Descending) }; + lastQuery.OrderBy = new[] { (ItemSortBy.DatePlayed, SortOrder.Descending), (ItemSortBy.ParentIndexNumber, SortOrder.Descending), (ItemSortBy.IndexNumber, SortOrder.Descending) }; } var lastWatchedEpisode = _libraryManager.GetItemList(lastQuery).Cast<Episode>().FirstOrDefault(); - Func<Episode> getEpisode = () => + Episode GetEpisode() { var nextQuery = new InternalItemsQuery(user) { AncestorWithPresentationUniqueKey = null, SeriesPresentationUniqueKey = seriesKey, IncludeItemTypes = new[] { BaseItemKind.Episode }, - OrderBy = new[] { (ItemSortBy.SortName, SortOrder.Ascending) }, + OrderBy = new[] { (ItemSortBy.ParentIndexNumber, SortOrder.Ascending), (ItemSortBy.IndexNumber, SortOrder.Ascending) }, Limit = 1, IsPlayed = rewatching, IsVirtualItem = false, ParentIndexNumberNotEquals = 0, - MinSortName = lastWatchedEpisode?.SortName, DtoOptions = dtoOptions }; @@ -297,7 +286,7 @@ namespace Emby.Server.Implementations.TV } return nextEpisode; - }; + } if (lastWatchedEpisode != null) { @@ -305,11 +294,11 @@ namespace Emby.Server.Implementations.TV var lastWatchedDate = userData.LastPlayedDate ?? DateTime.MinValue.AddDays(1); - return new Tuple<DateTime, Func<Episode>>(lastWatchedDate, getEpisode); + return (lastWatchedDate, GetEpisode); } // Return the first episode - return new Tuple<DateTime, Func<Episode>>(DateTime.MinValue, getEpisode); + return (DateTime.MinValue, GetEpisode); } private static QueryResult<BaseItem> GetResult(IEnumerable<BaseItem> items, NextUpQuery query) diff --git a/Jellyfin.Api/Controllers/PersonsController.cs b/Jellyfin.Api/Controllers/PersonsController.cs index be4b9eded..33f1aea39 100644 --- a/Jellyfin.Api/Controllers/PersonsController.cs +++ b/Jellyfin.Api/Controllers/PersonsController.cs @@ -98,7 +98,10 @@ namespace Jellyfin.Api.Controllers Limit = limit ?? 0 }); - return new QueryResult<BaseItemDto>(peopleItems.Select(person => _dtoService.GetItemByNameDto(person, dtoOptions, null, user)).ToArray()); + return new QueryResult<BaseItemDto>( + peopleItems + .Select(person => _dtoService.GetItemByNameDto(person, dtoOptions, null, user)) + .ToArray()); } /// <summary> diff --git a/Jellyfin.Api/Controllers/UniversalAudioController.cs b/Jellyfin.Api/Controllers/UniversalAudioController.cs index 43b8e2414..c463fb08a 100644 --- a/Jellyfin.Api/Controllers/UniversalAudioController.cs +++ b/Jellyfin.Api/Controllers/UniversalAudioController.cs @@ -111,7 +111,13 @@ namespace Jellyfin.Api.Controllers [FromQuery] bool enableRedirection = true) { var deviceProfile = GetDeviceProfile(container, transcodingContainer, audioCodec, transcodingProtocol, breakOnNonKeyFrames, transcodingAudioChannels, maxAudioSampleRate, maxAudioBitDepth, maxAudioChannels); - (await _authorizationContext.GetAuthorizationInfo(Request).ConfigureAwait(false)).DeviceId = deviceId; + var authorizationInfo = await _authorizationContext.GetAuthorizationInfo(Request).ConfigureAwait(false); + authorizationInfo.DeviceId = deviceId; + + if (!userId.HasValue || userId.Value.Equals(Guid.Empty)) + { + userId = authorizationInfo.UserId; + } var authInfo = await _authorizationContext.GetAuthorizationInfo(Request).ConfigureAwait(false); diff --git a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs index 13dc878c1..2adb006e4 100644 --- a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs +++ b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs @@ -654,7 +654,7 @@ namespace Jellyfin.Api.Helpers { if (EnableThrottling(state)) { - transcodingJob.TranscodingThrottler = new TranscodingThrottler(transcodingJob, new Logger<TranscodingThrottler>(new LoggerFactory()), _serverConfigurationManager, _fileSystem); + transcodingJob.TranscodingThrottler = new TranscodingThrottler(transcodingJob, new Logger<TranscodingThrottler>(new LoggerFactory()), _serverConfigurationManager, _fileSystem, _mediaEncoder); transcodingJob.TranscodingThrottler.Start(); } } diff --git a/Jellyfin.Api/Jellyfin.Api.csproj b/Jellyfin.Api/Jellyfin.Api.csproj index ce01b415b..7e64cf645 100644 --- a/Jellyfin.Api/Jellyfin.Api.csproj +++ b/Jellyfin.Api/Jellyfin.Api.csproj @@ -17,7 +17,7 @@ </PropertyGroup> <ItemGroup> - <PackageReference Include="Microsoft.AspNetCore.Authorization" Version="6.0.8" /> + <PackageReference Include="Microsoft.AspNetCore.Authorization" Version="6.0.9" /> <PackageReference Include="Microsoft.Extensions.Http" Version="6.0.0" /> <PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.3" /> <PackageReference Include="Swashbuckle.AspNetCore.ReDoc" Version="6.4.0" /> diff --git a/Jellyfin.Api/Models/PlaybackDtos/TranscodingThrottler.cs b/Jellyfin.Api/Models/PlaybackDtos/TranscodingThrottler.cs index 7a1ca252c..99376873c 100644 --- a/Jellyfin.Api/Models/PlaybackDtos/TranscodingThrottler.cs +++ b/Jellyfin.Api/Models/PlaybackDtos/TranscodingThrottler.cs @@ -2,6 +2,7 @@ using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common.Configuration; +using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.IO; using Microsoft.Extensions.Logging; @@ -17,6 +18,7 @@ namespace Jellyfin.Api.Models.PlaybackDtos private readonly ILogger<TranscodingThrottler> _logger; private readonly IConfigurationManager _config; private readonly IFileSystem _fileSystem; + private readonly IMediaEncoder _mediaEncoder; private Timer? _timer; private bool _isPaused; @@ -27,12 +29,14 @@ namespace Jellyfin.Api.Models.PlaybackDtos /// <param name="logger">Instance of the <see cref="ILogger{TranscodingThrottler}"/> interface.</param> /// <param name="config">Instance of the <see cref="IConfigurationManager"/> interface.</param> /// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param> - public TranscodingThrottler(TranscodingJobDto job, ILogger<TranscodingThrottler> logger, IConfigurationManager config, IFileSystem fileSystem) + /// <param name="mediaEncoder">Instance of the <see cref="IMediaEncoder"/> interface.</param> + public TranscodingThrottler(TranscodingJobDto job, ILogger<TranscodingThrottler> logger, IConfigurationManager config, IFileSystem fileSystem, IMediaEncoder mediaEncoder) { _job = job; _logger = logger; _config = config; _fileSystem = fileSystem; + _mediaEncoder = mediaEncoder; } /// <summary> @@ -55,7 +59,8 @@ namespace Jellyfin.Api.Models.PlaybackDtos try { - await _job.Process!.StandardInput.WriteLineAsync().ConfigureAwait(false); + var resumeKey = _mediaEncoder.IsPkeyPauseSupported ? "u" : Environment.NewLine; + await _job.Process!.StandardInput.WriteAsync(resumeKey).ConfigureAwait(false); _isPaused = false; } catch (Exception ex) @@ -125,11 +130,13 @@ namespace Jellyfin.Api.Models.PlaybackDtos { if (!_isPaused) { - _logger.LogDebug("Sending pause command to ffmpeg"); + var pauseKey = _mediaEncoder.IsPkeyPauseSupported ? "p" : "c"; + + _logger.LogDebug("Sending pause command [{Key}] to ffmpeg", pauseKey); try { - await _job.Process!.StandardInput.WriteAsync("c").ConfigureAwait(false); + await _job.Process!.StandardInput.WriteAsync(pauseKey).ConfigureAwait(false); _isPaused = true; } catch (Exception ex) diff --git a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj index 678f96083..83b226278 100644 --- a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj +++ b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj @@ -27,13 +27,13 @@ <ItemGroup> <PackageReference Include="System.Linq.Async" Version="6.0.1" /> - <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="6.0.8" /> - <PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.8" /> - <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.8"> + <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="6.0.9" /> + <PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.9" /> + <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.9"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> </PackageReference> - <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.8"> + <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.9"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> </PackageReference> diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj index ab13e314e..2517894fb 100644 --- a/Jellyfin.Server/Jellyfin.Server.csproj +++ b/Jellyfin.Server/Jellyfin.Server.csproj @@ -37,8 +37,8 @@ <PackageReference Include="CommandLineParser" Version="2.9.1" /> <PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="6.0.1" /> <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="6.0.0" /> - <PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks" Version="6.0.8" /> - <PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore" Version="6.0.8" /> + <PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks" Version="6.0.9" /> + <PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore" Version="6.0.9" /> <PackageReference Include="prometheus-net" Version="6.0.0" /> <PackageReference Include="prometheus-net.AspNetCore" Version="6.0.0" /> <PackageReference Include="Serilog.AspNetCore" Version="4.1.0" /> diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index 1860da4c7..92d12a86c 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -892,29 +892,7 @@ namespace MediaBrowser.Controller.Entities private static BaseItem[] SortItemsByRequest(InternalItemsQuery query, IReadOnlyList<BaseItem> items) { - var ids = query.ItemIds; - int size = items.Count; - - // ids can potentially contain non-unique guids, but query result cannot, - // so we include only first occurrence of each guid - var positions = new Dictionary<Guid, int>(size); - int index = 0; - for (int i = 0; i < ids.Length; i++) - { - if (positions.TryAdd(ids[i], index)) - { - index++; - } - } - - var newItems = new BaseItem[size]; - for (int i = 0; i < size; i++) - { - var item = items[i]; - newItems[positions[item.Id]] = item; - } - - return newItems; + return items.OrderBy(i => Array.IndexOf(query.ItemIds, i.Id)).ToArray(); } public QueryResult<BaseItem> GetItems(InternalItemsQuery query) diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 1d1077716..42c5517f9 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -4991,13 +4991,13 @@ namespace MediaBrowser.Controller.MediaEncoding // The default value of -probesize is more than enough, so leave it as is. var ffmpegAnalyzeDuration = _config.GetFFmpegAnalyzeDuration() ?? string.Empty; - if (!string.IsNullOrEmpty(ffmpegAnalyzeDuration)) + if (state.MediaSource.AnalyzeDurationMs > 0) { - analyzeDurationArgument = "-analyzeduration " + ffmpegAnalyzeDuration; + analyzeDurationArgument = "-analyzeduration " + (state.MediaSource.AnalyzeDurationMs.Value * 1000).ToString(CultureInfo.InvariantCulture); } - else if (state.MediaSource.AnalyzeDurationMs.HasValue) + else if (!string.IsNullOrEmpty(ffmpegAnalyzeDuration)) { - analyzeDurationArgument = "-analyzeduration " + (state.MediaSource.AnalyzeDurationMs.Value * 1000).ToString(CultureInfo.InvariantCulture); + analyzeDurationArgument = "-analyzeduration " + ffmpegAnalyzeDuration; } if (!string.IsNullOrEmpty(analyzeDurationArgument)) diff --git a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs index dae30cd8b..69d0bf45c 100644 --- a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs +++ b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs @@ -38,6 +38,12 @@ namespace MediaBrowser.Controller.MediaEncoding Version EncoderVersion { get; } /// <summary> + /// Whether p key pausing is supported. + /// </summary> + /// <value><c>true</c> if p key pausing is supported, <c>false</c> otherwise.</value> + bool IsPkeyPauseSupported { get; } + + /// <summary> /// Gets a value indicating whether the configured Vaapi device is from AMD(radeonsi/r600 Mesa driver). /// </summary> /// <value><c>true</c> if the Vaapi device is an AMD(radeonsi/r600 Mesa driver) GPU, <c>false</c> otherwise.</value> diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs index d378c6e13..9b4b1db94 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs @@ -153,7 +153,7 @@ namespace MediaBrowser.MediaEncoding.Encoder string output; try { - output = GetProcessOutput(_encoderPath, "-version", false); + output = GetProcessOutput(_encoderPath, "-version", false, null); } catch (Exception ex) { @@ -234,7 +234,7 @@ namespace MediaBrowser.MediaEncoding.Encoder string output; try { - output = GetProcessOutput(_encoderPath, "-version", false); + output = GetProcessOutput(_encoderPath, "-version", false, null); } catch (Exception ex) { @@ -341,7 +341,7 @@ namespace MediaBrowser.MediaEncoding.Encoder try { - var output = GetProcessOutput(_encoderPath, "-v verbose -hide_banner -init_hw_device vaapi=va:" + renderNodePath, true); + var output = GetProcessOutput(_encoderPath, "-v verbose -hide_banner -init_hw_device vaapi=va:" + renderNodePath, true, null); return output.Contains(driverName, StringComparison.Ordinal); } catch (Exception ex) @@ -356,7 +356,7 @@ namespace MediaBrowser.MediaEncoding.Encoder string? output = null; try { - output = GetProcessOutput(_encoderPath, "-hwaccels", false); + output = GetProcessOutput(_encoderPath, "-hwaccels", false, null); } catch (Exception ex) { @@ -384,7 +384,7 @@ namespace MediaBrowser.MediaEncoding.Encoder string output; try { - output = GetProcessOutput(_encoderPath, "-h filter=" + filter, false); + output = GetProcessOutput(_encoderPath, "-h filter=" + filter, false, null); } catch (Exception ex) { @@ -402,13 +402,34 @@ namespace MediaBrowser.MediaEncoding.Encoder return false; } + public bool CheckSupportedRuntimeKey(string keyDesc) + { + if (string.IsNullOrEmpty(keyDesc)) + { + return false; + } + + string output; + try + { + output = GetProcessOutput(_encoderPath, "-hide_banner -f lavfi -i nullsrc=s=1x1:d=500 -f null -", true, "?"); + } + catch (Exception ex) + { + _logger.LogError(ex, "Error checking supported runtime key"); + return false; + } + + return output.Contains(keyDesc, StringComparison.Ordinal); + } + private IEnumerable<string> GetCodecs(Codec codec) { string codecstr = codec == Codec.Encoder ? "encoders" : "decoders"; string output; try { - output = GetProcessOutput(_encoderPath, "-" + codecstr, false); + output = GetProcessOutput(_encoderPath, "-" + codecstr, false, null); } catch (Exception ex) { @@ -439,7 +460,7 @@ namespace MediaBrowser.MediaEncoding.Encoder string output; try { - output = GetProcessOutput(_encoderPath, "-filters", false); + output = GetProcessOutput(_encoderPath, "-filters", false, null); } catch (Exception ex) { @@ -477,7 +498,7 @@ namespace MediaBrowser.MediaEncoding.Encoder return dict; } - private string GetProcessOutput(string path, string arguments, bool readStdErr) + private string GetProcessOutput(string path, string arguments, bool readStdErr, string? testKey) { using (var process = new Process() { @@ -487,6 +508,7 @@ namespace MediaBrowser.MediaEncoding.Encoder UseShellExecute = false, WindowStyle = ProcessWindowStyle.Hidden, ErrorDialog = false, + RedirectStandardInput = !string.IsNullOrEmpty(testKey), RedirectStandardOutput = true, RedirectStandardError = true } @@ -496,6 +518,11 @@ namespace MediaBrowser.MediaEncoding.Encoder process.Start(); + if (!string.IsNullOrEmpty(testKey)) + { + process.StandardInput.Write(testKey); + } + return readStdErr ? process.StandardError.ReadToEnd() : process.StandardOutput.ReadToEnd(); } } diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 7f301a9d8..757a01715 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -67,6 +67,8 @@ namespace MediaBrowser.MediaEncoding.Encoder private List<string> _filters = new List<string>(); private IDictionary<int, bool> _filtersWithOption = new Dictionary<int, bool>(); + private bool _isPkeyPauseSupported = false; + private bool _isVaapiDeviceAmd = false; private bool _isVaapiDeviceInteliHD = false; private bool _isVaapiDeviceInteli965 = false; @@ -100,6 +102,8 @@ namespace MediaBrowser.MediaEncoding.Encoder public Version EncoderVersion => _ffmpegVersion; + public bool IsPkeyPauseSupported => _isPkeyPauseSupported; + public bool IsVaapiDeviceAmd => _isVaapiDeviceAmd; public bool IsVaapiDeviceInteliHD => _isVaapiDeviceInteliHD; @@ -154,6 +158,8 @@ namespace MediaBrowser.MediaEncoding.Encoder _threads = EncodingHelper.GetNumberOfThreads(null, options, null); + _isPkeyPauseSupported = validator.CheckSupportedRuntimeKey("p pause transcoding"); + // Check the Vaapi device vendor if (OperatingSystem.IsLinux() && SupportsHwaccel("vaapi") @@ -376,15 +382,15 @@ namespace MediaBrowser.MediaEncoding.Encoder string analyzeDuration = string.Empty; string ffmpegAnalyzeDuration = _config.GetFFmpegAnalyzeDuration() ?? string.Empty; - if (!string.IsNullOrEmpty(ffmpegAnalyzeDuration)) - { - analyzeDuration = "-analyzeduration " + ffmpegAnalyzeDuration; - } - else if (request.MediaSource.AnalyzeDurationMs > 0) + if (request.MediaSource.AnalyzeDurationMs > 0) { analyzeDuration = "-analyzeduration " + (request.MediaSource.AnalyzeDurationMs * 1000).ToString(); } + else if (!string.IsNullOrEmpty(ffmpegAnalyzeDuration)) + { + analyzeDuration = "-analyzeduration " + ffmpegAnalyzeDuration; + } var forceEnableLogging = request.MediaSource.Protocol != MediaProtocol.File; diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index 4f511f996..ad2ff1ba2 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -34,13 +34,13 @@ <ItemGroup> <PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" /> - <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.1" /> + <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.2" /> <PackageReference Include="MimeTypes" Version="2.4.0"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> </PackageReference> <PackageReference Include="System.Globalization" Version="4.3.0" /> - <PackageReference Include="System.Text.Json" Version="6.0.5" /> + <PackageReference Include="System.Text.Json" Version="6.0.6" /> </ItemGroup> <ItemGroup> diff --git a/debian/jellyfin.service b/debian/jellyfin.service index 2f97c4654..1150924a0 100644 --- a/debian/jellyfin.service +++ b/debian/jellyfin.service @@ -8,7 +8,7 @@ EnvironmentFile = /etc/default/jellyfin User = jellyfin Group = jellyfin WorkingDirectory = /var/lib/jellyfin -ExecStart = /usr/bin/jellyfin ${JELLYFIN_WEB_OPT} ${JELLYFIN_RESTART_OPT} ${JELLYFIN_FFMPEG_OPT} ${JELLYFIN_SERVICE_OPT} ${JELLYFIN_NOWEBAPP_OPT} ${JELLYFIN_ADDITIONAL_OPTS} +ExecStart = /usr/bin/jellyfin $JELLYFIN_WEB_OPT $JELLYFIN_RESTART_OPT $JELLYFIN_FFMPEG_OPT $JELLYFIN_SERVICE_OPT $JELLYFIN_NOWEBAPP_OPT $JELLYFIN_ADDITIONAL_OPTS Restart = on-failure TimeoutSec = 15 SuccessExitStatus=0 143 diff --git a/deployment/Dockerfile.centos.amd64 b/deployment/Dockerfile.centos.amd64 index 81d75c1aa..0bae42bc8 100644 --- a/deployment/Dockerfile.centos.amd64 +++ b/deployment/Dockerfile.centos.amd64 @@ -13,7 +13,7 @@ RUN yum update -yq \ && yum install -yq @buildsys-build rpmdevtools yum-plugins-core libcurl-devel fontconfig-devel freetype-devel openssl-devel glibc-devel libicu-devel git wget # Install DotNET SDK -RUN wget -q https://download.visualstudio.microsoft.com/download/pr/cd0d0a4d-2a6a-4d0d-b42e-dfd3b880e222/008a93f83aba6d1acf75ded3d2cfba24/dotnet-sdk-6.0.400-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget -q https://download.visualstudio.microsoft.com/download/pr/8159607a-e686-4ead-ac99-b4c97290a5fd/ec6070b1b2cc0651ebe57cf1bd411315/dotnet-sdk-6.0.401-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/deployment/Dockerfile.fedora.amd64 b/deployment/Dockerfile.fedora.amd64 index 4139ed96d..20aa777b6 100644 --- a/deployment/Dockerfile.fedora.amd64 +++ b/deployment/Dockerfile.fedora.amd64 @@ -12,7 +12,7 @@ RUN dnf update -yq \ && dnf install -yq @buildsys-build rpmdevtools git dnf-plugins-core libcurl-devel fontconfig-devel freetype-devel openssl-devel glibc-devel libicu-devel systemd wget make # Install DotNET SDK -RUN wget -q https://download.visualstudio.microsoft.com/download/pr/cd0d0a4d-2a6a-4d0d-b42e-dfd3b880e222/008a93f83aba6d1acf75ded3d2cfba24/dotnet-sdk-6.0.400-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget -q https://download.visualstudio.microsoft.com/download/pr/8159607a-e686-4ead-ac99-b4c97290a5fd/ec6070b1b2cc0651ebe57cf1bd411315/dotnet-sdk-6.0.401-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/deployment/Dockerfile.ubuntu.amd64 b/deployment/Dockerfile.ubuntu.amd64 index 7863d1313..ccc0f76cd 100644 --- a/deployment/Dockerfile.ubuntu.amd64 +++ b/deployment/Dockerfile.ubuntu.amd64 @@ -17,7 +17,7 @@ RUN apt-get update -yqq \ libfreetype6-dev libssl-dev libssl1.1 liblttng-ust0 # Install dotnet repository -RUN wget -q https://download.visualstudio.microsoft.com/download/pr/cd0d0a4d-2a6a-4d0d-b42e-dfd3b880e222/008a93f83aba6d1acf75ded3d2cfba24/dotnet-sdk-6.0.400-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget -q https://download.visualstudio.microsoft.com/download/pr/8159607a-e686-4ead-ac99-b4c97290a5fd/ec6070b1b2cc0651ebe57cf1bd411315/dotnet-sdk-6.0.401-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/deployment/Dockerfile.ubuntu.arm64 b/deployment/Dockerfile.ubuntu.arm64 index 206caea11..893180974 100644 --- a/deployment/Dockerfile.ubuntu.arm64 +++ b/deployment/Dockerfile.ubuntu.arm64 @@ -16,7 +16,7 @@ RUN apt-get update -yqq \ mmv build-essential lsb-release # Install dotnet repository -RUN wget -q https://download.visualstudio.microsoft.com/download/pr/cd0d0a4d-2a6a-4d0d-b42e-dfd3b880e222/008a93f83aba6d1acf75ded3d2cfba24/dotnet-sdk-6.0.400-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget -q https://download.visualstudio.microsoft.com/download/pr/8159607a-e686-4ead-ac99-b4c97290a5fd/ec6070b1b2cc0651ebe57cf1bd411315/dotnet-sdk-6.0.401-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/deployment/Dockerfile.ubuntu.armhf b/deployment/Dockerfile.ubuntu.armhf index 5bd1a5638..bf1edf777 100644 --- a/deployment/Dockerfile.ubuntu.armhf +++ b/deployment/Dockerfile.ubuntu.armhf @@ -16,7 +16,7 @@ RUN apt-get update -yqq \ mmv build-essential lsb-release # Install dotnet repository -RUN wget -q https://download.visualstudio.microsoft.com/download/pr/cd0d0a4d-2a6a-4d0d-b42e-dfd3b880e222/008a93f83aba6d1acf75ded3d2cfba24/dotnet-sdk-6.0.400-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget -q https://download.visualstudio.microsoft.com/download/pr/8159607a-e686-4ead-ac99-b4c97290a5fd/ec6070b1b2cc0651ebe57cf1bd411315/dotnet-sdk-6.0.401-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/fedora/jellyfin.service b/fedora/jellyfin.service index eb0d64087..2fb9f30e0 100644 --- a/fedora/jellyfin.service +++ b/fedora/jellyfin.service @@ -8,7 +8,7 @@ EnvironmentFile = /etc/sysconfig/jellyfin User = jellyfin Group = jellyfin WorkingDirectory = /var/lib/jellyfin -ExecStart = /usr/bin/jellyfin ${JELLYFIN_WEB_OPT} ${JELLYFIN_RESTART_OPT} ${JELLYFIN_FFMPEG_OPT} ${JELLYFIN_SERVICE_OPT} ${JELLYFIN_NOWEBAPP_OPT} ${JELLYFIN_ADDITIONAL_OPTS} +ExecStart = /usr/bin/jellyfin $JELLYFIN_WEB_OPT $JELLYFIN_RESTART_OPT $JELLYFIN_FFMPEG_OPT $JELLYFIN_SERVICE_OPT $JELLYFIN_NOWEBAPP_OPT $JELLYFIN_ADDITIONAL_OPTS Restart = on-failure TimeoutSec = 15 SuccessExitStatus=0 143 diff --git a/src/Jellyfin.MediaEncoding.Keyframes/Jellyfin.MediaEncoding.Keyframes.csproj b/src/Jellyfin.MediaEncoding.Keyframes/Jellyfin.MediaEncoding.Keyframes.csproj index 29cdf561f..9585cb60c 100644 --- a/src/Jellyfin.MediaEncoding.Keyframes/Jellyfin.MediaEncoding.Keyframes.csproj +++ b/src/Jellyfin.MediaEncoding.Keyframes/Jellyfin.MediaEncoding.Keyframes.csproj @@ -21,7 +21,7 @@ </ItemGroup> <ItemGroup> - <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.1" /> + <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.2" /> </ItemGroup> <ItemGroup> diff --git a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj index 97a549943..a742029b6 100644 --- a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj +++ b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj @@ -15,7 +15,7 @@ <PackageReference Include="AutoFixture" Version="4.17.0" /> <PackageReference Include="AutoFixture.AutoMoq" Version="4.17.0" /> <PackageReference Include="AutoFixture.Xunit2" Version="4.17.0" /> - <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="6.0.8" /> + <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="6.0.9" /> <PackageReference Include="Microsoft.Extensions.Options" Version="6.0.0" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.1" /> <PackageReference Include="xunit" Version="2.4.2" /> diff --git a/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj b/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj index 2be523a80..c2ab03e25 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj +++ b/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj @@ -9,7 +9,7 @@ <PackageReference Include="AutoFixture" Version="4.17.0" /> <PackageReference Include="AutoFixture.AutoMoq" Version="4.17.0" /> <PackageReference Include="AutoFixture.Xunit2" Version="4.17.0" /> - <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="6.0.8" /> + <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="6.0.9" /> <PackageReference Include="Microsoft.Extensions.Options" Version="6.0.0" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.1" /> <PackageReference Include="xunit" Version="2.4.2" /> diff --git a/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj b/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj index e69f1f0e0..88686b7df 100644 --- a/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj +++ b/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj @@ -10,7 +10,7 @@ <PackageReference Include="AutoFixture" Version="4.17.0" /> <PackageReference Include="AutoFixture.AutoMoq" Version="4.17.0" /> <PackageReference Include="AutoFixture.Xunit2" Version="4.17.0" /> - <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="6.0.8" /> + <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="6.0.9" /> <PackageReference Include="Microsoft.Extensions.Options" Version="6.0.0" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.1" /> <PackageReference Include="xunit" Version="2.4.2" /> |
