From f954dc5c969ef5654c31bec7a81b0b92b38637ae Mon Sep 17 00:00:00 2001 From: Bond-009 Date: Wed, 28 Jun 2023 05:36:39 +0200 Subject: [PATCH] Do HEAD request to get content type instead of checking for extension (#8823) --- .../LiveTv/TunerHosts/M3UTunerHost.cs | 21 ++++++--- .../LiveTv/TunerHosts/SharedHttpStream.cs | 47 +++++-------------- 2 files changed, 25 insertions(+), 43 deletions(-) diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs index bcb42e1626..acf3964c8c 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs @@ -30,12 +30,14 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts { public class M3UTunerHost : BaseTunerHost, ITunerHost, IConfigurableTunerHost { - private static readonly string[] _disallowedSharedStreamExtensions = + private static readonly string[] _disallowedMimeTypes = { - ".mkv", - ".mp4", - ".m3u8", - ".mpd" + "video/x-matroska", + "video/mp4", + "application/vnd.apple.mpegurl", + "application/mpegurl", + "application/x-mpegurl", + "video/vnd.mpeg.dash.mpd" }; private readonly IHttpClientFactory _httpClientFactory; @@ -118,9 +120,14 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts if (mediaSource.Protocol == MediaProtocol.Http && !mediaSource.RequiresLooping) { - var extension = Path.GetExtension(mediaSource.Path) ?? string.Empty; + using var message = new HttpRequestMessage(HttpMethod.Head, mediaSource.Path); + using var response = await _httpClientFactory.CreateClient(NamedClient.Default) + .SendAsync(message, cancellationToken) + .ConfigureAwait(false); - if (!_disallowedSharedStreamExtensions.Contains(extension, StringComparison.OrdinalIgnoreCase)) + response.EnsureSuccessStatusCode(); + + if (!_disallowedMimeTypes.Contains(response.Content.Headers.ContentType?.ToString(), StringComparison.OrdinalIgnoreCase)) { return new SharedHttpStream(mediaSource, tunerHost, streamId, FileSystem, _httpClientFactory, Logger, Config, _appHost, _streamHelper); } diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs index e84e1e074c..51f46f4dac 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs @@ -38,7 +38,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts _httpClientFactory = httpClientFactory; _appHost = appHost; OriginalStreamId = originalStreamId; - EnableStreamSharing = true; } public override async Task Open(CancellationToken openCancellationToken) @@ -59,39 +58,13 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts .GetAsync(url, HttpCompletionOption.ResponseHeadersRead, CancellationToken.None) .ConfigureAwait(false); - var contentType = response.Content.Headers.ContentType?.ToString() ?? string.Empty; - if (contentType.Contains("matroska", StringComparison.OrdinalIgnoreCase) - || contentType.Contains("mp4", StringComparison.OrdinalIgnoreCase) - || contentType.Contains("dash", StringComparison.OrdinalIgnoreCase) - || contentType.Contains("mpegURL", StringComparison.OrdinalIgnoreCase) - || contentType.Contains("text/", StringComparison.OrdinalIgnoreCase)) - { - // Close the stream without any sharing features - response.Dispose(); - return; - } - - SetTempFilePath("ts"); - var taskCompletionSource = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); _ = StartStreaming(response, taskCompletionSource, LiveStreamCancellationTokenSource.Token); - // OpenedMediaSource.Protocol = MediaProtocol.File; - // OpenedMediaSource.Path = tempFile; - // OpenedMediaSource.ReadAtNativeFramerate = true; - MediaSource.Path = _appHost.GetApiUrlForLocalAccess() + "/LiveTv/LiveStreamFiles/" + UniqueId + "/stream.ts"; MediaSource.Protocol = MediaProtocol.Http; - // OpenedMediaSource.Path = TempFilePath; - // OpenedMediaSource.Protocol = MediaProtocol.File; - - // OpenedMediaSource.Path = _tempFilePath; - // OpenedMediaSource.Protocol = MediaProtocol.File; - // OpenedMediaSource.SupportsDirectPlay = false; - // OpenedMediaSource.SupportsDirectStream = true; - // OpenedMediaSource.SupportsTranscoding = true; var res = await taskCompletionSource.Task.ConfigureAwait(false); if (!res) { @@ -108,15 +81,17 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts try { Logger.LogInformation("Beginning {StreamType} stream to {FilePath}", GetType().Name, TempFilePath); - using var message = response; - await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); - await using var fileStream = new FileStream(TempFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous); - await StreamHelper.CopyToAsync( - stream, - fileStream, - IODefaults.CopyToBufferSize, - () => Resolve(openTaskCompletionSource), - cancellationToken).ConfigureAwait(false); + using (response) + { + await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); + await using var fileStream = new FileStream(TempFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous); + await StreamHelper.CopyToAsync( + stream, + fileStream, + IODefaults.CopyToBufferSize, + () => Resolve(openTaskCompletionSource), + cancellationToken).ConfigureAwait(false); + } } catch (OperationCanceledException ex) {