mirror of
https://github.com/jellyfin/jellyfin.git
synced 2026-07-06 14:22:55 +01:00
Merge branch 'master' into network-rewrite
This commit is contained in:
@@ -801,16 +801,14 @@ namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
return allowed.Contains(ChannelId);
|
||||
}
|
||||
else
|
||||
{
|
||||
var collectionFolders = LibraryManager.GetCollectionFolders(this, allCollectionFolders);
|
||||
|
||||
foreach (var folder in collectionFolders)
|
||||
var collectionFolders = LibraryManager.GetCollectionFolders(this, allCollectionFolders);
|
||||
|
||||
foreach (var folder in collectionFolders)
|
||||
{
|
||||
if (allowed.Contains(folder.Id))
|
||||
{
|
||||
if (allowed.Contains(folder.Id))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -893,16 +891,6 @@ namespace MediaBrowser.Controller.Entities
|
||||
|
||||
var sortable = Name.Trim().ToLowerInvariant();
|
||||
|
||||
foreach (var removeChar in ConfigurationManager.Configuration.SortRemoveCharacters)
|
||||
{
|
||||
sortable = sortable.Replace(removeChar, string.Empty, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
foreach (var replaceChar in ConfigurationManager.Configuration.SortReplaceCharacters)
|
||||
{
|
||||
sortable = sortable.Replace(replaceChar, " ", StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
foreach (var search in ConfigurationManager.Configuration.SortRemoveWords)
|
||||
{
|
||||
// Remove from beginning if a space follows
|
||||
@@ -921,12 +909,22 @@ namespace MediaBrowser.Controller.Entities
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var removeChar in ConfigurationManager.Configuration.SortRemoveCharacters)
|
||||
{
|
||||
sortable = sortable.Replace(removeChar, string.Empty, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
foreach (var replaceChar in ConfigurationManager.Configuration.SortReplaceCharacters)
|
||||
{
|
||||
sortable = sortable.Replace(replaceChar, " ", StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
return ModifySortChunks(sortable);
|
||||
}
|
||||
|
||||
internal static string ModifySortChunks(string name)
|
||||
internal static string ModifySortChunks(ReadOnlySpan<char> name)
|
||||
{
|
||||
void AppendChunk(StringBuilder builder, bool isDigitChunk, ReadOnlySpan<char> chunk)
|
||||
static void AppendChunk(StringBuilder builder, bool isDigitChunk, ReadOnlySpan<char> chunk)
|
||||
{
|
||||
if (isDigitChunk && chunk.Length < 10)
|
||||
{
|
||||
@@ -936,7 +934,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
builder.Append(chunk);
|
||||
}
|
||||
|
||||
if (name.Length == 0)
|
||||
if (name.IsEmpty)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
@@ -950,13 +948,13 @@ namespace MediaBrowser.Controller.Entities
|
||||
var isDigit = char.IsDigit(name[i]);
|
||||
if (isDigit != isDigitChunk)
|
||||
{
|
||||
AppendChunk(builder, isDigitChunk, name.AsSpan(chunkStart, i - chunkStart));
|
||||
AppendChunk(builder, isDigitChunk, name.Slice(chunkStart, i - chunkStart));
|
||||
chunkStart = i;
|
||||
isDigitChunk = isDigit;
|
||||
}
|
||||
}
|
||||
|
||||
AppendChunk(builder, isDigitChunk, name.AsSpan(chunkStart));
|
||||
AppendChunk(builder, isDigitChunk, name.Slice(chunkStart));
|
||||
|
||||
// logger.LogDebug("ModifySortChunks Start: {0} End: {1}", name, builder.ToString());
|
||||
return builder.ToString().RemoveDiacritics();
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
#nullable disable
|
||||
|
||||
#pragma warning disable CA1819, CS1591
|
||||
|
||||
namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
public interface IHasShares
|
||||
{
|
||||
Share[] Shares { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Jellyfin.Data.Enums;
|
||||
using MediaBrowser.Model.Entities;
|
||||
|
||||
namespace MediaBrowser.Controller.Entities
|
||||
@@ -17,38 +18,38 @@ namespace MediaBrowser.Controller.Entities
|
||||
// Normalize
|
||||
if (string.Equals(person.Role, PersonType.GuestStar, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
person.Type = PersonType.GuestStar;
|
||||
person.Type = PersonKind.GuestStar;
|
||||
}
|
||||
else if (string.Equals(person.Role, PersonType.Director, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
person.Type = PersonType.Director;
|
||||
person.Type = PersonKind.Director;
|
||||
}
|
||||
else if (string.Equals(person.Role, PersonType.Producer, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
person.Type = PersonType.Producer;
|
||||
person.Type = PersonKind.Producer;
|
||||
}
|
||||
else if (string.Equals(person.Role, PersonType.Writer, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
person.Type = PersonType.Writer;
|
||||
person.Type = PersonKind.Writer;
|
||||
}
|
||||
|
||||
// If the type is GuestStar and there's already an Actor entry, then update it to avoid dupes
|
||||
if (string.Equals(person.Type, PersonType.GuestStar, StringComparison.OrdinalIgnoreCase))
|
||||
if (person.Type == PersonKind.GuestStar)
|
||||
{
|
||||
var existing = people.FirstOrDefault(p => p.Name.Equals(person.Name, StringComparison.OrdinalIgnoreCase) && p.Type.Equals(PersonType.Actor, StringComparison.OrdinalIgnoreCase));
|
||||
var existing = people.FirstOrDefault(p => p.Name.Equals(person.Name, StringComparison.OrdinalIgnoreCase) && p.Type == PersonKind.Actor);
|
||||
|
||||
if (existing is not null)
|
||||
{
|
||||
existing.Type = PersonType.GuestStar;
|
||||
existing.Type = PersonKind.GuestStar;
|
||||
MergeExisting(existing, person);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (string.Equals(person.Type, PersonType.Actor, StringComparison.OrdinalIgnoreCase))
|
||||
if (person.Type == PersonKind.Actor)
|
||||
{
|
||||
// If the actor already exists without a role and we have one, fill it in
|
||||
var existing = people.FirstOrDefault(p => p.Name.Equals(person.Name, StringComparison.OrdinalIgnoreCase) && (p.Type.Equals(PersonType.Actor, StringComparison.OrdinalIgnoreCase) || p.Type.Equals(PersonType.GuestStar, StringComparison.OrdinalIgnoreCase)));
|
||||
var existing = people.FirstOrDefault(p => p.Name.Equals(person.Name, StringComparison.OrdinalIgnoreCase) && (p.Type == PersonKind.Actor || p.Type == PersonKind.GuestStar));
|
||||
if (existing is null)
|
||||
{
|
||||
// Wasn't there - add it
|
||||
@@ -68,8 +69,8 @@ namespace MediaBrowser.Controller.Entities
|
||||
else
|
||||
{
|
||||
var existing = people.FirstOrDefault(p =>
|
||||
string.Equals(p.Name, person.Name, StringComparison.OrdinalIgnoreCase) &&
|
||||
string.Equals(p.Type, person.Type, StringComparison.OrdinalIgnoreCase));
|
||||
string.Equals(p.Name, person.Name, StringComparison.OrdinalIgnoreCase)
|
||||
&& p.Type == person.Type);
|
||||
|
||||
// Check for dupes based on the combination of Name and Type
|
||||
if (existing is null)
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Jellyfin.Data.Enums;
|
||||
using MediaBrowser.Model.Entities;
|
||||
|
||||
namespace MediaBrowser.Controller.Entities
|
||||
@@ -36,7 +37,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
/// Gets or sets the type.
|
||||
/// </summary>
|
||||
/// <value>The type.</value>
|
||||
public string Type { get; set; }
|
||||
public PersonKind Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the ascending sort order.
|
||||
@@ -57,10 +58,6 @@ namespace MediaBrowser.Controller.Entities
|
||||
return Name;
|
||||
}
|
||||
|
||||
public bool IsType(string type)
|
||||
{
|
||||
return string.Equals(Type, type, StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(Role, type, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
public bool IsType(PersonKind type) => Type == type || string.Equals(type.ToString(), Role, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
#nullable disable
|
||||
|
||||
#pragma warning disable CS1591
|
||||
|
||||
namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
public class Share
|
||||
{
|
||||
public string UserId { get; set; }
|
||||
|
||||
public bool CanEdit { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -197,10 +197,8 @@ namespace MediaBrowser.Controller.LiveTv
|
||||
{
|
||||
return 2.0 / 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 16.0 / 9;
|
||||
}
|
||||
|
||||
return 16.0 / 9;
|
||||
}
|
||||
|
||||
public override string GetClientTypeName()
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
using System;
|
||||
|
||||
namespace MediaBrowser.Controller.Lyrics;
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -89,6 +89,16 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
{ "truehd", 6 },
|
||||
};
|
||||
|
||||
public static readonly string[] LosslessAudioCodecs = new string[]
|
||||
{
|
||||
"alac",
|
||||
"ape",
|
||||
"flac",
|
||||
"mlp",
|
||||
"truehd",
|
||||
"wavpack"
|
||||
};
|
||||
|
||||
public EncodingHelper(
|
||||
IApplicationPaths appPaths,
|
||||
IMediaEncoder mediaEncoder,
|
||||
@@ -128,14 +138,10 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
|
||||
if (!string.IsNullOrEmpty(hwType)
|
||||
&& encodingOptions.EnableHardwareEncoding
|
||||
&& codecMap.ContainsKey(hwType))
|
||||
&& codecMap.TryGetValue(hwType, out var preferredEncoder)
|
||||
&& _mediaEncoder.SupportsEncoder(preferredEncoder))
|
||||
{
|
||||
var preferredEncoder = codecMap[hwType];
|
||||
|
||||
if (_mediaEncoder.SupportsEncoder(preferredEncoder))
|
||||
{
|
||||
return preferredEncoder;
|
||||
}
|
||||
return preferredEncoder;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -551,7 +557,8 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
{
|
||||
return Array.FindIndex(_videoProfilesH264, x => string.Equals(x, profile, StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
else if (string.Equals("hevc", videoCodec, StringComparison.OrdinalIgnoreCase))
|
||||
|
||||
if (string.Equals("hevc", videoCodec, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return Array.FindIndex(_videoProfilesH265, x => string.Equals(x, profile, StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
@@ -620,6 +627,11 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
return "flac";
|
||||
}
|
||||
|
||||
if (string.Equals(codec, "dts", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return "dca";
|
||||
}
|
||||
|
||||
return codec.ToLowerInvariant();
|
||||
}
|
||||
|
||||
@@ -827,39 +839,38 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
}
|
||||
|
||||
var filterDevArgs = GetFilterHwDeviceArgs(VaapiAlias);
|
||||
var doOclTonemap = isHwTonemapAvailable && IsOpenclFullSupported();
|
||||
|
||||
if (isHwTonemapAvailable && IsOpenclFullSupported())
|
||||
if (_mediaEncoder.IsVaapiDeviceInteliHD || _mediaEncoder.IsVaapiDeviceInteli965)
|
||||
{
|
||||
if (_mediaEncoder.IsVaapiDeviceInteliHD || _mediaEncoder.IsVaapiDeviceInteli965)
|
||||
if (doOclTonemap && !isVaapiDecoder)
|
||||
{
|
||||
if (!isVaapiDecoder)
|
||||
{
|
||||
args.Append(GetOpenclDeviceArgs(0, null, VaapiAlias, OpenclAlias));
|
||||
filterDevArgs = GetFilterHwDeviceArgs(OpenclAlias);
|
||||
}
|
||||
}
|
||||
else if (_mediaEncoder.IsVaapiDeviceAmd)
|
||||
{
|
||||
if (!IsVulkanFullSupported()
|
||||
|| !_mediaEncoder.IsVaapiDeviceSupportVulkanFmtModifier
|
||||
|| Environment.OSVersion.Version < _minKernelVersionAmdVkFmtModifier)
|
||||
{
|
||||
args.Append(GetOpenclDeviceArgs(0, "Advanced Micro Devices", null, OpenclAlias));
|
||||
filterDevArgs = GetFilterHwDeviceArgs(OpenclAlias);
|
||||
}
|
||||
else
|
||||
{
|
||||
// libplacebo wants an explicitly set vulkan filter device.
|
||||
args.Append(GetVulkanDeviceArgs(0, null, VaapiAlias, VulkanAlias));
|
||||
filterDevArgs = GetFilterHwDeviceArgs(VulkanAlias);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
args.Append(GetOpenclDeviceArgs(0, null, null, OpenclAlias));
|
||||
args.Append(GetOpenclDeviceArgs(0, null, VaapiAlias, OpenclAlias));
|
||||
filterDevArgs = GetFilterHwDeviceArgs(OpenclAlias);
|
||||
}
|
||||
}
|
||||
else if (_mediaEncoder.IsVaapiDeviceAmd)
|
||||
{
|
||||
if (IsVulkanFullSupported()
|
||||
&& _mediaEncoder.IsVaapiDeviceSupportVulkanFmtModifier
|
||||
&& Environment.OSVersion.Version >= _minKernelVersionAmdVkFmtModifier)
|
||||
{
|
||||
// libplacebo wants an explicitly set vulkan filter device.
|
||||
args.Append(GetVulkanDeviceArgs(0, null, VaapiAlias, VulkanAlias));
|
||||
filterDevArgs = GetFilterHwDeviceArgs(VulkanAlias);
|
||||
}
|
||||
else if (doOclTonemap)
|
||||
{
|
||||
// ROCm/ROCr OpenCL runtime
|
||||
args.Append(GetOpenclDeviceArgs(0, "Advanced Micro Devices", null, OpenclAlias));
|
||||
filterDevArgs = GetFilterHwDeviceArgs(OpenclAlias);
|
||||
}
|
||||
}
|
||||
else if (doOclTonemap)
|
||||
{
|
||||
args.Append(GetOpenclDeviceArgs(0, null, null, OpenclAlias));
|
||||
filterDevArgs = GetFilterHwDeviceArgs(OpenclAlias);
|
||||
}
|
||||
|
||||
args.Append(filterDevArgs);
|
||||
}
|
||||
@@ -1099,19 +1110,19 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
{
|
||||
return "-bsf:v h264_mp4toannexb";
|
||||
}
|
||||
else if (IsH265(stream))
|
||||
|
||||
if (IsH265(stream))
|
||||
{
|
||||
return "-bsf:v hevc_mp4toannexb";
|
||||
}
|
||||
else if (IsAAC(stream))
|
||||
|
||||
if (IsAAC(stream))
|
||||
{
|
||||
// Convert adts header(mpegts) to asc header(mp4).
|
||||
return "-bsf:a aac_adtstoasc";
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static string GetAudioBitStreamArguments(EncodingJobInfo state, string segmentContainer, string mediaSourceContainer)
|
||||
@@ -1189,10 +1200,8 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
{
|
||||
return FormattableString.Invariant($" -rc_mode CBR -b:v {bitrate} -maxrate {bitrate} -bufsize {bufsize}");
|
||||
}
|
||||
else
|
||||
{
|
||||
return FormattableString.Invariant($" -rc_mode VBR -b:v {bitrate} -maxrate {bitrate} -bufsize {bufsize}");
|
||||
}
|
||||
|
||||
return FormattableString.Invariant($" -rc_mode VBR -b:v {bitrate} -maxrate {bitrate} -bufsize {bufsize}");
|
||||
}
|
||||
|
||||
return FormattableString.Invariant($" -b:v {bitrate} -maxrate {bitrate} -bufsize {bufsize}");
|
||||
@@ -1406,7 +1415,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
var param = string.Empty;
|
||||
|
||||
// Tutorials: Enable Intel GuC / HuC firmware loading for Low Power Encoding.
|
||||
// https://01.org/linuxgraphics/downloads/firmware
|
||||
// https://01.org/group/43/downloads/firmware
|
||||
// https://wiki.archlinux.org/title/intel_graphics#Enable_GuC_/_HuC_firmware_loading
|
||||
// Intel Low Power Encoding can save unnecessary CPU-GPU synchronization,
|
||||
// which will reduce overhead in performance intensive tasks such as 4k transcoding and tonemapping.
|
||||
@@ -2050,9 +2059,9 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
}
|
||||
}
|
||||
|
||||
// Video bitrate must fall within requested value
|
||||
// Audio bitrate must fall within requested value
|
||||
if (request.AudioBitRate.HasValue
|
||||
&& audioStream.BitDepth.HasValue
|
||||
&& audioStream.BitRate.HasValue
|
||||
&& audioStream.BitRate.Value > request.AudioBitRate.Value)
|
||||
{
|
||||
return false;
|
||||
@@ -2139,7 +2148,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
var outputScaleFactor = GetVideoBitrateScaleFactor(outputVideoCodec);
|
||||
|
||||
// Don't scale the real bitrate lower than the requested bitrate
|
||||
var scaleFactor = Math.Min(outputScaleFactor / inputScaleFactor, 1);
|
||||
var scaleFactor = Math.Max(outputScaleFactor / inputScaleFactor, 1);
|
||||
|
||||
if (bitrate <= 500000)
|
||||
{
|
||||
@@ -2161,56 +2170,96 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
return Convert.ToInt32(scaleFactor * bitrate);
|
||||
}
|
||||
|
||||
public int? GetAudioBitrateParam(BaseEncodingJobOptions request, MediaStream audioStream)
|
||||
public int? GetAudioBitrateParam(BaseEncodingJobOptions request, MediaStream audioStream, int? outputAudioChannels)
|
||||
{
|
||||
return GetAudioBitrateParam(request.AudioBitRate, request.AudioCodec, audioStream);
|
||||
return GetAudioBitrateParam(request.AudioBitRate, request.AudioCodec, audioStream, outputAudioChannels);
|
||||
}
|
||||
|
||||
public int? GetAudioBitrateParam(int? audioBitRate, string audioCodec, MediaStream audioStream)
|
||||
public int? GetAudioBitrateParam(int? audioBitRate, string audioCodec, MediaStream audioStream, int? outputAudioChannels)
|
||||
{
|
||||
if (audioStream is null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (audioBitRate.HasValue && string.IsNullOrEmpty(audioCodec))
|
||||
var inputChannels = audioStream.Channels ?? 0;
|
||||
var outputChannels = outputAudioChannels ?? 0;
|
||||
var bitrate = audioBitRate ?? int.MaxValue;
|
||||
|
||||
if (string.IsNullOrEmpty(audioCodec)
|
||||
|| string.Equals(audioCodec, "aac", StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(audioCodec, "mp3", StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(audioCodec, "opus", StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(audioCodec, "vorbis", StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(audioCodec, "ac3", StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(audioCodec, "eac3", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return Math.Min(384000, audioBitRate.Value);
|
||||
return (inputChannels, outputChannels) switch
|
||||
{
|
||||
(>= 6, >= 6 or 0) => Math.Min(640000, bitrate),
|
||||
(> 0, > 0) => Math.Min(outputChannels * 128000, bitrate),
|
||||
(> 0, _) => Math.Min(inputChannels * 128000, bitrate),
|
||||
(_, _) => Math.Min(384000, bitrate)
|
||||
};
|
||||
}
|
||||
|
||||
if (audioBitRate.HasValue && !string.IsNullOrEmpty(audioCodec))
|
||||
if (string.Equals(audioCodec, "dts", StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(audioCodec, "dca", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (string.Equals(audioCodec, "aac", StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(audioCodec, "mp3", StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(audioCodec, "opus", StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(audioCodec, "vorbis", StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(audioCodec, "ac3", StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(audioCodec, "eac3", StringComparison.OrdinalIgnoreCase))
|
||||
return (inputChannels, outputChannels) switch
|
||||
{
|
||||
if ((audioStream.Channels ?? 0) >= 6)
|
||||
{
|
||||
return Math.Min(640000, audioBitRate.Value);
|
||||
}
|
||||
|
||||
return Math.Min(384000, audioBitRate.Value);
|
||||
}
|
||||
|
||||
if (string.Equals(audioCodec, "flac", StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(audioCodec, "alac", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if ((audioStream.Channels ?? 0) >= 6)
|
||||
{
|
||||
return Math.Min(3584000, audioBitRate.Value);
|
||||
}
|
||||
|
||||
return Math.Min(1536000, audioBitRate.Value);
|
||||
}
|
||||
(>= 6, >= 6 or 0) => Math.Min(768000, bitrate),
|
||||
(> 0, > 0) => Math.Min(outputChannels * 136000, bitrate),
|
||||
(> 0, _) => Math.Min(inputChannels * 136000, bitrate),
|
||||
(_, _) => Math.Min(672000, bitrate)
|
||||
};
|
||||
}
|
||||
|
||||
// Empty bitrate area is not allow on iOS
|
||||
// Default audio bitrate to 128K if it is not being requested
|
||||
// Default audio bitrate to 128K per channel if we don't have codec specific defaults
|
||||
// https://ffmpeg.org/ffmpeg-codecs.html#toc-Codec-Options
|
||||
return 128000;
|
||||
return 128000 * (outputAudioChannels ?? audioStream.Channels ?? 2);
|
||||
}
|
||||
|
||||
public string GetAudioVbrModeParam(string encoder, int bitratePerChannel)
|
||||
{
|
||||
if (string.Equals(encoder, "libfdk_aac", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return " -vbr:a " + bitratePerChannel switch
|
||||
{
|
||||
< 32000 => "1",
|
||||
< 48000 => "2",
|
||||
< 64000 => "3",
|
||||
< 96000 => "4",
|
||||
_ => "5"
|
||||
};
|
||||
}
|
||||
|
||||
if (string.Equals(encoder, "libmp3lame", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return " -qscale:a " + bitratePerChannel switch
|
||||
{
|
||||
< 48000 => "8",
|
||||
< 64000 => "6",
|
||||
< 88000 => "4",
|
||||
< 112000 => "2",
|
||||
_ => "0"
|
||||
};
|
||||
}
|
||||
|
||||
if (string.Equals(encoder, "libvorbis", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return " -qscale:a " + bitratePerChannel switch
|
||||
{
|
||||
< 40000 => "0",
|
||||
< 56000 => "2",
|
||||
< 80000 => "4",
|
||||
< 112000 => "6",
|
||||
_ => "8"
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public string GetAudioFilterParam(EncodingJobInfo state, EncodingOptions encodingOptions)
|
||||
@@ -2564,8 +2613,8 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
|
||||
if (outputWidth > maximumWidth || outputHeight > maximumHeight)
|
||||
{
|
||||
var scaleW = (double)maximumWidth / (double)outputWidth;
|
||||
var scaleH = (double)maximumHeight / (double)outputHeight;
|
||||
var scaleW = (double)maximumWidth / outputWidth;
|
||||
var scaleH = (double)maximumHeight / outputHeight;
|
||||
var scale = Math.Min(scaleW, scaleH);
|
||||
outputWidth = Math.Min(maximumWidth, (int)(outputWidth * scale));
|
||||
outputHeight = Math.Min(maximumHeight, (int)(outputHeight * scale));
|
||||
@@ -2712,79 +2761,76 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
widthParam,
|
||||
heightParam);
|
||||
}
|
||||
else
|
||||
{
|
||||
return GetFixedSwScaleFilter(threedFormat, requestedWidth.Value, requestedHeight.Value);
|
||||
}
|
||||
|
||||
return GetFixedSwScaleFilter(threedFormat, requestedWidth.Value, requestedHeight.Value);
|
||||
}
|
||||
|
||||
// If Max dimensions were supplied, for width selects lowest even number between input width and width req size and selects lowest even number from in width*display aspect and requested size
|
||||
else if (requestedMaxWidth.HasValue && requestedMaxHeight.HasValue)
|
||||
|
||||
if (requestedMaxWidth.HasValue && requestedMaxHeight.HasValue)
|
||||
{
|
||||
var maxWidthParam = requestedMaxWidth.Value.ToString(CultureInfo.InvariantCulture);
|
||||
var maxHeightParam = requestedMaxHeight.Value.ToString(CultureInfo.InvariantCulture);
|
||||
|
||||
return string.Format(
|
||||
CultureInfo.InvariantCulture,
|
||||
"scale=trunc(min(max(iw\\,ih*a)\\,min({0}\\,{1}*a))/{2})*{2}:trunc(min(max(iw/a\\,ih)\\,min({0}/a\\,{1}))/2)*2",
|
||||
maxWidthParam,
|
||||
maxHeightParam,
|
||||
scaleVal);
|
||||
CultureInfo.InvariantCulture,
|
||||
"scale=trunc(min(max(iw\\,ih*a)\\,min({0}\\,{1}*a))/{2})*{2}:trunc(min(max(iw/a\\,ih)\\,min({0}/a\\,{1}))/2)*2",
|
||||
maxWidthParam,
|
||||
maxHeightParam,
|
||||
scaleVal);
|
||||
}
|
||||
|
||||
// If a fixed width was requested
|
||||
else if (requestedWidth.HasValue)
|
||||
if (requestedWidth.HasValue)
|
||||
{
|
||||
if (threedFormat.HasValue)
|
||||
{
|
||||
// This method can handle 0 being passed in for the requested height
|
||||
return GetFixedSwScaleFilter(threedFormat, requestedWidth.Value, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
var widthParam = requestedWidth.Value.ToString(CultureInfo.InvariantCulture);
|
||||
|
||||
return string.Format(
|
||||
CultureInfo.InvariantCulture,
|
||||
"scale={0}:trunc(ow/a/2)*2",
|
||||
widthParam);
|
||||
}
|
||||
var widthParam = requestedWidth.Value.ToString(CultureInfo.InvariantCulture);
|
||||
|
||||
return string.Format(
|
||||
CultureInfo.InvariantCulture,
|
||||
"scale={0}:trunc(ow/a/2)*2",
|
||||
widthParam);
|
||||
}
|
||||
|
||||
// If a fixed height was requested
|
||||
else if (requestedHeight.HasValue)
|
||||
if (requestedHeight.HasValue)
|
||||
{
|
||||
var heightParam = requestedHeight.Value.ToString(CultureInfo.InvariantCulture);
|
||||
|
||||
return string.Format(
|
||||
CultureInfo.InvariantCulture,
|
||||
"scale=trunc(oh*a/{1})*{1}:{0}",
|
||||
heightParam,
|
||||
scaleVal);
|
||||
CultureInfo.InvariantCulture,
|
||||
"scale=trunc(oh*a/{1})*{1}:{0}",
|
||||
heightParam,
|
||||
scaleVal);
|
||||
}
|
||||
|
||||
// If a max width was requested
|
||||
else if (requestedMaxWidth.HasValue)
|
||||
if (requestedMaxWidth.HasValue)
|
||||
{
|
||||
var maxWidthParam = requestedMaxWidth.Value.ToString(CultureInfo.InvariantCulture);
|
||||
|
||||
return string.Format(
|
||||
CultureInfo.InvariantCulture,
|
||||
"scale=trunc(min(max(iw\\,ih*a)\\,{0})/{1})*{1}:trunc(ow/a/2)*2",
|
||||
maxWidthParam,
|
||||
scaleVal);
|
||||
CultureInfo.InvariantCulture,
|
||||
"scale=trunc(min(max(iw\\,ih*a)\\,{0})/{1})*{1}:trunc(ow/a/2)*2",
|
||||
maxWidthParam,
|
||||
scaleVal);
|
||||
}
|
||||
|
||||
// If a max height was requested
|
||||
else if (requestedMaxHeight.HasValue)
|
||||
if (requestedMaxHeight.HasValue)
|
||||
{
|
||||
var maxHeightParam = requestedMaxHeight.Value.ToString(CultureInfo.InvariantCulture);
|
||||
|
||||
return string.Format(
|
||||
CultureInfo.InvariantCulture,
|
||||
"scale=trunc(oh*a/{1})*{1}:min(max(iw/a\\,ih)\\,{0})",
|
||||
maxHeightParam,
|
||||
scaleVal);
|
||||
CultureInfo.InvariantCulture,
|
||||
"scale=trunc(oh*a/{1})*{1}:min(max(iw/a\\,ih)\\,{0})",
|
||||
maxHeightParam,
|
||||
scaleVal);
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
@@ -2858,18 +2904,21 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
"yadif_cuda={0}:-1:0",
|
||||
doubleRateDeint ? "1" : "0");
|
||||
}
|
||||
else if (hwDeintSuffix.Contains("vaapi", StringComparison.OrdinalIgnoreCase))
|
||||
|
||||
if (hwDeintSuffix.Contains("vaapi", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return string.Format(
|
||||
CultureInfo.InvariantCulture,
|
||||
"deinterlace_vaapi=rate={0}",
|
||||
doubleRateDeint ? "field" : "frame");
|
||||
}
|
||||
else if (hwDeintSuffix.Contains("qsv", StringComparison.OrdinalIgnoreCase))
|
||||
|
||||
if (hwDeintSuffix.Contains("qsv", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return "deinterlace_qsv=mode=2";
|
||||
}
|
||||
else if (hwDeintSuffix.Contains("videotoolbox", StringComparison.OrdinalIgnoreCase))
|
||||
|
||||
if (hwDeintSuffix.Contains("videotoolbox", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return string.Format(
|
||||
CultureInfo.InvariantCulture,
|
||||
@@ -2900,7 +2949,8 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
options.VppTonemappingBrightness,
|
||||
options.VppTonemappingContrast);
|
||||
}
|
||||
else if (string.Equals(hwTonemapSuffix, "vulkan", StringComparison.OrdinalIgnoreCase))
|
||||
|
||||
if (string.Equals(hwTonemapSuffix, "vulkan", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
args = "libplacebo=format={1}:tonemapping={2}:color_primaries=bt709:color_trc=bt709:colorspace=bt709:peak_detect=0:upscaler=none:downscaler=none";
|
||||
|
||||
@@ -4214,7 +4264,8 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
// sw => hw
|
||||
if (doVkTonemap)
|
||||
{
|
||||
mainFilters.Add("hwupload_vaapi");
|
||||
mainFilters.Add("hwupload=derive_device=vaapi");
|
||||
mainFilters.Add("format=vaapi");
|
||||
mainFilters.Add("hwmap=derive_device=vulkan");
|
||||
mainFilters.Add("format=vulkan");
|
||||
}
|
||||
@@ -4325,12 +4376,15 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
|
||||
// prefer vaapi hwupload to vulkan hwupload,
|
||||
// Mesa RADV does not support a dedicated transfer queue.
|
||||
subFilters.Add("hwupload_vaapi");
|
||||
subFilters.Add("hwupload=derive_device=vaapi");
|
||||
subFilters.Add("format=vaapi");
|
||||
subFilters.Add("hwmap=derive_device=vulkan");
|
||||
subFilters.Add("format=vulkan");
|
||||
|
||||
overlayFilters.Add("overlay_vulkan=eof_action=endall:shortest=1:repeatlast=0");
|
||||
overlayFilters.Add("scale_vulkan=format=nv12");
|
||||
|
||||
// TODO: figure out why libplacebo can sync without vaSyncSurface VPP support in radeonsi.
|
||||
overlayFilters.Add("libplacebo=format=nv12:apply_filmgrain=0:apply_dolbyvision=0:upscaler=none:downscaler=none:dithering=none");
|
||||
|
||||
// OUTPUT vaapi(nv12/bgra) surface(vram)
|
||||
// reverse-mapping via vaapi-vulkan interop.
|
||||
@@ -4772,26 +4826,27 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
{
|
||||
return videoStream.BitDepth.Value;
|
||||
}
|
||||
else if (string.Equals(videoStream.PixelFormat, "yuv420p", StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(videoStream.PixelFormat, "yuvj420p", StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(videoStream.PixelFormat, "yuv444p", StringComparison.OrdinalIgnoreCase))
|
||||
|
||||
if (string.Equals(videoStream.PixelFormat, "yuv420p", StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(videoStream.PixelFormat, "yuvj420p", StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(videoStream.PixelFormat, "yuv444p", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return 8;
|
||||
}
|
||||
else if (string.Equals(videoStream.PixelFormat, "yuv420p10le", StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(videoStream.PixelFormat, "yuv444p10le", StringComparison.OrdinalIgnoreCase))
|
||||
|
||||
if (string.Equals(videoStream.PixelFormat, "yuv420p10le", StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(videoStream.PixelFormat, "yuv444p10le", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return 10;
|
||||
}
|
||||
else if (string.Equals(videoStream.PixelFormat, "yuv420p12le", StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(videoStream.PixelFormat, "yuv444p12le", StringComparison.OrdinalIgnoreCase))
|
||||
|
||||
if (string.Equals(videoStream.PixelFormat, "yuv420p12le", StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(videoStream.PixelFormat, "yuv444p12le", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return 12;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 8;
|
||||
}
|
||||
|
||||
return 8;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -5023,11 +5078,9 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
return " -hwaccel cuda" + (outputHwSurface ? " -hwaccel_output_format cuda" : string.Empty)
|
||||
+ (nvdecNoInternalCopy ? " -hwaccel_flags +unsafe_output" : string.Empty) + " -threads 1" + (isAv1 ? " -c:v av1" : string.Empty);
|
||||
}
|
||||
else
|
||||
{
|
||||
// cuvid decoder doesn't have threading issue.
|
||||
return " -hwaccel cuda" + (outputHwSurface ? " -hwaccel_output_format cuda" : string.Empty);
|
||||
}
|
||||
|
||||
// cuvid decoder doesn't have threading issue.
|
||||
return " -hwaccel cuda" + (outputHwSurface ? " -hwaccel_output_format cuda" : string.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5385,7 +5438,8 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
// Automatically set thread count
|
||||
return mustSetThreadCount ? Math.Max(Environment.ProcessorCount - 1, 1) : 0;
|
||||
}
|
||||
else if (threads >= Environment.ProcessorCount)
|
||||
|
||||
if (threads >= Environment.ProcessorCount)
|
||||
{
|
||||
return Environment.ProcessorCount;
|
||||
}
|
||||
@@ -5670,14 +5724,22 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
}
|
||||
|
||||
var inputChannels = audioStream is null ? 6 : audioStream.Channels ?? 6;
|
||||
var shiftAudioCodecs = new List<string>();
|
||||
if (inputChannels >= 6)
|
||||
{
|
||||
return;
|
||||
// DTS and TrueHD are not supported by HLS
|
||||
// Keep them in the supported codecs list, but shift them to the end of the list so that if transcoding happens, another codec is used
|
||||
shiftAudioCodecs.Add("dca");
|
||||
shiftAudioCodecs.Add("truehd");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Transcoding to 2ch ac3 or eac3 almost always causes a playback failure
|
||||
// Keep them in the supported codecs list, but shift them to the end of the list so that if transcoding happens, another codec is used
|
||||
shiftAudioCodecs.Add("ac3");
|
||||
shiftAudioCodecs.Add("eac3");
|
||||
}
|
||||
|
||||
// Transcoding to 2ch ac3 almost always causes a playback failure
|
||||
// Keep it in the supported codecs list, but shift it to the end of the list so that if transcoding happens, another codec is used
|
||||
var shiftAudioCodecs = new[] { "ac3", "eac3" };
|
||||
if (audioCodecs.All(i => shiftAudioCodecs.Contains(i, StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
return;
|
||||
@@ -5919,10 +5981,17 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
}
|
||||
|
||||
var bitrate = state.OutputAudioBitrate;
|
||||
|
||||
if (bitrate.HasValue)
|
||||
if (bitrate.HasValue && !LosslessAudioCodecs.Contains(codec, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
args += " -ab " + bitrate.Value.ToString(CultureInfo.InvariantCulture);
|
||||
var vbrParam = GetAudioVbrModeParam(codec, bitrate.Value / (channels ?? 2));
|
||||
if (encodingOptions.EnableAudioVbr && vbrParam is not null)
|
||||
{
|
||||
args += vbrParam;
|
||||
}
|
||||
else
|
||||
{
|
||||
args += " -ab " + bitrate.Value.ToString(CultureInfo.InvariantCulture);
|
||||
}
|
||||
}
|
||||
|
||||
if (state.OutputAudioSampleRate.HasValue)
|
||||
@@ -5940,23 +6009,33 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
var audioTranscodeParams = new List<string>();
|
||||
|
||||
var bitrate = state.OutputAudioBitrate;
|
||||
var channels = state.OutputAudioChannels;
|
||||
var outputCodec = state.OutputAudioCodec;
|
||||
|
||||
if (bitrate.HasValue)
|
||||
if (bitrate.HasValue && !LosslessAudioCodecs.Contains(outputCodec, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
audioTranscodeParams.Add("-ab " + bitrate.Value.ToString(CultureInfo.InvariantCulture));
|
||||
var vbrParam = GetAudioVbrModeParam(GetAudioEncoder(state), bitrate.Value / (channels ?? 2));
|
||||
if (encodingOptions.EnableAudioVbr && vbrParam is not null)
|
||||
{
|
||||
audioTranscodeParams.Add(vbrParam);
|
||||
}
|
||||
else
|
||||
{
|
||||
audioTranscodeParams.Add("-ab " + bitrate.Value.ToString(CultureInfo.InvariantCulture));
|
||||
}
|
||||
}
|
||||
|
||||
if (state.OutputAudioChannels.HasValue)
|
||||
if (channels.HasValue)
|
||||
{
|
||||
audioTranscodeParams.Add("-ac " + state.OutputAudioChannels.Value.ToString(CultureInfo.InvariantCulture));
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(state.OutputAudioCodec))
|
||||
if (!string.IsNullOrEmpty(outputCodec))
|
||||
{
|
||||
audioTranscodeParams.Add("-acodec " + GetAudioEncoder(state));
|
||||
}
|
||||
|
||||
if (!string.Equals(state.OutputAudioCodec, "opus", StringComparison.OrdinalIgnoreCase))
|
||||
if (!string.Equals(outputCodec, "opus", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
// opus only supports specific sampling rates
|
||||
var sampleRate = state.OutputAudioSampleRate;
|
||||
|
||||
@@ -56,5 +56,20 @@ namespace MediaBrowser.Controller.Playlists
|
||||
/// <param name="newIndex">The new index.</param>
|
||||
/// <returns>Task.</returns>
|
||||
Task MoveItemAsync(string playlistId, string entryId, int newIndex);
|
||||
|
||||
/// <summary>
|
||||
/// Removed all playlists of a user.
|
||||
/// If the playlist is shared, ownership is transferred.
|
||||
/// </summary>
|
||||
/// <param name="userId">The user id.</param>
|
||||
/// <returns>Task.</returns>
|
||||
Task RemovePlaylistsAsync(Guid userId);
|
||||
|
||||
/// <summary>
|
||||
/// Updates a playlist.
|
||||
/// </summary>
|
||||
/// <param name="playlist">The updated playlist.</param>
|
||||
/// <returns>Task.</returns>
|
||||
Task UpdatePlaylistAsync(Playlist playlist);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ using MediaBrowser.Controller.Dto;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Entities.Audio;
|
||||
using MediaBrowser.Controller.Providers;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.Querying;
|
||||
|
||||
namespace MediaBrowser.Controller.Playlists
|
||||
@@ -232,7 +233,8 @@ namespace MediaBrowser.Controller.Playlists
|
||||
return base.IsVisible(user);
|
||||
}
|
||||
|
||||
if (user.Id.Equals(OwnerUserId))
|
||||
var userId = user.Id;
|
||||
if (userId.Equals(OwnerUserId))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -240,10 +242,9 @@ namespace MediaBrowser.Controller.Playlists
|
||||
var shares = Shares;
|
||||
if (shares.Length == 0)
|
||||
{
|
||||
return base.IsVisible(user);
|
||||
return false;
|
||||
}
|
||||
|
||||
var userId = user.Id;
|
||||
return shares.Any(share => Guid.TryParse(share.UserId, out var id) && id.Equals(userId));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma warning disable CA1819, CS1591
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using MediaBrowser.Model.Entities;
|
||||
|
||||
@@ -23,7 +24,7 @@ namespace MediaBrowser.Controller.Providers
|
||||
|
||||
public bool ReplaceAllImages { get; set; }
|
||||
|
||||
public ImageType[] ReplaceImages { get; set; }
|
||||
public IReadOnlyList<ImageType> ReplaceImages { get; set; }
|
||||
|
||||
public bool IsAutomated { get; set; }
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@ using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Jellyfin.Data.Entities.Security;
|
||||
using Jellyfin.Data.Events;
|
||||
using MediaBrowser.Controller.Authentication;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Model.Session;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
|
||||
@@ -533,11 +533,9 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates
|
||||
_logger.LogWarning("Session {SessionId} is seeking to wrong position, correcting.", session.Id);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Session is ready.
|
||||
context.SetBuffering(session, false);
|
||||
}
|
||||
|
||||
// Session is ready.
|
||||
context.SetBuffering(session, false);
|
||||
|
||||
if (!context.IsBuffering())
|
||||
{
|
||||
|
||||
@@ -313,17 +313,13 @@ namespace MediaBrowser.Controller.SyncPlay.Queue
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Restoring playing item.
|
||||
SetPlayingItemByPlaylistId(playingItem.PlaylistItemId);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// Restoring playing item.
|
||||
SetPlayingItemByPlaylistId(playingItem.PlaylistItemId);
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -528,10 +524,8 @@ namespace MediaBrowser.Controller.SyncPlay.Queue
|
||||
{
|
||||
return _shuffledPlaylist;
|
||||
}
|
||||
else
|
||||
{
|
||||
return _sortedPlaylist;
|
||||
}
|
||||
|
||||
return _sortedPlaylist;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -544,14 +538,13 @@ namespace MediaBrowser.Controller.SyncPlay.Queue
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else if (ShuffleMode.Equals(GroupShuffleMode.Shuffle))
|
||||
|
||||
if (ShuffleMode.Equals(GroupShuffleMode.Shuffle))
|
||||
{
|
||||
return _shuffledPlaylist[PlayingItemIndex];
|
||||
}
|
||||
else
|
||||
{
|
||||
return _sortedPlaylist[PlayingItemIndex];
|
||||
}
|
||||
|
||||
return _sortedPlaylist[PlayingItemIndex];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user