diff options
| author | Brian Howe <howe.m.brian@gmail.com> | 2024-02-27 21:07:30 -0600 |
|---|---|---|
| committer | Brian Howe <howe.m.brian@gmail.com> | 2024-02-27 21:07:30 -0600 |
| commit | 54eb81395ef8d3d4cb064b56361ce94fc72b38b5 (patch) | |
| tree | 73240b556055557b0ae034ef5d5ba60cb5cb051e /Jellyfin.Api/Models | |
| parent | 7f1fec688cc1a6f7f69fa5b059af01cf9c456d3f (diff) | |
| parent | 4786901bb796c3e912f13b686571fde8d16f49c5 (diff) | |
Merge branch 'master' into bhowe34/fix-replace-missing-metadata-for-music
Diffstat (limited to 'Jellyfin.Api/Models')
8 files changed, 6 insertions, 779 deletions
diff --git a/Jellyfin.Api/Models/PlaybackDtos/TranscodingJobDto.cs b/Jellyfin.Api/Models/PlaybackDtos/TranscodingJobDto.cs deleted file mode 100644 index 480ddab09..000000000 --- a/Jellyfin.Api/Models/PlaybackDtos/TranscodingJobDto.cs +++ /dev/null @@ -1,283 +0,0 @@ -using System; -using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; -using System.Threading; -using MediaBrowser.Controller.MediaEncoding; -using MediaBrowser.Model.Dto; -using Microsoft.Extensions.Logging; - -namespace Jellyfin.Api.Models.PlaybackDtos; - -/// <summary> -/// Class TranscodingJob. -/// </summary> -public class TranscodingJobDto : IDisposable -{ - /// <summary> - /// The process lock. - /// </summary> - [SuppressMessage("Microsoft.Performance", "CA1051:NoVisibleInstanceFields", MessageId = "ProcessLock", Justification = "Imported from ServiceStack")] - [SuppressMessage("Microsoft.Performance", "SA1401:PrivateField", MessageId = "ProcessLock", Justification = "Imported from ServiceStack")] - public readonly object ProcessLock = new object(); - - /// <summary> - /// Timer lock. - /// </summary> - private readonly object _timerLock = new object(); - - /// <summary> - /// Initializes a new instance of the <see cref="TranscodingJobDto"/> class. - /// </summary> - /// <param name="logger">Instance of the <see cref="ILogger{TranscodingJobDto}"/> interface.</param> - public TranscodingJobDto(ILogger<TranscodingJobDto> logger) - { - Logger = logger; - } - - /// <summary> - /// Gets or sets the play session identifier. - /// </summary> - /// <value>The play session identifier.</value> - public string? PlaySessionId { get; set; } - - /// <summary> - /// Gets or sets the live stream identifier. - /// </summary> - /// <value>The live stream identifier.</value> - public string? LiveStreamId { get; set; } - - /// <summary> - /// Gets or sets a value indicating whether is live output. - /// </summary> - public bool IsLiveOutput { get; set; } - - /// <summary> - /// Gets or sets the path. - /// </summary> - /// <value>The path.</value> - public MediaSourceInfo? MediaSource { get; set; } - - /// <summary> - /// Gets or sets path. - /// </summary> - public string? Path { get; set; } - - /// <summary> - /// Gets or sets the type. - /// </summary> - /// <value>The type.</value> - public TranscodingJobType Type { get; set; } - - /// <summary> - /// Gets or sets the process. - /// </summary> - /// <value>The process.</value> - public Process? Process { get; set; } - - /// <summary> - /// Gets logger. - /// </summary> - public ILogger<TranscodingJobDto> Logger { get; private set; } - - /// <summary> - /// Gets or sets the active request count. - /// </summary> - /// <value>The active request count.</value> - public int ActiveRequestCount { get; set; } - - /// <summary> - /// Gets or sets the kill timer. - /// </summary> - /// <value>The kill timer.</value> - private Timer? KillTimer { get; set; } - - /// <summary> - /// Gets or sets device id. - /// </summary> - public string? DeviceId { get; set; } - - /// <summary> - /// Gets or sets cancellation token source. - /// </summary> - public CancellationTokenSource? CancellationTokenSource { get; set; } - - /// <summary> - /// Gets or sets a value indicating whether has exited. - /// </summary> - public bool HasExited { get; set; } - - /// <summary> - /// Gets or sets exit code. - /// </summary> - public int ExitCode { get; set; } - - /// <summary> - /// Gets or sets a value indicating whether is user paused. - /// </summary> - public bool IsUserPaused { get; set; } - - /// <summary> - /// Gets or sets id. - /// </summary> - public string? Id { get; set; } - - /// <summary> - /// Gets or sets framerate. - /// </summary> - public float? Framerate { get; set; } - - /// <summary> - /// Gets or sets completion percentage. - /// </summary> - public double? CompletionPercentage { get; set; } - - /// <summary> - /// Gets or sets bytes downloaded. - /// </summary> - public long BytesDownloaded { get; set; } - - /// <summary> - /// Gets or sets bytes transcoded. - /// </summary> - public long? BytesTranscoded { get; set; } - - /// <summary> - /// Gets or sets bit rate. - /// </summary> - public int? BitRate { get; set; } - - /// <summary> - /// Gets or sets transcoding position ticks. - /// </summary> - public long? TranscodingPositionTicks { get; set; } - - /// <summary> - /// Gets or sets download position ticks. - /// </summary> - public long? DownloadPositionTicks { get; set; } - - /// <summary> - /// Gets or sets transcoding throttler. - /// </summary> - public TranscodingThrottler? TranscodingThrottler { get; set; } - - /// <summary> - /// Gets or sets last ping date. - /// </summary> - public DateTime LastPingDate { get; set; } - - /// <summary> - /// Gets or sets ping timeout. - /// </summary> - public int PingTimeout { get; set; } - - /// <summary> - /// Stop kill timer. - /// </summary> - public void StopKillTimer() - { - lock (_timerLock) - { - KillTimer?.Change(Timeout.Infinite, Timeout.Infinite); - } - } - - /// <summary> - /// Dispose kill timer. - /// </summary> - public void DisposeKillTimer() - { - lock (_timerLock) - { - if (KillTimer is not null) - { - KillTimer.Dispose(); - KillTimer = null; - } - } - } - - /// <summary> - /// Start kill timer. - /// </summary> - /// <param name="callback">Callback action.</param> - public void StartKillTimer(Action<object?> callback) - { - StartKillTimer(callback, PingTimeout); - } - - /// <summary> - /// Start kill timer. - /// </summary> - /// <param name="callback">Callback action.</param> - /// <param name="intervalMs">Callback interval.</param> - public void StartKillTimer(Action<object?> callback, int intervalMs) - { - if (HasExited) - { - return; - } - - lock (_timerLock) - { - if (KillTimer is null) - { - Logger.LogDebug("Starting kill timer at {0}ms. JobId {1} PlaySessionId {2}", intervalMs, Id, PlaySessionId); - KillTimer = new Timer(new TimerCallback(callback), this, intervalMs, Timeout.Infinite); - } - else - { - Logger.LogDebug("Changing kill timer to {0}ms. JobId {1} PlaySessionId {2}", intervalMs, Id, PlaySessionId); - KillTimer.Change(intervalMs, Timeout.Infinite); - } - } - } - - /// <summary> - /// Change kill timer if started. - /// </summary> - public void ChangeKillTimerIfStarted() - { - if (HasExited) - { - return; - } - - lock (_timerLock) - { - if (KillTimer is not null) - { - var intervalMs = PingTimeout; - - Logger.LogDebug("Changing kill timer to {0}ms. JobId {1} PlaySessionId {2}", intervalMs, Id, PlaySessionId); - KillTimer.Change(intervalMs, Timeout.Infinite); - } - } - } - - /// <inheritdoc /> - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - /// <summary> - /// Dispose all resources. - /// </summary> - /// <param name="disposing">Whether to dispose all resources.</param> - protected virtual void Dispose(bool disposing) - { - if (disposing) - { - Process?.Dispose(); - Process = null; - KillTimer?.Dispose(); - KillTimer = null; - CancellationTokenSource?.Dispose(); - CancellationTokenSource = null; - TranscodingThrottler?.Dispose(); - TranscodingThrottler = null; - } - } -} diff --git a/Jellyfin.Api/Models/PlaybackDtos/TranscodingThrottler.cs b/Jellyfin.Api/Models/PlaybackDtos/TranscodingThrottler.cs deleted file mode 100644 index b577c4ea6..000000000 --- a/Jellyfin.Api/Models/PlaybackDtos/TranscodingThrottler.cs +++ /dev/null @@ -1,219 +0,0 @@ -using System; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Common.Configuration; -using MediaBrowser.Controller.MediaEncoding; -using MediaBrowser.Model.Configuration; -using MediaBrowser.Model.IO; -using Microsoft.Extensions.Logging; - -namespace Jellyfin.Api.Models.PlaybackDtos; - -/// <summary> -/// Transcoding throttler. -/// </summary> -public class TranscodingThrottler : IDisposable -{ - private readonly TranscodingJobDto _job; - private readonly ILogger<TranscodingThrottler> _logger; - private readonly IConfigurationManager _config; - private readonly IFileSystem _fileSystem; - private readonly IMediaEncoder _mediaEncoder; - private Timer? _timer; - private bool _isPaused; - - /// <summary> - /// Initializes a new instance of the <see cref="TranscodingThrottler"/> class. - /// </summary> - /// <param name="job">Transcoding job dto.</param> - /// <param name="logger">Instance of the <see cref="ILogger{TranscodingThrottler}"/> interface.</param> - /// <param name="config">Instance of the <see cref="IConfigurationManager"/> interface.</param> - /// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param> - /// <param name="mediaEncoder">Instance of the <see cref="IMediaEncoder"/> interface.</param> - public TranscodingThrottler(TranscodingJobDto job, ILogger<TranscodingThrottler> logger, IConfigurationManager config, IFileSystem fileSystem, IMediaEncoder mediaEncoder) - { - _job = job; - _logger = logger; - _config = config; - _fileSystem = fileSystem; - _mediaEncoder = mediaEncoder; - } - - /// <summary> - /// Start timer. - /// </summary> - public void Start() - { - _timer = new Timer(TimerCallback, null, 5000, 5000); - } - - /// <summary> - /// Unpause transcoding. - /// </summary> - /// <returns>A <see cref="Task"/>.</returns> - public async Task UnpauseTranscoding() - { - if (_isPaused) - { - _logger.LogDebug("Sending resume command to ffmpeg"); - - try - { - var resumeKey = _mediaEncoder.IsPkeyPauseSupported ? "u" : Environment.NewLine; - await _job.Process!.StandardInput.WriteAsync(resumeKey).ConfigureAwait(false); - _isPaused = false; - } - catch (Exception ex) - { - _logger.LogError(ex, "Error resuming transcoding"); - } - } - } - - /// <summary> - /// Stop throttler. - /// </summary> - /// <returns>A <see cref="Task"/>.</returns> - public async Task Stop() - { - DisposeTimer(); - await UnpauseTranscoding().ConfigureAwait(false); - } - - /// <summary> - /// Dispose throttler. - /// </summary> - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - /// <summary> - /// Dispose throttler. - /// </summary> - /// <param name="disposing">Disposing.</param> - protected virtual void Dispose(bool disposing) - { - if (disposing) - { - DisposeTimer(); - } - } - - private EncodingOptions GetOptions() - { - return _config.GetEncodingOptions(); - } - - private async void TimerCallback(object? state) - { - if (_job.HasExited) - { - DisposeTimer(); - return; - } - - var options = GetOptions(); - - if (options.EnableThrottling && IsThrottleAllowed(_job, options.ThrottleDelaySeconds)) - { - await PauseTranscoding().ConfigureAwait(false); - } - else - { - await UnpauseTranscoding().ConfigureAwait(false); - } - } - - private async Task PauseTranscoding() - { - if (!_isPaused) - { - var pauseKey = _mediaEncoder.IsPkeyPauseSupported ? "p" : "c"; - - _logger.LogDebug("Sending pause command [{Key}] to ffmpeg", pauseKey); - - try - { - await _job.Process!.StandardInput.WriteAsync(pauseKey).ConfigureAwait(false); - _isPaused = true; - } - catch (Exception ex) - { - _logger.LogError(ex, "Error pausing transcoding"); - } - } - } - - private bool IsThrottleAllowed(TranscodingJobDto job, int thresholdSeconds) - { - var bytesDownloaded = job.BytesDownloaded; - var transcodingPositionTicks = job.TranscodingPositionTicks ?? 0; - var downloadPositionTicks = job.DownloadPositionTicks ?? 0; - - var path = job.Path ?? throw new ArgumentException("Path can't be null."); - - var gapLengthInTicks = TimeSpan.FromSeconds(thresholdSeconds).Ticks; - - if (downloadPositionTicks > 0 && transcodingPositionTicks > 0) - { - // HLS - time-based consideration - - var targetGap = gapLengthInTicks; - var gap = transcodingPositionTicks - downloadPositionTicks; - - if (gap < targetGap) - { - _logger.LogDebug("Not throttling transcoder gap {0} target gap {1}", gap, targetGap); - return false; - } - - _logger.LogDebug("Throttling transcoder gap {0} target gap {1}", gap, targetGap); - return true; - } - - if (bytesDownloaded > 0 && transcodingPositionTicks > 0) - { - // Progressive Streaming - byte-based consideration - - try - { - var bytesTranscoded = job.BytesTranscoded ?? _fileSystem.GetFileInfo(path).Length; - - // Estimate the bytes the transcoder should be ahead - double gapFactor = gapLengthInTicks; - gapFactor /= transcodingPositionTicks; - var targetGap = bytesTranscoded * gapFactor; - - var gap = bytesTranscoded - bytesDownloaded; - - if (gap < targetGap) - { - _logger.LogDebug("Not throttling transcoder gap {0} target gap {1} bytes downloaded {2}", gap, targetGap, bytesDownloaded); - return false; - } - - _logger.LogDebug("Throttling transcoder gap {0} target gap {1} bytes downloaded {2}", gap, targetGap, bytesDownloaded); - return true; - } - catch (Exception ex) - { - _logger.LogError(ex, "Error getting output size"); - return false; - } - } - - _logger.LogDebug("No throttle data for {Path}", path); - return false; - } - - private void DisposeTimer() - { - if (_timer is not null) - { - _timer.Dispose(); - _timer = null; - } - } -} diff --git a/Jellyfin.Api/Models/SessionDtos/ClientCapabilitiesDto.cs b/Jellyfin.Api/Models/SessionDtos/ClientCapabilitiesDto.cs index b021771a0..acd3f29e3 100644 --- a/Jellyfin.Api/Models/SessionDtos/ClientCapabilitiesDto.cs +++ b/Jellyfin.Api/Models/SessionDtos/ClientCapabilitiesDto.cs @@ -31,26 +31,11 @@ public class ClientCapabilitiesDto public bool SupportsMediaControl { get; set; } /// <summary> - /// Gets or sets a value indicating whether session supports content uploading. - /// </summary> - public bool SupportsContentUploading { get; set; } - - /// <summary> - /// Gets or sets the message callback url. - /// </summary> - public string? MessageCallbackUrl { get; set; } - - /// <summary> /// Gets or sets a value indicating whether session supports a persistent identifier. /// </summary> public bool SupportsPersistentIdentifier { get; set; } /// <summary> - /// Gets or sets a value indicating whether session supports sync. - /// </summary> - public bool SupportsSync { get; set; } - - /// <summary> /// Gets or sets the device profile. /// </summary> public DeviceProfile? DeviceProfile { get; set; } @@ -76,10 +61,7 @@ public class ClientCapabilitiesDto PlayableMediaTypes = PlayableMediaTypes, SupportedCommands = SupportedCommands, SupportsMediaControl = SupportsMediaControl, - SupportsContentUploading = SupportsContentUploading, - MessageCallbackUrl = MessageCallbackUrl, SupportsPersistentIdentifier = SupportsPersistentIdentifier, - SupportsSync = SupportsSync, DeviceProfile = DeviceProfile, AppStoreUrl = AppStoreUrl, IconUrl = IconUrl diff --git a/Jellyfin.Api/Models/StreamingDtos/HlsAudioRequestDto.cs b/Jellyfin.Api/Models/StreamingDtos/HlsAudioRequestDto.cs index 4f1abb1ff..bd176bb6a 100644 --- a/Jellyfin.Api/Models/StreamingDtos/HlsAudioRequestDto.cs +++ b/Jellyfin.Api/Models/StreamingDtos/HlsAudioRequestDto.cs @@ -1,4 +1,6 @@ -namespace Jellyfin.Api.Models.StreamingDtos; +using MediaBrowser.Controller.Streaming; + +namespace Jellyfin.Api.Models.StreamingDtos; /// <summary> /// The hls video request dto. diff --git a/Jellyfin.Api/Models/StreamingDtos/HlsVideoRequestDto.cs b/Jellyfin.Api/Models/StreamingDtos/HlsVideoRequestDto.cs index 1cd3d0132..53b6d7575 100644 --- a/Jellyfin.Api/Models/StreamingDtos/HlsVideoRequestDto.cs +++ b/Jellyfin.Api/Models/StreamingDtos/HlsVideoRequestDto.cs @@ -1,4 +1,6 @@ -namespace Jellyfin.Api.Models.StreamingDtos; +using MediaBrowser.Controller.Streaming; + +namespace Jellyfin.Api.Models.StreamingDtos; /// <summary> /// The hls video request dto. diff --git a/Jellyfin.Api/Models/StreamingDtos/StreamState.cs b/Jellyfin.Api/Models/StreamingDtos/StreamState.cs deleted file mode 100644 index cc1f9163e..000000000 --- a/Jellyfin.Api/Models/StreamingDtos/StreamState.cs +++ /dev/null @@ -1,185 +0,0 @@ -using System; -using Jellyfin.Api.Helpers; -using Jellyfin.Api.Models.PlaybackDtos; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.MediaEncoding; -using MediaBrowser.Model.Dlna; - -namespace Jellyfin.Api.Models.StreamingDtos; - -/// <summary> -/// The stream state dto. -/// </summary> -public class StreamState : EncodingJobInfo, IDisposable -{ - private readonly IMediaSourceManager _mediaSourceManager; - private readonly TranscodingJobHelper _transcodingJobHelper; - private bool _disposed; - - /// <summary> - /// Initializes a new instance of the <see cref="StreamState" /> class. - /// </summary> - /// <param name="mediaSourceManager">Instance of the <see cref="IMediaSourceManager" /> interface.</param> - /// <param name="transcodingType">The <see cref="TranscodingJobType" />.</param> - /// <param name="transcodingJobHelper">The <see cref="TranscodingJobHelper" /> singleton.</param> - public StreamState(IMediaSourceManager mediaSourceManager, TranscodingJobType transcodingType, TranscodingJobHelper transcodingJobHelper) - : base(transcodingType) - { - _mediaSourceManager = mediaSourceManager; - _transcodingJobHelper = transcodingJobHelper; - } - - /// <summary> - /// Gets or sets the requested url. - /// </summary> - public string? RequestedUrl { get; set; } - - /// <summary> - /// Gets or sets the request. - /// </summary> - public StreamingRequestDto Request - { - get => (StreamingRequestDto)BaseRequest; - set - { - BaseRequest = value; - IsVideoRequest = VideoRequest is not null; - } - } - - /// <summary> - /// Gets the video request. - /// </summary> - public VideoRequestDto? VideoRequest => Request as VideoRequestDto; - - /// <summary> - /// Gets or sets the direct stream provicer. - /// </summary> - /// <remarks> - /// Deprecated. - /// </remarks> - public IDirectStreamProvider? DirectStreamProvider { get; set; } - - /// <summary> - /// Gets or sets the path to wait for. - /// </summary> - public string? WaitForPath { get; set; } - - /// <summary> - /// Gets a value indicating whether the request outputs video. - /// </summary> - public bool IsOutputVideo => Request is VideoRequestDto; - - /// <summary> - /// Gets the segment length. - /// </summary> - public int SegmentLength - { - get - { - if (Request.SegmentLength.HasValue) - { - return Request.SegmentLength.Value; - } - - if (EncodingHelper.IsCopyCodec(OutputVideoCodec)) - { - var userAgent = UserAgent ?? string.Empty; - - if (userAgent.Contains("AppleTV", StringComparison.OrdinalIgnoreCase) - || userAgent.Contains("cfnetwork", StringComparison.OrdinalIgnoreCase) - || userAgent.Contains("ipad", StringComparison.OrdinalIgnoreCase) - || userAgent.Contains("iphone", StringComparison.OrdinalIgnoreCase) - || userAgent.Contains("ipod", StringComparison.OrdinalIgnoreCase)) - { - return 6; - } - - if (IsSegmentedLiveStream) - { - return 3; - } - - return 6; - } - - return 3; - } - } - - /// <summary> - /// Gets the minimum number of segments. - /// </summary> - public int MinSegments - { - get - { - if (Request.MinSegments.HasValue) - { - return Request.MinSegments.Value; - } - - return SegmentLength >= 10 ? 2 : 3; - } - } - - /// <summary> - /// Gets or sets the user agent. - /// </summary> - public string? UserAgent { get; set; } - - /// <summary> - /// Gets or sets a value indicating whether to estimate the content length. - /// </summary> - public bool EstimateContentLength { get; set; } - - /// <summary> - /// Gets or sets the transcode seek info. - /// </summary> - public TranscodeSeekInfo TranscodeSeekInfo { get; set; } - - /// <summary> - /// Gets or sets the transcoding job. - /// </summary> - public TranscodingJobDto? TranscodingJob { get; set; } - - /// <inheritdoc /> - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - /// <inheritdoc /> - public override void ReportTranscodingProgress(TimeSpan? transcodingPosition, float? framerate, double? percentComplete, long? bytesTranscoded, int? bitRate) - { - _transcodingJobHelper.ReportTranscodingProgress(TranscodingJob!, this, transcodingPosition, framerate, percentComplete, bytesTranscoded, bitRate); - } - - /// <summary> - /// Disposes the stream state. - /// </summary> - /// <param name="disposing">Whether the object is currently being disposed.</param> - protected virtual void Dispose(bool disposing) - { - if (_disposed) - { - return; - } - - if (disposing) - { - // REVIEW: Is this the right place for this? - if (MediaSource.RequiresClosing - && string.IsNullOrWhiteSpace(Request.LiveStreamId) - && !string.IsNullOrWhiteSpace(MediaSource.LiveStreamId)) - { - _mediaSourceManager.CloseLiveStream(MediaSource.LiveStreamId).GetAwaiter().GetResult(); - } - } - - TranscodingJob = null; - - _disposed = true; - } -} diff --git a/Jellyfin.Api/Models/StreamingDtos/StreamingRequestDto.cs b/Jellyfin.Api/Models/StreamingDtos/StreamingRequestDto.cs deleted file mode 100644 index a357498d4..000000000 --- a/Jellyfin.Api/Models/StreamingDtos/StreamingRequestDto.cs +++ /dev/null @@ -1,49 +0,0 @@ -using MediaBrowser.Controller.MediaEncoding; - -namespace Jellyfin.Api.Models.StreamingDtos; - -/// <summary> -/// The audio streaming request dto. -/// </summary> -public class StreamingRequestDto : BaseEncodingJobOptions -{ - /// <summary> - /// Gets or sets the params. - /// </summary> - public string? Params { get; set; } - - /// <summary> - /// Gets or sets the play session id. - /// </summary> - public string? PlaySessionId { get; set; } - - /// <summary> - /// Gets or sets the tag. - /// </summary> - public string? Tag { get; set; } - - /// <summary> - /// Gets or sets the segment container. - /// </summary> - public string? SegmentContainer { get; set; } - - /// <summary> - /// Gets or sets the segment length. - /// </summary> - public int? SegmentLength { get; set; } - - /// <summary> - /// Gets or sets the min segments. - /// </summary> - public int? MinSegments { get; set; } - - /// <summary> - /// Gets or sets the position of the requested segment in ticks. - /// </summary> - public long CurrentRuntimeTicks { get; set; } - - /// <summary> - /// Gets or sets the actual segment length in ticks. - /// </summary> - public long ActualSegmentLengthTicks { get; set; } -} diff --git a/Jellyfin.Api/Models/StreamingDtos/VideoRequestDto.cs b/Jellyfin.Api/Models/StreamingDtos/VideoRequestDto.cs deleted file mode 100644 index 8548fec1a..000000000 --- a/Jellyfin.Api/Models/StreamingDtos/VideoRequestDto.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace Jellyfin.Api.Models.StreamingDtos; - -/// <summary> -/// The video request dto. -/// </summary> -public class VideoRequestDto : StreamingRequestDto -{ - /// <summary> - /// Gets a value indicating whether this instance has fixed resolution. - /// </summary> - /// <value><c>true</c> if this instance has fixed resolution; otherwise, <c>false</c>.</value> - public bool HasFixedResolution => Width.HasValue || Height.HasValue; - - /// <summary> - /// Gets or sets a value indicating whether to enable subtitles in the manifest. - /// </summary> - public bool EnableSubtitlesInManifest { get; set; } - - /// <summary> - /// Gets or sets a value indicating whether to enable trickplay images. - /// </summary> - public bool EnableTrickplay { get; set; } -} |
