mirror of
https://github.com/NixOS/nixpkgs.git
synced 2026-07-06 17:13:24 -05:00
nixos/jellyfin: add hardware transcode options to module (#457987)
This commit is contained in:
commit
0430acab84
2 changed files with 464 additions and 12 deletions
|
|
@ -8,14 +8,80 @@
|
|||
let
|
||||
inherit (lib)
|
||||
mkIf
|
||||
mkDefault
|
||||
getExe
|
||||
maintainers
|
||||
mkEnableOption
|
||||
mkOption
|
||||
mkPackageOption
|
||||
boolToString
|
||||
escapeXML
|
||||
nameValuePair
|
||||
optionalString
|
||||
concatMapStringsSep
|
||||
escapeShellArg
|
||||
literalExpression
|
||||
;
|
||||
inherit (lib.types)
|
||||
bool
|
||||
enum
|
||||
ints
|
||||
nullOr
|
||||
path
|
||||
str
|
||||
submodule
|
||||
;
|
||||
inherit (lib.types) str path bool;
|
||||
cfg = config.services.jellyfin;
|
||||
filteredDecodingCodecs = builtins.filter (
|
||||
c: c != "hevcRExt10bit" && c != "hevcRExt12bit" && cfg.transcoding.hardwareDecodingCodecs.${c}
|
||||
) (builtins.attrNames cfg.transcoding.hardwareDecodingCodecs);
|
||||
encodingXmlText = ''
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<EncodingOptions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
||||
<HardwareAccelerationType>${cfg.hardwareAcceleration.type}</HardwareAccelerationType>
|
||||
${optionalString (
|
||||
cfg.hardwareAcceleration.type == "vaapi" && cfg.hardwareAcceleration.device != null
|
||||
) "<VaapiDevice>${escapeXML cfg.hardwareAcceleration.device}</VaapiDevice>"}
|
||||
${optionalString (
|
||||
cfg.hardwareAcceleration.type == "qsv" && cfg.hardwareAcceleration.device != null
|
||||
) "<OpenclDevice>${escapeXML cfg.hardwareAcceleration.device}</OpenclDevice>"}
|
||||
<EncodingThreadCount>${
|
||||
if cfg.transcoding.threadCount != null then toString cfg.transcoding.threadCount else "-1"
|
||||
}</EncodingThreadCount>
|
||||
<EnableThrottling>${boolToString cfg.transcoding.throttleTranscoding}</EnableThrottling>
|
||||
<EnableTonemapping>${boolToString cfg.transcoding.enableToneMapping}</EnableTonemapping>
|
||||
<EnableSubtitleExtraction>${boolToString cfg.transcoding.enableSubtitleExtraction}</EnableSubtitleExtraction>
|
||||
<H264Crf>${toString cfg.transcoding.h264Crf}</H264Crf>
|
||||
<H265Crf>${toString cfg.transcoding.h265Crf}</H265Crf>
|
||||
<EnableHardwareEncoding>${boolToString cfg.transcoding.enableHardwareEncoding}</EnableHardwareEncoding>
|
||||
<AllowHevcEncoding>${boolToString cfg.transcoding.hardwareEncodingCodecs.hevc}</AllowHevcEncoding>
|
||||
<AllowAv1Encoding>${boolToString cfg.transcoding.hardwareEncodingCodecs.av1}</AllowAv1Encoding>
|
||||
<EnableIntelLowPowerH264HwEncoder>${boolToString cfg.transcoding.enableIntelLowPowerEncoding}</EnableIntelLowPowerH264HwEncoder>
|
||||
<EnableIntelLowPowerHevcHwEncoder>${boolToString cfg.transcoding.enableIntelLowPowerEncoding}</EnableIntelLowPowerHevcHwEncoder>
|
||||
<EnableDecodingColorDepth10HevcRext>${boolToString cfg.transcoding.hardwareDecodingCodecs.hevcRExt10bit}</EnableDecodingColorDepth10HevcRext>
|
||||
<EnableDecodingColorDepth12HevcRext>${boolToString cfg.transcoding.hardwareDecodingCodecs.hevcRExt12bit}</EnableDecodingColorDepth12HevcRext>
|
||||
<HardwareDecodingCodecs>
|
||||
${concatMapStringsSep "\n " (
|
||||
codec: "<string>${escapeXML codec}</string>"
|
||||
) filteredDecodingCodecs}
|
||||
</HardwareDecodingCodecs>
|
||||
</EncodingOptions>
|
||||
'';
|
||||
encodingXmlFile = pkgs.writeText "encoding.xml" encodingXmlText;
|
||||
codecListToType =
|
||||
desc: list:
|
||||
submodule {
|
||||
options = builtins.listToAttrs (
|
||||
map (
|
||||
name:
|
||||
nameValuePair name (mkOption {
|
||||
type = bool;
|
||||
default = false;
|
||||
description = "Enable ${desc} for ${name} codec.";
|
||||
})
|
||||
) list
|
||||
);
|
||||
};
|
||||
in
|
||||
{
|
||||
options = {
|
||||
|
|
@ -48,7 +114,7 @@ in
|
|||
configDir = mkOption {
|
||||
type = path;
|
||||
default = "${cfg.dataDir}/config";
|
||||
defaultText = "\${cfg.dataDir}/config";
|
||||
defaultText = literalExpression ''"''${cfg.dataDir}/config"'';
|
||||
description = ''
|
||||
Directory containing the server configuration files,
|
||||
passed with `--configdir` see [configuration-directory](https://jellyfin.org/docs/general/administration/configuration/#configuration-directory)
|
||||
|
|
@ -67,7 +133,7 @@ in
|
|||
logDir = mkOption {
|
||||
type = path;
|
||||
default = "${cfg.dataDir}/log";
|
||||
defaultText = "\${cfg.dataDir}/log";
|
||||
defaultText = literalExpression ''"''${cfg.dataDir}/log"'';
|
||||
description = ''
|
||||
Directory where the Jellyfin logs will be stored,
|
||||
passed with `--logdir` see [#log-directory](https://jellyfin.org/docs/general/administration/configuration/#log-directory)
|
||||
|
|
@ -83,10 +149,216 @@ in
|
|||
only be used if they are unchanged, see [Port Bindings](https://jellyfin.org/docs/general/networking/#port-bindings).
|
||||
'';
|
||||
};
|
||||
|
||||
hardwareAcceleration = {
|
||||
enable = mkEnableOption "hardware acceleration for video transcoding";
|
||||
|
||||
device = mkOption {
|
||||
type = nullOr path;
|
||||
default = null;
|
||||
example = "/dev/dri/renderD128";
|
||||
description = ''
|
||||
Path to the hardware acceleration device that Jellyfin should use.
|
||||
For obscure configurations, additional devices can be added via
|
||||
{option}`systemd.services.jellyfin.serviceConfig.DeviceAllow`.
|
||||
'';
|
||||
};
|
||||
|
||||
# see MediaBrowser.Model/Entities/HardwareAccelerationType.cs in jellyfin source
|
||||
type = mkOption {
|
||||
type = enum [
|
||||
"none"
|
||||
"amf"
|
||||
"qsv"
|
||||
"nvenc"
|
||||
"v4l2m2m"
|
||||
"vaapi"
|
||||
# videotoolbox is MacOS-only
|
||||
"rkmpp"
|
||||
];
|
||||
default = "none";
|
||||
description = ''
|
||||
The method of hardware acceleration. See [Hardware Acceleration](https://jellyfin.org/docs/general/post-install/transcoding/hardware-acceleration) for more details.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
forceEncodingConfig = mkOption {
|
||||
type = bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Whether to overwrite Jellyfin's `encoding.xml` configuration file on each service start.
|
||||
|
||||
When enabled, the encoding configuration specified in {option}`services.jellyfin.transcoding`
|
||||
and {option}`services.jellyfin.hardwareAcceleration` will be applied on every service restart.
|
||||
A backup of the existing `encoding.xml` will be created at `encoding.xml.backup-$timestamp`.
|
||||
|
||||
::: {.warning}
|
||||
Enabling this option means that any changes made to transcoding settings through
|
||||
Jellyfin's web dashboard will be lost on the next service restart. The NixOS configuration
|
||||
becomes the single source of truth for encoding settings.
|
||||
:::
|
||||
|
||||
When disabled (the default), the encoding configuration is only written if no `encoding.xml`
|
||||
exists yet. This allows settings to be changed through Jellyfin's web dashboard and persist
|
||||
across restarts, but means the NixOS configuration options will be ignored after the initial setup.
|
||||
'';
|
||||
};
|
||||
|
||||
transcoding = {
|
||||
maxConcurrentStreams = mkOption {
|
||||
type = nullOr ints.positive;
|
||||
default = null;
|
||||
example = 2;
|
||||
description = ''
|
||||
Maximum number of concurrent transcoding streams.
|
||||
Set to null for unlimited (limited by hardware capabilities).
|
||||
'';
|
||||
};
|
||||
|
||||
enableToneMapping = mkOption {
|
||||
type = bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Enable tone mapping when transcoding HDR content.
|
||||
'';
|
||||
};
|
||||
|
||||
enableSubtitleExtraction = mkOption {
|
||||
type = bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Embedded subtitles can be extracted from videos and delivered to clients in plain text, in order to help prevent video transcoding. On some systems this can take a long time and cause video playback to stall during the extraction process. Disable this to have embedded subtitles burned in with video transcoding when they are not natively supported by the client device.
|
||||
'';
|
||||
};
|
||||
|
||||
throttleTranscoding = mkOption {
|
||||
type = bool;
|
||||
default = false;
|
||||
description = ''
|
||||
When a transcode or remux gets far enough ahead from the current playback position, pause the process so it will consume fewer resources. This is most useful when watching without seeking often. Turn this off if you experience playback issues.
|
||||
'';
|
||||
};
|
||||
|
||||
threadCount = mkOption {
|
||||
type = nullOr ints.positive;
|
||||
default = null;
|
||||
example = 4;
|
||||
description = ''
|
||||
Number of threads to use when transcoding.
|
||||
Set to null to use automatic detection.
|
||||
'';
|
||||
};
|
||||
|
||||
hardwareDecodingCodecs = mkOption {
|
||||
type = codecListToType "hardware decoding" [
|
||||
"h264"
|
||||
"hevc"
|
||||
"mpeg2"
|
||||
"vc1"
|
||||
"vp8"
|
||||
"vp9"
|
||||
"av1"
|
||||
"hevc10bit"
|
||||
"hevcRExt10bit"
|
||||
"hevcRExt12bit"
|
||||
];
|
||||
default = { };
|
||||
example = {
|
||||
vp9 = true;
|
||||
h264 = true;
|
||||
};
|
||||
description = ''
|
||||
Which codecs to enable for hardware decoding.
|
||||
'';
|
||||
};
|
||||
|
||||
hardwareEncodingCodecs = mkOption {
|
||||
type = codecListToType "hardware encoding" [
|
||||
"hevc"
|
||||
"av1"
|
||||
];
|
||||
default = { };
|
||||
example = {
|
||||
av1 = true;
|
||||
};
|
||||
description = ''
|
||||
Which codecs to enable for hardware encoding. h264 is always enabled.
|
||||
'';
|
||||
};
|
||||
|
||||
encodingPreset = mkOption {
|
||||
type = enum [
|
||||
"auto"
|
||||
"veryslow"
|
||||
"slower"
|
||||
"slow"
|
||||
"medium"
|
||||
"fast"
|
||||
"faster"
|
||||
"veryfast"
|
||||
"superfast"
|
||||
"ultrafast"
|
||||
];
|
||||
default = "auto";
|
||||
description = ''
|
||||
Encoder preset for transcoding.
|
||||
Lower presets sacrifice quality for speed, higher presets optimize quality.
|
||||
'';
|
||||
};
|
||||
|
||||
deleteSegments = mkOption {
|
||||
type = bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Delete transcoding segments when finished.
|
||||
'';
|
||||
};
|
||||
|
||||
h264Crf = mkOption {
|
||||
type = ints.between 0 51;
|
||||
default = 23;
|
||||
description = ''
|
||||
Constant Rate Factor (CRF) for H.264 encoding. Lower values result in better quality. Range: 0-51.
|
||||
'';
|
||||
};
|
||||
|
||||
h265Crf = mkOption {
|
||||
type = ints.between 0 51;
|
||||
default = 28;
|
||||
description = ''
|
||||
Constant Rate Factor (CRF) for H.265 encoding. Lower values result in better quality. Range: 0-51.
|
||||
'';
|
||||
};
|
||||
|
||||
enableHardwareEncoding = mkOption {
|
||||
type = bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Enable hardware encoding for video transcoding.
|
||||
'';
|
||||
};
|
||||
|
||||
enableIntelLowPowerEncoding = mkOption {
|
||||
type = bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Enable low-power encoding mode for Intel Quick Sync Video.
|
||||
Requires i915 HuC firmware to be configured.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
assertions = [
|
||||
{
|
||||
assertion = cfg.hardwareAcceleration.enable -> cfg.hardwareAcceleration.device != null;
|
||||
message = "services.jellyfin.hardwareAcceleration.device cannot be null when hardware acceleration is enabled.";
|
||||
}
|
||||
];
|
||||
|
||||
systemd = {
|
||||
tmpfiles.settings.jellyfinDirs = {
|
||||
"${cfg.dataDir}"."d" = {
|
||||
|
|
@ -112,6 +384,47 @@ in
|
|||
wants = [ "network-online.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
|
||||
preStart = mkIf cfg.hardwareAcceleration.enable (
|
||||
''
|
||||
configDir=${escapeShellArg cfg.configDir}
|
||||
encodingXml="$configDir/encoding.xml"
|
||||
''
|
||||
+ (
|
||||
if cfg.forceEncodingConfig then
|
||||
''
|
||||
if [[ -e $encodingXml ]]; then
|
||||
# this intentionally removes trailing newlines
|
||||
currentText="$(<"$encodingXml")"
|
||||
configuredText="$(<${encodingXmlFile})"
|
||||
if [[ $currentText == "$configuredText" ]]; then
|
||||
# don't need to do anything
|
||||
exit 0
|
||||
else
|
||||
encodingXmlBackup="$configDir/encoding.xml.backup-$(date -u +"%FT%H_%M_%SZ")"
|
||||
mv --update=none-fail -T "$encodingXml" "$encodingXmlBackup"
|
||||
fi
|
||||
fi
|
||||
cp --update=none-fail -T ${encodingXmlFile} "$encodingXml"
|
||||
chmod u+w "$encodingXml"
|
||||
''
|
||||
else
|
||||
''
|
||||
if [[ -e $encodingXml ]]; then
|
||||
# this intentionally removes trailing newlines
|
||||
currentText="$(<"$encodingXml")"
|
||||
configuredText="$(<${encodingXmlFile})"
|
||||
if [[ $currentText != "$configuredText" ]]; then
|
||||
echo "WARN: $encodingXml already exists and is different from the configured settings. transcoding options NOT applied." >&2
|
||||
echo "WARN: Set config.services.jellyfin.forceEncodingConfig = true to override." >&2
|
||||
fi
|
||||
else
|
||||
cp --update=none-fail -T ${encodingXmlFile} "$encodingXml"
|
||||
chmod u+w "$encodingXml"
|
||||
fi
|
||||
''
|
||||
)
|
||||
);
|
||||
|
||||
# This is mostly follows: https://github.com/jellyfin/jellyfin/blob/master/fedora/jellyfin.service
|
||||
# Upstream also disable some hardenings when running in LXC, we do the same with the isContainer option
|
||||
serviceConfig = {
|
||||
|
|
@ -154,7 +467,10 @@ in
|
|||
LockPersonality = true;
|
||||
PrivateTmp = !config.boot.isContainer;
|
||||
# needed for hardware acceleration
|
||||
PrivateDevices = false;
|
||||
# PrivateDevices defaults to false for backwards compatibility - users may have
|
||||
# hardware acceleration set up outside of NixOS configuration
|
||||
PrivateDevices = mkDefault false;
|
||||
DeviceAllow = mkIf cfg.hardwareAcceleration.enable [ "${cfg.hardwareAcceleration.device} rw" ];
|
||||
PrivateUsers = true;
|
||||
RemoveIPC = true;
|
||||
|
||||
|
|
|
|||
|
|
@ -4,11 +4,65 @@
|
|||
name = "jellyfin";
|
||||
meta.maintainers = with lib.maintainers; [ minijackson ];
|
||||
|
||||
nodes.machine = {
|
||||
services.jellyfin.enable = true;
|
||||
environment.systemPackages = with pkgs; [ ffmpeg ];
|
||||
# Jellyfin fails to start if the data dir doesn't have at least 2GiB of free space
|
||||
virtualisation.diskSize = 3 * 1024;
|
||||
nodes = {
|
||||
machine = {
|
||||
services.jellyfin.enable = true;
|
||||
environment.systemPackages = with pkgs; [ ffmpeg ];
|
||||
# Jellyfin fails to start if the data dir doesn't have at least 2GiB of free space
|
||||
virtualisation.diskSize = 3 * 1024;
|
||||
};
|
||||
|
||||
machineWithTranscoding = {
|
||||
services.jellyfin = {
|
||||
enable = true;
|
||||
hardwareAcceleration = {
|
||||
enable = true;
|
||||
type = "vaapi";
|
||||
device = "/dev/dri/renderD128";
|
||||
};
|
||||
transcoding = {
|
||||
enableToneMapping = false;
|
||||
threadCount = 4;
|
||||
enableHardwareEncoding = true;
|
||||
enableSubtitleExtraction = false;
|
||||
deleteSegments = true;
|
||||
h264Crf = 23;
|
||||
h265Crf = 26;
|
||||
throttleTranscoding = false;
|
||||
enableIntelLowPowerEncoding = true;
|
||||
hardwareDecodingCodecs = {
|
||||
h264 = true;
|
||||
hevc = true;
|
||||
vp9 = true;
|
||||
hevcRExt10bit = true;
|
||||
hevcRExt12bit = true;
|
||||
};
|
||||
hardwareEncodingCodecs = {
|
||||
hevc = true;
|
||||
av1 = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
environment.systemPackages = with pkgs; [ ffmpeg ];
|
||||
virtualisation.diskSize = 3 * 1024;
|
||||
};
|
||||
|
||||
machineWithForceConfig = {
|
||||
services.jellyfin = {
|
||||
enable = true;
|
||||
forceEncodingConfig = true;
|
||||
hardwareAcceleration = {
|
||||
enable = true;
|
||||
type = "vaapi";
|
||||
device = "/dev/dri/renderD128";
|
||||
};
|
||||
transcoding = {
|
||||
threadCount = 2;
|
||||
};
|
||||
};
|
||||
environment.systemPackages = with pkgs; [ ffmpeg ];
|
||||
virtualisation.diskSize = 3 * 1024;
|
||||
};
|
||||
};
|
||||
|
||||
# Documentation of the Jellyfin API: https://api.jellyfin.org/
|
||||
|
|
@ -28,13 +82,46 @@
|
|||
import json
|
||||
from urllib.parse import urlencode
|
||||
|
||||
machine.wait_for_unit("jellyfin.service")
|
||||
machine.wait_for_open_port(8096)
|
||||
machine.wait_until_succeeds("journalctl --since -1m --unit jellyfin --grep 'Startup complete'")
|
||||
def wait_for_jellyfin(machine):
|
||||
machine.wait_for_unit("jellyfin.service")
|
||||
machine.wait_for_open_port(8096)
|
||||
machine.wait_until_succeeds("journalctl --since -1m --unit jellyfin --grep 'Startup complete'")
|
||||
|
||||
wait_for_jellyfin(machine)
|
||||
machine.succeed("curl --fail http://localhost:8096/")
|
||||
|
||||
machine.wait_until_succeeds("curl --fail http://localhost:8096/health | grep Healthy")
|
||||
|
||||
# Test hardware acceleration configuration
|
||||
with subtest("Hardware acceleration configuration"):
|
||||
wait_for_jellyfin(machineWithTranscoding)
|
||||
|
||||
# Check device access
|
||||
machineWithTranscoding.succeed("systemctl show jellyfin.service --property=DeviceAllow | grep '/dev/dri/renderD128 rw'")
|
||||
|
||||
# Test forceEncodingConfig backup functionality
|
||||
with subtest("Force encoding config creates backup"):
|
||||
wait_for_jellyfin(machineWithForceConfig)
|
||||
|
||||
# Verify encoding.xml exists
|
||||
machineWithForceConfig.succeed("test -f /var/lib/jellyfin/config/encoding.xml")
|
||||
|
||||
# Stop service before modifying config
|
||||
machineWithForceConfig.succeed("systemctl stop jellyfin.service")
|
||||
|
||||
# Create a marker in the current encoding.xml to verify backup works
|
||||
machineWithForceConfig.succeed("echo '<!-- MARKER -->' > /var/lib/jellyfin/config/encoding.xml")
|
||||
|
||||
# Restart the service to trigger the backup
|
||||
machineWithForceConfig.succeed("systemctl restart jellyfin.service")
|
||||
wait_for_jellyfin(machineWithForceConfig)
|
||||
|
||||
# Verify backup was created with the marker (uses glob pattern for timestamped backup)
|
||||
machineWithForceConfig.succeed("grep -q 'MARKER' /var/lib/jellyfin/config/encoding.xml.backup-*")
|
||||
|
||||
# Verify the new encoding.xml does not have the marker (was overwritten)
|
||||
machineWithForceConfig.fail("grep -q 'MARKER' /var/lib/jellyfin/config/encoding.xml")
|
||||
|
||||
auth_header = 'MediaBrowser Client="NixOS Integration Tests", DeviceId="1337", Device="Apple II", Version="20.09"'
|
||||
|
||||
|
||||
|
|
@ -48,6 +135,55 @@
|
|||
else:
|
||||
return f"curl --fail -X post 'http://localhost:8096{path}' -H 'X-Emby-Authorization:{auth_header}'"
|
||||
|
||||
# Test dashboard-based configuration verification
|
||||
with subtest("Dashboard configuration verification"):
|
||||
# Complete setup and get admin token
|
||||
machineWithTranscoding.wait_until_succeeds(api_get("/Startup/Configuration"))
|
||||
machineWithTranscoding.succeed(api_get("/Startup/FirstUser"))
|
||||
machineWithTranscoding.succeed(api_post("/Startup/Complete"))
|
||||
|
||||
auth_result = json.loads(machineWithTranscoding.succeed(
|
||||
api_post("/Users/AuthenticateByName", "${payloads.auth}")
|
||||
))
|
||||
token = auth_result["AccessToken"]
|
||||
|
||||
def api_get_with_token(path):
|
||||
return f"curl --fail 'http://localhost:8096{path}' -H 'X-Emby-Authorization:MediaBrowser Client=\"Test\", DeviceId=\"test\", Token={token}'"
|
||||
|
||||
# Get encoding config and verify key settings
|
||||
config = json.loads(machineWithTranscoding.succeed(api_get_with_token("/System/Configuration/encoding")))
|
||||
|
||||
# Main hardware acceleration settings verification
|
||||
assert config.get("HardwareAccelerationType") == "vaapi", f"Hardware acceleration type: expected 'vaapi', got '{config.get('HardwareAccelerationType')}'"
|
||||
assert config.get("VaapiDevice") == "/dev/dri/renderD128", f"VAAPI device: expected '/dev/dri/renderD128', got '{config.get('VaapiDevice')}'"
|
||||
assert config.get("EncodingThreadCount") == 4, f"Thread count: expected 4, got '{config.get('EncodingThreadCount')}'"
|
||||
assert config.get("EnableHardwareEncoding") == True, f"Hardware encoding: expected True, got '{config.get('EnableHardwareEncoding')}'"
|
||||
|
||||
# Transcoding settings verification
|
||||
assert config.get("H264Crf") == 23, f"H264 CRF: expected 23, got '{config.get('H264Crf')}'"
|
||||
assert config.get("H265Crf") == 26, f"H265 CRF: expected 26, got '{config.get('H265Crf')}'"
|
||||
assert config.get("EnableTonemapping") == False, f"Tone mapping: expected False, got '{config.get('EnableTonemapping')}'"
|
||||
assert config.get("EnableThrottling") == False, f"Throttling: expected False, got '{config.get('EnableThrottling')}'"
|
||||
assert config.get("EnableSubtitleExtraction") == False, f"Subtitle extraction: expected False, got '{config.get('EnableSubtitleExtraction')}'"
|
||||
|
||||
# Hardware encoding codecs verification
|
||||
assert config.get("AllowHevcEncoding") == True, f"Allow HEVC encoding: expected True, got '{config.get('AllowHevcEncoding')}'"
|
||||
assert config.get("AllowAv1Encoding") == True, f"Allow AV1 encoding: expected True, got '{config.get('AllowAv1Encoding')}'"
|
||||
|
||||
# Intel low power encoding verification
|
||||
assert config.get("EnableIntelLowPowerH264HwEncoder") == True, f"Intel low power H264: expected True, got '{config.get('EnableIntelLowPowerH264HwEncoder')}'"
|
||||
assert config.get("EnableIntelLowPowerHevcHwEncoder") == True, f"Intel low power HEVC: expected True, got '{config.get('EnableIntelLowPowerHevcHwEncoder')}'"
|
||||
|
||||
# HEVC RExt color depth verification
|
||||
assert config.get("EnableDecodingColorDepth10HevcRext") == True, f"HEVC RExt 10bit: expected True, got '{config.get('EnableDecodingColorDepth10HevcRext')}'"
|
||||
assert config.get("EnableDecodingColorDepth12HevcRext") == True, f"HEVC RExt 12bit: expected True, got '{config.get('EnableDecodingColorDepth12HevcRext')}'"
|
||||
|
||||
# Hardware decoding codecs verification
|
||||
decoding_codecs = config.get("HardwareDecodingCodecs", [])
|
||||
assert "h264" in decoding_codecs, f"h264 should be in HardwareDecodingCodecs, got {decoding_codecs}"
|
||||
assert "hevc" in decoding_codecs, f"hevc should be in HardwareDecodingCodecs, got {decoding_codecs}"
|
||||
assert "vp9" in decoding_codecs, f"vp9 should be in HardwareDecodingCodecs, got {decoding_codecs}"
|
||||
|
||||
|
||||
with machine.nested("Wizard completes"):
|
||||
machine.wait_until_succeeds(api_get("/Startup/Configuration"))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue