mirror of https://github.com/ErsatzTV/ErsatzTV.git
28 changed files with 4185 additions and 70 deletions
@ -0,0 +1,6 @@
@@ -0,0 +1,6 @@
|
||||
using LanguageExt; |
||||
using MediatR; |
||||
|
||||
namespace ErsatzTV.Application.Channels.Queries; |
||||
|
||||
public record GetChannelFramerate(string ChannelNumber) : IRequest<Option<int>>; |
||||
@ -0,0 +1,99 @@
@@ -0,0 +1,99 @@
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Linq; |
||||
using System.Threading; |
||||
using System.Threading.Tasks; |
||||
using ErsatzTV.Core.Domain; |
||||
using ErsatzTV.Core.Extensions; |
||||
using ErsatzTV.Infrastructure.Data; |
||||
using LanguageExt; |
||||
using MediatR; |
||||
using Microsoft.EntityFrameworkCore; |
||||
using Microsoft.Extensions.Logging; |
||||
using static LanguageExt.Prelude; |
||||
|
||||
namespace ErsatzTV.Application.Channels.Queries; |
||||
|
||||
public class GetChannelFramerateHandler : IRequestHandler<GetChannelFramerate, Option<int>> |
||||
{ |
||||
private readonly IDbContextFactory<TvContext> _dbContextFactory; |
||||
private readonly ILogger<GetChannelFramerateHandler> _logger; |
||||
|
||||
public GetChannelFramerateHandler( |
||||
IDbContextFactory<TvContext> dbContextFactory, |
||||
ILogger<GetChannelFramerateHandler> logger) |
||||
{ |
||||
_dbContextFactory = dbContextFactory; |
||||
_logger = logger; |
||||
} |
||||
|
||||
public async Task<Option<int>> Handle(GetChannelFramerate request, CancellationToken cancellationToken) |
||||
{ |
||||
// 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) |
||||
.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) |
||||
.Filter(p => p.Channel.Number == request.ChannelNumber) |
||||
.ToListAsync(cancellationToken); |
||||
|
||||
var frameRates = playouts.Map(p => p.Items.Map(i => i.MediaItem.GetHeadVersion())) |
||||
.Flatten() |
||||
.Map(mv => mv.RFrameRate) |
||||
.ToList(); |
||||
|
||||
|
||||
var distinct = frameRates.Distinct().ToList(); |
||||
if (distinct.Count > 1) |
||||
{ |
||||
// TODO: something more intelligent than minimum framerate?
|
||||
int result = frameRates.Map(ParseFrameRate).Min(); |
||||
_logger.LogInformation( |
||||
"Normalizing frame rate for channel {ChannelNumber} from {Distinct} to {FrameRate}", |
||||
request.ChannelNumber, |
||||
distinct, |
||||
result); |
||||
return result; |
||||
} |
||||
|
||||
_logger.LogInformation( |
||||
"All content on channel {ChannelNumber} has the same frame rate of {FrameRate}; will not normalize", |
||||
request.ChannelNumber, |
||||
distinct[0]); |
||||
return None; |
||||
} |
||||
|
||||
private int ParseFrameRate(string frameRate) |
||||
{ |
||||
if (!int.TryParse(frameRate, out int fr)) |
||||
{ |
||||
string[] split = (frameRate ?? string.Empty).Split("/"); |
||||
if (int.TryParse(split[0], out int left) && int.TryParse(split[1], out int right)) |
||||
{ |
||||
fr = (int)Math.Round(left / (double)right); |
||||
} |
||||
else |
||||
{ |
||||
fr = 24; |
||||
} |
||||
} |
||||
|
||||
return fr; |
||||
} |
||||
} |
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,26 @@
@@ -0,0 +1,26 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations; |
||||
|
||||
#nullable disable |
||||
|
||||
namespace ErsatzTV.Infrastructure.Migrations |
||||
{ |
||||
public partial class Add_FFmpegProfile_NormalizeFramerate : Migration |
||||
{ |
||||
protected override void Up(MigrationBuilder migrationBuilder) |
||||
{ |
||||
migrationBuilder.AddColumn<bool>( |
||||
name: "NormalizeFramerate", |
||||
table: "FFmpegProfile", |
||||
type: "INTEGER", |
||||
nullable: false, |
||||
defaultValue: true); |
||||
} |
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder) |
||||
{ |
||||
migrationBuilder.DropColumn( |
||||
name: "NormalizeFramerate", |
||||
table: "FFmpegProfile"); |
||||
} |
||||
} |
||||
} |
||||
Loading…
Reference in new issue