Browse Source

Prepare DynamicHlsController merge

David 4 years ago
parent
commit
d3dc9da5d6
1 changed files with 176 additions and 37 deletions
  1. 176 37
      Jellyfin.Api/Controllers/UniversalAudioController.cs

+ 176 - 37
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());