mirror of
https://github.com/rustdesk/rustdesk.git
synced 2026-03-29 16:11:01 +03:00
codec set quality seperately and refactor network delay
Signed-off-by: 21pages <pages21@163.com>
This commit is contained in:
@@ -7,7 +7,7 @@ use hbb_common::log;
|
||||
use hbb_common::message_proto::{EncodedVideoFrame, EncodedVideoFrames, Message, VideoFrame};
|
||||
use hbb_common::ResultType;
|
||||
|
||||
use crate::codec::EncoderApi;
|
||||
use crate::codec::{base_bitrate, EncoderApi, Quality};
|
||||
use crate::{GoogleImage, STRIDE_ALIGN};
|
||||
|
||||
use super::vpx::{vp8e_enc_control_id::*, vpx_codec_err_t::*, *};
|
||||
@@ -19,6 +19,9 @@ use std::{ptr, slice};
|
||||
generate_call_macro!(call_vpx, false);
|
||||
generate_call_ptr_macro!(call_vpx_ptr);
|
||||
|
||||
const DEFAULT_QP_MAX: u32 = 56; // no more than 63
|
||||
const DEFAULT_QP_MIN: u32 = 12; // no more than 63
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub enum VpxVideoCodecId {
|
||||
VP8,
|
||||
@@ -64,8 +67,9 @@ impl EncoderApi for VpxEncoder {
|
||||
c.g_h = config.height;
|
||||
c.g_timebase.num = config.timebase[0];
|
||||
c.g_timebase.den = config.timebase[1];
|
||||
c.rc_target_bitrate = config.bitrate;
|
||||
c.rc_undershoot_pct = 95;
|
||||
// When the data buffer falls below this percentage of fullness, a dropped frame is indicated. Set the threshold to zero (0) to disable this feature.
|
||||
// In dynamic scenes, low bitrate gets low fps while high bitrate gets high fps.
|
||||
c.rc_dropframe_thresh = 25;
|
||||
c.g_threads = if config.num_threads == 0 {
|
||||
num_cpus::get() as _
|
||||
@@ -79,6 +83,21 @@ impl EncoderApi for VpxEncoder {
|
||||
// c.kf_min_dist = 0;
|
||||
// c.kf_max_dist = 999999;
|
||||
c.kf_mode = vpx_kf_mode::VPX_KF_DISABLED; // reduce bandwidth a lot
|
||||
let (q_min, q_max, b) = Self::convert_quality(config.quality);
|
||||
if q_min > 0 && q_min < q_max && q_max < 64 {
|
||||
c.rc_min_quantizer = q_min;
|
||||
c.rc_max_quantizer = q_max;
|
||||
} else {
|
||||
c.rc_min_quantizer = DEFAULT_QP_MIN;
|
||||
c.rc_max_quantizer = DEFAULT_QP_MAX;
|
||||
}
|
||||
let base_bitrate = base_bitrate(config.width as _, config.height as _);
|
||||
let bitrate = base_bitrate * b / 100;
|
||||
if bitrate > 0 {
|
||||
c.rc_target_bitrate = bitrate;
|
||||
} else {
|
||||
c.rc_target_bitrate = base_bitrate;
|
||||
}
|
||||
|
||||
/*
|
||||
The VPX encoder supports two-pass encoding for rate control purposes.
|
||||
@@ -177,11 +196,24 @@ impl EncoderApi for VpxEncoder {
|
||||
true
|
||||
}
|
||||
|
||||
fn set_bitrate(&mut self, bitrate: u32) -> ResultType<()> {
|
||||
let mut new_enc_cfg = unsafe { *self.ctx.config.enc.to_owned() };
|
||||
new_enc_cfg.rc_target_bitrate = bitrate;
|
||||
call_vpx!(vpx_codec_enc_config_set(&mut self.ctx, &new_enc_cfg));
|
||||
return Ok(());
|
||||
fn set_quality(&mut self, quality: Quality) -> ResultType<()> {
|
||||
let mut c = unsafe { *self.ctx.config.enc.to_owned() };
|
||||
let (q_min, q_max, b) = Self::convert_quality(quality);
|
||||
if q_min > 0 && q_min < q_max && q_max < 64 {
|
||||
c.rc_min_quantizer = q_min;
|
||||
c.rc_max_quantizer = q_max;
|
||||
}
|
||||
let bitrate = base_bitrate(self.width as _, self.height as _) * b / 100;
|
||||
if bitrate > 0 {
|
||||
c.rc_target_bitrate = bitrate;
|
||||
}
|
||||
call_vpx!(vpx_codec_enc_config_set(&mut self.ctx, &c));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn bitrate(&self) -> u32 {
|
||||
let c = unsafe { *self.ctx.config.enc.to_owned() };
|
||||
c.rc_target_bitrate
|
||||
}
|
||||
}
|
||||
|
||||
@@ -258,6 +290,34 @@ impl VpxEncoder {
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_quality(quality: Quality) -> (u32, u32, u32) {
|
||||
match quality {
|
||||
Quality::Best => (6, 45, 150),
|
||||
Quality::Balanced => (12, 56, 100 * 2 / 3),
|
||||
Quality::Low => (18, 56, 50),
|
||||
Quality::Custom(b) => {
|
||||
let (q_min, q_max) = Self::calc_q_values(b);
|
||||
(q_min, q_max, b)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn calc_q_values(b: u32) -> (u32, u32) {
|
||||
let b = std::cmp::min(b, 200);
|
||||
let q_min1: i32 = 36;
|
||||
let q_min2 = 12;
|
||||
let q_max1 = 56;
|
||||
let q_max2 = 37;
|
||||
|
||||
let t = b as f32 / 200.0;
|
||||
|
||||
let q_min: u32 = ((1.0 - t) * q_min1 as f32 + t * q_min2 as f32).round() as u32;
|
||||
let q_max = ((1.0 - t) * q_max1 as f32 + t * q_max2 as f32).round() as u32;
|
||||
|
||||
(q_min, q_max)
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for VpxEncoder {
|
||||
@@ -289,8 +349,8 @@ pub struct VpxEncoderConfig {
|
||||
pub height: c_uint,
|
||||
/// The timebase numerator and denominator (in seconds).
|
||||
pub timebase: [c_int; 2],
|
||||
/// The target bitrate (in kilobits per second).
|
||||
pub bitrate: c_uint,
|
||||
/// The image quality
|
||||
pub quality: Quality,
|
||||
/// The codec
|
||||
pub codec: VpxVideoCodecId,
|
||||
pub num_threads: u32,
|
||||
|
||||
Reference in New Issue
Block a user