diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index c1e1bf2b62..50cb68a95e 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 03c21b1202..477eef7ab0 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 ff6c0fb2c9..7c767c1417 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