mirror of https://github.com/ErsatzTV/ErsatzTV.git
16 changed files with 469 additions and 34 deletions
@ -0,0 +1,204 @@ |
|||||||
|
using System.Collections.Generic; |
||||||
|
using System.Linq; |
||||||
|
using ErsatzTV.FFmpeg.Capabilities.Vaapi; |
||||||
|
using FluentAssertions; |
||||||
|
using NUnit.Framework; |
||||||
|
|
||||||
|
namespace ErsatzTV.FFmpeg.Tests.Capabilities.Vaapi; |
||||||
|
|
||||||
|
[TestFixture] |
||||||
|
public class VaapiCapabilityParserTests |
||||||
|
{ |
||||||
|
private const string BriefOutput = @"Trying display: wayland
|
||||||
|
vainfo: VA-API version: 1.18 (libva 2.18.2) |
||||||
|
vainfo: Driver version: Mesa Gallium driver 23.1.2 for AMD Radeon RX 6750 XT (navi22, LLVM 15.0.7, DRM 3.52, 6.3.8-arch1-1) |
||||||
|
vainfo: Supported profile and entrypoints |
||||||
|
VAProfileMPEG2Simple : VAEntrypointVLD |
||||||
|
VAProfileMPEG2Main : VAEntrypointVLD |
||||||
|
VAProfileVC1Simple : VAEntrypointVLD |
||||||
|
VAProfileVC1Main : VAEntrypointVLD |
||||||
|
VAProfileVC1Advanced : VAEntrypointVLD |
||||||
|
VAProfileH264ConstrainedBaseline: VAEntrypointVLD |
||||||
|
VAProfileH264ConstrainedBaseline: VAEntrypointEncSlice |
||||||
|
VAProfileH264Main : VAEntrypointVLD |
||||||
|
VAProfileH264Main : VAEntrypointEncSlice |
||||||
|
VAProfileH264High : VAEntrypointVLD |
||||||
|
VAProfileH264High : VAEntrypointEncSlice |
||||||
|
VAProfileHEVCMain : VAEntrypointVLD |
||||||
|
VAProfileHEVCMain : VAEntrypointEncSlice |
||||||
|
VAProfileHEVCMain10 : VAEntrypointVLD |
||||||
|
VAProfileHEVCMain10 : VAEntrypointEncSlice |
||||||
|
VAProfileJPEGBaseline : VAEntrypointVLD |
||||||
|
VAProfileVP9Profile0 : VAEntrypointVLD |
||||||
|
VAProfileVP9Profile2 : VAEntrypointVLD |
||||||
|
VAProfileAV1Profile0 : VAEntrypointVLD |
||||||
|
VAProfileNone : VAEntrypointVideoProc";
|
||||||
|
|
||||||
|
private const string FullOutput = @"Trying display: wayland
|
||||||
|
vainfo: VA-API version: 1.18 (libva 2.18.2) |
||||||
|
vainfo: Driver version: Mesa Gallium driver 23.1.2 for AMD Radeon RX 6750 XT (navi22, LLVM 15.0.7, DRM 3.52, 6.3.8-arch1-1) |
||||||
|
vainfo: Supported config attributes per profile/entrypoint pair |
||||||
|
VAProfileMPEG2Simple/VAEntrypointVLD |
||||||
|
VAConfigAttribRTFormat : VA_RT_FORMAT_YUV420 |
||||||
|
|
||||||
|
VAProfileMPEG2Main/VAEntrypointVLD |
||||||
|
VAConfigAttribRTFormat : VA_RT_FORMAT_YUV420 |
||||||
|
|
||||||
|
VAProfileVC1Simple/VAEntrypointVLD |
||||||
|
VAConfigAttribRTFormat : VA_RT_FORMAT_YUV420 |
||||||
|
|
||||||
|
VAProfileVC1Main/VAEntrypointVLD |
||||||
|
VAConfigAttribRTFormat : VA_RT_FORMAT_YUV420 |
||||||
|
|
||||||
|
VAProfileVC1Advanced/VAEntrypointVLD |
||||||
|
VAConfigAttribRTFormat : VA_RT_FORMAT_YUV420 |
||||||
|
|
||||||
|
VAProfileH264ConstrainedBaseline/VAEntrypointVLD |
||||||
|
VAConfigAttribRTFormat : VA_RT_FORMAT_YUV420 |
||||||
|
|
||||||
|
VAProfileH264ConstrainedBaseline/VAEntrypointEncSlice |
||||||
|
VAConfigAttribRTFormat : VA_RT_FORMAT_YUV420 |
||||||
|
VAConfigAttribRateControl : VA_RC_CBR |
||||||
|
VA_RC_VBR |
||||||
|
VA_RC_CQP |
||||||
|
VAConfigAttribEncPackedHeaders : VA_ENC_PACKED_HEADER_NONE |
||||||
|
VAConfigAttribEncMaxRefFrames : l0=1 |
||||||
|
l1=0 |
||||||
|
VAConfigAttribEncMaxSlices : 128 |
||||||
|
VAConfigAttribEncSliceStructure : VA_ENC_SLICE_STRUCTURE_POWER_OF_TWO_ROWS |
||||||
|
VA_ENC_SLICE_STRUCTURE_EQUAL_ROWS |
||||||
|
VAConfigAttribEncQualityRange : number of supported quality levels is 32 |
||||||
|
VAConfigAttribEncRateControlExt : max_num_temporal_layers_minus1=3 temporal_layer_bitrate_control_flag=1 |
||||||
|
VAConfigAttribMaxFrameSize : max_frame_size=1 |
||||||
|
multiple_pass=0 |
||||||
|
|
||||||
|
VAProfileH264Main/VAEntrypointVLD |
||||||
|
VAConfigAttribRTFormat : VA_RT_FORMAT_YUV420 |
||||||
|
|
||||||
|
VAProfileH264Main/VAEntrypointEncSlice |
||||||
|
VAConfigAttribRTFormat : VA_RT_FORMAT_YUV420 |
||||||
|
VAConfigAttribRateControl : VA_RC_CBR |
||||||
|
VA_RC_VBR |
||||||
|
VA_RC_CQP |
||||||
|
VAConfigAttribEncPackedHeaders : VA_ENC_PACKED_HEADER_NONE |
||||||
|
VAConfigAttribEncMaxRefFrames : l0=1 |
||||||
|
l1=0 |
||||||
|
VAConfigAttribEncMaxSlices : 128 |
||||||
|
VAConfigAttribEncSliceStructure : VA_ENC_SLICE_STRUCTURE_POWER_OF_TWO_ROWS |
||||||
|
VA_ENC_SLICE_STRUCTURE_EQUAL_ROWS |
||||||
|
VAConfigAttribEncQualityRange : number of supported quality levels is 32 |
||||||
|
VAConfigAttribEncRateControlExt : max_num_temporal_layers_minus1=3 temporal_layer_bitrate_control_flag=1 |
||||||
|
VAConfigAttribMaxFrameSize : max_frame_size=1 |
||||||
|
multiple_pass=0 |
||||||
|
|
||||||
|
VAProfileH264High/VAEntrypointVLD |
||||||
|
VAConfigAttribRTFormat : VA_RT_FORMAT_YUV420 |
||||||
|
|
||||||
|
VAProfileH264High/VAEntrypointEncSlice |
||||||
|
VAConfigAttribRTFormat : VA_RT_FORMAT_YUV420 |
||||||
|
VA_RT_FORMAT_YUV420_10 |
||||||
|
VA_RT_FORMAT_YUV420_10BPP |
||||||
|
VAConfigAttribRateControl : VA_RC_CBR |
||||||
|
VA_RC_VBR |
||||||
|
VA_RC_CQP |
||||||
|
VAConfigAttribEncPackedHeaders : VA_ENC_PACKED_HEADER_NONE |
||||||
|
VAConfigAttribEncMaxRefFrames : l0=1 |
||||||
|
l1=0 |
||||||
|
VAConfigAttribEncMaxSlices : 128 |
||||||
|
VAConfigAttribEncSliceStructure : VA_ENC_SLICE_STRUCTURE_POWER_OF_TWO_ROWS |
||||||
|
VA_ENC_SLICE_STRUCTURE_EQUAL_ROWS |
||||||
|
VAConfigAttribEncQualityRange : number of supported quality levels is 32 |
||||||
|
VAConfigAttribEncRateControlExt : max_num_temporal_layers_minus1=3 temporal_layer_bitrate_control_flag=1 |
||||||
|
VAConfigAttribMaxFrameSize : max_frame_size=1 |
||||||
|
multiple_pass=0 |
||||||
|
|
||||||
|
VAProfileHEVCMain/VAEntrypointVLD |
||||||
|
VAConfigAttribRTFormat : VA_RT_FORMAT_YUV420 |
||||||
|
|
||||||
|
VAProfileHEVCMain/VAEntrypointEncSlice |
||||||
|
VAConfigAttribRTFormat : VA_RT_FORMAT_YUV420 |
||||||
|
VAConfigAttribRateControl : VA_RC_CBR |
||||||
|
VA_RC_VBR |
||||||
|
VA_RC_CQP |
||||||
|
VAConfigAttribEncPackedHeaders : VA_ENC_PACKED_HEADER_SEQUENCE |
||||||
|
VAConfigAttribEncMaxRefFrames : l0=1 |
||||||
|
l1=0 |
||||||
|
VAConfigAttribEncMaxSlices : 128 |
||||||
|
VAConfigAttribEncSliceStructure : VA_ENC_SLICE_STRUCTURE_POWER_OF_TWO_ROWS |
||||||
|
VA_ENC_SLICE_STRUCTURE_EQUAL_ROWS |
||||||
|
VAConfigAttribEncQualityRange : number of supported quality levels is 32 |
||||||
|
VAConfigAttribMaxFrameSize : max_frame_size=1 |
||||||
|
multiple_pass=0 |
||||||
|
|
||||||
|
VAProfileHEVCMain10/VAEntrypointVLD |
||||||
|
VAConfigAttribRTFormat : VA_RT_FORMAT_YUV420 |
||||||
|
VA_RT_FORMAT_YUV420_10 |
||||||
|
VA_RT_FORMAT_YUV420_10BPP |
||||||
|
|
||||||
|
VAProfileHEVCMain10/VAEntrypointEncSlice |
||||||
|
VAConfigAttribRTFormat : VA_RT_FORMAT_YUV420 |
||||||
|
VA_RT_FORMAT_YUV420_10 |
||||||
|
VA_RT_FORMAT_YUV420_10BPP |
||||||
|
VAConfigAttribRateControl : VA_RC_CBR |
||||||
|
VA_RC_VBR |
||||||
|
VA_RC_CQP |
||||||
|
VAConfigAttribEncPackedHeaders : VA_ENC_PACKED_HEADER_SEQUENCE |
||||||
|
VAConfigAttribEncMaxRefFrames : l0=1 |
||||||
|
l1=0 |
||||||
|
VAConfigAttribEncMaxSlices : 128 |
||||||
|
VAConfigAttribEncSliceStructure : VA_ENC_SLICE_STRUCTURE_POWER_OF_TWO_ROWS |
||||||
|
VA_ENC_SLICE_STRUCTURE_EQUAL_ROWS |
||||||
|
VAConfigAttribEncQualityRange : number of supported quality levels is 32 |
||||||
|
VAConfigAttribMaxFrameSize : max_frame_size=1 |
||||||
|
multiple_pass=0 |
||||||
|
|
||||||
|
VAProfileJPEGBaseline/VAEntrypointVLD |
||||||
|
VAConfigAttribRTFormat : VA_RT_FORMAT_YUV420 |
||||||
|
VA_RT_FORMAT_YUV422 |
||||||
|
VA_RT_FORMAT_YUV444 |
||||||
|
VA_RT_FORMAT_YUV400 |
||||||
|
|
||||||
|
VAProfileVP9Profile0/VAEntrypointVLD |
||||||
|
VAConfigAttribRTFormat : VA_RT_FORMAT_YUV420 |
||||||
|
|
||||||
|
VAProfileVP9Profile2/VAEntrypointVLD |
||||||
|
VAConfigAttribRTFormat : VA_RT_FORMAT_YUV420_10 |
||||||
|
VA_RT_FORMAT_YUV420_10BPP |
||||||
|
|
||||||
|
VAProfileAV1Profile0/VAEntrypointVLD |
||||||
|
VAConfigAttribRTFormat : VA_RT_FORMAT_YUV420 |
||||||
|
VA_RT_FORMAT_YUV420_10 |
||||||
|
VA_RT_FORMAT_YUV420_10BPP |
||||||
|
|
||||||
|
VAProfileNone/VAEntrypointVideoProc |
||||||
|
VAConfigAttribRTFormat : VA_RT_FORMAT_YUV420 |
||||||
|
VA_RT_FORMAT_YUV422 |
||||||
|
VA_RT_FORMAT_YUV444 |
||||||
|
VA_RT_FORMAT_YUV400 |
||||||
|
VA_RT_FORMAT_YUV420_10 |
||||||
|
VA_RT_FORMAT_RGB32 |
||||||
|
VA_RT_FORMAT_YUV420_10BPP";
|
||||||
|
|
||||||
|
[Test] |
||||||
|
public void ShouldParseEntrypoints() |
||||||
|
{ |
||||||
|
List<VaapiProfileEntrypoint> brief = VaapiCapabilityParser.Parse(BriefOutput); |
||||||
|
List<VaapiProfileEntrypoint> full = VaapiCapabilityParser.ParseFull(FullOutput); |
||||||
|
|
||||||
|
brief.Count.Should().Be(20); |
||||||
|
full.Count.Should().Be(20); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void Full_ShouldParseRateControlModes() |
||||||
|
{ |
||||||
|
List<VaapiProfileEntrypoint> full = VaapiCapabilityParser.ParseFull(FullOutput); |
||||||
|
|
||||||
|
full.Count.Should().Be(20); |
||||||
|
full.Count(e => e.VaapiEntrypoint.StartsWith("VAEntrypointEnc")).Should().BeGreaterThan(0); |
||||||
|
foreach (VaapiProfileEntrypoint entrypoint in full.Where(e => e.VaapiEntrypoint.StartsWith("VAEntrypointEnc"))) |
||||||
|
{ |
||||||
|
entrypoint.RateControlModes.Count.Should().BeGreaterThan(0); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,68 @@ |
|||||||
|
using System.Text.RegularExpressions; |
||||||
|
|
||||||
|
namespace ErsatzTV.FFmpeg.Capabilities.Vaapi; |
||||||
|
|
||||||
|
public static class VaapiCapabilityParser |
||||||
|
{ |
||||||
|
public static List<VaapiProfileEntrypoint> Parse(string output) |
||||||
|
{ |
||||||
|
var profileEntrypoints = new List<VaapiProfileEntrypoint>(); |
||||||
|
|
||||||
|
foreach (string line in string.Join("", output).Split("\n")) |
||||||
|
{ |
||||||
|
const string PROFILE_ENTRYPOINT_PATTERN = @"(VAProfile\w*).*(VAEntrypoint\w*)"; |
||||||
|
Match match = Regex.Match(line, PROFILE_ENTRYPOINT_PATTERN); |
||||||
|
if (match.Success) |
||||||
|
{ |
||||||
|
profileEntrypoints.Add( |
||||||
|
new VaapiProfileEntrypoint( |
||||||
|
match.Groups[1].Value.Trim(), |
||||||
|
match.Groups[2].Value.Trim())); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return profileEntrypoints; |
||||||
|
} |
||||||
|
|
||||||
|
public static List<VaapiProfileEntrypoint> ParseFull(string output) |
||||||
|
{ |
||||||
|
var profileEntrypoints = new List<VaapiProfileEntrypoint>(); |
||||||
|
var profile = new VaapiProfileEntrypoint(string.Empty, string.Empty); |
||||||
|
string[] allLines = string.Join("", output).Split("\n"); |
||||||
|
|
||||||
|
for (var i = 0; i < allLines.Length; i++) |
||||||
|
{ |
||||||
|
string line = allLines[i]; |
||||||
|
const string PROFILE_ENTRYPOINT_PATTERN = @"(VAProfile\w*).*(VAEntrypoint\w*)"; |
||||||
|
const string PROFILE_RATE_CONTROL_PATTERN = @".*VA_RC_(\w*).*"; |
||||||
|
Match match = Regex.Match(line, PROFILE_ENTRYPOINT_PATTERN); |
||||||
|
if (match.Success) |
||||||
|
{ |
||||||
|
profile = new VaapiProfileEntrypoint(match.Groups[1].Value.Trim(), match.Groups[2].Value.Trim()); |
||||||
|
profileEntrypoints.Add(profile); |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
// check for rate control
|
||||||
|
match = Regex.Match(line, PROFILE_RATE_CONTROL_PATTERN); |
||||||
|
if (match.Success) |
||||||
|
{ |
||||||
|
switch (match.Groups[1].Value.Trim().ToLowerInvariant()) |
||||||
|
{ |
||||||
|
case "cqp": |
||||||
|
profile.AddRateControlMode(RateControlMode.CQP); |
||||||
|
break; |
||||||
|
case "vbr": |
||||||
|
profile.AddRateControlMode(RateControlMode.VBR); |
||||||
|
break; |
||||||
|
case "cbr": |
||||||
|
profile.AddRateControlMode(RateControlMode.CBR); |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return profileEntrypoints; |
||||||
|
} |
||||||
|
} |
||||||
@ -1,3 +1,13 @@ |
|||||||
namespace ErsatzTV.FFmpeg.Capabilities.Vaapi; |
namespace ErsatzTV.FFmpeg.Capabilities.Vaapi; |
||||||
|
|
||||||
public record VaapiProfileEntrypoint(string VaapiProfile, string VaapiEntrypoint); |
public record VaapiProfileEntrypoint(string VaapiProfile, string VaapiEntrypoint) |
||||||
|
{ |
||||||
|
private readonly System.Collections.Generic.HashSet<RateControlMode> _rateControlModes = new(); |
||||||
|
|
||||||
|
public IReadOnlyCollection<RateControlMode> RateControlModes => _rateControlModes; |
||||||
|
|
||||||
|
public bool AddRateControlMode(RateControlMode mode) |
||||||
|
{ |
||||||
|
return _rateControlModes.Add(mode); |
||||||
|
} |
||||||
|
} |
||||||
|
|||||||
Loading…
Reference in new issue