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/). @@ -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`
- 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
### Fixed
- 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 @@ @@ -6,7 +6,7 @@
</PropertyGroup>
<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="Microsoft.Extensions.DependencyInjection" 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 @@ @@ -8,12 +8,15 @@
</PropertyGroup>
<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="Moq" Version="4.16.1" />
<PackageReference Include="NUnit" Version="3.13.2" />
<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>

36
ErsatzTV.FFmpeg/Filter/FrameRateFilter.cs

@ -0,0 +1,36 @@ @@ -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 @@ -8,7 +8,8 @@ public class RealtimeInputOption : IPipelineStep
// some builds of ffmpeg seem to hang when realtime input is requested with multithreading,
// 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> FilterOptions => Array.Empty<string>();

13
ErsatzTV.FFmpeg/Option/ThreadCountOption.cs

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

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

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

1
ErsatzTV.sln.DotSettings

@ -34,6 +34,7 @@ @@ -34,6 +34,7 @@
<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/=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/=igndts/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Jellyfin/@EntryIndexedValue">True</s:Boolean>

2
ErsatzTV/ErsatzTV.csproj

@ -33,7 +33,7 @@ @@ -33,7 +33,7 @@
<PackageReference Include="PPioli.FluentValidation.Blazor" Version="5.0.0" />
<PackageReference Include="Refit.HttpClientFactory" Version="6.3.2" />
<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.Sinks.SQLite" Version="6.0.0" />
<PackageReference Include="System.IO.FileSystem.Primitives" Version="4.3.0" />

Loading…
Cancel
Save