mirror of
https://github.com/rustdesk/rustdesk.git
synced 2026-09-07 21:11:05 +03:00
fix svt-av1 build on windows, benchmark
Signed-off-by: 21pages <sunboeasy@gmail.com>
This commit is contained in:
1096
libs/scrap/examples/av1_benchmark.rs
Normal file
1096
libs/scrap/examples/av1_benchmark.rs
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1176,6 +1176,8 @@ pub fn test_av1() {
|
||||
height,
|
||||
quality,
|
||||
keyframe_interval,
|
||||
qp_range: None,
|
||||
preset: None,
|
||||
}),
|
||||
i444,
|
||||
)
|
||||
|
||||
@@ -30,6 +30,13 @@ pub struct SvtAv1EncoderConfig {
|
||||
pub height: u32,
|
||||
pub quality: f32,
|
||||
pub keyframe_interval: Option<usize>,
|
||||
// SVT cannot update min/max QP on the fly. Product callers leave this
|
||||
// unset so dynamic quality changes retain the full project QP envelope;
|
||||
// controlled comparisons can pin the same range used by another encoder.
|
||||
pub qp_range: Option<(u32, u32)>,
|
||||
// RTC supports M7 through M13. Product callers use the screen-content
|
||||
// default; benchmarks can override it to measure the speed/quality curve.
|
||||
pub preset: Option<i8>,
|
||||
}
|
||||
|
||||
pub struct SvtAv1Encoder {
|
||||
@@ -68,6 +75,16 @@ impl EncoderApi for SvtAv1Encoder {
|
||||
config.height
|
||||
);
|
||||
}
|
||||
if let Some((min_qp, max_qp)) = config.qp_range {
|
||||
if min_qp > max_qp || max_qp > 63 {
|
||||
bail!("invalid svt-av1 QP range {min_qp}..{max_qp}");
|
||||
}
|
||||
}
|
||||
if let Some(preset) = config.preset {
|
||||
if !(7..=13).contains(&preset) {
|
||||
bail!("invalid svt-av1 RTC preset M{preset}; expected M7..M13");
|
||||
}
|
||||
}
|
||||
let mut handle: *mut EbComponentType = ptr::null_mut();
|
||||
let mut c: MaybeUninit<EbSvtAv1EncConfiguration> = MaybeUninit::zeroed();
|
||||
let res = unsafe { svt_av1_enc_init_handle(&mut handle, c.as_mut_ptr()) };
|
||||
@@ -176,7 +193,9 @@ impl SvtAv1Encoder {
|
||||
}
|
||||
|
||||
fn apply_config(c: &mut EbSvtAv1EncConfiguration, cfg: &SvtAv1EncoderConfig, bitrate: u32) {
|
||||
c.enc_mode = Self::preset(cfg.width, cfg.height);
|
||||
c.enc_mode = cfg
|
||||
.preset
|
||||
.unwrap_or_else(|| Self::preset(cfg.width, cfg.height));
|
||||
c.source_width = cfg.width;
|
||||
c.source_height = cfg.height;
|
||||
// CBR budgets bits per frame from this rate, set_fps adjusts it on the
|
||||
@@ -190,18 +209,35 @@ impl SvtAv1Encoder {
|
||||
// blocks until the packet for the sent picture is ready, and rate/keyframe
|
||||
// changes on the fly are allowed.
|
||||
c.pred_structure = PredStructure::LOW_DELAY;
|
||||
// A four-picture temporal hierarchy improves reference efficiency without
|
||||
// introducing B-frame reordering. Two is also the highest hierarchy SVT
|
||||
// validates for low-delay CBR, and still preserves one packet per input.
|
||||
c.hierarchical_levels = 2;
|
||||
c.rtc = true;
|
||||
c.rate_control_mode = SvtAv1RcMode::SVT_AV1_RC_MODE_CBR as _;
|
||||
c.target_bit_rate = bitrate.min(MAX_TARGET_BITRATE_KBPS) * 1000;
|
||||
// Full envelope of aom's calc_q_values so later bitrate changes are not clipped.
|
||||
c.min_qp_allowed = 5;
|
||||
c.max_qp_allowed = 45;
|
||||
let (q_min, q_max) = Self::calc_q_values(cfg.quality);
|
||||
c.qp = (q_min + q_max) / 2;
|
||||
let initial_qp_range = Self::quality_qp_range(cfg.quality);
|
||||
let (min_qp, max_qp) = cfg.qp_range.unwrap_or((5, 45));
|
||||
c.min_qp_allowed = min_qp;
|
||||
c.max_qp_allowed = max_qp;
|
||||
c.qp = ((initial_qp_range.0 + initial_qp_range.1) / 2).clamp(min_qp, max_qp);
|
||||
c.look_ahead_distance = 0;
|
||||
c.recode_loop = 0; // DISALLOW_RECODE
|
||||
// SVT 4.2's RTC CBR path only re-runs mode decision once when an inter
|
||||
// frame would overflow the virtual buffer. This keeps network bursts
|
||||
// bounded without enabling unrestricted multi-pass re-encoding.
|
||||
c.recode_loop = 1; // ALLOW_RECODE_KFMAXBW / one RTC VBV recode
|
||||
c.scene_change_detection = 0;
|
||||
c.screen_content_mode = 1;
|
||||
// Temporal filtering is primarily useful for camera/video content. It
|
||||
// costs CPU and can soften text, while low-delay screen sharing cannot
|
||||
// benefit from future-frame filtering.
|
||||
c.enable_tf = 0;
|
||||
c.enable_tf_key = false;
|
||||
c.enable_overlays = false;
|
||||
// Use SVT's anti-alias-aware adaptive screen detection: UI/text can use
|
||||
// Palette and IntraBC while camera/video regions stay on the natural-
|
||||
// content path. RTC only supports these tools at M8 or slower.
|
||||
c.screen_content_mode = 3;
|
||||
c.enable_intrabc = true;
|
||||
c.tune = 1; // PSNR, low delay does not support tune 0
|
||||
c.level_of_parallelism = Self::parallelism();
|
||||
c.intra_refresh_type = SvtAv1IntraRefreshType::SVT_AV1_KF_REFRESH; // closed GOP
|
||||
@@ -215,15 +251,11 @@ impl SvtAv1Encoder {
|
||||
c.force_key_frames = false;
|
||||
}
|
||||
|
||||
fn preset(width: u32, height: u32) -> i8 {
|
||||
// Mirrors aom's get_cpu_speed buckets, M9-M13 are the rtc presets.
|
||||
if width * height <= 320 * 180 {
|
||||
9
|
||||
} else if width * height <= 640 * 360 {
|
||||
10
|
||||
} else {
|
||||
11
|
||||
}
|
||||
fn preset(_width: u32, _height: u32) -> i8 {
|
||||
// SVT-AV1 forces screen_content_mode to 0 for RTC presets M9 and faster,
|
||||
// so use M8 to keep the screen-content path enabled.
|
||||
// TODO: After benchmarking, select a quality-dependent preset in M0..=M8.
|
||||
8
|
||||
}
|
||||
|
||||
fn parallelism() -> u32 {
|
||||
@@ -353,9 +385,9 @@ impl SvtAv1Encoder {
|
||||
(bitrate * ratio) as u32
|
||||
}
|
||||
|
||||
// Same mapping as AomEncoder::calc_q_values, only used to seed the start qp.
|
||||
// Same mapping as AomEncoder::calc_q_values.
|
||||
#[inline]
|
||||
fn calc_q_values(ratio: f32) -> (u32, u32) {
|
||||
pub fn quality_qp_range(ratio: f32) -> (u32, u32) {
|
||||
let b = (ratio * 100.0) as u32;
|
||||
let b = std::cmp::min(b, 200);
|
||||
let q_min1 = 24;
|
||||
@@ -447,6 +479,8 @@ mod tests {
|
||||
height,
|
||||
quality: 1.0,
|
||||
keyframe_interval: None,
|
||||
qp_range: None,
|
||||
preset: None,
|
||||
}),
|
||||
false,
|
||||
)
|
||||
@@ -480,7 +514,7 @@ mod tests {
|
||||
assert_eq!(img.width(), width as usize);
|
||||
decoded += 1;
|
||||
}
|
||||
assert!(decoded >= 1, "aom failed to decode svt-av1 frame {i}");
|
||||
assert!(decoded >= 1, "aom failed to decode svt-av1 frame {}", i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -492,6 +526,8 @@ mod tests {
|
||||
height: 62,
|
||||
quality: 1.0,
|
||||
keyframe_interval: None,
|
||||
qp_range: None,
|
||||
preset: None,
|
||||
}),
|
||||
false,
|
||||
)
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
diff --git a/CMakeLists.txt b/CMakeLists.txt
|
||||
index c0c9767..93ec320 100644
|
||||
--- a/CMakeLists.txt
|
||||
+++ b/CMakeLists.txt
|
||||
@@ -192,7 +192,7 @@ set(PC_LIBS_PRIVATE)
|
||||
set(PC_REQUIRES_PRIVATE)
|
||||
|
||||
@@ -194,5 +194,5 @@
|
||||
#Clang support, required to build static with LTO
|
||||
-if(CMAKE_C_COMPILER_ID MATCHES "Clang" AND UNIX AND NOT APPLE)
|
||||
+if(FALSE)
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
diff --git a/Source/Lib/ASM_AVX2/synonyms_avx2.h b/Source/Lib/ASM_AVX2/synonyms_avx2.h
|
||||
index f615e2569..9a7667724 100644
|
||||
--- a/Source/Lib/ASM_AVX2/synonyms_avx2.h
|
||||
+++ b/Source/Lib/ASM_AVX2/synonyms_avx2.h
|
||||
@@ -75,7 +75,13 @@ static INLINE __m256i yy_loadu2_128(const void *hi, const void *lo) {
|
||||
return yy_set_m128i(mhi, mlo);
|
||||
}
|
||||
|
||||
@@ -86,3 +86,9 @@
|
||||
-static INLINE __m256i yy_unpacklo_epi128(const __m256i in0, const __m256i in1) {
|
||||
+#if defined(_MSC_VER) && _MSC_VER >= 1950
|
||||
+#define MAYBE_INLINE NOINLINE
|
||||
@@ -16,4 +12,3 @@ index f615e2569..9a7667724 100644
|
||||
+static MAYBE_INLINE __m256i yy_unpacklo_epi128(const __m256i in0, const __m256i in1) {
|
||||
return _mm256_inserti128_si256(in0, _mm256_castsi256_si128(in1), 1);
|
||||
}
|
||||
|
||||
|
||||
@@ -1042,6 +1042,8 @@ fn get_encoder_config(
|
||||
height: c.height as _,
|
||||
quality,
|
||||
keyframe_interval,
|
||||
qp_range: None,
|
||||
preset: None,
|
||||
});
|
||||
}
|
||||
log::info!(
|
||||
|
||||
Reference in New Issue
Block a user