diff options
Diffstat (limited to 'MediaBrowser.Api')
| -rw-r--r-- | MediaBrowser.Api/Attachments/AttachmentService.cs | 63 | ||||
| -rw-r--r-- | MediaBrowser.Api/Library/LibraryService.cs | 5 | ||||
| -rw-r--r-- | MediaBrowser.Api/Playback/BaseStreamingService.cs | 2 | ||||
| -rw-r--r-- | MediaBrowser.Api/Playback/MediaInfoService.cs | 103 | ||||
| -rw-r--r-- | MediaBrowser.Api/Playback/UniversalAudioService.cs | 2 |
5 files changed, 132 insertions, 43 deletions
diff --git a/MediaBrowser.Api/Attachments/AttachmentService.cs b/MediaBrowser.Api/Attachments/AttachmentService.cs new file mode 100644 index 000000000..1632ca1b0 --- /dev/null +++ b/MediaBrowser.Api/Attachments/AttachmentService.cs @@ -0,0 +1,63 @@ +using System; +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.MediaEncoding; +using MediaBrowser.Controller.Net; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Services; +using Microsoft.Extensions.Logging; + +namespace MediaBrowser.Api.Attachments +{ + [Route("/Videos/{Id}/{MediaSourceId}/Attachments/{Index}", "GET", Summary = "Gets specified attachment.")] + public class GetAttachment + { + [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] + public Guid Id { get; set; } + + [ApiMember(Name = "MediaSourceId", Description = "MediaSourceId", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] + public string MediaSourceId { get; set; } + + [ApiMember(Name = "Index", Description = "The attachment stream index", IsRequired = true, DataType = "int", ParameterType = "path", Verb = "GET")] + public int Index { get; set; } + } + + public class AttachmentService : BaseApiService + { + private readonly ILibraryManager _libraryManager; + private readonly IAttachmentExtractor _attachmentExtractor; + + public AttachmentService( + ILogger<AttachmentService> logger, + IServerConfigurationManager serverConfigurationManager, + IHttpResultFactory httpResultFactory, + ILibraryManager libraryManager, + IAttachmentExtractor attachmentExtractor) + : base(logger, serverConfigurationManager, httpResultFactory) + { + _libraryManager = libraryManager; + _attachmentExtractor = attachmentExtractor; + } + + public async Task<object> Get(GetAttachment request) + { + var (attachment, attachmentStream) = await GetAttachment(request).ConfigureAwait(false); + var mime = string.IsNullOrWhiteSpace(attachment.MimeType) ? "application/octet-stream" : attachment.MimeType; + + return ResultFactory.GetResult(Request, attachmentStream, mime); + } + + private Task<(MediaAttachment, Stream)> GetAttachment(GetAttachment request) + { + var item = _libraryManager.GetItemById(request.Id); + + return _attachmentExtractor.GetAttachment(item, + request.MediaSourceId, + request.Index, + CancellationToken.None); + } + } +} diff --git a/MediaBrowser.Api/Library/LibraryService.cs b/MediaBrowser.Api/Library/LibraryService.cs index 0cc5e112f..b1ea3e262 100644 --- a/MediaBrowser.Api/Library/LibraryService.cs +++ b/MediaBrowser.Api/Library/LibraryService.cs @@ -1006,8 +1006,8 @@ namespace MediaBrowser.Api.Library public void Delete(DeleteItems request) { var ids = string.IsNullOrWhiteSpace(request.Ids) - ? Array.Empty<string>() - : request.Ids.Split(','); + ? Array.Empty<string>() + : request.Ids.Split(','); foreach (var i in ids) { @@ -1028,7 +1028,6 @@ namespace MediaBrowser.Api.Library _libraryManager.DeleteItem(item, new DeleteOptions { DeleteFileLocation = true - }, true); } } diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 5881e22a7..1f7dc0d71 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -759,7 +759,7 @@ namespace MediaBrowser.Api.Playback if (mediaSource == null) { - var mediaSources = await MediaSourceManager.GetPlayackMediaSources(LibraryManager.GetItemById(request.Id), null, false, false, cancellationToken).ConfigureAwait(false); + var mediaSources = await MediaSourceManager.GetPlaybackMediaSources(LibraryManager.GetItemById(request.Id), null, false, false, cancellationToken).ConfigureAwait(false); mediaSource = string.IsNullOrEmpty(request.MediaSourceId) ? mediaSources[0] diff --git a/MediaBrowser.Api/Playback/MediaInfoService.cs b/MediaBrowser.Api/Playback/MediaInfoService.cs index c3032416b..4b9bb8010 100644 --- a/MediaBrowser.Api/Playback/MediaInfoService.cs +++ b/MediaBrowser.Api/Playback/MediaInfoService.cs @@ -1,6 +1,13 @@ +#pragma warning disable CS1591 +#pragma warning disable SA1402 +#pragma warning disable SA1600 +#pragma warning disable SA1649 + using System; +using System.Buffers; using System.Collections.Generic; using System.Globalization; +using System.Text.Json; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -54,7 +61,7 @@ namespace MediaBrowser.Api.Playback public class GetBitrateTestBytes { [ApiMember(Name = "Size", Description = "Size", IsRequired = true, DataType = "int", ParameterType = "query", Verb = "GET")] - public long Size { get; set; } + public int Size { get; set; } public GetBitrateTestBytes() { @@ -72,7 +79,6 @@ namespace MediaBrowser.Api.Playback private readonly INetworkManager _networkManager; private readonly IMediaEncoder _mediaEncoder; private readonly IUserManager _userManager; - private readonly IJsonSerializer _json; private readonly IAuthorizationContext _authContext; public MediaInfoService( @@ -85,7 +91,6 @@ namespace MediaBrowser.Api.Playback INetworkManager networkManager, IMediaEncoder mediaEncoder, IUserManager userManager, - IJsonSerializer json, IAuthorizationContext authContext) : base(logger, serverConfigurationManager, httpResultFactory) { @@ -95,20 +100,35 @@ namespace MediaBrowser.Api.Playback _networkManager = networkManager; _mediaEncoder = mediaEncoder; _userManager = userManager; - _json = json; _authContext = authContext; } public object Get(GetBitrateTestBytes request) { - var bytes = new byte[request.Size]; + const int MaxSize = 10_000_000; + + var size = request.Size; + + if (size <= 0) + { + throw new ArgumentException($"The requested size ({size}) is equal to or smaller than 0.", nameof(request)); + } - for (var i = 0; i < bytes.Length; i++) + if (size > MaxSize) { - bytes[i] = 0; + throw new ArgumentException($"The requested size ({size}) is larger than the max allowed value ({MaxSize}).", nameof(request)); } - return ResultFactory.GetResult(null, bytes, "application/octet-stream"); + byte[] buffer = ArrayPool<byte>.Shared.Rent(size); + try + { + new Random().NextBytes(buffer); + return ResultFactory.GetResult(null, buffer, "application/octet-stream"); + } + finally + { + ArrayPool<byte>.Shared.Return(buffer); + } } public async Task<object> Get(GetPlaybackInfo request) @@ -166,8 +186,7 @@ namespace MediaBrowser.Api.Playback public void Post(CloseMediaSource request) { - var task = _mediaSourceManager.CloseLiveStream(request.LiveStreamId); - Task.WaitAll(task); + _mediaSourceManager.CloseLiveStream(request.LiveStreamId).GetAwaiter().GetResult(); } public async Task<PlaybackInfoResponse> GetPlaybackInfo(GetPostedPlaybackInfo request) @@ -176,7 +195,7 @@ namespace MediaBrowser.Api.Playback var profile = request.DeviceProfile; - //Logger.LogInformation("GetPostedPlaybackInfo profile: {profile}", _json.SerializeToString(profile)); + Logger.LogInformation("GetPostedPlaybackInfo profile: {@Profile}", profile); if (profile == null) { @@ -215,9 +234,7 @@ namespace MediaBrowser.Api.Playback StartTimeTicks = request.StartTimeTicks, SubtitleStreamIndex = request.SubtitleStreamIndex, UserId = request.UserId, - OpenToken = mediaSource.OpenToken, - //EnableMediaProbe = request.EnableMediaProbe - + OpenToken = mediaSource.OpenToken }).ConfigureAwait(false); info.MediaSources = new MediaSourceInfo[] { openStreamResult.MediaSource }; @@ -251,9 +268,8 @@ namespace MediaBrowser.Api.Playback { // Since we're going to be setting properties on MediaSourceInfos that come out of _mediaSourceManager, we should clone it // Should we move this directly into MediaSourceManager? - - var json = _json.SerializeToString(obj); - return _json.DeserializeFromString<T>(json); + var json = JsonSerializer.SerializeToUtf8Bytes(obj); + return JsonSerializer.Deserialize<T>(json); } private async Task<PlaybackInfoResponse> GetPlaybackInfo(Guid id, Guid userId, string[] supportedLiveMediaTypes, string mediaSourceId = null, string liveStreamId = null) @@ -268,7 +284,7 @@ namespace MediaBrowser.Api.Playback try { // TODO handle supportedLiveMediaTypes ? - mediaSources = await _mediaSourceManager.GetPlayackMediaSources(item, user, true, false, CancellationToken.None).ConfigureAwait(false); + mediaSources = await _mediaSourceManager.GetPlaybackMediaSources(item, user, true, false, CancellationToken.None).ConfigureAwait(false); } catch (Exception ex) { @@ -294,7 +310,7 @@ namespace MediaBrowser.Api.Playback result.MediaSources = new MediaSourceInfo[] { mediaSource }; } - if (result.MediaSources.Length == 0) + if (result.MediaSources.Count == 0) { if (!result.ErrorCode.HasValue) { @@ -311,7 +327,8 @@ namespace MediaBrowser.Api.Playback return result; } - private void SetDeviceSpecificData(Guid itemId, + private void SetDeviceSpecificData( + Guid itemId, PlaybackInfoResponse result, DeviceProfile profile, AuthorizationInfo auth, @@ -339,7 +356,8 @@ namespace MediaBrowser.Api.Playback SortMediaSources(result, maxBitrate); } - private void SetDeviceSpecificData(BaseItem item, + private void SetDeviceSpecificData( + BaseItem item, MediaSourceInfo mediaSource, DeviceProfile profile, AuthorizationInfo auth, @@ -383,10 +401,12 @@ namespace MediaBrowser.Api.Playback { mediaSource.SupportsDirectPlay = false; } + if (!enableDirectStream) { mediaSource.SupportsDirectStream = false; } + if (!enableTranscoding) { mediaSource.SupportsTranscoding = false; @@ -434,9 +454,9 @@ namespace MediaBrowser.Api.Playback } // The MediaSource supports direct stream, now test to see if the client supports it - var streamInfo = string.Equals(item.MediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase) ? - streamBuilder.BuildAudioItem(options) : - streamBuilder.BuildVideoItem(options); + var streamInfo = string.Equals(item.MediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase) + ? streamBuilder.BuildAudioItem(options) + : streamBuilder.BuildVideoItem(options); if (streamInfo == null || !streamInfo.IsDirectStream) { @@ -473,9 +493,9 @@ namespace MediaBrowser.Api.Playback } // The MediaSource supports direct stream, now test to see if the client supports it - var streamInfo = string.Equals(item.MediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase) ? - streamBuilder.BuildAudioItem(options) : - streamBuilder.BuildVideoItem(options); + var streamInfo = string.Equals(item.MediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase) + ? streamBuilder.BuildAudioItem(options) + : streamBuilder.BuildVideoItem(options); if (streamInfo == null || !streamInfo.IsDirectStream) { @@ -493,9 +513,9 @@ namespace MediaBrowser.Api.Playback options.MaxBitrate = GetMaxBitrate(maxBitrate, user); // The MediaSource supports direct stream, now test to see if the client supports it - var streamInfo = string.Equals(item.MediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase) ? - streamBuilder.BuildAudioItem(options) : - streamBuilder.BuildVideoItem(options); + var streamInfo = string.Equals(item.MediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase) + ? streamBuilder.BuildAudioItem(options) + : streamBuilder.BuildVideoItem(options); if (streamInfo != null) { @@ -510,10 +530,12 @@ namespace MediaBrowser.Api.Playback { mediaSource.TranscodingUrl += "&allowVideoStreamCopy=false"; } + if (!allowAudioStreamCopy) { mediaSource.TranscodingUrl += "&allowAudioStreamCopy=false"; } + mediaSource.TranscodingContainer = streamInfo.Container; mediaSource.TranscodingSubProtocol = streamInfo.SubProtocol; } @@ -522,6 +544,16 @@ namespace MediaBrowser.Api.Playback SetDeviceSpecificSubtitleInfo(streamInfo, mediaSource, auth.Token); } } + + foreach (var attachment in mediaSource.MediaAttachments) + { + attachment.DeliveryUrl = string.Format( + CultureInfo.InvariantCulture, + "/Videos/{0}/{1}/Attachments/{2}", + item.Id, + mediaSource.Id, + attachment.Index); + } } private long? GetMaxBitrate(long? clientMaxBitrate, User user) @@ -599,14 +631,11 @@ namespace MediaBrowser.Api.Playback }).ThenBy(i => { - switch (i.Protocol) + return i.Protocol switch { - case MediaProtocol.File: - return 0; - default: - return 1; - } - + MediaProtocol.File => 0, + _ => 1, + }; }).ThenBy(i => { if (maxBitrate.HasValue) diff --git a/MediaBrowser.Api/Playback/UniversalAudioService.cs b/MediaBrowser.Api/Playback/UniversalAudioService.cs index 625ea9ac1..cbf981dfe 100644 --- a/MediaBrowser.Api/Playback/UniversalAudioService.cs +++ b/MediaBrowser.Api/Playback/UniversalAudioService.cs @@ -74,7 +74,6 @@ namespace MediaBrowser.Api.Playback [Authenticated] public class UniversalAudioService : BaseApiService { - private readonly ILoggerFactory _loggerFactory; private readonly EncodingHelper _encodingHelper; public UniversalAudioService( @@ -243,7 +242,6 @@ namespace MediaBrowser.Api.Playback NetworkManager, MediaEncoder, UserManager, - JsonSerializer, AuthorizationContext) { Request = Request |
