Merge pull request #3775 from crobibero/api-dynamic-hls

Move DynamicHlsService to Jellyfin.Api
This commit is contained in:
David 2020-08-01 17:42:33 +02:00 committed by GitHub
commit d50a022036
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 2376 additions and 17 deletions

View File

@ -70,7 +70,7 @@ namespace Jellyfin.Api.Auth
return false; return false;
} }
var ip = NormalizeIp(_httpContextAccessor.HttpContext.Connection.RemoteIpAddress).ToString(); var ip = RequestHelpers.NormalizeIp(_httpContextAccessor.HttpContext.Connection.RemoteIpAddress).ToString();
var isInLocalNetwork = _networkManager.IsInLocalNetwork(ip); var isInLocalNetwork = _networkManager.IsInLocalNetwork(ip);
// User cannot access remotely and user is remote // User cannot access remotely and user is remote
if (!user.HasPermission(PermissionKind.EnableRemoteAccess) && !isInLocalNetwork) if (!user.HasPermission(PermissionKind.EnableRemoteAccess) && !isInLocalNetwork)
@ -100,10 +100,5 @@ namespace Jellyfin.Api.Auth
return true; return true;
} }
private static IPAddress NormalizeIp(IPAddress ip)
{
return ip.IsIPv4MappedToIPv6 ? ip.MapToIPv4() : ip;
}
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,125 @@
using System;
using System.Globalization;
using System.Text;
namespace Jellyfin.Api.Helpers
{
/// <summary>
/// Hls Codec string helpers.
/// </summary>
public static class HlsCodecStringHelpers
{
/// <summary>
/// Gets a MP3 codec string.
/// </summary>
/// <returns>MP3 codec string.</returns>
public static string GetMP3String()
{
return "mp4a.40.34";
}
/// <summary>
/// Gets an AAC codec string.
/// </summary>
/// <param name="profile">AAC profile.</param>
/// <returns>AAC codec string.</returns>
public static string GetAACString(string profile)
{
StringBuilder result = new StringBuilder("mp4a", 9);
if (string.Equals(profile, "HE", StringComparison.OrdinalIgnoreCase))
{
result.Append(".40.5");
}
else
{
// Default to LC if profile is invalid
result.Append(".40.2");
}
return result.ToString();
}
/// <summary>
/// Gets a H.264 codec string.
/// </summary>
/// <param name="profile">H.264 profile.</param>
/// <param name="level">H.264 level.</param>
/// <returns>H.264 string.</returns>
public static string GetH264String(string profile, int level)
{
StringBuilder result = new StringBuilder("avc1", 11);
if (string.Equals(profile, "high", StringComparison.OrdinalIgnoreCase))
{
result.Append(".6400");
}
else if (string.Equals(profile, "main", StringComparison.OrdinalIgnoreCase))
{
result.Append(".4D40");
}
else if (string.Equals(profile, "baseline", StringComparison.OrdinalIgnoreCase))
{
result.Append(".42E0");
}
else
{
// Default to constrained baseline if profile is invalid
result.Append(".4240");
}
string levelHex = level.ToString("X2", CultureInfo.InvariantCulture);
result.Append(levelHex);
return result.ToString();
}
/// <summary>
/// Gets a H.265 codec string.
/// </summary>
/// <param name="profile">H.265 profile.</param>
/// <param name="level">H.265 level.</param>
/// <returns>H.265 string.</returns>
public static string GetH265String(string profile, int level)
{
// The h265 syntax is a bit of a mystery at the time this comment was written.
// This is what I've found through various sources:
// FORMAT: [codecTag].[profile].[constraint?].L[level * 30].[UNKNOWN]
StringBuilder result = new StringBuilder("hev1", 16);
if (string.Equals(profile, "main10", StringComparison.OrdinalIgnoreCase))
{
result.Append(".2.6");
}
else
{
// Default to main if profile is invalid
result.Append(".1.6");
}
result.Append(".L")
.Append(level * 3)
.Append(".B0");
return result.ToString();
}
/// <summary>
/// Gets an AC-3 codec string.
/// </summary>
/// <returns>AC-3 codec string.</returns>
public static string GetAC3String()
{
return "mp4a.a5";
}
/// <summary>
/// Gets an E-AC-3 codec string.
/// </summary>
/// <returns>E-AC-3 codec string.</returns>
public static string GetEAC3String()
{
return "mp4a.a6";
}
}
}

View File

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Net;
using Jellyfin.Data.Enums; using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Session; using MediaBrowser.Controller.Session;
@ -172,5 +173,10 @@ namespace Jellyfin.Api.Helpers
.Select(i => i!.Value) .Select(i => i!.Value)
.ToArray(); .ToArray();
} }
internal static IPAddress NormalizeIp(IPAddress ip)
{
return ip.IsIPv4MappedToIPv6 ? ip.MapToIPv4() : ip;
}
} }
} }

View File

@ -219,7 +219,7 @@ namespace Jellyfin.Api.Helpers
/// <param name="playSessionId">The play session identifier.</param> /// <param name="playSessionId">The play session identifier.</param>
/// <param name="deleteFiles">The delete files.</param> /// <param name="deleteFiles">The delete files.</param>
/// <returns>Task.</returns> /// <returns>Task.</returns>
public Task KillTranscodingJobs(string deviceId, string playSessionId, Func<string, bool> deleteFiles) public Task KillTranscodingJobs(string deviceId, string? playSessionId, Func<string, bool> deleteFiles)
{ {
return KillTranscodingJobs( return KillTranscodingJobs(
j => string.IsNullOrWhiteSpace(playSessionId) j => string.IsNullOrWhiteSpace(playSessionId)
@ -503,9 +503,9 @@ namespace Jellyfin.Api.Helpers
} }
} }
var process = new Process() var process = new Process
{ {
StartInfo = new ProcessStartInfo() StartInfo = new ProcessStartInfo
{ {
WindowStyle = ProcessWindowStyle.Hidden, WindowStyle = ProcessWindowStyle.Hidden,
CreateNoWindow = true, CreateNoWindow = true,

View File

@ -0,0 +1,13 @@
namespace Jellyfin.Api.Models.StreamingDtos
{
/// <summary>
/// The hls video request dto.
/// </summary>
public class HlsAudioRequestDto : StreamingRequestDto
{
/// <summary>
/// Gets or sets a value indicating whether enable adaptive bitrate streaming.
/// </summary>
public bool EnableAdaptiveBitrateStreaming { get; set; }
}
}

View File

@ -0,0 +1,13 @@
namespace Jellyfin.Api.Models.StreamingDtos
{
/// <summary>
/// The hls video request dto.
/// </summary>
public class HlsVideoRequestDto : VideoRequestDto
{
/// <summary>
/// Gets or sets a value indicating whether enable adaptive bitrate streaming.
/// </summary>
public bool EnableAdaptiveBitrateStreaming { get; set; }
}
}

View File

@ -27,8 +27,6 @@ namespace MediaBrowser.Api.Playback.Hls
/// <summary> /// <summary>
/// Options is needed for chromecast. Threw Head in there since it's related /// Options is needed for chromecast. Threw Head in there since it's related
/// </summary> /// </summary>
[Route("/Videos/{Id}/master.m3u8", "GET", Summary = "Gets a video stream using HTTP live streaming.")]
[Route("/Videos/{Id}/master.m3u8", "HEAD", Summary = "Gets a video stream using HTTP live streaming.")]
public class GetMasterHlsVideoPlaylist : VideoStreamRequest, IMasterHlsRequest public class GetMasterHlsVideoPlaylist : VideoStreamRequest, IMasterHlsRequest
{ {
public bool EnableAdaptiveBitrateStreaming { get; set; } public bool EnableAdaptiveBitrateStreaming { get; set; }
@ -39,8 +37,6 @@ namespace MediaBrowser.Api.Playback.Hls
} }
} }
[Route("/Audio/{Id}/master.m3u8", "GET", Summary = "Gets an audio stream using HTTP live streaming.")]
[Route("/Audio/{Id}/master.m3u8", "HEAD", Summary = "Gets an audio stream using HTTP live streaming.")]
public class GetMasterHlsAudioPlaylist : StreamRequest, IMasterHlsRequest public class GetMasterHlsAudioPlaylist : StreamRequest, IMasterHlsRequest
{ {
public bool EnableAdaptiveBitrateStreaming { get; set; } public bool EnableAdaptiveBitrateStreaming { get; set; }
@ -56,17 +52,14 @@ namespace MediaBrowser.Api.Playback.Hls
bool EnableAdaptiveBitrateStreaming { get; set; } bool EnableAdaptiveBitrateStreaming { get; set; }
} }
[Route("/Videos/{Id}/main.m3u8", "GET", Summary = "Gets a video stream using HTTP live streaming.")]
public class GetVariantHlsVideoPlaylist : VideoStreamRequest public class GetVariantHlsVideoPlaylist : VideoStreamRequest
{ {
} }
[Route("/Audio/{Id}/main.m3u8", "GET", Summary = "Gets an audio stream using HTTP live streaming.")]
public class GetVariantHlsAudioPlaylist : StreamRequest public class GetVariantHlsAudioPlaylist : StreamRequest
{ {
} }
[Route("/Videos/{Id}/hls1/{PlaylistId}/{SegmentId}.{SegmentContainer}", "GET")]
public class GetHlsVideoSegment : VideoStreamRequest public class GetHlsVideoSegment : VideoStreamRequest
{ {
public string PlaylistId { get; set; } public string PlaylistId { get; set; }
@ -78,7 +71,6 @@ namespace MediaBrowser.Api.Playback.Hls
public string SegmentId { get; set; } public string SegmentId { get; set; }
} }
[Route("/Audio/{Id}/hls1/{PlaylistId}/{SegmentId}.{SegmentContainer}", "GET")]
public class GetHlsAudioSegment : StreamRequest public class GetHlsAudioSegment : StreamRequest
{ {
public string PlaylistId { get; set; } public string PlaylistId { get; set; }