diff options
| author | David <daullmer@gmail.com> | 2020-08-01 15:09:44 +0200 |
|---|---|---|
| committer | David <daullmer@gmail.com> | 2020-08-01 15:10:57 +0200 |
| commit | d3dc9da5d6780f110bc71b0772d27a97ebb0349f (patch) | |
| tree | d8c8310f3adf23ea811a086480b82fd4a7348963 /Jellyfin.Api/Controllers | |
| parent | a3dcca3826d1b33645d1064da29634cb8a06a3d2 (diff) | |
Prepare DynamicHlsController merge
Diffstat (limited to 'Jellyfin.Api/Controllers')
| -rw-r--r-- | Jellyfin.Api/Controllers/UniversalAudioController.cs | 213 |
1 files changed, 176 insertions, 37 deletions
diff --git a/Jellyfin.Api/Controllers/UniversalAudioController.cs b/Jellyfin.Api/Controllers/UniversalAudioController.cs index 9e7b23b78..311c0a3b9 100644 --- a/Jellyfin.Api/Controllers/UniversalAudioController.cs +++ b/Jellyfin.Api/Controllers/UniversalAudioController.cs @@ -4,6 +4,7 @@ using System.Globalization; using System.Linq; using System.Net.Http; using System.Threading.Tasks; +using Jellyfin.Api.Constants; using Jellyfin.Api.Helpers; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; @@ -15,6 +16,8 @@ using MediaBrowser.Controller.Net; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.IO; using MediaBrowser.Model.MediaInfo; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; @@ -40,8 +43,26 @@ namespace Jellyfin.Api.Controllers private readonly TranscodingJobHelper _transcodingJobHelper; private readonly IConfiguration _configuration; private readonly ISubtitleEncoder _subtitleEncoder; - private readonly IStreamHelper _streamHelper; + private readonly IHttpClientFactory _httpClientFactory; + /// <summary> + /// Initializes a new instance of the <see cref="UniversalAudioController"/> class. + /// </summary> + /// <param name="loggerFactory">Instance of the <see cref="ILoggerFactory"/> interface.</param> + /// <param name="serverConfigurationManager">Instance of the <see cref="IServerConfigurationManager"/> interface.</param> + /// <param name="userManager">Instance of the <see cref="IUserManager"/> interface.</param> + /// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param> + /// <param name="mediaEncoder">Instance of the <see cref="IMediaEncoder"/> interface.</param> + /// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param> + /// <param name="dlnaManager">Instance of the <see cref="IDlnaManager"/> interface.</param> + /// <param name="deviceManager">Instance of the <see cref="IDeviceManager"/> interface.</param> + /// <param name="mediaSourceManager">Instance of the <see cref="IMediaSourceManager"/> interface.</param> + /// <param name="authorizationContext">Instance of the <see cref="IAuthorizationContext"/> interface.</param> + /// <param name="networkManager">Instance of the <see cref="INetworkManager"/> interface.</param> + /// <param name="transcodingJobHelper">Instance of the <see cref="TranscodingJobHelper"/> interface.</param> + /// <param name="configuration">Instance of the <see cref="IConfiguration"/> interface.</param> + /// <param name="subtitleEncoder">Instance of the <see cref="ISubtitleEncoder"/> interface.</param> + /// <param name="httpClientFactory">Instance of the <see cref="IHttpClientFactory"/> interface.</param> public UniversalAudioController( ILoggerFactory loggerFactory, IServerConfigurationManager serverConfigurationManager, @@ -57,7 +78,7 @@ namespace Jellyfin.Api.Controllers TranscodingJobHelper transcodingJobHelper, IConfiguration configuration, ISubtitleEncoder subtitleEncoder, - IStreamHelper streamHelper) + IHttpClientFactory httpClientFactory) { _userManager = userManager; _libraryManager = libraryManager; @@ -73,13 +94,39 @@ namespace Jellyfin.Api.Controllers _transcodingJobHelper = transcodingJobHelper; _configuration = configuration; _subtitleEncoder = subtitleEncoder; - _streamHelper = streamHelper; + _httpClientFactory = httpClientFactory; } + /// <summary> + /// Gets an audio stream. + /// </summary> + /// <param name="itemId">The item id.</param> + /// <param name="container">Optional. The audio container.</param> + /// <param name="mediaSourceId">The media version id, if playing an alternate version.</param> + /// <param name="deviceId">The device id of the client requesting. Used to stop encoding processes when needed.</param> + /// <param name="userId">Optional. The user id.</param> + /// <param name="audioCodec">Optional. The audio codec to transcode to.</param> + /// <param name="maxAudioChannels">Optional. The maximum number of audio channels.</param> + /// <param name="transcodingAudioChannels">Optional. The number of how many audio channels to transcode to.</param> + /// <param name="maxStreamingBitrate">Optional. The maximum streaming bitrate.</param> + /// <param name="startTimeTicks">Optional. Specify a starting offset, in ticks. 1 tick = 10000 ms.</param> + /// <param name="transcodingContainer">Optional. The container to transcode to.</param> + /// <param name="transcodingProtocol">Optional. The transcoding protocol.</param> + /// <param name="maxAudioSampleRate">Optional. The maximum audio sample rate.</param> + /// <param name="maxAudioBitDepth">Optional. The maximum audio bit depth.</param> + /// <param name="enableRemoteMedia">Optional. Whether to enable remote media.</param> + /// <param name="breakOnNonKeyFrames">Optional. Whether to break on non key frames.</param> + /// <param name="enableRedirection">Whether to enable redirection. Defaults to true.</param> + /// <response code="200">Audio stream returned.</response> + /// <response code="302">Redirected to remote audio stream.</response> + /// <returns>A <see cref="Task"/> containing the audio file.</returns> [HttpGet("/Audio/{itemId}/universal")] [HttpGet("/Audio/{itemId}/{universal=universal}.{container?}")] [HttpHead("/Audio/{itemId}/universal")] [HttpHead("/Audio/{itemId}/{universal=universal}.{container?}")] + [Authorize(Policy = Policies.DefaultAuthorization)] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status302Found)] public async Task<ActionResult> GetUniversalAudioStream( [FromRoute] Guid itemId, [FromRoute] string? container, @@ -121,44 +168,138 @@ namespace Jellyfin.Api.Controllers var isStatic = mediaSource.SupportsDirectStream; if (!isStatic && string.Equals(mediaSource.TranscodingSubProtocol, "hls", StringComparison.OrdinalIgnoreCase)) { - // TODO new DynamicHlsController - // var dynamicHlsController = new DynamicHlsController(); + var dynamicHlsController = new DynamicHlsController( + _libraryManager, + _userManager, + _dlnaManager, + _authorizationContext, + _mediaSourceManager, + _serverConfigurationManager, + _mediaEncoder, + _fileSystem, + _subtitleEncoder, + _configuration, + _deviceManager, + _transcodingJobHelper, + _networkManager, + _loggerFactory.CreateLogger<DynamicHlsController>()); var transcodingProfile = deviceProfile.TranscodingProfiles[0]; // hls segment container can only be mpegts or fmp4 per ffmpeg documentation // TODO: remove this when we switch back to the segment muxer - var supportedHLSContainers = new[] { "mpegts", "fmp4" }; - - /* - var newRequest = new GetMasterHlsAudioPlaylist - { - AudioBitRate = isStatic ? (int?)null : Convert.ToInt32(Math.Min(request.MaxStreamingBitrate ?? 192000, int.MaxValue)), - AudioCodec = transcodingProfile.AudioCodec, - Container = ".m3u8", - DeviceId = request.DeviceId, - Id = request.Id, - MaxAudioChannels = request.MaxAudioChannels, - MediaSourceId = mediaSource.Id, - PlaySessionId = playbackInfoResult.PlaySessionId, - StartTimeTicks = request.StartTimeTicks, - Static = isStatic, - // fallback to mpegts if device reports some weird value unsupported by hls - SegmentContainer = Array.Exists(supportedHLSContainers, element => element == request.TranscodingContainer) ? request.TranscodingContainer : "mpegts", - AudioSampleRate = request.MaxAudioSampleRate, - MaxAudioBitDepth = request.MaxAudioBitDepth, - BreakOnNonKeyFrames = transcodingProfile.BreakOnNonKeyFrames, - TranscodeReasons = mediaSource.TranscodeReasons == null ? null : string.Join(",", mediaSource.TranscodeReasons.Select(i => i.ToString()).ToArray()) - }; + var supportedHlsContainers = new[] { "mpegts", "fmp4" }; if (isHeadRequest) { - audioController.Request.Method = HttpMethod.Head.Method; - return await service.Head(newRequest).ConfigureAwait(false); + dynamicHlsController.Request.Method = HttpMethod.Head.Method; + return await dynamicHlsController.GetMasterHlsAudioPlaylist( + itemId, + ".m3u8", + isStatic, + null, + null, + null, + playbackInfoResult.Value.PlaySessionId, + // fallback to mpegts if device reports some weird value unsupported by hls + Array.Exists(supportedHlsContainers, element => element == transcodingContainer) ? transcodingContainer : "mpegts", + null, + null, + mediaSource.Id, + deviceId, + transcodingProfile.AudioCodec, + null, + null, + transcodingProfile.BreakOnNonKeyFrames, + maxAudioSampleRate, + maxAudioBitDepth, + null, + isStatic ? (int?)null : Convert.ToInt32(Math.Min(maxStreamingBitrate ?? 192000, int.MaxValue)), + null, + maxAudioChannels, + null, + null, + null, + null, + null, + startTimeTicks, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + mediaSource.TranscodeReasons == null ? null : string.Join(",", mediaSource.TranscodeReasons.Select(i => i.ToString()).ToArray()), + null, + null, + null, + null, + null, + null) + .ConfigureAwait(false); } - return await service.Get(newRequest).ConfigureAwait(false);*/ - // TODO remove this line - return Content(string.Empty); + return await dynamicHlsController.GetMasterHlsAudioPlaylist( + itemId, + ".m3u8", + isStatic, + null, + null, + null, + playbackInfoResult.Value.PlaySessionId, + // fallback to mpegts if device reports some weird value unsupported by hls + Array.Exists(supportedHlsContainers, element => element == transcodingContainer) ? transcodingContainer : "mpegts", + null, + null, + mediaSource.Id, + deviceId, + transcodingProfile.AudioCodec, + null, + null, + transcodingProfile.BreakOnNonKeyFrames, + maxAudioSampleRate, + maxAudioBitDepth, + null, + isStatic ? (int?)null : Convert.ToInt32(Math.Min(maxStreamingBitrate ?? 192000, int.MaxValue)), + null, + maxAudioChannels, + null, + null, + null, + null, + null, + startTimeTicks, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + mediaSource.TranscodeReasons == null ? null : string.Join(",", mediaSource.TranscodeReasons.Select(i => i.ToString()).ToArray()), + null, + null, + null, + null, + null, + null) + .ConfigureAwait(false); } else { @@ -170,14 +311,12 @@ namespace Jellyfin.Api.Controllers _mediaSourceManager, _serverConfigurationManager, _mediaEncoder, - _streamHelper, _fileSystem, _subtitleEncoder, _configuration, _deviceManager, _transcodingJobHelper, - // TODO HttpClient - new HttpClient()); + _httpClientFactory); if (isHeadRequest) { @@ -304,11 +443,11 @@ namespace Jellyfin.Api.Controllers var directPlayProfiles = new List<DirectPlayProfile>(); - var containers = (container ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); + var containers = RequestHelpers.Split(container, ',', true); foreach (var cont in containers) { - var parts = cont.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries); + var parts = RequestHelpers.Split(cont, ',', true); var audioCodecs = parts.Length == 1 ? null : string.Join(",", parts.Skip(1).ToArray()); |
