|
|
@ -210,8 +210,6 @@ namespace MediaBrowser.Api.Playback.Hls
|
|
|
|
{
|
|
|
|
{
|
|
|
|
ApiEntryPoint.Instance.KillTranscodingJobs(request.DeviceId, request.PlaySessionId, p => false);
|
|
|
|
ApiEntryPoint.Instance.KillTranscodingJobs(request.DeviceId, request.PlaySessionId, p => false);
|
|
|
|
|
|
|
|
|
|
|
|
await ReadSegmentLengths(playlistPath).ConfigureAwait(false);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (currentTranscodingIndex.HasValue)
|
|
|
|
if (currentTranscodingIndex.HasValue)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
DeleteLastFile(playlistPath, segmentExtension, 0);
|
|
|
|
DeleteLastFile(playlistPath, segmentExtension, 0);
|
|
|
@ -255,55 +253,8 @@ namespace MediaBrowser.Api.Playback.Hls
|
|
|
|
return await GetSegmentResult(playlistPath, segmentPath, requestedIndex, segmentLength, job, cancellationToken).ConfigureAwait(false);
|
|
|
|
return await GetSegmentResult(playlistPath, segmentPath, requestedIndex, segmentLength, job, cancellationToken).ConfigureAwait(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private static readonly ConcurrentDictionary<string, double> SegmentLengths = new ConcurrentDictionary<string, double>(StringComparer.OrdinalIgnoreCase);
|
|
|
|
// 256k
|
|
|
|
private async Task ReadSegmentLengths(string playlist)
|
|
|
|
private const int BufferSize = 262144;
|
|
|
|
{
|
|
|
|
|
|
|
|
try
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
using (var fileStream = GetPlaylistFileStream(playlist))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
using (var reader = new StreamReader(fileStream))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
double duration = -1;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
while (!reader.EndOfStream)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
var text = await reader.ReadLineAsync().ConfigureAwait(false);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (text.StartsWith("#EXTINF", StringComparison.OrdinalIgnoreCase))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
var parts = text.Split(new[] { ':' }, 2);
|
|
|
|
|
|
|
|
if (parts.Length == 2)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
var time = parts[1].Trim(new[] { ',' }).Trim();
|
|
|
|
|
|
|
|
double timeValue;
|
|
|
|
|
|
|
|
if (double.TryParse(time, NumberStyles.Any, CultureInfo.InvariantCulture, out timeValue))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
duration = timeValue;
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (duration != -1)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
SegmentLengths.AddOrUpdate(text, duration, (k, v) => duration);
|
|
|
|
|
|
|
|
Logger.Debug("Added segment length of {0} for {1}", duration, text);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
duration = -1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
catch (DirectoryNotFoundException)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
catch (FileNotFoundException)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private long GetSeekPositionTicks(StreamState state, string playlist, int requestedIndex)
|
|
|
|
private long GetSeekPositionTicks(StreamState state, string playlist, int requestedIndex)
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -455,11 +406,9 @@ namespace MediaBrowser.Api.Playback.Hls
|
|
|
|
{
|
|
|
|
{
|
|
|
|
using (var fileStream = GetPlaylistFileStream(playlistPath))
|
|
|
|
using (var fileStream = GetPlaylistFileStream(playlistPath))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
using (var reader = new StreamReader(fileStream))
|
|
|
|
using (var reader = new StreamReader(fileStream, Encoding.UTF8, true, BufferSize))
|
|
|
|
{
|
|
|
|
|
|
|
|
while (!reader.EndOfStream)
|
|
|
|
|
|
|
|
{
|
|
|
|
{
|
|
|
|
var text = await reader.ReadLineAsync().ConfigureAwait(false);
|
|
|
|
var text = await reader.ReadToEndAsync().ConfigureAwait(false);
|
|
|
|
|
|
|
|
|
|
|
|
// If it appears in the playlist, it's done
|
|
|
|
// If it appears in the playlist, it's done
|
|
|
|
if (text.IndexOf(segmentFilename, StringComparison.OrdinalIgnoreCase) != -1)
|
|
|
|
if (text.IndexOf(segmentFilename, StringComparison.OrdinalIgnoreCase) != -1)
|
|
|
@ -468,8 +417,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
|
|
|
{
|
|
|
|
{
|
|
|
|
return GetSegmentResult(segmentPath, segmentIndex, segmentLength, transcodingJob);
|
|
|
|
return GetSegmentResult(segmentPath, segmentIndex, segmentLength, transcodingJob);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
//break;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|