mirror of
https://github.com/jellyfin/jellyfin.git
synced 2025-07-09 03:04:24 -04:00
Restructure the code to make it more testable
This commit is contained in:
parent
be233b49b6
commit
fa38b741ce
@ -49,13 +49,12 @@ namespace Jellyfin.MediaEncoding.Hls.Playlist
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public string CreateMainPlaylist(CreateMainPlaylistRequest request)
|
public string CreateMainPlaylist(CreateMainPlaylistRequest request)
|
||||||
{
|
{
|
||||||
IReadOnlyList<double> segments = Array.Empty<double>();
|
IReadOnlyList<double> segments;
|
||||||
if (IsExtractionAllowedForFile(request.FilePath))
|
if (TryExtractKeyframes(request.FilePath, out var keyframeData))
|
||||||
{
|
{
|
||||||
segments = ComputeSegments(request.FilePath, request.DesiredSegmentLengthMs);
|
segments = ComputeSegments(keyframeData, request.DesiredSegmentLengthMs);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
if (segments.Count == 0)
|
|
||||||
{
|
{
|
||||||
segments = ComputeEqualLengthSegments(request.DesiredSegmentLengthMs, request.TotalRuntimeTicks);
|
segments = ComputeEqualLengthSegments(request.DesiredSegmentLengthMs, request.TotalRuntimeTicks);
|
||||||
}
|
}
|
||||||
@ -115,9 +114,14 @@ namespace Jellyfin.MediaEncoding.Hls.Playlist
|
|||||||
return builder.ToString();
|
return builder.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private IReadOnlyList<double> ComputeSegments(string filePath, int desiredSegmentLengthMs)
|
private bool TryExtractKeyframes(string filePath, [NotNullWhen(true)] out KeyframeData? keyframeData)
|
||||||
{
|
{
|
||||||
KeyframeData keyframeData;
|
keyframeData = null;
|
||||||
|
if (!IsExtractionAllowedForFile(filePath, _serverConfigurationManager.GetEncodingOptions().AllowAutomaticKeyframeExtractionForExtensions))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
var cachePath = GetCachePath(filePath);
|
var cachePath = GetCachePath(filePath);
|
||||||
if (TryReadFromCache(cachePath, out var cachedResult))
|
if (TryReadFromCache(cachePath, out var cachedResult))
|
||||||
{
|
{
|
||||||
@ -132,31 +136,13 @@ namespace Jellyfin.MediaEncoding.Hls.Playlist
|
|||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.LogError(ex, "Keyframe extraction failed for path {FilePath}", filePath);
|
_logger.LogError(ex, "Keyframe extraction failed for path {FilePath}", filePath);
|
||||||
return Array.Empty<double>();
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
CacheResult(cachePath, keyframeData);
|
CacheResult(cachePath, keyframeData);
|
||||||
}
|
}
|
||||||
|
|
||||||
long lastKeyframe = 0;
|
return keyframeData.KeyframeTicks.Count > 0;
|
||||||
var result = new List<double>();
|
|
||||||
// Scale the segment length to ticks to match the keyframes
|
|
||||||
var desiredSegmentLengthTicks = TimeSpan.FromMilliseconds(desiredSegmentLengthMs).Ticks;
|
|
||||||
var desiredCutTime = desiredSegmentLengthTicks;
|
|
||||||
for (var j = 0; j < keyframeData.KeyframeTicks.Count; j++)
|
|
||||||
{
|
|
||||||
var keyframe = keyframeData.KeyframeTicks[j];
|
|
||||||
if (keyframe >= desiredCutTime)
|
|
||||||
{
|
|
||||||
var currentSegmentLength = keyframe - lastKeyframe;
|
|
||||||
result.Add(TimeSpan.FromTicks(currentSegmentLength).TotalSeconds);
|
|
||||||
lastKeyframe = keyframe;
|
|
||||||
desiredCutTime += desiredSegmentLengthTicks;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
result.Add(TimeSpan.FromTicks(keyframeData.TotalDuration - lastKeyframe).TotalSeconds);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CacheResult(string cachePath, KeyframeData keyframeData)
|
private void CacheResult(string cachePath, KeyframeData keyframeData)
|
||||||
@ -188,11 +174,10 @@ namespace Jellyfin.MediaEncoding.Hls.Playlist
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsExtractionAllowedForFile(ReadOnlySpan<char> filePath)
|
internal static bool IsExtractionAllowedForFile(ReadOnlySpan<char> filePath, string[] allowedExtensions)
|
||||||
{
|
{
|
||||||
// Remove the leading dot
|
// Remove the leading dot
|
||||||
var extension = Path.GetExtension(filePath)[1..];
|
var extension = Path.GetExtension(filePath)[1..];
|
||||||
var allowedExtensions = _serverConfigurationManager.GetEncodingOptions().AllowAutomaticKeyframeExtractionForExtensions;
|
|
||||||
for (var i = 0; i < allowedExtensions.Length; i++)
|
for (var i = 0; i < allowedExtensions.Length; i++)
|
||||||
{
|
{
|
||||||
var allowedExtension = allowedExtensions[i];
|
var allowedExtension = allowedExtensions[i];
|
||||||
@ -205,7 +190,30 @@ namespace Jellyfin.MediaEncoding.Hls.Playlist
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static double[] ComputeEqualLengthSegments(long desiredSegmentLengthMs, long totalRuntimeTicks)
|
internal static IReadOnlyList<double> ComputeSegments(KeyframeData keyframeData, int desiredSegmentLengthMs)
|
||||||
|
{
|
||||||
|
long lastKeyframe = 0;
|
||||||
|
var result = new List<double>();
|
||||||
|
// Scale the segment length to ticks to match the keyframes
|
||||||
|
var desiredSegmentLengthTicks = TimeSpan.FromMilliseconds(desiredSegmentLengthMs).Ticks;
|
||||||
|
var desiredCutTime = desiredSegmentLengthTicks;
|
||||||
|
for (var j = 0; j < keyframeData.KeyframeTicks.Count; j++)
|
||||||
|
{
|
||||||
|
var keyframe = keyframeData.KeyframeTicks[j];
|
||||||
|
if (keyframe >= desiredCutTime)
|
||||||
|
{
|
||||||
|
var currentSegmentLength = keyframe - lastKeyframe;
|
||||||
|
result.Add(TimeSpan.FromTicks(currentSegmentLength).TotalSeconds);
|
||||||
|
lastKeyframe = keyframe;
|
||||||
|
desiredCutTime += desiredSegmentLengthTicks;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result.Add(TimeSpan.FromTicks(keyframeData.TotalDuration - lastKeyframe).TotalSeconds);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static double[] ComputeEqualLengthSegments(long desiredSegmentLengthMs, long totalRuntimeTicks)
|
||||||
{
|
{
|
||||||
var segmentLengthTicks = TimeSpan.FromMilliseconds(desiredSegmentLengthMs).Ticks;
|
var segmentLengthTicks = TimeSpan.FromMilliseconds(desiredSegmentLengthMs).Ticks;
|
||||||
var wholeSegments = totalRuntimeTicks / segmentLengthTicks;
|
var wholeSegments = totalRuntimeTicks / segmentLengthTicks;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user