jellyfin/Emby.Server.Implementations/LiveTv/TunerHosts/MulticastStream.cs

108 lines
3.2 KiB
C#
Raw Normal View History

2016-10-07 15:08:13 +00:00
using System;
2017-02-01 20:55:56 +00:00
using System.Collections.Concurrent;
2016-10-07 15:08:13 +00:00
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Model.Logging;
2016-11-03 23:35:19 +00:00
namespace Emby.Server.Implementations.LiveTv.TunerHosts
2016-10-07 15:08:13 +00:00
{
public class MulticastStream
{
2017-02-01 20:55:56 +00:00
private readonly ConcurrentDictionary<Guid,QueueStream> _outputStreams = new ConcurrentDictionary<Guid, QueueStream>();
2016-10-07 15:08:13 +00:00
private const int BufferSize = 81920;
private CancellationToken _cancellationToken;
private readonly ILogger _logger;
2017-02-01 20:55:56 +00:00
private readonly ConcurrentQueue<byte[]> _sharedBuffer = new ConcurrentQueue<byte[]>();
2016-10-07 15:08:13 +00:00
public MulticastStream(ILogger logger)
{
_logger = logger;
}
public async Task CopyUntilCancelled(Stream source, Action onStarted, CancellationToken cancellationToken)
{
_cancellationToken = cancellationToken;
2016-11-23 06:54:09 +00:00
byte[] buffer = new byte[BufferSize];
2016-10-07 15:08:13 +00:00
while (!cancellationToken.IsCancellationRequested)
{
var bytesRead = await source.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false);
if (bytesRead > 0)
{
byte[] copy = new byte[bytesRead];
Buffer.BlockCopy(buffer, 0, copy, 0, bytesRead);
2017-02-01 20:55:56 +00:00
_sharedBuffer.Enqueue(copy);
while (_sharedBuffer.Count > 3000)
2016-10-07 15:08:13 +00:00
{
2017-02-01 20:55:56 +00:00
byte[] bytes;
_sharedBuffer.TryDequeue(out bytes);
2016-10-07 15:08:13 +00:00
}
2017-02-01 20:55:56 +00:00
var allStreams = _outputStreams.ToList();
foreach (var stream in allStreams)
2016-10-07 15:08:13 +00:00
{
2017-02-01 20:55:56 +00:00
stream.Value.Queue(copy);
2016-10-07 15:08:13 +00:00
}
if (onStarted != null)
{
var onStartedCopy = onStarted;
onStarted = null;
Task.Run(onStartedCopy);
}
}
else
{
await Task.Delay(100).ConfigureAwait(false);
}
}
}
public Task CopyToAsync(Stream stream)
{
var result = new QueueStream(stream, _logger)
{
OnFinished = OnFinished
};
2017-02-01 20:55:56 +00:00
var initial = _sharedBuffer.ToList();
var list = new List<byte>();
foreach (var bytes in initial)
2016-10-07 15:08:13 +00:00
{
2017-02-01 20:55:56 +00:00
list.AddRange(bytes);
2016-10-07 15:08:13 +00:00
}
2017-02-01 20:55:56 +00:00
_logger.Info("QueueStream started with {0} initial bytes", list.Count);
result.Queue(list.ToArray());
_outputStreams.TryAdd(result.Id, result);
2016-10-07 15:08:13 +00:00
result.Start(_cancellationToken);
return result.TaskCompletion.Task;
}
public void RemoveOutputStream(QueueStream stream)
{
2017-02-01 20:55:56 +00:00
QueueStream removed;
_outputStreams.TryRemove(stream.Id, out removed);
2016-10-07 15:08:13 +00:00
}
private void OnFinished(QueueStream queueStream)
{
RemoveOutputStream(queueStream);
}
}
}