Skip to content

Commit d195f61

Browse files
committed
fix(amf): default AMD encoding to FFmpeg
Native AMF has limited device and driver coverage, while the FFmpeg path remains the broadly supported implementation. Make FFmpeg the automatic AMD choice and expose native AMF only as an explicit experimental option. Use unambiguous encoder names across both UIs and preserve the old names as hidden aliases that retain their previous implementation semantics. Generated with [Codex](https://openai.com/codex/) Model: GPT 5.6-Sol High
1 parent 2eb4035 commit d195f61

57 files changed

Lines changed: 284 additions & 251 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

docs/configuration.md

Lines changed: 31 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -912,7 +912,7 @@ editing the `conf` file in a text editor. Use the examples as reference.
912912
<br>
913913
**FreeBSD/Linux + VA-API:**
914914
<br>
915-
Unlike with *amdvce* and *nvenc*, it doesn't matter if video encoding is done on a different GPU.
915+
Unlike with AMD AMF encoders and *nvenc*, it doesn't matter if video encoding is done on a different GPU.
916916
@code{}
917917
ls /dev/dri/renderD* # to find all devices capable of VAAPI
918918
# replace ``renderD129`` with the device from above to list the name and capabilities of the device
@@ -2662,13 +2662,19 @@ editing the `conf` file in a text editor. Use the examples as reference.
26622662
<td>For Intel graphics cards</td>
26632663
</tr>
26642664
<tr>
2665-
<td>amdvce</td>
2666-
<td>For AMD graphics cards (native AMF encoder)</td>
2665+
<td>amdvce_ffmpeg</td>
2666+
<td>For AMD graphics cards. This is the supported FFmpeg-based AMF encoder and the
2667+
implementation used by automatic selection on Windows.
2668+
@note{Existing configurations using @code{}amdvce_legacy@endcode are accepted as
2669+
a compatibility alias for @code{}amdvce_ffmpeg@endcode. The former native
2670+
@code{}amdvce@endcode value is accepted as an alias for
2671+
@code{}amdvce_experimental@endcode.}</td>
26672672
</tr>
26682673
<tr>
2669-
<td>amdvce_legacy</td>
2670-
<td>Explicit rollback to the FFmpeg-based AMD AMF encoder. Never selected automatically —
2671-
automatic probing and `amdvce` fail closed instead of silently falling back.
2674+
<td>amdvce_experimental</td>
2675+
<td>Experimental native AMD AMF encoder. It is not selected automatically, has limited
2676+
hardware test coverage, and may not work with older GPUs or driver versions. Explicit
2677+
selection fails closed instead of silently changing encoder implementations.
26722678
@note{Applies to Windows only.}</td>
26732679
</tr>
26742680
<tr>
@@ -3356,9 +3362,9 @@ They appear in the Frame Limiter section of the settings UI.
33563362
or newer, which reports AMF 1.4.32. FFmpeg refuses 10-bit P010 surfaces on any older runtime, so HDR
33573363
is not offered to clients even though Sunshine's own AMF check only needs 1.4.23. Update your
33583364
graphics drivers if HDR is unavailable on an AMD GPU. This limitation applies to the
3359-
@code{amdvce_legacy} rollback encoder only; the native @code{amdvce} encoder talks to AMF directly
3360-
and is not subject to FFmpeg's 10-bit refusal. Sunshine carries one narrow exception for the legacy
3361-
encoder: on a Radeon Pro 5500 XT (PCI @code{1002:7340}) running AMF 1.4.31.x, it presents 1.4.32 to
3365+
@code{amdvce_ffmpeg} encoder only; the experimental native @code{amdvce_experimental} encoder talks to AMF
3366+
directly and is not subject to FFmpeg's 10-bit refusal. Sunshine carries one narrow exception for the
3367+
FFmpeg-based encoder: on a Radeon Pro 5500 XT (PCI @code{1002:7340}) running AMF 1.4.31.x, it presents 1.4.32 to
33623368
FFmpeg for the duration of codec validation so HEVC Main10 is not refused. The exception is applied
33633369
automatically, has no configuration option, and does not apply to any other adapter. The detected AMF
33643370
runtime version is written to the log on every AMD HDR HEVC attempt (search for
@@ -3371,7 +3377,7 @@ runtime version is written to the log on every AMD HDR HEVC attempt (search for
33713377
<td>Description</td>
33723378
<td colspan="2">
33733379
The encoder usage profile is used to set the base set of encoding parameters.
3374-
@note{This option only applies when using amdvce [encoder](#encoder).}
3380+
@note{This option applies to the AMD [encoders](#encoder).}
33753381
@note{The other AMF options that follow will override a subset of the settings applied by your usage
33763382
profile, but there are hidden parameters set in usage profiles that cannot be overridden elsewhere.}
33773383
</td>
@@ -3418,7 +3424,7 @@ runtime version is written to the log on every AMD HDR HEVC attempt (search for
34183424
<td>Description</td>
34193425
<td colspan="2">
34203426
The encoder rate control.
3421-
@note{This option only applies when using amdvce [encoder](#encoder).}
3427+
@note{This option applies to the AMD [encoders](#encoder).}
34223428
@warning{The `vbr_latency` option generally works best, but some bitrate overshoots may still occur.
34233429
Enabling HRD allows all bitrate based rate controls to better constrain peak bitrate, but may result in
34243430
encoding artifacts depending on your card.}
@@ -3475,7 +3481,7 @@ runtime version is written to the log on every AMD HDR HEVC attempt (search for
34753481
<td colspan="2">
34763482
The target quality level used by the `qvbr` rate control method, where 1 is the lowest quality and 51
34773483
is the highest. Higher values spend more bits to preserve quality.
3478-
@note{This option only applies to AMD [encoders](#encoder) with `amd_rc` set to `qvbr`. Native `amdvce` automatically enables PreAnalysis with a one-frame low-latency lookahead for `qvbr`, `hqvbr`, and `hqcbr`.}
3484+
@note{This option only applies to AMD [encoders](#encoder) with `amd_rc` set to `qvbr`. Native `amdvce_experimental` automatically enables PreAnalysis with a one-frame low-latency lookahead for `qvbr`, `hqvbr`, and `hqcbr`.}
34793485
@note{Leave this at `0` to keep the encoder default.}
34803486
</td>
34813487
</tr>
@@ -3504,7 +3510,7 @@ runtime version is written to the log on every AMD HDR HEVC attempt (search for
35043510
<td>Description</td>
35053511
<td colspan="2">
35063512
Enable Hypothetical Reference Decoder (HRD) enforcement to help constrain the target bitrate.
3507-
@note{This option only applies when using amdvce [encoder](#encoder).}
3513+
@note{This option applies to the AMD [encoders](#encoder).}
35083514
@warning{HRD is known to cause encoding artifacts or negatively affect encoding quality on certain cards.}
35093515
</td>
35103516
</tr>
@@ -3530,7 +3536,7 @@ runtime version is written to the log on every AMD HDR HEVC attempt (search for
35303536
<td colspan="2">
35313537
The quality profile controls the tradeoff between speed and quality of encoding.
35323538
`auto` leaves the quality property unset so the selected AMF usage preset can choose it.
3533-
@note{This option only applies when using amdvce [encoder](#encoder).}
3539+
@note{This option applies to the AMD [encoders](#encoder).}
35343540
</td>
35353541
</tr>
35363542
<tr>
@@ -3570,9 +3576,9 @@ runtime version is written to the log on every AMD HDR HEVC attempt (search for
35703576
<tr>
35713577
<td>Description</td>
35723578
<td colspan="2">
3573-
Preanalysis can increase encoding quality at the cost of latency. Native `amdvce` uses a one-frame
3579+
Preanalysis can increase encoding quality at the cost of latency. Native `amdvce_experimental` uses a one-frame
35743580
low-latency lookahead; it is enabled automatically by `qvbr`, `hqvbr`, and `hqcbr`. The setting is
3575-
also forwarded to `amdvce_legacy`.
3581+
also forwarded to `amdvce_ffmpeg`.
35763582
</td>
35773583
</tr>
35783584
<tr>
@@ -3599,7 +3605,7 @@ runtime version is written to the log on every AMD HDR HEVC attempt (search for
35993605
allocation of more bits to smooth areas compared to more textured areas.
36003606
`auto` leaves the property unset so the selected AMF usage preset can choose it. VBAQ is enabled
36013607
by default.
3602-
@note{This option only applies when using amdvce [encoder](#encoder).}
3608+
@note{This option applies to the AMD [encoders](#encoder).}
36033609
</td>
36043610
</tr>
36053611
<tr>
@@ -3636,8 +3642,7 @@ runtime version is written to the log on every AMD HDR HEVC attempt (search for
36363642
<td>Description</td>
36373643
<td colspan="2">
36383644
The entropy encoding to use.
3639-
@note{This option only applies when using H.264 with the amdvce
3640-
[encoder](#encoder).}
3645+
@note{This option only applies when using H.264 with an AMD [encoder](#encoder).}
36413646
</td>
36423647
</tr>
36433648
<tr>
@@ -3675,7 +3680,7 @@ runtime version is written to the log on every AMD HDR HEVC attempt (search for
36753680
<td colspan="2">
36763681
Enable AV1 screen-content coding tools, which can improve efficiency and text/UI clarity for desktop and
36773682
screen-heavy content.
3678-
@note{AV1 only. This option only applies to the native amdvce [encoder](#encoder) (not amdvce_legacy).}
3683+
@note{AV1 only. This option only applies to the native amdvce_experimental [encoder](#encoder) (not amdvce_ffmpeg).}
36793684
@note{Leave at `auto` to use the driver default.}
36803685
</td>
36813686
</tr>
@@ -3713,7 +3718,7 @@ runtime version is written to the log on every AMD HDR HEVC attempt (search for
37133718
<td>Description</td>
37143719
<td colspan="2">
37153720
AV1 encoding-latency tier. Lower tiers finish each frame faster at the cost of higher power draw.
3716-
@note{AV1 only. This option only applies to the native amdvce [encoder](#encoder) (not amdvce_legacy).}
3721+
@note{AV1 only. This option only applies to the native amdvce_experimental [encoder](#encoder) (not amdvce_ffmpeg).}
37173722
@note{Leave at `auto` to use the driver default.}
37183723
</td>
37193724
</tr>
@@ -4202,23 +4207,23 @@ playnite_exclude_categories = ["Steam", {"id": "deck", "name": "Steam Deck"}]
42024207

42034208
### amd_ltr_frames
42044209

4205-
Sets the number of long-term reference frames used by the native AMD encoder. Leave this at the automatic default unless a client or driver-specific recovery workflow requires a fixed value.
4210+
Sets the number of long-term reference frames used by the experimental native AMD encoder. Leave this at the automatic default unless a client or driver-specific recovery workflow requires a fixed value.
42064211

42074212
### amd_input_queue_size
42084213

4209-
Sets the native AMD encoder input queue depth. A positive explicit value overrides automatic low-latency queue selection.
4214+
Sets the experimental native AMD encoder input queue depth. A positive explicit value overrides automatic low-latency queue selection.
42104215

42114216
### amd_smart_access_video
42124217

4213-
Controls AMD SmartAccess Video when the installed AMF runtime exposes that capability. Use `auto` to leave the driver default unchanged.
4218+
Controls SmartAccess Video for the experimental native AMD encoder when the installed AMF runtime exposes that capability. Use `auto` to leave the driver default unchanged.
42144219

42154220
### amd_lowlatency_mode
42164221

4217-
Controls AMD's native encoder low-latency mode. Use `auto` to leave the driver default unchanged.
4222+
Controls the experimental native AMD encoder's low-latency mode. Use `auto` to leave the driver default unchanged.
42184223

42194224
### amd_high_motion_quality_boost
42204225

4221-
Controls AMD's high-motion quality boost. Use `auto` to leave the driver default unchanged.
4226+
Controls high-motion quality boost for the experimental native AMD encoder. Use `auto` to leave the driver default unchanged.
42224227

42234228
### dd_paused_virtual_display_timeout_secs
42244229

src/amf/amf_lifecycle.h

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -227,18 +227,30 @@ namespace amf::lifecycle {
227227
};
228228

229229
struct encoder_selection_policy_t {
230-
bool include_legacy = false;
230+
bool include_experimental = false;
231231
bool fail_closed = false;
232232
};
233233

234+
inline constexpr std::string_view canonical_encoder_name(
235+
std::string_view requested_encoder) noexcept {
236+
if (requested_encoder == "amdvce_legacy") {
237+
return "amdvce_ffmpeg";
238+
}
239+
if (requested_encoder == "amdvce") {
240+
return "amdvce_experimental";
241+
}
242+
return requested_encoder;
243+
}
244+
234245
inline constexpr encoder_selection_policy_t encoder_selection_policy(
235246
std::string_view requested_encoder) noexcept {
236-
// Native AMF and the FFmpeg AMF implementation are separate, explicit
237-
// contracts. Automatic probing must never make a native feature/property
238-
// failure look successful by selecting the legacy encoder behind the user.
247+
// The FFmpeg AMF implementation is the supported default. The native AMF
248+
// implementation has limited hardware coverage and is only considered when
249+
// the user explicitly opts into the experimental encoder.
250+
const auto canonical_encoder = canonical_encoder_name(requested_encoder);
239251
return {
240-
requested_encoder == "amdvce_legacy",
241-
requested_encoder == "amdvce",
252+
canonical_encoder == "amdvce_experimental",
253+
canonical_encoder == "amdvce_experimental",
242254
};
243255
}
244256

src/config.cpp

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include <nlohmann/json.hpp>
3434

3535
// local includes
36+
#include "amf/amf_lifecycle.h"
3637
#include "config.h"
3738
#include "config_key.h"
3839
#include "config_playnite.h"
@@ -1714,7 +1715,7 @@ namespace config {
17141715
int_f(vars, "amd_vbaq", video.amd.amd_vbaq, amd::tristate_from_view);
17151716
bool_f(vars, "amd_enforce_hrd", (bool &) video.amd.amd_enforce_hrd);
17161717

1717-
// Native AMF encoder (amdvce) tuning knobs.
1718+
// Native AMF encoder (amdvce_experimental) tuning knobs.
17181719
int_f(vars, "amd_ltr_frames", video.amd.amd_ltr_frames);
17191720
if (video.amd.amd_ltr_frames < 0 || video.amd.amd_ltr_frames > 2) {
17201721
BOOST_LOG(warning) << "config: amd_ltr_frames must be between 0 and 2, clamping: "sv << video.amd.amd_ltr_frames;
@@ -1755,6 +1756,12 @@ namespace config {
17551756
string_f(vars, "capture", video.capture);
17561757
bool_f(vars, "wgc_pacing_smoothing", video.wgc_pacing_smoothing);
17571758
string_f(vars, "encoder", video.encoder);
1759+
const auto configured_encoder = video.encoder;
1760+
video.encoder = std::string(amf::lifecycle::canonical_encoder_name(video.encoder));
1761+
if (video.encoder != configured_encoder) {
1762+
BOOST_LOG(info) << "config: encoder = " << configured_encoder
1763+
<< " is deprecated; using " << video.encoder << '.';
1764+
}
17581765
string_f(vars, "adapter_name", video.adapter_name);
17591766
string_f(vars, "adapter_pnp_id", video.adapter_pnp_id);
17601767
if (!video.adapter_pnp_id.empty() && video.adapter_name.empty()) {
@@ -2832,7 +2839,10 @@ namespace config {
28322839
if (name == adapter_pnp_id_key) {
28332840
continue;
28342841
}
2835-
base.insert_or_assign(name, value);
2842+
base.insert_or_assign(
2843+
name,
2844+
name == "encoder" ? std::string(amf::lifecycle::canonical_encoder_name(value)) : value
2845+
);
28362846
}
28372847

28382848
const auto adapter_name = overrides.find(std::string(adapter_name_key));
@@ -3077,6 +3087,9 @@ namespace config {
30773087
if (!is_valid_override_key(normalized_key) || !is_allowed_override_key(normalized_key)) {
30783088
continue;
30793089
}
3090+
if (normalized_key == "encoder") {
3091+
v = std::string(amf::lifecycle::canonical_encoder_name(v));
3092+
}
30803093
filtered.emplace(std::move(normalized_key), std::move(v));
30813094
}
30823095

src/config.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ namespace config {
9696
std::optional<int> amd_preanalysis;
9797
std::optional<int> amd_vbaq; // nullopt = follow usage-preset default
9898
int amd_coder;
99-
// Native AMF encoder (amdvce) tuning knobs.
99+
// Native AMF encoder (amdvce_experimental) tuning knobs.
100100
int amd_ltr_frames; // Long-term reference frames for RFI (0 = off)
101101
int amd_input_queue_size; // AMF input queue depth (0 = driver default)
102102
// Curated tri-state native-AMF feature knobs. nullopt (auto) leaves the

src/platform/windows/display_vram.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2221,7 +2221,7 @@ namespace platf::dxgi {
22212221
<< " bitrate=" << client_config.bitrate << "kbps (active=" << active_encoder_count << ')';
22222222

22232223
// AMF SDK integer values are passed straight through from the existing
2224-
// amd_* config (shared with the FFmpeg amdvce_legacy path).
2224+
// amd_* config (shared with the FFmpeg amdvce_ffmpeg path).
22252225
if (client_config.videoFormat == 0) {
22262226
amf_cfg.usage = config::video.amd.amd_usage_h264;
22272227
amf_cfg.quality_preset = config::video.amd.amd_quality_h264;

0 commit comments

Comments
 (0)