mirror of
https://github.com/jellyfin/jellyfin.git
synced 2024-09-06 05:47:14 -04:00
use stream id's to close streams
This commit is contained in:
parent
c87c516ea3
commit
ca0c0bdcb9
@ -132,6 +132,7 @@ namespace MediaBrowser.Api
|
||||
/// Called when [transcode beginning].
|
||||
/// </summary>
|
||||
/// <param name="path">The path.</param>
|
||||
/// <param name="streamId">The stream identifier.</param>
|
||||
/// <param name="transcodingJobId">The transcoding job identifier.</param>
|
||||
/// <param name="type">The type.</param>
|
||||
/// <param name="process">The process.</param>
|
||||
@ -140,6 +141,7 @@ namespace MediaBrowser.Api
|
||||
/// <param name="cancellationTokenSource">The cancellation token source.</param>
|
||||
/// <returns>TranscodingJob.</returns>
|
||||
public TranscodingJob OnTranscodeBeginning(string path,
|
||||
string streamId,
|
||||
string transcodingJobId,
|
||||
TranscodingJobType type,
|
||||
Process process,
|
||||
@ -157,7 +159,8 @@ namespace MediaBrowser.Api
|
||||
ActiveRequestCount = 1,
|
||||
DeviceId = deviceId,
|
||||
CancellationTokenSource = cancellationTokenSource,
|
||||
Id = transcodingJobId
|
||||
Id = transcodingJobId,
|
||||
StreamId = streamId
|
||||
};
|
||||
|
||||
_activeTranscodingJobs.Add(job);
|
||||
@ -316,17 +319,26 @@ namespace MediaBrowser.Api
|
||||
/// Kills the single transcoding job.
|
||||
/// </summary>
|
||||
/// <param name="deviceId">The device id.</param>
|
||||
/// <param name="streamId">The stream identifier.</param>
|
||||
/// <param name="deleteFiles">The delete files.</param>
|
||||
/// <returns>Task.</returns>
|
||||
/// <exception cref="ArgumentNullException">deviceId</exception>
|
||||
internal void KillTranscodingJobs(string deviceId, Func<string, bool> deleteFiles)
|
||||
internal void KillTranscodingJobs(string deviceId, string streamId, Func<string, bool> deleteFiles)
|
||||
{
|
||||
if (string.IsNullOrEmpty(deviceId))
|
||||
{
|
||||
throw new ArgumentNullException("deviceId");
|
||||
}
|
||||
|
||||
KillTranscodingJobs(j => string.Equals(deviceId, j.DeviceId, StringComparison.OrdinalIgnoreCase), deleteFiles);
|
||||
KillTranscodingJobs(j =>
|
||||
{
|
||||
if (string.Equals(deviceId, j.DeviceId, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return string.IsNullOrWhiteSpace(streamId) || string.Equals(streamId, j.StreamId, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}, deleteFiles);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -335,7 +347,7 @@ namespace MediaBrowser.Api
|
||||
/// <param name="killJob">The kill job.</param>
|
||||
/// <param name="deleteFiles">The delete files.</param>
|
||||
/// <returns>Task.</returns>
|
||||
internal void KillTranscodingJobs(Func<TranscodingJob, bool> killJob, Func<string, bool> deleteFiles)
|
||||
private void KillTranscodingJobs(Func<TranscodingJob, bool> killJob, Func<string, bool> deleteFiles)
|
||||
{
|
||||
var jobs = new List<TranscodingJob>();
|
||||
|
||||
@ -516,6 +528,11 @@ namespace MediaBrowser.Api
|
||||
/// </summary>
|
||||
public class TranscodingJob
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the stream identifier.
|
||||
/// </summary>
|
||||
/// <value>The stream identifier.</value>
|
||||
public string StreamId { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the path.
|
||||
/// </summary>
|
||||
|
@ -134,7 +134,7 @@ namespace MediaBrowser.Api.Playback
|
||||
var data = GetCommandLineArguments("dummy\\dummy", "dummyTranscodingId", state, false);
|
||||
|
||||
data += "-" + (state.Request.DeviceId ?? string.Empty);
|
||||
data += "-" + (state.Request.ClientTime ?? string.Empty);
|
||||
data += "-" + (state.Request.StreamId ?? state.Request.ClientTime ?? string.Empty);
|
||||
|
||||
var dataHash = data.GetMD5().ToString("N");
|
||||
|
||||
@ -1054,6 +1054,7 @@ namespace MediaBrowser.Api.Playback
|
||||
}
|
||||
|
||||
var transcodingJob = ApiEntryPoint.Instance.OnTranscodeBeginning(outputPath,
|
||||
state.Request.StreamId ?? state.Request.ClientTime,
|
||||
transcodingId,
|
||||
TranscodingJobType,
|
||||
process,
|
||||
@ -1523,7 +1524,7 @@ namespace MediaBrowser.Api.Playback
|
||||
}
|
||||
else if (i == 16)
|
||||
{
|
||||
request.ClientTime = val;
|
||||
request.StreamId = val;
|
||||
}
|
||||
else if (i == 17)
|
||||
{
|
||||
|
@ -162,7 +162,7 @@ namespace MediaBrowser.Api.Playback.Dash
|
||||
// If the playlist doesn't already exist, startup ffmpeg
|
||||
try
|
||||
{
|
||||
KillTranscodingJobs(request.DeviceId, playlistPath);
|
||||
ApiEntryPoint.Instance.KillTranscodingJobs(request.DeviceId, request.StreamId, p => false);
|
||||
|
||||
if (currentTranscodingIndex.HasValue)
|
||||
{
|
||||
@ -204,11 +204,6 @@ namespace MediaBrowser.Api.Playback.Dash
|
||||
return await GetSegmentResult(playlistPath, segmentPath, requestedIndex, segmentLength, job ?? ApiEntryPoint.Instance.GetTranscodingJob(playlistPath, TranscodingJobType), cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private void KillTranscodingJobs(string deviceId, string playlistPath)
|
||||
{
|
||||
ApiEntryPoint.Instance.KillTranscodingJobs(j => j.Type == TranscodingJobType && string.Equals(j.DeviceId, deviceId, StringComparison.OrdinalIgnoreCase), p => !string.Equals(p, playlistPath, StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
private long GetPositionTicks(StreamState state, int requestedIndex)
|
||||
{
|
||||
if (requestedIndex <= 0)
|
||||
|
@ -136,7 +136,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||
// If the playlist doesn't already exist, startup ffmpeg
|
||||
try
|
||||
{
|
||||
ApiEntryPoint.Instance.KillTranscodingJobs(j => j.Type == TranscodingJobType && string.Equals(j.DeviceId, request.DeviceId, StringComparison.OrdinalIgnoreCase), p => !string.Equals(p, playlistPath, StringComparison.OrdinalIgnoreCase));
|
||||
ApiEntryPoint.Instance.KillTranscodingJobs(request.DeviceId, request.StreamId ?? request.ClientTime, p => false);
|
||||
|
||||
if (currentTranscodingIndex.HasValue)
|
||||
{
|
||||
|
@ -47,6 +47,9 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||
{
|
||||
[ApiMember(Name = "DeviceId", Description = "The device id of the client requesting. Used to stop encoding processes when needed.", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "DELETE")]
|
||||
public string DeviceId { get; set; }
|
||||
|
||||
[ApiMember(Name = "StreamId", Description = "The stream id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "DELETE")]
|
||||
public string StreamId { get; set; }
|
||||
}
|
||||
|
||||
public class HlsSegmentService : BaseApiService
|
||||
@ -69,7 +72,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||
|
||||
public void Delete(StopEncodingProcess request)
|
||||
{
|
||||
ApiEntryPoint.Instance.KillTranscodingJobs(request.DeviceId, path => true);
|
||||
ApiEntryPoint.Instance.KillTranscodingJobs(request.DeviceId, request.StreamId, path => true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -1,4 +1,5 @@
|
||||
using MediaBrowser.Controller.Library;
|
||||
using System;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.Net;
|
||||
using MediaBrowser.Model.Dlna;
|
||||
using MediaBrowser.Model.Dto;
|
||||
|
@ -71,6 +71,7 @@ namespace MediaBrowser.Api.Playback
|
||||
|
||||
public string Params { get; set; }
|
||||
public string ClientTime { get; set; }
|
||||
public string StreamId { get; set; }
|
||||
|
||||
public string TranscodingJobId { get; set; }
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
using MediaBrowser.Common;
|
||||
using MediaBrowser.Common.Configuration;
|
||||
using MediaBrowser.Common.Extensions;
|
||||
using MediaBrowser.Common.IO;
|
||||
using MediaBrowser.Common.Progress;
|
||||
using MediaBrowser.Common.ScheduledTasks;
|
||||
using MediaBrowser.Controller.Channels;
|
||||
@ -24,7 +23,6 @@ using MediaBrowser.Model.Serialization;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
@ -747,8 +745,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
||||
programs = programs.Where(p => p.IsMovie == query.IsMovie.Value);
|
||||
}
|
||||
|
||||
var serviceName = ActiveService.Name;
|
||||
|
||||
var programList = programs.ToList();
|
||||
|
||||
var genres = programList.SelectMany(i => i.Genres)
|
||||
@ -757,7 +753,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
||||
.ToDictionary(i => i.Name, StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
programs = programList.OrderBy(i => i.HasImage(ImageType.Primary) ? 0 : 1)
|
||||
.ThenByDescending(i => GetRecommendationScore(i, user.Id, serviceName, genres))
|
||||
.ThenByDescending(i => GetRecommendationScore(i, user.Id, genres))
|
||||
.ThenBy(i => i.StartDate);
|
||||
|
||||
if (query.Limit.HasValue)
|
||||
@ -807,7 +803,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
||||
return result;
|
||||
}
|
||||
|
||||
private int GetRecommendationScore(LiveTvProgram program, Guid userId, string serviceName, Dictionary<string, Genre> genres)
|
||||
private int GetRecommendationScore(LiveTvProgram program, Guid userId, Dictionary<string, Genre> genres)
|
||||
{
|
||||
var score = 0;
|
||||
|
||||
@ -821,7 +817,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
||||
score++;
|
||||
}
|
||||
|
||||
var internalChannelId = _tvDtoService.GetInternalChannelId(serviceName, program.ExternalChannelId);
|
||||
var internalChannelId = _tvDtoService.GetInternalChannelId(program.ServiceName, program.ExternalChannelId);
|
||||
var channel = GetInternalChannel(internalChannelId);
|
||||
|
||||
var channelUserdata = _userDataManager.GetUserData(userId, channel.GetUserDataKey());
|
||||
@ -879,11 +875,17 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
||||
|
||||
private async Task AddRecordingInfo(IEnumerable<ProgramInfoDto> programs, CancellationToken cancellationToken)
|
||||
{
|
||||
var timers = await ActiveService.GetTimersAsync(cancellationToken).ConfigureAwait(false);
|
||||
var timerList = timers.ToList();
|
||||
var timers = new Dictionary<string, List<TimerInfo>>();
|
||||
|
||||
foreach (var program in programs)
|
||||
{
|
||||
List<TimerInfo> timerList;
|
||||
if (!timers.TryGetValue(program.ServiceName, out timerList))
|
||||
{
|
||||
var tempTimers = await GetService(program.ServiceName).GetTimersAsync(cancellationToken).ConfigureAwait(false);
|
||||
timers[program.ServiceName] = timerList = tempTimers.ToList();
|
||||
}
|
||||
|
||||
var timer = timerList.FirstOrDefault(i => string.Equals(i.ProgramId, program.ExternalId, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
if (timer != null)
|
||||
@ -922,15 +924,43 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
||||
|
||||
private async Task RefreshChannelsInternal(IProgress<double> progress, CancellationToken cancellationToken)
|
||||
{
|
||||
// Avoid implicitly captured closure
|
||||
var service = ActiveService;
|
||||
var numComplete = 0;
|
||||
double progressPerService = _services.Count == 0
|
||||
? 0
|
||||
: 1 / _services.Count;
|
||||
|
||||
if (service == null)
|
||||
foreach (var service in _services)
|
||||
{
|
||||
progress.Report(100);
|
||||
return;
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
try
|
||||
{
|
||||
var innerProgress = new ActionableProgress<double>();
|
||||
innerProgress.RegisterAction(p => progress.Report(p * progressPerService));
|
||||
|
||||
await RefreshChannelsInternal(service, innerProgress, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.ErrorException("Error refreshing channels for service", ex);
|
||||
}
|
||||
|
||||
numComplete++;
|
||||
double percent = numComplete;
|
||||
percent /= _services.Count;
|
||||
|
||||
progress.Report(100 * percent);
|
||||
}
|
||||
|
||||
progress.Report(100);
|
||||
}
|
||||
|
||||
private async Task RefreshChannelsInternal(ILiveTvService service, IProgress<double> progress, CancellationToken cancellationToken)
|
||||
{
|
||||
progress.Report(10);
|
||||
|
||||
var allChannels = await GetChannels(service, cancellationToken).ConfigureAwait(false);
|
||||
@ -1192,16 +1222,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
||||
|
||||
public async Task<QueryResult<RecordingInfoDto>> GetRecordings(RecordingQuery query, CancellationToken cancellationToken)
|
||||
{
|
||||
var service = ActiveService;
|
||||
|
||||
if (service == null)
|
||||
{
|
||||
return new QueryResult<RecordingInfoDto>
|
||||
{
|
||||
Items = new RecordingInfoDto[] { }
|
||||
};
|
||||
}
|
||||
|
||||
var user = string.IsNullOrEmpty(query.UserId) ? null : _userManager.GetUserById(query.UserId);
|
||||
|
||||
var internalResult = await GetInternalRecordings(query, cancellationToken).ConfigureAwait(false);
|
||||
@ -1209,6 +1229,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
||||
var returnArray = internalResult.Items.Cast<ILiveTvRecording>()
|
||||
.Select(i =>
|
||||
{
|
||||
var service = GetService(i);
|
||||
|
||||
var channel = string.IsNullOrEmpty(i.RecordingInfo.ChannelId) ? null : GetInternalChannel(_tvDtoService.GetInternalChannelId(service.Name, i.RecordingInfo.ChannelId));
|
||||
return _tvDtoService.GetRecordingInfoDto(i, channel, service, user);
|
||||
})
|
||||
@ -1413,8 +1435,12 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
||||
return program;
|
||||
}
|
||||
|
||||
private async Task<SeriesTimerInfo> GetNewTimerDefaultsInternal(CancellationToken cancellationToken, LiveTvProgram program = null)
|
||||
private async Task<Tuple<SeriesTimerInfo,ILiveTvService>> GetNewTimerDefaultsInternal(CancellationToken cancellationToken, LiveTvProgram program = null)
|
||||
{
|
||||
var service = program != null && !string.IsNullOrWhiteSpace(program.ServiceName) ?
|
||||
GetService(program) :
|
||||
_services.FirstOrDefault();
|
||||
|
||||
ProgramInfo programInfo = null;
|
||||
|
||||
if (program != null)
|
||||
@ -1448,18 +1474,18 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
||||
};
|
||||
}
|
||||
|
||||
var info = await ActiveService.GetNewTimerDefaultsAsync(cancellationToken, programInfo).ConfigureAwait(false);
|
||||
var info = await service.GetNewTimerDefaultsAsync(cancellationToken, programInfo).ConfigureAwait(false);
|
||||
|
||||
info.Id = null;
|
||||
|
||||
return info;
|
||||
return new Tuple<SeriesTimerInfo, ILiveTvService>(info, service);
|
||||
}
|
||||
|
||||
public async Task<SeriesTimerInfoDto> GetNewTimerDefaults(CancellationToken cancellationToken)
|
||||
{
|
||||
var info = await GetNewTimerDefaultsInternal(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
var obj = _tvDtoService.GetSeriesTimerInfoDto(info, ActiveService, null);
|
||||
var obj = _tvDtoService.GetSeriesTimerInfoDto(info.Item1, info.Item2, null);
|
||||
|
||||
return obj;
|
||||
}
|
||||
@ -1470,7 +1496,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
||||
var programDto = await GetProgram(programId, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
var defaults = await GetNewTimerDefaultsInternal(cancellationToken, program).ConfigureAwait(false);
|
||||
var info = _tvDtoService.GetSeriesTimerInfoDto(defaults, ActiveService, null);
|
||||
var info = _tvDtoService.GetSeriesTimerInfoDto(defaults.Item1, defaults.Item2, null);
|
||||
|
||||
info.Days = new List<DayOfWeek>
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user