mirror of https://github.com/ErsatzTV/ErsatzTV.git
Browse Source
* normalize bit depth and color for nvenc * fix hls direct * update changelog * add bit depth option to ffmpeg profilepull/1032/head
42 changed files with 13457 additions and 102 deletions
@ -0,0 +1,7 @@ |
|||||||
|
namespace ErsatzTV.Core.Domain; |
||||||
|
|
||||||
|
public enum FFmpegProfileBitDepth |
||||||
|
{ |
||||||
|
EightBit = 0, |
||||||
|
TenBit = 1 |
||||||
|
} |
||||||
@ -0,0 +1,14 @@ |
|||||||
|
namespace ErsatzTV.FFmpeg; |
||||||
|
|
||||||
|
public record ColorParams(string ColorRange, string ColorSpace, string ColorTransfer, string ColorPrimaries) |
||||||
|
{ |
||||||
|
public static readonly ColorParams Default = new("tv", "bt709", "bt709", "bt709"); |
||||||
|
|
||||||
|
public bool IsHdr => ColorTransfer is "arib-std-b67" or "smpte2084"; |
||||||
|
|
||||||
|
public bool IsUnknown => string.IsNullOrWhiteSpace(ColorSpace) && |
||||||
|
string.IsNullOrWhiteSpace(ColorTransfer) && |
||||||
|
string.IsNullOrWhiteSpace(ColorPrimaries); |
||||||
|
|
||||||
|
public bool IsBt709 => this == Default; |
||||||
|
} |
||||||
@ -0,0 +1,43 @@ |
|||||||
|
using ErsatzTV.FFmpeg.Format; |
||||||
|
|
||||||
|
namespace ErsatzTV.FFmpeg.Filter; |
||||||
|
|
||||||
|
public class ColorspaceFilter : BaseFilter |
||||||
|
{ |
||||||
|
private readonly VideoStream _videoStream; |
||||||
|
private readonly IPixelFormat _desiredPixelFormat; |
||||||
|
|
||||||
|
public ColorspaceFilter(VideoStream videoStream, IPixelFormat desiredPixelFormat) |
||||||
|
{ |
||||||
|
_videoStream = videoStream; |
||||||
|
_desiredPixelFormat = desiredPixelFormat; |
||||||
|
} |
||||||
|
|
||||||
|
public override FrameState NextState(FrameState currentState) => |
||||||
|
currentState with |
||||||
|
{ |
||||||
|
PixelFormat = Some(_desiredPixelFormat), |
||||||
|
FrameDataLocation = FrameDataLocation.Software |
||||||
|
}; |
||||||
|
|
||||||
|
public override string Filter |
||||||
|
{ |
||||||
|
get |
||||||
|
{ |
||||||
|
string setParams = string.Empty; |
||||||
|
if (_videoStream.ColorParams.IsUnknown) |
||||||
|
{ |
||||||
|
setParams = "setparams=range=tv:colorspace=bt709:color_trc=bt709:color_primaries=bt709"; |
||||||
|
} |
||||||
|
|
||||||
|
string colorspace = _desiredPixelFormat.BitDepth switch |
||||||
|
{ |
||||||
|
10 when !_videoStream.ColorParams.IsUnknown => "colorspace=all=bt709:format=yuv420p10", |
||||||
|
8 when !_videoStream.ColorParams.IsUnknown => "colorspace=all=bt709:format=yuv420p", |
||||||
|
_ => string.Empty |
||||||
|
}; |
||||||
|
|
||||||
|
return string.Join(',', new[] { setParams, colorspace }.Filter(s => !string.IsNullOrWhiteSpace(s))); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,45 @@ |
|||||||
|
using ErsatzTV.FFmpeg.Format; |
||||||
|
|
||||||
|
namespace ErsatzTV.FFmpeg.Filter; |
||||||
|
|
||||||
|
public class TonemapFilter : BaseFilter |
||||||
|
{ |
||||||
|
private readonly FrameState _currentState; |
||||||
|
private readonly IPixelFormat _desiredPixelFormat; |
||||||
|
|
||||||
|
public TonemapFilter(FrameState currentState, IPixelFormat desiredPixelFormat) |
||||||
|
{ |
||||||
|
_currentState = currentState; |
||||||
|
_desiredPixelFormat = desiredPixelFormat; |
||||||
|
} |
||||||
|
|
||||||
|
public override FrameState NextState(FrameState currentState) => |
||||||
|
currentState with |
||||||
|
{ |
||||||
|
PixelFormat = Some(_desiredPixelFormat), |
||||||
|
FrameDataLocation = FrameDataLocation.Software |
||||||
|
}; |
||||||
|
|
||||||
|
public override string Filter |
||||||
|
{ |
||||||
|
get |
||||||
|
{ |
||||||
|
string pixelFormat = _currentState.PixelFormat.Match(pf => pf.FFmpegName, () => string.Empty); |
||||||
|
|
||||||
|
var tonemap = |
||||||
|
$"setparams=colorspace=bt2020c,zscale=transfer=linear,tonemap=hable,zscale=transfer=bt709,format={_desiredPixelFormat.FFmpegName}"; |
||||||
|
|
||||||
|
if (_currentState.FrameDataLocation == FrameDataLocation.Hardware) |
||||||
|
{ |
||||||
|
if (!string.IsNullOrWhiteSpace(pixelFormat)) |
||||||
|
{ |
||||||
|
return $"hwdownload,format={pixelFormat},{tonemap}"; |
||||||
|
} |
||||||
|
|
||||||
|
return $"hwdownload,{tonemap}"; |
||||||
|
} |
||||||
|
|
||||||
|
return tonemap; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,26 @@ |
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations; |
||||||
|
|
||||||
|
#nullable disable |
||||||
|
|
||||||
|
namespace ErsatzTV.Infrastructure.Migrations |
||||||
|
{ |
||||||
|
public partial class Add_FFmpegProfileBitDepth : Migration |
||||||
|
{ |
||||||
|
protected override void Up(MigrationBuilder migrationBuilder) |
||||||
|
{ |
||||||
|
migrationBuilder.AddColumn<int>( |
||||||
|
name: "BitDepth", |
||||||
|
table: "FFmpegProfile", |
||||||
|
type: "INTEGER", |
||||||
|
nullable: false, |
||||||
|
defaultValue: 0); |
||||||
|
} |
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder) |
||||||
|
{ |
||||||
|
migrationBuilder.DropColumn( |
||||||
|
name: "BitDepth", |
||||||
|
table: "FFmpegProfile"); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,55 @@ |
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations; |
||||||
|
|
||||||
|
#nullable disable |
||||||
|
|
||||||
|
namespace ErsatzTV.Infrastructure.Migrations |
||||||
|
{ |
||||||
|
public partial class Add_MediaStreamColor : Migration |
||||||
|
{ |
||||||
|
protected override void Up(MigrationBuilder migrationBuilder) |
||||||
|
{ |
||||||
|
migrationBuilder.AddColumn<string>( |
||||||
|
name: "ColorPrimaries", |
||||||
|
table: "MediaStream", |
||||||
|
type: "TEXT", |
||||||
|
nullable: true); |
||||||
|
|
||||||
|
migrationBuilder.AddColumn<string>( |
||||||
|
name: "ColorRange", |
||||||
|
table: "MediaStream", |
||||||
|
type: "TEXT", |
||||||
|
nullable: true); |
||||||
|
|
||||||
|
migrationBuilder.AddColumn<string>( |
||||||
|
name: "ColorSpace", |
||||||
|
table: "MediaStream", |
||||||
|
type: "TEXT", |
||||||
|
nullable: true); |
||||||
|
|
||||||
|
migrationBuilder.AddColumn<string>( |
||||||
|
name: "ColorTransfer", |
||||||
|
table: "MediaStream", |
||||||
|
type: "TEXT", |
||||||
|
nullable: true); |
||||||
|
} |
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder) |
||||||
|
{ |
||||||
|
migrationBuilder.DropColumn( |
||||||
|
name: "ColorPrimaries", |
||||||
|
table: "MediaStream"); |
||||||
|
|
||||||
|
migrationBuilder.DropColumn( |
||||||
|
name: "ColorRange", |
||||||
|
table: "MediaStream"); |
||||||
|
|
||||||
|
migrationBuilder.DropColumn( |
||||||
|
name: "ColorSpace", |
||||||
|
table: "MediaStream"); |
||||||
|
|
||||||
|
migrationBuilder.DropColumn( |
||||||
|
name: "ColorTransfer", |
||||||
|
table: "MediaStream"); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,31 @@ |
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations; |
||||||
|
|
||||||
|
#nullable disable |
||||||
|
|
||||||
|
namespace ErsatzTV.Infrastructure.Migrations |
||||||
|
{ |
||||||
|
public partial class Reset_AllStatistics20221103 : Migration |
||||||
|
{ |
||||||
|
protected override void Up(MigrationBuilder migrationBuilder) |
||||||
|
{ |
||||||
|
// reset all statistics EXCEPT songs since they don't contain video streams
|
||||||
|
|
||||||
|
migrationBuilder.Sql("UPDATE MediaVersion SET DateUpdated = '0001-01-01 00:00:00' WHERE SongId IS NULL"); |
||||||
|
migrationBuilder.Sql("UPDATE LibraryFolder SET Etag = NULL WHERE Id IN (SELECT LF.Id FROM LibraryFolder LF INNER JOIN LibraryPath LP on LP.Id = LF.LibraryPathId INNER JOIN Library L on L.Id = LP.LibraryId WHERE MediaKind != 5)"); |
||||||
|
migrationBuilder.Sql("UPDATE EmbyMovie SET Etag = NULL"); |
||||||
|
migrationBuilder.Sql("UPDATE EmbyShow SET Etag = NULL"); |
||||||
|
migrationBuilder.Sql("UPDATE EmbySeason SET Etag = NULL"); |
||||||
|
migrationBuilder.Sql("UPDATE EmbyEpisode SET Etag = NULL"); |
||||||
|
migrationBuilder.Sql("UPDATE JellyfinMovie SET Etag = NULL"); |
||||||
|
migrationBuilder.Sql("UPDATE JellyfinShow SET Etag = NULL"); |
||||||
|
migrationBuilder.Sql("UPDATE JellyfinSeason SET Etag = NULL"); |
||||||
|
migrationBuilder.Sql("UPDATE JellyfinEpisode SET Etag = NULL"); |
||||||
|
migrationBuilder.Sql("UPDATE LibraryPath SET LastScan = '0001-01-01 00:00:00' WHERE Id IN (SELECT LP.Id FROM LibraryPath LP INNER JOIN Library L on L.Id = LP.LibraryId WHERE MediaKind != 5)"); |
||||||
|
migrationBuilder.Sql("UPDATE Library SET LastScan = '0001-01-01 00:00:00' WHERE MediaKind != 5"); |
||||||
|
} |
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder) |
||||||
|
{ |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
Loading…
Reference in new issue