improve video startup performance
This commit is contained in:
parent
1d849e3f25
commit
30538f0731
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
@ -11,10 +12,11 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
|||
{
|
||||
public class MulticastStream
|
||||
{
|
||||
private readonly List<QueueStream> _outputStreams = new List<QueueStream>();
|
||||
private readonly ConcurrentDictionary<Guid,QueueStream> _outputStreams = new ConcurrentDictionary<Guid, QueueStream>();
|
||||
private const int BufferSize = 81920;
|
||||
private CancellationToken _cancellationToken;
|
||||
private readonly ILogger _logger;
|
||||
private readonly ConcurrentQueue<byte[]> _sharedBuffer = new ConcurrentQueue<byte[]>();
|
||||
|
||||
public MulticastStream(ILogger logger)
|
||||
{
|
||||
|
@ -35,17 +37,19 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
|||
{
|
||||
byte[] copy = new byte[bytesRead];
|
||||
Buffer.BlockCopy(buffer, 0, copy, 0, bytesRead);
|
||||
|
||||
List<QueueStream> streams = null;
|
||||
|
||||
lock (_outputStreams)
|
||||
_sharedBuffer.Enqueue(copy);
|
||||
|
||||
while (_sharedBuffer.Count > 3000)
|
||||
{
|
||||
streams = _outputStreams.ToList();
|
||||
byte[] bytes;
|
||||
_sharedBuffer.TryDequeue(out bytes);
|
||||
}
|
||||
|
||||
foreach (var stream in streams)
|
||||
var allStreams = _outputStreams.ToList();
|
||||
foreach (var stream in allStreams)
|
||||
{
|
||||
stream.Queue(copy);
|
||||
stream.Value.Queue(copy);
|
||||
}
|
||||
|
||||
if (onStarted != null)
|
||||
|
@ -70,11 +74,20 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
|||
OnFinished = OnFinished
|
||||
};
|
||||
|
||||
lock (_outputStreams)
|
||||
var initial = _sharedBuffer.ToList();
|
||||
var list = new List<byte>();
|
||||
|
||||
foreach (var bytes in initial)
|
||||
{
|
||||
_outputStreams.Add(result);
|
||||
list.AddRange(bytes);
|
||||
}
|
||||
|
||||
_logger.Info("QueueStream started with {0} initial bytes", list.Count);
|
||||
|
||||
result.Queue(list.ToArray());
|
||||
|
||||
_outputStreams.TryAdd(result.Id, result);
|
||||
|
||||
result.Start(_cancellationToken);
|
||||
|
||||
return result.TaskCompletion.Task;
|
||||
|
@ -82,10 +95,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
|||
|
||||
public void RemoveOutputStream(QueueStream stream)
|
||||
{
|
||||
lock (_outputStreams)
|
||||
{
|
||||
_outputStreams.Remove(stream);
|
||||
}
|
||||
QueueStream removed;
|
||||
_outputStreams.TryRemove(stream.Id, out removed);
|
||||
}
|
||||
|
||||
private void OnFinished(QueueStream queueStream)
|
||||
|
|
|
@ -19,7 +19,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
|||
|
||||
public Action<QueueStream> OnFinished { get; set; }
|
||||
private readonly ILogger _logger;
|
||||
private bool _isActive;
|
||||
public Guid Id = Guid.NewGuid();
|
||||
|
||||
public QueueStream(Stream outputStream, ILogger logger)
|
||||
{
|
||||
|
@ -30,10 +30,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
|||
|
||||
public void Queue(byte[] bytes)
|
||||
{
|
||||
if (_isActive)
|
||||
{
|
||||
_queue.Enqueue(bytes);
|
||||
}
|
||||
_queue.Enqueue(bytes);
|
||||
}
|
||||
|
||||
public void Start(CancellationToken cancellationToken)
|
||||
|
@ -59,10 +56,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
|||
|
||||
try
|
||||
{
|
||||
while (!cancellationToken.IsCancellationRequested)
|
||||
while (true)
|
||||
{
|
||||
_isActive = true;
|
||||
|
||||
var bytes = Dequeue();
|
||||
if (bytes != null)
|
||||
{
|
||||
|
@ -73,9 +68,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
|||
await Task.Delay(50, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
TaskCompletion.TrySetResult(true);
|
||||
_logger.Debug("QueueStream complete");
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
|
@ -89,8 +81,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
|||
}
|
||||
finally
|
||||
{
|
||||
_isActive = false;
|
||||
|
||||
if (OnFinished != null)
|
||||
{
|
||||
OnFinished(this);
|
||||
|
|
|
@ -2720,6 +2720,15 @@ namespace MediaBrowser.Api.Playback
|
|||
//inputModifier += " -noaccurate_seek";
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(state.InputContainer))
|
||||
{
|
||||
var inputFormat = GetInputFormat(state.InputContainer);
|
||||
if (!string.IsNullOrWhiteSpace(inputFormat))
|
||||
{
|
||||
inputModifier += " -f " + inputFormat;
|
||||
}
|
||||
}
|
||||
|
||||
if (state.RunTimeTicks.HasValue)
|
||||
{
|
||||
foreach (var stream in state.MediaSource.MediaStreams)
|
||||
|
@ -2738,23 +2747,21 @@ namespace MediaBrowser.Api.Playback
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
//var videoStream = state.VideoStream;
|
||||
//if (videoStream != null && !string.IsNullOrWhiteSpace(videoStream.Codec))
|
||||
//{
|
||||
// inputModifier += " -codec:0 " + videoStream.Codec;
|
||||
|
||||
// var audioStream = state.AudioStream;
|
||||
// if (audioStream != null && !string.IsNullOrWhiteSpace(audioStream.Codec))
|
||||
// {
|
||||
// inputModifier += " -codec:1 " + audioStream.Codec;
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
return inputModifier;
|
||||
}
|
||||
|
||||
private string GetInputFormat(string container)
|
||||
{
|
||||
if (string.Equals(container, "mkv", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return "matroska";
|
||||
}
|
||||
|
||||
return container;
|
||||
}
|
||||
|
||||
private string GetDecoderFromCodec(string codec)
|
||||
{
|
||||
if (string.Equals(codec, "mp2", StringComparison.OrdinalIgnoreCase))
|
||||
|
|
|
@ -103,7 +103,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||
throw;
|
||||
}
|
||||
|
||||
var waitForSegments = state.SegmentLength >= 10 ? 2 : 3;
|
||||
var waitForSegments = state.SegmentLength >= 10 ? 2 : 2;
|
||||
await WaitForMinimumSegmentCount(playlist, waitForSegments, cancellationTokenSource.Token).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user