aboutsummaryrefslogtreecommitdiff
path: root/Emby.Server.Implementations/Library/MediaSourceManager.cs
diff options
context:
space:
mode:
authorJoshua M. Boniface <joshua@boniface.me>2021-08-18 02:46:59 -0400
committerGitHub <noreply@github.com>2021-08-18 02:46:59 -0400
commit72d3f7020ad80ce1a53eeae8c5d57abeb22a4679 (patch)
treedd43e663838cdc7d99a4af565523df58ae23c856 /Emby.Server.Implementations/Library/MediaSourceManager.cs
parent7aef0fce444e6d8e06386553ec7ea1401a01bbb1 (diff)
parente5cbafdb6b47377052e0d638908ef96e30a997d6 (diff)
Merge branch 'master' into patch-2
Diffstat (limited to 'Emby.Server.Implementations/Library/MediaSourceManager.cs')
-rw-r--r--Emby.Server.Implementations/Library/MediaSourceManager.cs92
1 files changed, 36 insertions, 56 deletions
diff --git a/Emby.Server.Implementations/Library/MediaSourceManager.cs b/Emby.Server.Implementations/Library/MediaSourceManager.cs
index 67cf8bf5b..91c9e61cf 100644
--- a/Emby.Server.Implementations/Library/MediaSourceManager.cs
+++ b/Emby.Server.Implementations/Library/MediaSourceManager.cs
@@ -1,16 +1,21 @@
+#nullable disable
+
#pragma warning disable CS1591
using System;
+using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
+using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Extensions;
+using Jellyfin.Extensions.Json;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.MediaEncoding;
@@ -22,7 +27,6 @@ using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Globalization;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.MediaInfo;
-using MediaBrowser.Model.Serialization;
using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.Library
@@ -35,7 +39,6 @@ namespace Emby.Server.Implementations.Library
private readonly IItemRepository _itemRepo;
private readonly IUserManager _userManager;
private readonly ILibraryManager _libraryManager;
- private readonly IJsonSerializer _jsonSerializer;
private readonly IFileSystem _fileSystem;
private readonly ILogger<MediaSourceManager> _logger;
private readonly IUserDataManager _userDataManager;
@@ -43,8 +46,9 @@ namespace Emby.Server.Implementations.Library
private readonly ILocalizationManager _localizationManager;
private readonly IApplicationPaths _appPaths;
- private readonly Dictionary<string, ILiveStream> _openStreams = new Dictionary<string, ILiveStream>(StringComparer.OrdinalIgnoreCase);
+ private readonly ConcurrentDictionary<string, ILiveStream> _openStreams = new ConcurrentDictionary<string, ILiveStream>(StringComparer.OrdinalIgnoreCase);
private readonly SemaphoreSlim _liveStreamSemaphore = new SemaphoreSlim(1, 1);
+ private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options;
private IMediaSourceProvider[] _providers;
@@ -55,7 +59,6 @@ namespace Emby.Server.Implementations.Library
IUserManager userManager,
ILibraryManager libraryManager,
ILogger<MediaSourceManager> logger,
- IJsonSerializer jsonSerializer,
IFileSystem fileSystem,
IUserDataManager userDataManager,
IMediaEncoder mediaEncoder)
@@ -64,7 +67,6 @@ namespace Emby.Server.Implementations.Library
_userManager = userManager;
_libraryManager = libraryManager;
_logger = logger;
- _jsonSerializer = jsonSerializer;
_fileSystem = fileSystem;
_userDataManager = userDataManager;
_mediaEncoder = mediaEncoder;
@@ -199,10 +201,15 @@ namespace Emby.Server.Implementations.Library
{
source.SupportsTranscoding = user.HasPermission(PermissionKind.EnableAudioPlaybackTranscoding);
}
+ else if (string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase))
+ {
+ source.SupportsTranscoding = user.HasPermission(PermissionKind.EnableVideoPlaybackTranscoding);
+ source.SupportsDirectStream = user.HasPermission(PermissionKind.EnablePlaybackRemuxing);
+ }
}
}
- return SortMediaSources(list).Where(i => i.Type != MediaSourceType.Placeholder).ToList();
+ return SortMediaSources(list);
}
public MediaProtocol GetPathProtocol(string path)
@@ -345,7 +352,7 @@ namespace Emby.Server.Implementations.Library
private string[] NormalizeLanguage(string language)
{
- if (language == null)
+ if (string.IsNullOrEmpty(language))
{
return Array.Empty<string>();
}
@@ -374,8 +381,7 @@ namespace Emby.Server.Implementations.Library
}
}
- var preferredSubs = string.IsNullOrEmpty(user.SubtitleLanguagePreference)
- ? Array.Empty<string>() : NormalizeLanguage(user.SubtitleLanguagePreference);
+ var preferredSubs = NormalizeLanguage(user.SubtitleLanguagePreference);
var defaultAudioIndex = source.DefaultAudioStreamIndex;
var audioLangage = defaultAudioIndex == null
@@ -404,9 +410,7 @@ namespace Emby.Server.Implementations.Library
}
}
- var preferredAudio = string.IsNullOrEmpty(user.AudioLanguagePreference)
- ? Array.Empty<string>()
- : NormalizeLanguage(user.AudioLanguagePreference);
+ var preferredAudio = NormalizeLanguage(user.AudioLanguagePreference);
source.DefaultAudioStreamIndex = MediaStreamSelector.GetDefaultAudioStreamIndex(source.MediaStreams, preferredAudio, user.PlayDefaultAudioTrack);
}
@@ -436,7 +440,7 @@ namespace Emby.Server.Implementations.Library
}
}
- private static IEnumerable<MediaSourceInfo> SortMediaSources(IEnumerable<MediaSourceInfo> sources)
+ private static List<MediaSourceInfo> SortMediaSources(IEnumerable<MediaSourceInfo> sources)
{
return sources.OrderBy(i =>
{
@@ -451,8 +455,9 @@ namespace Emby.Server.Implementations.Library
{
var stream = i.VideoStream;
- return stream == null || stream.Width == null ? 0 : stream.Width.Value;
+ return stream?.Width ?? 0;
})
+ .Where(i => i.Type != MediaSourceType.Placeholder)
.ToList();
}
@@ -503,7 +508,7 @@ namespace Emby.Server.Implementations.Library
// hack - these two values were taken from LiveTVMediaSourceProvider
string cacheKey = request.OpenToken;
- await new LiveStreamHelper(_mediaEncoder, _logger, _jsonSerializer, _appPaths)
+ await new LiveStreamHelper(_mediaEncoder, _logger, _appPaths)
.AddMediaInfoWithProbe(mediaSource, isAudio, cacheKey, true, cancellationToken)
.ConfigureAwait(false);
}
@@ -515,9 +520,9 @@ namespace Emby.Server.Implementations.Library
}
// TODO: @bond Fix
- var json = _jsonSerializer.SerializeToString(mediaSource);
+ var json = JsonSerializer.SerializeToUtf8Bytes(mediaSource, _jsonOptions);
_logger.LogInformation("Live stream opened: " + json);
- var clone = _jsonSerializer.DeserializeFromString<MediaSourceInfo>(json);
+ var clone = JsonSerializer.Deserialize<MediaSourceInfo>(json, _jsonOptions);
if (!request.UserId.Equals(Guid.Empty))
{
@@ -582,29 +587,11 @@ namespace Emby.Server.Implementations.Library
mediaSource.InferTotalBitrate();
}
- public async Task<IDirectStreamProvider> GetDirectStreamProviderByUniqueId(string uniqueId, CancellationToken cancellationToken)
+ public Task<IDirectStreamProvider> GetDirectStreamProviderByUniqueId(string uniqueId, CancellationToken cancellationToken)
{
- await _liveStreamSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
-
- try
- {
- var info = _openStreams.Values.FirstOrDefault(i =>
- {
- var liveStream = i as ILiveStream;
- if (liveStream != null)
- {
- return string.Equals(liveStream.UniqueId, uniqueId, StringComparison.OrdinalIgnoreCase);
- }
-
- return false;
- });
+ var info = _openStreams.FirstOrDefault(i => i.Value != null && string.Equals(i.Value.UniqueId, uniqueId, StringComparison.OrdinalIgnoreCase));
- return info as IDirectStreamProvider;
- }
- finally
- {
- _liveStreamSemaphore.Release();
- }
+ return Task.FromResult(info.Value as IDirectStreamProvider);
}
public async Task<LiveStreamResponse> OpenLiveStream(LiveStreamRequest request, CancellationToken cancellationToken)
@@ -651,7 +638,8 @@ namespace Emby.Server.Implementations.Library
{
try
{
- mediaInfo = _jsonSerializer.DeserializeFromFile<MediaInfo>(cacheFilePath);
+ await using FileStream jsonStream = File.OpenRead(cacheFilePath);
+ mediaInfo = await JsonSerializer.DeserializeAsync<MediaInfo>(jsonStream, _jsonOptions, cancellationToken).ConfigureAwait(false);
// _logger.LogDebug("Found cached media info");
}
@@ -687,7 +675,8 @@ namespace Emby.Server.Implementations.Library
if (cacheFilePath != null)
{
Directory.CreateDirectory(Path.GetDirectoryName(cacheFilePath));
- _jsonSerializer.SerializeToFile(mediaInfo, cacheFilePath);
+ await using FileStream createStream = File.Create(cacheFilePath);
+ await JsonSerializer.SerializeAsync(createStream, mediaInfo, _jsonOptions, cancellationToken).ConfigureAwait(false);
// _logger.LogDebug("Saved media info to {0}", cacheFilePath);
}
@@ -793,29 +782,20 @@ namespace Emby.Server.Implementations.Library
return new Tuple<MediaSourceInfo, IDirectStreamProvider>(info.MediaSource, info as IDirectStreamProvider);
}
- private async Task<ILiveStream> GetLiveStreamInfo(string id, CancellationToken cancellationToken)
+ private Task<ILiveStream> GetLiveStreamInfo(string id, CancellationToken cancellationToken)
{
if (string.IsNullOrEmpty(id))
{
throw new ArgumentNullException(nameof(id));
}
- await _liveStreamSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
-
- try
+ if (_openStreams.TryGetValue(id, out ILiveStream info))
{
- if (_openStreams.TryGetValue(id, out ILiveStream info))
- {
- return info;
- }
- else
- {
- throw new ResourceNotFoundException();
- }
+ return Task.FromResult(info);
}
- finally
+ else
{
- _liveStreamSemaphore.Release();
+ return Task.FromException<ILiveStream>(new ResourceNotFoundException());
}
}
@@ -844,7 +824,7 @@ namespace Emby.Server.Implementations.Library
if (liveStream.ConsumerCount <= 0)
{
- _openStreams.Remove(id);
+ _openStreams.TryRemove(id, out _);
_logger.LogInformation("Closing live stream {0}", id);
@@ -866,7 +846,7 @@ namespace Emby.Server.Implementations.Library
throw new ArgumentException("Key can't be empty.", nameof(key));
}
- var keys = key.Split(new[] { LiveStreamIdDelimeter }, 2);
+ var keys = key.Split(LiveStreamIdDelimeter, 2);
var provider = _providers.FirstOrDefault(i => string.Equals(i.GetType().FullName.GetMD5().ToString("N", CultureInfo.InvariantCulture), keys[0], StringComparison.OrdinalIgnoreCase));