Merge pull request #4182 from ryanpetris/fix-hdhomerun

Fix HD Home Run streaming
This commit is contained in:
Joshua M. Boniface 2020-11-21 17:22:19 -05:00 committed by GitHub
commit d5eb7e786f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 54 additions and 52 deletions

View file

@ -111,11 +111,11 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
public async Task<bool> CheckTunerAvailability(IPAddress remoteIp, int tuner, CancellationToken cancellationToken) public async Task<bool> CheckTunerAvailability(IPAddress remoteIp, int tuner, CancellationToken cancellationToken)
{ {
using (var client = new TcpClient(new IPEndPoint(remoteIp, HdHomeRunPort))) using var client = new TcpClient();
using (var stream = client.GetStream()) client.Connect(remoteIp, HdHomeRunPort);
{
return await CheckTunerAvailability(stream, tuner, cancellationToken).ConfigureAwait(false); using var stream = client.GetStream();
} return await CheckTunerAvailability(stream, tuner, cancellationToken).ConfigureAwait(false);
} }
private static async Task<bool> CheckTunerAvailability(NetworkStream stream, int tuner, CancellationToken cancellationToken) private static async Task<bool> CheckTunerAvailability(NetworkStream stream, int tuner, CancellationToken cancellationToken)
@ -142,7 +142,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
{ {
_remoteEndPoint = new IPEndPoint(remoteIp, HdHomeRunPort); _remoteEndPoint = new IPEndPoint(remoteIp, HdHomeRunPort);
_tcpClient = new TcpClient(_remoteEndPoint); _tcpClient = new TcpClient();
_tcpClient.Connect(_remoteEndPoint);
if (!_lockkey.HasValue) if (!_lockkey.HasValue)
{ {
@ -221,30 +222,30 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
return; return;
} }
using (var tcpClient = new TcpClient(_remoteEndPoint)) using var tcpClient = new TcpClient();
using (var stream = tcpClient.GetStream()) tcpClient.Connect(_remoteEndPoint);
{
var commandList = commands.GetCommands();
byte[] buffer = ArrayPool<byte>.Shared.Rent(8192);
try
{
foreach (var command in commandList)
{
var channelMsg = CreateSetMessage(_activeTuner, command.Item1, command.Item2, _lockkey);
await stream.WriteAsync(channelMsg, 0, channelMsg.Length, cancellationToken).ConfigureAwait(false);
int receivedBytes = await stream.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false);
// parse response to make sure it worked using var stream = tcpClient.GetStream();
if (!ParseReturnMessage(buffer, receivedBytes, out _)) var commandList = commands.GetCommands();
{ byte[] buffer = ArrayPool<byte>.Shared.Rent(8192);
return; try
} {
foreach (var command in commandList)
{
var channelMsg = CreateSetMessage(_activeTuner, command.Item1, command.Item2, _lockkey);
await stream.WriteAsync(channelMsg, 0, channelMsg.Length, cancellationToken).ConfigureAwait(false);
int receivedBytes = await stream.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false);
// parse response to make sure it worked
if (!ParseReturnMessage(buffer, receivedBytes, out _))
{
return;
} }
} }
finally }
{ finally
ArrayPool<byte>.Shared.Return(buffer); {
} ArrayPool<byte>.Shared.Return(buffer);
} }
} }

View file

@ -70,7 +70,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
try try
{ {
await tcpClient.ConnectAsync(remoteAddress, HdHomerunManager.HdHomeRunPort).ConfigureAwait(false); await tcpClient.ConnectAsync(remoteAddress, HdHomerunManager.HdHomeRunPort).ConfigureAwait(false);
localAddress = ((IPEndPoint)tcpClient.Client.RemoteEndPoint).Address; localAddress = ((IPEndPoint)tcpClient.Client.LocalEndPoint).Address;
tcpClient.Close(); tcpClient.Close();
} }
catch (Exception ex) catch (Exception ex)
@ -80,6 +80,10 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
} }
} }
if (localAddress.IsIPv4MappedToIPv6) {
localAddress = localAddress.MapToIPv4();
}
var udpClient = new UdpClient(localPort, AddressFamily.InterNetwork); var udpClient = new UdpClient(localPort, AddressFamily.InterNetwork);
var hdHomerunManager = new HdHomerunManager(); var hdHomerunManager = new HdHomerunManager();
@ -110,12 +114,12 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
var taskCompletionSource = new TaskCompletionSource<bool>(); var taskCompletionSource = new TaskCompletionSource<bool>();
await StartStreaming( _ = StartStreaming(
udpClient, udpClient,
hdHomerunManager, hdHomerunManager,
remoteAddress, remoteAddress,
taskCompletionSource, taskCompletionSource,
LiveStreamCancellationTokenSource.Token).ConfigureAwait(false); LiveStreamCancellationTokenSource.Token);
// OpenedMediaSource.Protocol = MediaProtocol.File; // OpenedMediaSource.Protocol = MediaProtocol.File;
// OpenedMediaSource.Path = tempFile; // OpenedMediaSource.Path = tempFile;
@ -136,33 +140,30 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
return TempFilePath; return TempFilePath;
} }
private Task StartStreaming(UdpClient udpClient, HdHomerunManager hdHomerunManager, IPAddress remoteAddress, TaskCompletionSource<bool> openTaskCompletionSource, CancellationToken cancellationToken) private async Task StartStreaming(UdpClient udpClient, HdHomerunManager hdHomerunManager, IPAddress remoteAddress, TaskCompletionSource<bool> openTaskCompletionSource, CancellationToken cancellationToken)
{ {
return Task.Run(async () => using (udpClient)
using (hdHomerunManager)
{ {
using (udpClient) try
using (hdHomerunManager)
{ {
try await CopyTo(udpClient, TempFilePath, openTaskCompletionSource, cancellationToken).ConfigureAwait(false);
{ }
await CopyTo(udpClient, TempFilePath, openTaskCompletionSource, cancellationToken).ConfigureAwait(false); catch (OperationCanceledException ex)
} {
catch (OperationCanceledException ex) Logger.LogInformation("HDHR UDP stream cancelled or timed out from {0}", remoteAddress);
{ openTaskCompletionSource.TrySetException(ex);
Logger.LogInformation("HDHR UDP stream cancelled or timed out from {0}", remoteAddress); }
openTaskCompletionSource.TrySetException(ex); catch (Exception ex)
} {
catch (Exception ex) Logger.LogError(ex, "Error opening live stream:");
{ openTaskCompletionSource.TrySetException(ex);
Logger.LogError(ex, "Error opening live stream:");
openTaskCompletionSource.TrySetException(ex);
}
EnableStreamSharing = false;
} }
await DeleteTempFiles(new List<string> { TempFilePath }).ConfigureAwait(false); EnableStreamSharing = false;
}); }
await DeleteTempFiles(new List<string> { TempFilePath }).ConfigureAwait(false);
} }
private async Task CopyTo(UdpClient udpClient, string file, TaskCompletionSource<bool> openTaskCompletionSource, CancellationToken cancellationToken) private async Task CopyTo(UdpClient udpClient, string file, TaskCompletionSource<bool> openTaskCompletionSource, CancellationToken cancellationToken)