Browse Source

use single thread and disable framerate normalization (#639)

* try one thread for everything

* add (unused) framerate filter

* disable framerate normalization by default

* update dependencies
pull/640/head
Jason Dove 5 years ago committed by GitHub
parent
commit
66ab0b3990
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      CHANGELOG.md
  2. 2
      ErsatzTV.Core.Tests/ErsatzTV.Core.Tests.csproj
  3. 7
      ErsatzTV.FFmpeg.Tests/ErsatzTV.FFmpeg.Tests.csproj
  4. 36
      ErsatzTV.FFmpeg/Filter/FrameRateFilter.cs
  5. 3
      ErsatzTV.FFmpeg/Option/RealtimeInputOption.cs
  6. 13
      ErsatzTV.FFmpeg/Option/ThreadCountOption.cs
  7. 1
      ErsatzTV.FFmpeg/PipelineBuilder.cs
  8. 8
      ErsatzTV.Infrastructure/Data/Configurations/FFmpegProfileConfiguration.cs
  9. 3863
      ErsatzTV.Infrastructure/Migrations/20220216115303_Disable_FrameRateNormalization_ByDefault.Designer.cs
  10. 33
      ErsatzTV.Infrastructure/Migrations/20220216115303_Disable_FrameRateNormalization_ByDefault.cs
  11. 3863
      ErsatzTV.Infrastructure/Migrations/20220216115456_TurnOff_FrameRateNormalization.Designer.cs
  12. 19
      ErsatzTV.Infrastructure/Migrations/20220216115456_TurnOff_FrameRateNormalization.cs
  13. 20
      ErsatzTV.Infrastructure/Migrations/TvContextModelSnapshot.cs
  14. 1
      ErsatzTV.sln.DotSettings
  15. 2
      ErsatzTV/ErsatzTV.csproj

4
CHANGELOG.md

@ -8,6 +8,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Add improved but experimental transcoder logic, which can be toggled on and off in `Settings` - Add improved but experimental transcoder logic, which can be toggled on and off in `Settings`
- Fix `HLS Segmenter` bug when source video packet contains no duration (`N/A`) - Fix `HLS Segmenter` bug when source video packet contains no duration (`N/A`)
### Changed
- Disable framerate normalization by default and on all ffmpeg profiles
- If framerate normalization is desired (not typically needed), it can be re-enabled manually
## [0.4.1-alpha] - 2022-02-10 ## [0.4.1-alpha] - 2022-02-10
### Fixed ### Fixed
- Normalize smart quotes in search queries as they are unsupported by the search library - Normalize smart quotes in search queries as they are unsupported by the search library

2
ErsatzTV.Core.Tests/ErsatzTV.Core.Tests.csproj

@ -6,7 +6,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="FluentAssertions" Version="6.4.0" /> <PackageReference Include="FluentAssertions" Version="6.5.1" />
<PackageReference Include="LanguageExt.Core" Version="4.0.3" /> <PackageReference Include="LanguageExt.Core" Version="4.0.3" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0" /> <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="6.0.0" /> <PackageReference Include="Microsoft.Extensions.Logging" Version="6.0.0" />

7
ErsatzTV.FFmpeg.Tests/ErsatzTV.FFmpeg.Tests.csproj

@ -8,12 +8,15 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="FluentAssertions" Version="6.4.0" /> <PackageReference Include="FluentAssertions" Version="6.5.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" />
<PackageReference Include="Moq" Version="4.16.1" /> <PackageReference Include="Moq" Version="4.16.1" />
<PackageReference Include="NUnit" Version="3.13.2" /> <PackageReference Include="NUnit" Version="3.13.2" />
<PackageReference Include="NUnit3TestAdapter" Version="4.0.0" /> <PackageReference Include="NUnit3TestAdapter" Version="4.0.0" />
<PackageReference Include="coverlet.collector" Version="3.1.0" /> <PackageReference Include="coverlet.collector" Version="3.1.2">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

36
ErsatzTV.FFmpeg/Filter/FrameRateFilter.cs

@ -0,0 +1,36 @@
namespace ErsatzTV.FFmpeg.Filter;
public class FrameRateFilter : BaseFilter
{
private readonly FrameState _currentState;
private readonly int _frameRate;
public FrameRateFilter(FrameState currentState, int frameRate)
{
_currentState = currentState;
_frameRate = frameRate;
}
public override string Filter
{
get
{
string frameRate = $"framerate=fps={_frameRate}:flags=-scd";
string pixelFormat = _currentState.PixelFormat.Match(pf => pf.FFmpegName, () => string.Empty);
if (_currentState.FrameDataLocation == FrameDataLocation.Hardware)
{
if (!string.IsNullOrWhiteSpace(pixelFormat))
{
return $"hwdownload,format={pixelFormat},{frameRate}";
}
return $"hwdownload,{frameRate}";
}
return frameRate;
}
}
public override FrameState NextState(FrameState currentState) => currentState with { FrameRate = _frameRate };
}

3
ErsatzTV.FFmpeg/Option/RealtimeInputOption.cs

@ -8,7 +8,8 @@ public class RealtimeInputOption : IPipelineStep
// some builds of ffmpeg seem to hang when realtime input is requested with multithreading, // some builds of ffmpeg seem to hang when realtime input is requested with multithreading,
// so we force a single thread here // so we force a single thread here
public IList<string> GlobalOptions => new List<string> { "-threads", "1" }; // public IList<string> GlobalOptions => new List<string> { "-threads", "1" };
public IList<string> GlobalOptions => Array.Empty<string>();
public IList<string> InputOptions => new List<string> { "-re" }; public IList<string> InputOptions => new List<string> { "-re" };
public IList<string> FilterOptions => Array.Empty<string>(); public IList<string> FilterOptions => Array.Empty<string>();

13
ErsatzTV.FFmpeg/Option/ThreadCountOption.cs

@ -0,0 +1,13 @@
namespace ErsatzTV.FFmpeg.Option;
public class ThreadCountOption : GlobalOption
{
private readonly int _threadCount;
public ThreadCountOption(int threadCount)
{
_threadCount = threadCount;
}
public override IList<string> GlobalOptions => new List<string> { "-threads", _threadCount.ToString() };
}

1
ErsatzTV.FFmpeg/PipelineBuilder.cs

@ -26,6 +26,7 @@ public class PipelineBuilder
{ {
_pipelineSteps = new List<IPipelineStep> _pipelineSteps = new List<IPipelineStep>
{ {
new ThreadCountOption(1), // try everything single-threaded
new NoStandardInputOption(), new NoStandardInputOption(),
new HideBannerOption(), new HideBannerOption(),
new NoStatsOption(), new NoStatsOption(),

8
ErsatzTV.Infrastructure/Data/Configurations/FFmpegProfileConfiguration.cs

@ -6,6 +6,12 @@ namespace ErsatzTV.Infrastructure.Data.Configurations
{ {
public class FFmpegProfileConfiguration : IEntityTypeConfiguration<FFmpegProfile> public class FFmpegProfileConfiguration : IEntityTypeConfiguration<FFmpegProfile>
{ {
public void Configure(EntityTypeBuilder<FFmpegProfile> builder) => builder.ToTable("FFmpegProfile"); public void Configure(EntityTypeBuilder<FFmpegProfile> builder)
{
builder.ToTable("FFmpegProfile");
builder.Property(p => p.NormalizeFramerate)
.HasDefaultValue(false);
}
} }
} }

3863
ErsatzTV.Infrastructure/Migrations/20220216115303_Disable_FrameRateNormalization_ByDefault.Designer.cs generated

File diff suppressed because it is too large Load Diff

33
ErsatzTV.Infrastructure/Migrations/20220216115303_Disable_FrameRateNormalization_ByDefault.cs

@ -0,0 +1,33 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace ErsatzTV.Infrastructure.Migrations
{
public partial class Disable_FrameRateNormalization_ByDefault : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<bool>(
name: "NormalizeFramerate",
table: "FFmpegProfile",
type: "INTEGER",
nullable: false,
defaultValue: false,
oldClrType: typeof(bool),
oldType: "INTEGER");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<bool>(
name: "NormalizeFramerate",
table: "FFmpegProfile",
type: "INTEGER",
nullable: false,
oldClrType: typeof(bool),
oldType: "INTEGER",
oldDefaultValue: false);
}
}
}

3863
ErsatzTV.Infrastructure/Migrations/20220216115456_TurnOff_FrameRateNormalization.Designer.cs generated

File diff suppressed because it is too large Load Diff

19
ErsatzTV.Infrastructure/Migrations/20220216115456_TurnOff_FrameRateNormalization.cs

@ -0,0 +1,19 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace ErsatzTV.Infrastructure.Migrations
{
public partial class TurnOff_FrameRateNormalization : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.Sql("UPDATE FFmpegProfile SET NormalizeFramerate = 0");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
}
}
}

20
ErsatzTV.Infrastructure/Migrations/TvContextModelSnapshot.cs

@ -15,7 +15,7 @@ namespace ErsatzTV.Infrastructure.Migrations
protected override void BuildModel(ModelBuilder modelBuilder) protected override void BuildModel(ModelBuilder modelBuilder)
{ {
#pragma warning disable 612, 618 #pragma warning disable 612, 618
modelBuilder.HasAnnotation("ProductVersion", "6.0.1"); modelBuilder.HasAnnotation("ProductVersion", "6.0.2");
modelBuilder.Entity("ErsatzTV.Core.Domain.Actor", b => modelBuilder.Entity("ErsatzTV.Core.Domain.Actor", b =>
{ {
@ -506,7 +506,9 @@ namespace ErsatzTV.Infrastructure.Migrations
.HasColumnType("INTEGER"); .HasColumnType("INTEGER");
b.Property<bool>("NormalizeFramerate") b.Property<bool>("NormalizeFramerate")
.HasColumnType("INTEGER"); .ValueGeneratedOnAdd()
.HasColumnType("INTEGER")
.HasDefaultValue(false);
b.Property<bool>("NormalizeLoudness") b.Property<bool>("NormalizeLoudness")
.HasColumnType("INTEGER"); .HasColumnType("INTEGER");
@ -648,7 +650,7 @@ namespace ErsatzTV.Infrastructure.Migrations
b.HasIndex("SongMetadataId"); b.HasIndex("SongMetadataId");
b.ToTable("Genre", (string)null); b.ToTable("Genre");
}); });
modelBuilder.Entity("ErsatzTV.Core.Domain.JellyfinConnection", b => modelBuilder.Entity("ErsatzTV.Core.Domain.JellyfinConnection", b =>
@ -1055,7 +1057,7 @@ namespace ErsatzTV.Infrastructure.Migrations
b.HasIndex("ArtistMetadataId"); b.HasIndex("ArtistMetadataId");
b.ToTable("Mood", (string)null); b.ToTable("Mood");
}); });
modelBuilder.Entity("ErsatzTV.Core.Domain.MovieMetadata", b => modelBuilder.Entity("ErsatzTV.Core.Domain.MovieMetadata", b =>
@ -1163,7 +1165,7 @@ namespace ErsatzTV.Infrastructure.Migrations
b.HasIndex("SmartCollectionId"); b.HasIndex("SmartCollectionId");
b.ToTable("MultiCollectionSmartItem", (string)null); b.ToTable("MultiCollectionSmartItem");
}); });
modelBuilder.Entity("ErsatzTV.Core.Domain.MusicVideoMetadata", b => modelBuilder.Entity("ErsatzTV.Core.Domain.MusicVideoMetadata", b =>
@ -1771,7 +1773,7 @@ namespace ErsatzTV.Infrastructure.Migrations
b.HasIndex("ArtistMetadataId"); b.HasIndex("ArtistMetadataId");
b.ToTable("Style", (string)null); b.ToTable("Style");
}); });
modelBuilder.Entity("ErsatzTV.Core.Domain.Tag", b => modelBuilder.Entity("ErsatzTV.Core.Domain.Tag", b =>
@ -1825,7 +1827,7 @@ namespace ErsatzTV.Infrastructure.Migrations
b.HasIndex("SongMetadataId"); b.HasIndex("SongMetadataId");
b.ToTable("Tag", (string)null); b.ToTable("Tag");
}); });
modelBuilder.Entity("ErsatzTV.Core.Domain.TraktList", b => modelBuilder.Entity("ErsatzTV.Core.Domain.TraktList", b =>
@ -2846,7 +2848,7 @@ namespace ErsatzTV.Infrastructure.Migrations
.OnDelete(DeleteBehavior.Cascade) .OnDelete(DeleteBehavior.Cascade)
.IsRequired(); .IsRequired();
b.OwnsOne("ErsatzTV.Core.Domain.Playout.Anchor#ErsatzTV.Core.Domain.PlayoutAnchor", "Anchor", b1 => b.OwnsOne("ErsatzTV.Core.Domain.PlayoutAnchor", "Anchor", b1 =>
{ {
b1.Property<int>("PlayoutId") b1.Property<int>("PlayoutId")
.HasColumnType("INTEGER"); .HasColumnType("INTEGER");
@ -2949,7 +2951,7 @@ namespace ErsatzTV.Infrastructure.Migrations
.WithMany() .WithMany()
.HasForeignKey("SmartCollectionId"); .HasForeignKey("SmartCollectionId");
b.OwnsOne("ErsatzTV.Core.Domain.PlayoutProgramScheduleAnchor.EnumeratorState#ErsatzTV.Core.Domain.CollectionEnumeratorState", "EnumeratorState", b1 => b.OwnsOne("ErsatzTV.Core.Domain.CollectionEnumeratorState", "EnumeratorState", b1 =>
{ {
b1.Property<int>("PlayoutProgramScheduleAnchorId") b1.Property<int>("PlayoutProgramScheduleAnchorId")
.HasColumnType("INTEGER"); .HasColumnType("INTEGER");

1
ErsatzTV.sln.DotSettings

@ -34,6 +34,7 @@
<s:Boolean x:Key="/Default/UserDictionary/Words/=fontfile/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=fontfile/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Fprobe/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=Fprobe/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=genpts/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=genpts/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=hwdownload/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=hwupload/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=hwupload/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=igndts/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=igndts/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Jellyfin/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=Jellyfin/@EntryIndexedValue">True</s:Boolean>

2
ErsatzTV/ErsatzTV.csproj

@ -33,7 +33,7 @@
<PackageReference Include="PPioli.FluentValidation.Blazor" Version="5.0.0" /> <PackageReference Include="PPioli.FluentValidation.Blazor" Version="5.0.0" />
<PackageReference Include="Refit.HttpClientFactory" Version="6.3.2" /> <PackageReference Include="Refit.HttpClientFactory" Version="6.3.2" />
<PackageReference Include="Serilog" Version="2.10.0" /> <PackageReference Include="Serilog" Version="2.10.0" />
<PackageReference Include="Serilog.AspNetCore" Version="4.1.0" /> <PackageReference Include="Serilog.AspNetCore" Version="5.0.0" />
<PackageReference Include="Serilog.Settings.Configuration" Version="3.3.0" /> <PackageReference Include="Serilog.Settings.Configuration" Version="3.3.0" />
<PackageReference Include="Serilog.Sinks.SQLite" Version="6.0.0" /> <PackageReference Include="Serilog.Sinks.SQLite" Version="6.0.0" />
<PackageReference Include="System.IO.FileSystem.Primitives" Version="4.3.0" /> <PackageReference Include="System.IO.FileSystem.Primitives" Version="4.3.0" />

Loading…
Cancel
Save