Fix suggestions from review

pull/3592/head
David 4 years ago
parent d39f481a5c
commit ca3dcc3db0

@ -260,7 +260,7 @@ namespace Jellyfin.Api.Controllers
StreamOptions = streamOptions
};
var state = await StreamingHelpers.GetStreamingState(
using var state = await StreamingHelpers.GetStreamingState(
streamingRequest,
Request,
_authContext,
@ -283,14 +283,11 @@ namespace Jellyfin.Api.Controllers
{
StreamingHelpers.AddDlnaHeaders(state, Response.Headers, true, startTimeTicks, Request, _dlnaManager);
using (state)
{
// TODO AllowEndOfFile = false
await new ProgressiveFileCopier(_streamHelper, state.DirectStreamProvider).WriteToAsync(Response.Body, CancellationToken.None).ConfigureAwait(false);
// TODO AllowEndOfFile = false
await new ProgressiveFileCopier(_streamHelper, state.DirectStreamProvider).WriteToAsync(Response.Body, CancellationToken.None).ConfigureAwait(false);
// TODO (moved from MediaBrowser.Api): Don't hardcode contentType
return File(Response.Body, MimeTypes.GetMimeType("file.ts")!);
}
// TODO (moved from MediaBrowser.Api): Don't hardcode contentType
return File(Response.Body, MimeTypes.GetMimeType("file.ts")!);
}
// Static remote stream
@ -298,10 +295,7 @@ namespace Jellyfin.Api.Controllers
{
StreamingHelpers.AddDlnaHeaders(state, Response.Headers, true, startTimeTicks, Request, _dlnaManager);
using (state)
{
return await FileStreamResponseHelpers.GetStaticRemoteStreamResult(state, isHeadRequest, this, _httpClient).ConfigureAwait(false);
}
return await FileStreamResponseHelpers.GetStaticRemoteStreamResult(state, isHeadRequest, this, _httpClient).ConfigureAwait(false);
}
if (@static.HasValue && @static.Value && state.InputProtocol != MediaProtocol.File)
@ -322,80 +316,35 @@ namespace Jellyfin.Api.Controllers
{
var contentType = state.GetMimeType("." + state.OutputContainer, false) ?? state.GetMimeType(state.MediaPath);
using (state)
if (state.MediaSource.IsInfiniteStream)
{
if (state.MediaSource.IsInfiniteStream)
{
// TODO AllowEndOfFile = false
await new ProgressiveFileCopier(_streamHelper, state.MediaPath).WriteToAsync(Response.Body, CancellationToken.None).ConfigureAwait(false);
return File(Response.Body, contentType);
}
// TODO AllowEndOfFile = false
await new ProgressiveFileCopier(_streamHelper, state.MediaPath).WriteToAsync(Response.Body, CancellationToken.None).ConfigureAwait(false);
return FileStreamResponseHelpers.GetStaticFileResult(
state.MediaPath,
contentType,
isHeadRequest,
this);
return File(Response.Body, contentType);
}
}
/*
// Not static but transcode cache file exists
if (isTranscodeCached && state.VideoRequest == null)
{
var contentType = state.GetMimeType(outputPath)
try
{
if (transcodingJob != null)
{
ApiEntryPoint.Instance.OnTranscodeBeginRequest(transcodingJob);
}
return await ResultFactory.GetStaticFileResult(Request, new StaticFileResultOptions
{
ResponseHeaders = responseHeaders,
ContentType = contentType,
IsHeadRequest = isHeadRequest,
Path = outputPath,
FileShare = FileShare.ReadWrite,
OnComplete = () =>
{
if (transcodingJob != null)
{
ApiEntryPoint.Instance.OnTranscodeEndRequest(transcodingJob);
}
}).ConfigureAwait(false);
}
finally
{
state.Dispose();
}
}
*/
// Need to start ffmpeg (because media can't be returned directly)
try
{
var encodingOptions = _serverConfigurationManager.GetEncodingOptions();
var encodingHelper = new EncodingHelper(_mediaEncoder, _fileSystem, _subtitleEncoder, _configuration);
var ffmpegCommandLineArguments = encodingHelper.GetProgressiveAudioFullCommandLine(state, encodingOptions, outputPath);
return await FileStreamResponseHelpers.GetTranscodedFile(
state,
return FileStreamResponseHelpers.GetStaticFileResult(
state.MediaPath,
contentType,
isHeadRequest,
_streamHelper,
this,
_transcodingJobHelper,
ffmpegCommandLineArguments,
Request,
_transcodingJobType,
cancellationTokenSource).ConfigureAwait(false);
this);
}
catch
{
state.Dispose();
throw;
}
// Need to start ffmpeg (because media can't be returned directly)
var encodingOptions = _serverConfigurationManager.GetEncodingOptions();
var encodingHelper = new EncodingHelper(_mediaEncoder, _fileSystem, _subtitleEncoder, _configuration);
var ffmpegCommandLineArguments = encodingHelper.GetProgressiveAudioFullCommandLine(state, encodingOptions, outputPath);
return await FileStreamResponseHelpers.GetTranscodedFile(
state,
isHeadRequest,
_streamHelper,
this,
_transcodingJobHelper,
ffmpegCommandLineArguments,
Request,
_transcodingJobType,
cancellationTokenSource).ConfigureAwait(false);
}
}
}

@ -36,17 +36,14 @@ namespace Jellyfin.Api.Helpers
httpClient.DefaultRequestHeaders.Add(HeaderNames.UserAgent, useragent);
}
var response = await httpClient.GetAsync(state.MediaPath).ConfigureAwait(false);
using var response = await httpClient.GetAsync(state.MediaPath).ConfigureAwait(false);
var contentType = response.Content.Headers.ContentType.ToString();
controller.Response.Headers[HeaderNames.AcceptRanges] = "none";
if (isHeadRequest)
{
using (response)
{
return controller.File(Array.Empty<byte>(), contentType);
}
return controller.File(Array.Empty<byte>(), contentType);
}
return controller.File(await response.Content.ReadAsStreamAsync().ConfigureAwait(false), contentType);
@ -74,7 +71,7 @@ namespace Jellyfin.Api.Helpers
return controller.NoContent();
}
var stream = new FileStream(path, FileMode.Open, FileAccess.Read);
using var stream = new FileStream(path, FileMode.Open, FileAccess.Read);
return controller.File(stream, contentType);
}
@ -129,11 +126,9 @@ namespace Jellyfin.Api.Helpers
state.Dispose();
}
using (var memoryStream = new MemoryStream())
{
await new ProgressiveFileCopier(streamHelper, outputPath).WriteToAsync(memoryStream, CancellationToken.None).ConfigureAwait(false);
return controller.File(memoryStream, contentType);
}
await using var memoryStream = new MemoryStream();
await new ProgressiveFileCopier(streamHelper, outputPath).WriteToAsync(memoryStream, CancellationToken.None).ConfigureAwait(false);
return controller.File(memoryStream, contentType);
}
finally
{

@ -74,7 +74,7 @@ namespace Jellyfin.Api.Helpers
{
var timeSeek = httpRequest.Headers["TimeSeekRange.dlna.org"];
streamingRequest.StartTimeTicks = ParseTimeSeekHeader(timeSeek);
streamingRequest.StartTimeTicks = ParseTimeSeekHeader(timeSeek.ToString());
}
if (!string.IsNullOrWhiteSpace(streamingRequest.Params))
@ -108,31 +108,22 @@ namespace Jellyfin.Api.Helpers
state.User = userManager.GetUserById(auth.UserId);
}
/*
if ((Request.UserAgent ?? string.Empty).IndexOf("iphone", StringComparison.OrdinalIgnoreCase) != -1 ||
(Request.UserAgent ?? string.Empty).IndexOf("ipad", StringComparison.OrdinalIgnoreCase) != -1 ||
(Request.UserAgent ?? string.Empty).IndexOf("ipod", StringComparison.OrdinalIgnoreCase) != -1)
{
state.SegmentLength = 6;
}
*/
if (state.IsVideoRequest && !string.IsNullOrWhiteSpace(state.Request.VideoCodec))
{
state.SupportedVideoCodecs = state.Request.VideoCodec.Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).ToArray();
state.SupportedVideoCodecs = state.Request.VideoCodec.Split(',', StringSplitOptions.RemoveEmptyEntries);
state.Request.VideoCodec = state.SupportedVideoCodecs.FirstOrDefault();
}
if (!string.IsNullOrWhiteSpace(streamingRequest.AudioCodec))
{
state.SupportedAudioCodecs = streamingRequest.AudioCodec.Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).ToArray();
state.SupportedAudioCodecs = streamingRequest.AudioCodec.Split(',', StringSplitOptions.RemoveEmptyEntries);
state.Request.AudioCodec = state.SupportedAudioCodecs.FirstOrDefault(i => mediaEncoder.CanEncodeToAudioCodec(i))
?? state.SupportedAudioCodecs.FirstOrDefault();
}
if (!string.IsNullOrWhiteSpace(streamingRequest.SubtitleCodec))
{
state.SupportedSubtitleCodecs = streamingRequest.SubtitleCodec.Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).ToArray();
state.SupportedSubtitleCodecs = streamingRequest.SubtitleCodec.Split(',', StringSplitOptions.RemoveEmptyEntries);
state.Request.SubtitleCodec = state.SupportedSubtitleCodecs.FirstOrDefault(i => mediaEncoder.CanEncodeToSubtitleCodec(i))
?? state.SupportedSubtitleCodecs.FirstOrDefault();
}
@ -141,15 +132,6 @@ namespace Jellyfin.Api.Helpers
state.IsInputVideo = string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase);
/*
var primaryImage = item.GetImageInfo(ImageType.Primary, 0) ??
item.Parents.Select(i => i.GetImageInfo(ImageType.Primary, 0)).FirstOrDefault(i => i != null);
if (primaryImage != null)
{
state.AlbumCoverPath = primaryImage.Path;
}
*/
MediaSourceInfo? mediaSource = null;
if (string.IsNullOrWhiteSpace(streamingRequest.LiveStreamId))
{
@ -322,25 +304,24 @@ namespace Jellyfin.Api.Helpers
/// </summary>
/// <param name="value">The time seek header string.</param>
/// <returns>A nullable <see cref="long"/> representing the seek time in ticks.</returns>
private static long? ParseTimeSeekHeader(string value)
private static long? ParseTimeSeekHeader(ReadOnlySpan<char> value)
{
if (string.IsNullOrWhiteSpace(value))
if (value.IsEmpty)
{
return null;
}
const string Npt = "npt=";
if (!value.StartsWith(Npt, StringComparison.OrdinalIgnoreCase))
const string npt = "npt=";
if (!value.StartsWith(npt, StringComparison.OrdinalIgnoreCase))
{
throw new ArgumentException("Invalid timeseek header");
}
int index = value.IndexOf('-', StringComparison.InvariantCulture);
var index = value.IndexOf('-');
value = index == -1
? value.Substring(Npt.Length)
: value.Substring(Npt.Length, index - Npt.Length);
if (value.IndexOf(':', StringComparison.InvariantCulture) == -1)
? value.Slice(npt.Length)
: value.Slice(npt.Length, index - npt.Length);
if (value.IndexOf(':') == -1)
{
// Parses npt times in the format of '417.33'
if (double.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var seconds))
@ -351,26 +332,15 @@ namespace Jellyfin.Api.Helpers
throw new ArgumentException("Invalid timeseek header");
}
// Parses npt times in the format of '10:19:25.7'
var tokens = value.Split(new[] { ':' }, 3);
double secondsSum = 0;
var timeFactor = 3600;
foreach (var time in tokens)
try
{
if (double.TryParse(time, NumberStyles.Any, CultureInfo.InvariantCulture, out var digit))
{
secondsSum += digit * timeFactor;
}
else
{
throw new ArgumentException("Invalid timeseek header");
}
timeFactor /= 60;
// Parses npt times in the format of '10:19:25.7'
return TimeSpan.Parse(value).Ticks;
}
catch
{
throw new ArgumentException("Invalid timeseek header");
}
return TimeSpan.FromSeconds(secondsSum).Ticks;
}
/// <summary>

@ -88,11 +88,11 @@ namespace Jellyfin.Api.Models.StreamingDtos
{
var userAgent = UserAgent ?? string.Empty;
if (userAgent.IndexOf("AppleTV", StringComparison.OrdinalIgnoreCase) != -1 ||
userAgent.IndexOf("cfnetwork", StringComparison.OrdinalIgnoreCase) != -1 ||
userAgent.IndexOf("ipad", StringComparison.OrdinalIgnoreCase) != -1 ||
userAgent.IndexOf("iphone", StringComparison.OrdinalIgnoreCase) != -1 ||
userAgent.IndexOf("ipod", StringComparison.OrdinalIgnoreCase) != -1)
if (userAgent.IndexOf("AppleTV", StringComparison.OrdinalIgnoreCase) != -1
|| userAgent.IndexOf("cfnetwork", StringComparison.OrdinalIgnoreCase) != -1
|| userAgent.IndexOf("ipad", StringComparison.OrdinalIgnoreCase) != -1
|| userAgent.IndexOf("iphone", StringComparison.OrdinalIgnoreCase) != -1
|| userAgent.IndexOf("ipod", StringComparison.OrdinalIgnoreCase) != -1)
{
return 6;
}

Loading…
Cancel
Save