Backport pull request #11805 from jellyfin/release-10.9.z

Use SharedStream for LiveTV more restrictively

Original-merge: ef985896e2

Merged-by: crobibero <cody@robibe.ro>

Backported-by: Joshua M. Boniface <joshua@boniface.me>
pull/11833/head
gnattu 1 month ago committed by Joshua M. Boniface
parent 39ae56db0a
commit 876ae44b8a

@ -30,25 +30,8 @@ namespace Jellyfin.LiveTv.TunerHosts
{
public class M3UTunerHost : BaseTunerHost, ITunerHost, IConfigurableTunerHost
{
private static readonly string[] _disallowedMimeTypes =
{
"text/plain",
"text/html",
"video/x-matroska",
"video/mp4",
"application/vnd.apple.mpegurl",
"application/mpegurl",
"application/x-mpegurl",
"video/vnd.mpeg.dash.mpd"
};
private static readonly string[] _disallowedSharedStreamExtensions =
{
".mkv",
".mp4",
".m3u8",
".mpd"
};
private static readonly string[] _mimeTypesCanShareHttpStream = ["video/MP2T"];
private static readonly string[] _extensionsCanShareHttpStream = [".ts", ".tsv", ".m2t"];
private readonly IHttpClientFactory _httpClientFactory;
private readonly IServerApplicationHost _appHost;
@ -113,28 +96,34 @@ namespace Jellyfin.LiveTv.TunerHosts
if (mediaSource.Protocol == MediaProtocol.Http && !mediaSource.RequiresLooping)
{
using var message = new HttpRequestMessage(HttpMethod.Head, mediaSource.Path);
using var response = await _httpClientFactory.CreateClient(NamedClient.Default)
.SendAsync(message, cancellationToken)
.ConfigureAwait(false);
var extension = Path.GetExtension(new UriBuilder(mediaSource.Path).Path);
if (response.IsSuccessStatusCode)
if (string.IsNullOrEmpty(extension))
{
if (!_disallowedMimeTypes.Contains(response.Content.Headers.ContentType?.MediaType, StringComparison.OrdinalIgnoreCase))
try
{
return new SharedHttpStream(mediaSource, tunerHost, streamId, FileSystem, _httpClientFactory, Logger, Config, _appHost, _streamHelper);
using var message = new HttpRequestMessage(HttpMethod.Head, mediaSource.Path);
using var response = await _httpClientFactory.CreateClient(NamedClient.Default)
.SendAsync(message, cancellationToken)
.ConfigureAwait(false);
if (response.IsSuccessStatusCode)
{
if (_mimeTypesCanShareHttpStream.Contains(response.Content.Headers.ContentType?.MediaType, StringComparison.OrdinalIgnoreCase))
{
return new SharedHttpStream(mediaSource, tunerHost, streamId, FileSystem, _httpClientFactory, Logger, Config, _appHost, _streamHelper);
}
}
}
}
else
{
// Fallback to check path extension when the server does not support HEAD method
// Use UriBuilder to remove all query string as GetExtension will include them when used directly
var extension = Path.GetExtension(new UriBuilder(mediaSource.Path).Path);
if (!_disallowedSharedStreamExtensions.Contains(extension, StringComparison.OrdinalIgnoreCase))
catch (Exception)
{
return new SharedHttpStream(mediaSource, tunerHost, streamId, FileSystem, _httpClientFactory, Logger, Config, _appHost, _streamHelper);
Logger.LogWarning("HEAD request to check MIME type failed, shared stream disabled");
}
}
else if (_extensionsCanShareHttpStream.Contains(extension, StringComparison.OrdinalIgnoreCase))
{
return new SharedHttpStream(mediaSource, tunerHost, streamId, FileSystem, _httpClientFactory, Logger, Config, _appHost, _streamHelper);
}
}
return new LiveStream(mediaSource, tunerHost, FileSystem, Logger, Config, _streamHelper);

Loading…
Cancel
Save