Merge pull request #5282 from 21pages/record

enable keyframe interval when recording
This commit is contained in:
RustDesk
2023-08-08 08:19:06 +08:00
committed by GitHub
15 changed files with 105 additions and 45 deletions

View File

@@ -174,6 +174,12 @@ pub fn session_record_screen(session_id: SessionID, start: bool, width: usize, h
}
}
pub fn session_record_status(session_id: SessionID, status: bool) {
if let Some(session) = SESSIONS.read().unwrap().get(&session_id) {
session.record_status(status);
}
}
pub fn session_reconnect(session_id: SessionID, force_relay: bool) {
if let Some(session) = SESSIONS.read().unwrap().get(&session_id) {
session.reconnect(force_relay);

View File

@@ -1907,6 +1907,10 @@ impl Connection {
.lock()
.unwrap()
.user_auto_adjust_fps(self.inner.id(), fps),
Some(misc::Union::ClientRecordStatus(status)) => video_service::VIDEO_QOS
.lock()
.unwrap()
.user_record(self.inner.id(), status),
_ => {}
},
Some(message::Union::AudioFrame(frame)) => {

View File

@@ -36,6 +36,7 @@ struct UserData {
quality: Option<(i64, Quality)>, // (time, quality)
delay: Option<Delay>,
response_delayed: bool,
record: bool,
}
pub struct VideoQoS {
@@ -114,6 +115,10 @@ impl VideoQoS {
self.quality
}
pub fn record(&self) -> bool {
self.users.iter().any(|u| u.1.record)
}
pub fn abr_enabled() -> bool {
"N" != Config::get_option("enable-abr")
}
@@ -388,6 +393,12 @@ impl VideoQoS {
}
}
pub fn user_record(&mut self, id: i32, v: bool) {
if let Some(user) = self.users.get_mut(&id) {
user.record = v;
}
}
pub fn on_connection_close(&mut self, id: i32) {
self.users.remove(&id);
self.refresh(None);

View File

@@ -36,7 +36,7 @@ use hbb_common::{
use scrap::Capturer;
use scrap::{
aom::AomEncoderConfig,
codec::{Encoder, EncoderCfg, HwEncoderConfig},
codec::{Encoder, EncoderCfg, HwEncoderConfig, Quality},
record::{Recorder, RecorderContext},
vpxcodec::{VpxEncoderConfig, VpxVideoCodecId},
CodecName, Display, TraitCapturer,
@@ -518,37 +518,13 @@ fn run(sp: GenericService) -> ResultType<()> {
let mut spf;
let mut quality = video_qos.quality();
let abr = VideoQoS::abr_enabled();
drop(video_qos);
log::info!("init quality={:?}, abr enabled:{}", quality, abr);
let encoder_cfg = match Encoder::negotiated_codec() {
scrap::CodecName::H264(name) | scrap::CodecName::H265(name) => {
EncoderCfg::HW(HwEncoderConfig {
name,
width: c.width,
height: c.height,
quality,
})
}
name @ (scrap::CodecName::VP8 | scrap::CodecName::VP9) => {
EncoderCfg::VPX(VpxEncoderConfig {
width: c.width as _,
height: c.height as _,
timebase: [1, 1000], // Output timestamp precision
quality,
codec: if name == scrap::CodecName::VP8 {
VpxVideoCodecId::VP8
} else {
VpxVideoCodecId::VP9
},
})
}
scrap::CodecName::AV1 => EncoderCfg::AOM(AomEncoderConfig {
width: c.width as _,
height: c.height as _,
quality,
}),
};
let codec_name = Encoder::negotiated_codec();
let recorder = get_recorder(c.width, c.height, &codec_name);
let last_recording =
(recorder.lock().unwrap().is_some() || video_qos.record()) && codec_name != CodecName::AV1;
drop(video_qos);
let encoder_cfg = get_encoder_config(&c, quality, last_recording);
let mut encoder;
match Encoder::new(encoder_cfg) {
@@ -597,8 +573,6 @@ fn run(sp: GenericService) -> ResultType<()> {
let mut try_gdi = 1;
#[cfg(windows)]
log::info!("gdi: {}", c.is_gdi());
let codec_name = Encoder::negotiated_codec();
let recorder = get_recorder(c.width, c.height, &codec_name);
#[cfg(windows)]
start_uac_elevation_check();
@@ -617,6 +591,11 @@ fn run(sp: GenericService) -> ResultType<()> {
allow_err!(encoder.set_quality(quality));
video_qos.store_bitrate(encoder.bitrate());
}
let recording = (recorder.lock().unwrap().is_some() || video_qos.record())
&& codec_name != CodecName::AV1;
if recording != last_recording {
bail!("SWITCH");
}
drop(video_qos);
if *SWITCH.lock().unwrap() {
@@ -789,6 +768,41 @@ fn run(sp: GenericService) -> ResultType<()> {
Ok(())
}
fn get_encoder_config(c: &CapturerInfo, quality: Quality, recording: bool) -> EncoderCfg {
// https://www.wowza.com/community/t/the-correct-keyframe-interval-in-obs-studio/95162
let keyframe_interval = if recording { Some(240) } else { None };
match Encoder::negotiated_codec() {
scrap::CodecName::H264(name) | scrap::CodecName::H265(name) => {
EncoderCfg::HW(HwEncoderConfig {
name,
width: c.width,
height: c.height,
quality,
keyframe_interval,
})
}
name @ (scrap::CodecName::VP8 | scrap::CodecName::VP9) => {
EncoderCfg::VPX(VpxEncoderConfig {
width: c.width as _,
height: c.height as _,
quality,
codec: if name == scrap::CodecName::VP8 {
VpxVideoCodecId::VP8
} else {
VpxVideoCodecId::VP9
},
keyframe_interval,
})
}
scrap::CodecName::AV1 => EncoderCfg::AOM(AomEncoderConfig {
width: c.width as _,
height: c.height as _,
quality,
keyframe_interval,
}),
}
}
fn get_recorder(
width: usize,
height: usize,

View File

@@ -297,6 +297,7 @@ class Header: Reactor.Component {
event click $(span#recording) (_, me) {
recording = !recording;
header.update();
handler.record_status(recording);
if (recording)
handler.refresh_video();
else

View File

@@ -451,6 +451,7 @@ impl sciter::EventHandler for SciterSession {
fn save_custom_image_quality(i32);
fn refresh_video();
fn record_screen(bool, i32, i32);
fn record_status(bool);
fn get_toggle_option(String);
fn is_privacy_mode_supported();
fn toggle_option(String);

View File

@@ -240,6 +240,14 @@ impl<T: InvokeUiSession> Session<T> {
self.send(Data::RecordScreen(start, w, h, self.id.clone()));
}
pub fn record_status(&self, status: bool) {
let mut misc = Misc::new();
misc.set_client_record_status(status);
let mut msg = Message::new();
msg.set_misc(misc);
self.send(Data::Message(msg));
}
pub fn save_custom_image_quality(&mut self, custom_image_quality: i32) {
let msg = self
.lc