Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -2788,6 +2788,40 @@ editing the `conf` file in a text editor. Use the examples as reference.
</tr>
</table>

### amd_max_au_size

<table>
<tr>
<td>Description</td>
<td colspan="2">
Maximum Access Unit (frame) size for rate control, in bits. When set, the encoder
will cap the maximum encoded frame size. This prevents oversized frames from exceeding
FEC shard limits (DATA_SHARDS_MAX=255), which otherwise causes FEC to be skipped for
those frames. This is especially important for Wi-Fi streaming where packet loss on
large unprotected frames leads to dropped frames and stuttering.
@note{This option only applies to H.264 and HEVC when using amdvce [encoder](#encoder).
AV1 does not support this option.}
@note{Works with all rate control modes (CQP, CBR, VBR). Most beneficial with CQP
where frame sizes are otherwise unbounded.}
@note{Value is in bits. To calculate: (target_bitrate_mbps / fps / 1.2) × 1000000,
where 1.2 accounts for ~20% FEC overhead. Examples: 800000 for ~50 Mbps at 60fps,
1600000 for ~100 Mbps at 60fps, 400000 for ~50 Mbps at 120fps.}
</td>
</tr>
<tr>
<td>Default</td>
<td colspan="2">@code{}

@endcode</td>
</tr>
<tr>
<td>Example</td>
<td colspan="2">@code{}
amd_max_au_size = 800000
@endcode</td>
</tr>
</table>

## VideoToolbox Encoder

### vt_coder
Expand Down
2 changes: 2 additions & 0 deletions src/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,7 @@ namespace config {
(int) amd::quality_av1_e::balanced, // quality (av1)
0, // preanalysis
1, // vbaq
{}, // max_au_size (disabled by default)
(int) amd::coder_e::_auto, // coder
}, // amd

Expand Down Expand Up @@ -1129,6 +1130,7 @@ namespace config {
bool_f(vars, "amd_preanalysis", (bool &) video.amd.amd_preanalysis);
bool_f(vars, "amd_vbaq", (bool &) video.amd.amd_vbaq);
bool_f(vars, "amd_enforce_hrd", (bool &) video.amd.amd_enforce_hrd);
int_f(vars, "amd_max_au_size", video.amd.amd_max_au_size);
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This parses amd_max_au_size as an optional int but does not enforce non-negative values, and it will treat an explicit "0" as a configured value (so it will still be passed through to FFmpeg). If the intent is “0/empty disables”, consider normalizing values <= 0 to nullopt here (or validating a non-negative range) so downstream option application can skip setting the codec option entirely.

Suggested change
int_f(vars, "amd_max_au_size", video.amd.amd_max_au_size);
int_f(vars, "amd_max_au_size", video.amd.amd_max_au_size);
if (video.amd.amd_max_au_size && *video.amd.amd_max_au_size <= 0) {
video.amd.amd_max_au_size.reset();
}

Copilot uses AI. Check for mistakes.

int_f(vars, "vt_coder", video.vt.vt_coder, vt::coder_from_view);
int_f(vars, "vt_software", video.vt.vt_allow_sw, vt::allow_software_from_view);
Expand Down
1 change: 1 addition & 0 deletions src/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ namespace config {
std::optional<int> amd_quality_av1;
std::optional<int> amd_preanalysis;
std::optional<int> amd_vbaq;
std::optional<int> amd_max_au_size;
int amd_coder;
} amd;

Expand Down
2 changes: 2 additions & 0 deletions src/video.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -776,6 +776,7 @@ namespace video {
{"usage"s, &config::video.amd.amd_usage_hevc},
{"vbaq"s, &config::video.amd.amd_vbaq},
{"enforce_hrd"s, &config::video.amd.amd_enforce_hrd},
{"max_au_size"s, &config::video.amd.amd_max_au_size},
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The AMF "max_au_size" AVOption in FFmpeg for h264_amf/hevc_amf is specified in bits (and FFmpeg commonly uses -1 as the disable sentinel). The UI/docs describe this value as bytes and recommend 800000, which will be interpreted as ~100KB if passed through unchanged. Either convert bytes->bits before setting the codec option, or update the config/UI/docs to clearly use bits (and document the disable behavior).

Suggested change
{"max_au_size"s, &config::video.amd.amd_max_au_size},
{"max_au_size"s, []() {
// Config/UI use bytes; FFmpeg AMF option expects bits. Negative disables (maps to -1).
const int value_bytes = config::video.amd.amd_max_au_size;
if (value_bytes < 0) {
return -1;
}
return value_bytes * 8;
}},

Copilot uses AI. Check for mistakes.
{"level"s, [](const config_t &cfg) {
auto size = cfg.width * cfg.height;
// For 4K and below, try to use level 5.1 or 5.2 if possible
Expand Down Expand Up @@ -813,6 +814,7 @@ namespace video {
{"usage"s, &config::video.amd.amd_usage_h264},
{"vbaq"s, &config::video.amd.amd_vbaq},
{"enforce_hrd"s, &config::video.amd.amd_enforce_hrd},
{"max_au_size"s, &config::video.amd.amd_max_au_size},
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above: the FFmpeg "max_au_size" option is in bits. Passing the config value through as-is while documenting bytes will lead to an incorrect cap. Consider converting bytes->bits (and treating 0/empty as unset) before setting this option.

Suggested change
{"max_au_size"s, &config::video.amd.amd_max_au_size},
{"max_au_size"s, []() {
const auto bytes = config::video.amd.amd_max_au_size;
if (bytes <= 0) {
return 0;
}
return bytes * 8;
}},

Copilot uses AI. Check for mistakes.
},
{}, // SDR-specific options
{}, // HDR-specific options
Expand Down
1 change: 1 addition & 0 deletions src_assets/common/assets/web/config.html
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,7 @@ <h1 class="my-4">{{ $t('config.configuration') }}</h1>
"amd_preanalysis": "disabled",
"amd_vbaq": "enabled",
"amd_coder": "auto",
"amd_max_au_size": "",
},
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,14 @@ const config = ref(props.config)
v-model="config.amd_enforce_hrd"
default="false"
></Checkbox>

<!-- AMF Max AU Size -->
<div class="mb-3">
<label for="amd_max_au_size" class="form-label">{{ $t('config.amd_max_au_size') }}</label>
<input type="number" class="form-control" id="amd_max_au_size"
placeholder="-1" min="-1" v-model="config.amd_max_au_size" />
<div class="form-text">{{ $t('config.amd_max_au_size_desc') }}</div>
</div>
</div>
</div>
</div>
Expand Down
2 changes: 2 additions & 0 deletions src_assets/common/assets/web/public/assets/locale/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@
"amd_coder_desc": "Allows you to select the entropy encoding to prioritize quality or encoding speed. H.264 only.",
"amd_enforce_hrd": "AMF Hypothetical Reference Decoder (HRD) Enforcement",
"amd_enforce_hrd_desc": "Increases the constraints on rate control to meet HRD model requirements. This greatly reduces bitrate overflows, but may cause encoding artifacts or reduced quality on certain cards.",
"amd_max_au_size": "AMF Max AU Size (bits)",
"amd_max_au_size_desc": "Maximum Access Unit (frame) size in bits. Empty or -1 disables. Prevents oversized frames from exceeding FEC limits on Wi-Fi. H.264 and HEVC only. Formula: (target_bitrate_mbps / fps / 1.2) * 1000000. Example at 50 Mbps 60fps: (50/60/1.2)*1000000 = 694444. Recommended: 800000 for ~50 Mbps Wi-Fi.",
"amd_preanalysis": "AMF Preanalysis",
"amd_preanalysis_desc": "This enables rate-control preanalysis, which may increase quality at the expense of increased encoding latency.",
"amd_quality": "AMF Quality",
Expand Down