mirror of https://github.com/ErsatzTV/ErsatzTV.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
118 lines
4.8 KiB
118 lines
4.8 KiB
using ErsatzTV.Core.Domain; |
|
using ErsatzTV.Core.Extensions; |
|
using ErsatzTV.FFmpeg; |
|
using ErsatzTV.Infrastructure.Data; |
|
using Microsoft.EntityFrameworkCore; |
|
using Microsoft.Extensions.Logging; |
|
|
|
namespace ErsatzTV.Application.Channels; |
|
|
|
public class GetChannelFramerateHandler( |
|
IDbContextFactory<TvContext> dbContextFactory, |
|
ILogger<GetChannelFramerateHandler> logger) |
|
: IRequestHandler<GetChannelFramerate, Option<FrameRate>> |
|
{ |
|
public async Task<Option<FrameRate>> Handle(GetChannelFramerate request, CancellationToken cancellationToken) |
|
{ |
|
try |
|
{ |
|
await using TvContext dbContext = await dbContextFactory.CreateDbContextAsync(cancellationToken); |
|
|
|
FFmpegProfile ffmpegProfile = await dbContext.Channels |
|
.AsNoTracking() |
|
.Filter(c => c.Number == request.ChannelNumber) |
|
.Include(c => c.FFmpegProfile) |
|
.Map(c => c.FFmpegProfile) |
|
.SingleAsync(cancellationToken); |
|
|
|
if (!ffmpegProfile.NormalizeFramerate) |
|
{ |
|
return Option<FrameRate>.None; |
|
} |
|
|
|
// TODO: expand to check everything in collection rather than what's scheduled? |
|
logger.LogDebug("Checking frame rates for channel {ChannelNumber}", request.ChannelNumber); |
|
|
|
List<Playout> playouts = await dbContext.Playouts |
|
.AsNoTracking() |
|
.Include(p => p.Items) |
|
.ThenInclude(pi => pi.MediaItem) |
|
.ThenInclude(mi => (mi as Movie).MediaVersions) |
|
.Include(p => p.Items) |
|
.ThenInclude(pi => pi.MediaItem) |
|
.ThenInclude(mi => (mi as Episode).MediaVersions) |
|
.Include(p => p.Items) |
|
.ThenInclude(pi => pi.MediaItem) |
|
.ThenInclude(mi => (mi as Song).MediaVersions) |
|
.Include(p => p.Items) |
|
.ThenInclude(pi => pi.MediaItem) |
|
.ThenInclude(mi => (mi as MusicVideo).MediaVersions) |
|
.Include(p => p.Items) |
|
.ThenInclude(pi => pi.MediaItem) |
|
.ThenInclude(mi => (mi as OtherVideo).MediaVersions) |
|
.Include(p => p.Items) |
|
.ThenInclude(pi => pi.MediaItem) |
|
.ThenInclude(mi => (mi as Image).MediaVersions) |
|
.Include(p => p.Items) |
|
.ThenInclude(pi => pi.MediaItem) |
|
.ThenInclude(mi => (mi as RemoteStream).MediaVersions) |
|
.Filter(p => p.Channel.Number == request.ChannelNumber) |
|
.ToListAsync(cancellationToken); |
|
|
|
var frameRates = playouts.Map(p => p.Items.Map(i => i.MediaItem.GetHeadVersion())) |
|
.Flatten() |
|
.Map(mv => new FrameRate(mv.RFrameRate)) |
|
.ToList(); |
|
|
|
var distinct = frameRates.Distinct().ToList(); |
|
if (distinct.Count > 1) |
|
{ |
|
// TODO: something more intelligent than minimum framerate? |
|
var validFrameRates = frameRates.Where(fr => fr.ParsedFrameRate > 23).ToList(); |
|
if (validFrameRates.Count > 0) |
|
{ |
|
FrameRate result = validFrameRates.MinBy(fr => fr.ParsedFrameRate); |
|
logger.LogInformation( |
|
"Normalizing frame rate for channel {ChannelNumber} from {Distinct} to {FrameRate}", |
|
request.ChannelNumber, |
|
distinct.Map(fr => fr.RFrameRate), |
|
result.RFrameRate); |
|
return result; |
|
} |
|
|
|
FrameRate minFrameRate = frameRates.MinBy(fr => fr.ParsedFrameRate); |
|
logger.LogInformation( |
|
"Normalizing frame rate for channel {ChannelNumber} from {Distinct} to {FrameRate} instead of min value {MinFrameRate}", |
|
request.ChannelNumber, |
|
distinct.Map(fr => fr.RFrameRate), |
|
FrameRate.DefaultFrameRate.RFrameRate, |
|
minFrameRate.RFrameRate); |
|
|
|
return FrameRate.DefaultFrameRate; |
|
} |
|
|
|
if (distinct.Count != 0) |
|
{ |
|
logger.LogInformation( |
|
"All content on channel {ChannelNumber} has the same frame rate of {FrameRate}; will not normalize", |
|
request.ChannelNumber, |
|
distinct[0].RFrameRate); |
|
} |
|
else |
|
{ |
|
logger.LogInformation( |
|
"No content on channel {ChannelNumber} has frame rate information; will not normalize", |
|
request.ChannelNumber); |
|
} |
|
} |
|
catch (Exception ex) |
|
{ |
|
logger.LogWarning( |
|
ex, |
|
"Unexpected error checking frame rates on channel {ChannelNumber}", |
|
request.ChannelNumber); |
|
} |
|
|
|
return None; |
|
} |
|
}
|
|
|