From 8b9e7e1f59334f4bbecc8d4be19653d70b42a3be Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 23 May 2017 12:44:11 -0400 Subject: [PATCH] rework hdhr udp stream --- .../TunerHosts/HdHomerun/HdHomerunHost.cs | 3 +- .../HdHomerun/HdHomerunHttpStream.cs | 4 +-- .../HdHomerun/HdHomerunUdpStream.cs | 35 +++++++++++++------ 3 files changed, 29 insertions(+), 13 deletions(-) diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index c1e1bf2b6..50cb68a95 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -422,7 +422,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun SupportsTranscoding = true, IsInfiniteStream = true, IgnoreDts = true, - IgnoreIndex = true + //IgnoreIndex = true, + //ReadAtNativeFramerate = true }; mediaSource.InferTotalBitrate(); diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHttpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHttpStream.cs index 03c21b120..477eef7ab 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHttpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHttpStream.cs @@ -101,9 +101,9 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun _logger.Info("Beginning multicastStream.CopyUntilCancelled"); FileSystem.CreateDirectory(FileSystem.GetDirectoryName(_tempFilePath)); - using (var fileStream = FileSystem.GetFileStream(_tempFilePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, FileOpenOptions.Asynchronous | FileOpenOptions.SequentialScan)) + using (var fileStream = FileSystem.GetFileStream(_tempFilePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, FileOpenOptions.Asynchronous)) { - ResolveAfterDelay(2000, openTaskCompletionSource); + ResolveAfterDelay(3000, openTaskCompletionSource); await response.Content.CopyToAsync(fileStream, 81920, cancellationToken).ConfigureAwait(false); } diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs index ff6c0fb2c..7c767c141 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs @@ -121,11 +121,9 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun if (!cancellationToken.IsCancellationRequested) { FileSystem.CreateDirectory(FileSystem.GetDirectoryName(_tempFilePath)); - using (var fileStream = FileSystem.GetFileStream(_tempFilePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, FileOpenOptions.Asynchronous | FileOpenOptions.SequentialScan)) + using (var fileStream = FileSystem.GetFileStream(_tempFilePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, FileOpenOptions.Asynchronous)) { - ResolveAfterDelay(2000, openTaskCompletionSource); - - await new UdpClientStream(udpClient).CopyToAsync(fileStream, 81920, cancellationToken).ConfigureAwait(false); + await CopyTo(udpClient, fileStream, openTaskCompletionSource, cancellationToken).ConfigureAwait(false); } } } @@ -159,19 +157,36 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun }); } - private void ResolveAfterDelay(int delayMs, TaskCompletionSource openTaskCompletionSource) + private void Resolve(TaskCompletionSource openTaskCompletionSource) { - Task.Run(async () => - { - await Task.Delay(delayMs).ConfigureAwait(false); - openTaskCompletionSource.TrySetResult(true); - }); + Task.Run(() => + { + openTaskCompletionSource.TrySetResult(true); + }); } public Task CopyToAsync(Stream stream, CancellationToken cancellationToken) { return CopyFileTo(_tempFilePath, false, stream, cancellationToken); } + + private static int RtpHeaderBytes = 12; + private async Task CopyTo(ISocket udpClient, Stream outputStream, TaskCompletionSource openTaskCompletionSource, CancellationToken cancellationToken) + { + while (true) + { + var data = await udpClient.ReceiveAsync(cancellationToken).ConfigureAwait(false); + var bytesRead = data.ReceivedBytes - RtpHeaderBytes; + + await outputStream.WriteAsync(data.Buffer, RtpHeaderBytes, bytesRead, cancellationToken).ConfigureAwait(false); + + if (openTaskCompletionSource != null) + { + Resolve(openTaskCompletionSource); + openTaskCompletionSource = null; + } + } + } } // This handles the ReadAsync function only of a Stream object