Browse Source

use hardware acceleration for error messages (#813)

* logging fixes

* use hardware acceleration for error messages
pull/814/head
Jason Dove 4 years ago committed by GitHub
parent
commit
ea0d43cf99
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      CHANGELOG.md
  2. 15
      ErsatzTV.Application/Channels/Queries/GetChannelFramerateHandler.cs
  3. 13
      ErsatzTV.Application/Streaming/HlsSessionWorker.cs
  4. 4
      ErsatzTV.Application/Streaming/Queries/GetErrorProcessHandler.cs
  5. 12
      ErsatzTV.Application/Streaming/Queries/GetPlayoutItemProcessByChannelNumberHandler.cs
  6. 31
      ErsatzTV.Core/FFmpeg/FFmpegLibraryProcessService.cs
  7. 2
      ErsatzTV.Core/FFmpeg/FFmpegPlaybackSettingsCalculator.cs
  8. 4
      ErsatzTV.Core/Interfaces/FFmpeg/IFFmpegProcessService.cs
  9. 1
      ErsatzTV.FFmpeg/PipelineBuilder.cs

2
CHANGELOG.md

@ -6,6 +6,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). @@ -6,6 +6,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## [Unreleased]
### Fixed
- Fix error display with `HLS Segmenter` and `MPEG-TS` streaming modes
- Remove erroneous log messages about normalizing framerate on channels where framerate normalization is disabled
### Added
- Clean transcode cache folder on startup and after `HLS Segmenter` session terminates for any reason
@ -13,6 +14,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). @@ -13,6 +14,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
### Changed
- Remove thread limitation for scenarios where it is not required
- This should give a performance boost to installations that don't use hardware acceleration
- Use hardware acceleration to display error messages where configured
## [0.5.7-beta] - 2022-05-14
### Fixed

15
ErsatzTV.Application/Channels/Queries/GetChannelFramerateHandler.cs

@ -21,11 +21,22 @@ public class GetChannelFramerateHandler : IRequestHandler<GetChannelFramerate, O @@ -21,11 +21,22 @@ public class GetChannelFramerateHandler : IRequestHandler<GetChannelFramerate, O
public async Task<Option<int>> Handle(GetChannelFramerate request, CancellationToken cancellationToken)
{
await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(cancellationToken);
FFmpegProfile ffmpegProfile = await dbContext.Channels
.Filter(c => c.Number == request.ChannelNumber)
.Include(c => c.FFmpegProfile)
.Map(c => c.FFmpegProfile)
.SingleAsync(cancellationToken);
if (!ffmpegProfile.NormalizeFramerate)
{
return Option<int>.None;
}
// TODO: expand to check everything in collection rather than what's scheduled?
_logger.LogDebug("Checking frame rates for channel {ChannelNumber}", request.ChannelNumber);
await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(cancellationToken);
List<Playout> playouts = await dbContext.Playouts
.Include(p => p.Items)
.ThenInclude(pi => pi.MediaItem)

13
ErsatzTV.Application/Streaming/HlsSessionWorker.cs

@ -28,7 +28,6 @@ public class HlsSessionWorker : IHlsSessionWorker @@ -28,7 +28,6 @@ public class HlsSessionWorker : IHlsSessionWorker
private string _channelNumber;
private bool _firstProcess;
private DateTimeOffset _lastAccess;
private DateTimeOffset _playlistStart;
private Option<int> _targetFramerate;
private Timer _timer;
private DateTimeOffset _transcodedUntil;
@ -45,15 +44,7 @@ public class HlsSessionWorker : IHlsSessionWorker @@ -45,15 +44,7 @@ public class HlsSessionWorker : IHlsSessionWorker
_logger = logger;
}
public DateTimeOffset PlaylistStart
{
get => _playlistStart;
private set
{
_logger.LogDebug("Setting PlaylistStart to {PlaylistStart}", value);
_playlistStart = value;
}
}
public DateTimeOffset PlaylistStart { get; private set; }
public void Touch()
{
@ -396,7 +387,7 @@ public class HlsSessionWorker : IHlsSessionWorker @@ -396,7 +387,7 @@ public class HlsSessionWorker : IHlsSessionWorker
foreach (BaseError error in queryResult.LeftToSeq())
{
_logger.LogWarning("Unable to determine last pts offset - {@Error}", error);
_logger.LogWarning("Unable to determine last pts offset - {Error}", error.ToString());
}
foreach ((long pts, long duration) in queryResult.RightToSeq())

4
ErsatzTV.Application/Streaming/Queries/GetErrorProcessHandler.cs

@ -31,7 +31,9 @@ public class GetErrorProcessHandler : FFmpegProcessHandler<GetErrorProcess> @@ -31,7 +31,9 @@ public class GetErrorProcessHandler : FFmpegProcessHandler<GetErrorProcess>
request.MaybeDuration,
request.ErrorMessage,
request.HlsRealtime,
request.PtsOffset);
request.PtsOffset,
channel.FFmpegProfile.VaapiDriver,
channel.FFmpegProfile.VaapiDevice);
return new PlayoutItemProcessModel(process, request.MaybeDuration, request.Until);
}

12
ErsatzTV.Application/Streaming/Queries/GetPlayoutItemProcessByChannelNumberHandler.cs

@ -221,7 +221,9 @@ public class GetPlayoutItemProcessByChannelNumberHandler : FFmpegProcessHandler< @@ -221,7 +221,9 @@ public class GetPlayoutItemProcessByChannelNumberHandler : FFmpegProcessHandler<
maybeDuration,
"Channel is Offline",
request.HlsRealtime,
request.PtsOffset);
request.PtsOffset,
channel.FFmpegProfile.VaapiDriver,
channel.FFmpegProfile.VaapiDevice);
return new PlayoutItemProcessModel(offlineProcess, maybeDuration, finish);
case PlayoutItemDoesNotExistOnDisk:
@ -231,7 +233,9 @@ public class GetPlayoutItemProcessByChannelNumberHandler : FFmpegProcessHandler< @@ -231,7 +233,9 @@ public class GetPlayoutItemProcessByChannelNumberHandler : FFmpegProcessHandler<
maybeDuration,
error.Value,
request.HlsRealtime,
request.PtsOffset);
request.PtsOffset,
channel.FFmpegProfile.VaapiDriver,
channel.FFmpegProfile.VaapiDevice);
return new PlayoutItemProcessModel(doesNotExistProcess, maybeDuration, finish);
default:
@ -241,7 +245,9 @@ public class GetPlayoutItemProcessByChannelNumberHandler : FFmpegProcessHandler< @@ -241,7 +245,9 @@ public class GetPlayoutItemProcessByChannelNumberHandler : FFmpegProcessHandler<
maybeDuration,
"Channel is Offline",
request.HlsRealtime,
request.PtsOffset);
request.PtsOffset,
channel.FFmpegProfile.VaapiDriver,
channel.FFmpegProfile.VaapiDevice);
return new PlayoutItemProcessModel(errorProcess, maybeDuration, finish);
}

31
ErsatzTV.Core/FFmpeg/FFmpegLibraryProcessService.cs

@ -181,14 +181,7 @@ public class FFmpegLibraryProcessService : IFFmpegProcessService @@ -181,14 +181,7 @@ public class FFmpegLibraryProcessService : IFFmpegProcessService
string videoFormat = GetVideoFormat(playbackSettings);
HardwareAccelerationMode hwAccel = playbackSettings.HardwareAcceleration switch
{
HardwareAccelerationKind.Nvenc => HardwareAccelerationMode.Nvenc,
HardwareAccelerationKind.Qsv => HardwareAccelerationMode.Qsv,
HardwareAccelerationKind.Vaapi => HardwareAccelerationMode.Vaapi,
HardwareAccelerationKind.VideoToolbox => HardwareAccelerationMode.VideoToolbox,
_ => HardwareAccelerationMode.None
};
HardwareAccelerationMode hwAccel = GetHardwareAccelerationMode(playbackSettings);
OutputFormatKind outputFormat = channel.StreamingMode == StreamingMode.HttpLiveStreamingSegmenter
? OutputFormatKind.Hls
@ -259,7 +252,9 @@ public class FFmpegLibraryProcessService : IFFmpegProcessService @@ -259,7 +252,9 @@ public class FFmpegLibraryProcessService : IFFmpegProcessService
Option<TimeSpan> duration,
string errorMessage,
bool hlsRealtime,
long ptsOffset)
long ptsOffset,
VaapiDriver vaapiDriver,
string vaapiDevice)
{
FFmpegPlaybackSettings playbackSettings = _playbackSettingsCalculator.CalculateErrorSettings(
channel.StreamingMode,
@ -335,11 +330,13 @@ public class FFmpegLibraryProcessService : IFFmpegProcessService @@ -335,11 +330,13 @@ public class FFmpegLibraryProcessService : IFFmpegProcessService
var videoInputFile = new VideoInputFile(videoPath, new List<VideoStream> { ffmpegVideoStream });
HardwareAccelerationMode hwAccel = GetHardwareAccelerationMode(playbackSettings);
var ffmpegState = new FFmpegState(
false,
HardwareAccelerationMode.None,
None,
None,
hwAccel,
VaapiDriverName(hwAccel, vaapiDriver),
VaapiDeviceName(hwAccel, vaapiDevice),
playbackSettings.StreamSeek,
duration,
channel.StreamingMode != StreamingMode.HttpLiveStreamingDirect,
@ -602,4 +599,14 @@ public class FFmpegLibraryProcessService : IFFmpegProcessService @@ -602,4 +599,14 @@ public class FFmpegLibraryProcessService : IFFmpegProcessService
FFmpegProfileVideoFormat.Copy => VideoFormat.Copy,
_ => throw new ArgumentOutOfRangeException($"unexpected video format {playbackSettings.VideoFormat}")
};
private static HardwareAccelerationMode GetHardwareAccelerationMode(FFmpegPlaybackSettings playbackSettings) =>
playbackSettings.HardwareAcceleration switch
{
HardwareAccelerationKind.Nvenc => HardwareAccelerationMode.Nvenc,
HardwareAccelerationKind.Qsv => HardwareAccelerationMode.Qsv,
HardwareAccelerationKind.Vaapi => HardwareAccelerationMode.Vaapi,
HardwareAccelerationKind.VideoToolbox => HardwareAccelerationMode.VideoToolbox,
_ => HardwareAccelerationMode.None
};
}

2
ErsatzTV.Core/FFmpeg/FFmpegPlaybackSettingsCalculator.cs

@ -176,7 +176,7 @@ public class FFmpegPlaybackSettingsCalculator @@ -176,7 +176,7 @@ public class FFmpegPlaybackSettingsCalculator
bool hlsRealtime) =>
new()
{
HardwareAcceleration = HardwareAccelerationKind.None,
HardwareAcceleration = ffmpegProfile.HardwareAcceleration,
FormatFlags = CommonFormatFlags,
VideoFormat = ffmpegProfile.VideoFormat,
VideoBitrate = ffmpegProfile.VideoBitrate,

4
ErsatzTV.Core/Interfaces/FFmpeg/IFFmpegProcessService.cs

@ -42,7 +42,9 @@ public interface IFFmpegProcessService @@ -42,7 +42,9 @@ public interface IFFmpegProcessService
Option<TimeSpan> duration,
string errorMessage,
bool hlsRealtime,
long ptsOffset);
long ptsOffset,
VaapiDriver vaapiDriver,
string vaapiDevice);
Command ConcatChannel(string ffmpegPath, bool saveReports, Channel channel, string scheme, string host);

1
ErsatzTV.FFmpeg/PipelineBuilder.cs

@ -566,6 +566,7 @@ public class PipelineBuilder @@ -566,6 +566,7 @@ public class PipelineBuilder
// nvidia needs some extra format help if the only filter will be the download filter
if (ffmpegState.HardwareAccelerationMode == HardwareAccelerationMode.Nvenc &&
currentState.FrameDataLocation == FrameDataLocation.Hardware &&
_videoInputFile.Map(f => f.FilterSteps.Count).IfNone(1) == 0)
{
IPipelineFilterStep scaleFilter = AvailableScaleFilters.ForAcceleration(

Loading…
Cancel
Save