add zero copy mode hareware codec for windows (#6778)

Signed-off-by: 21pages <pages21@163.com>
This commit is contained in:
21pages
2024-01-02 16:58:10 +08:00
committed by GitHub
parent f47faa548b
commit 89150317e1
55 changed files with 2540 additions and 429 deletions

View File

@@ -1,5 +1,6 @@
use std::{
collections::HashMap,
ffi::c_void,
net::SocketAddr,
ops::Deref,
str::FromStr,
@@ -155,7 +156,7 @@ pub fn get_key_state(key: enigo::Key) -> bool {
cfg_if::cfg_if! {
if #[cfg(target_os = "android")] {
use hbb_common::libc::{c_float, c_int, c_void};
use hbb_common::libc::{c_float, c_int};
type Oboe = *mut c_void;
extern "C" {
fn create_oboe_player(channels: c_int, sample_rate: c_int) -> Oboe;
@@ -1020,6 +1021,7 @@ impl AudioHandler {
pub struct VideoHandler {
decoder: Decoder,
pub rgb: ImageRgb,
pub texture: *mut c_void,
recorder: Arc<Mutex<Option<Recorder>>>,
record: bool,
_display: usize, // useful for debug
@@ -1028,10 +1030,16 @@ pub struct VideoHandler {
impl VideoHandler {
/// Create a new video handler.
pub fn new(_display: usize) -> Self {
#[cfg(all(feature = "gpucodec", feature = "flutter"))]
let luid = crate::flutter::get_adapter_luid();
#[cfg(not(all(feature = "gpucodec", feature = "flutter")))]
let luid = Default::default();
println!("new session_get_adapter_luid: {:?}", luid);
log::info!("new video handler for display #{_display}");
VideoHandler {
decoder: Decoder::new(),
decoder: Decoder::new(luid),
rgb: ImageRgb::new(ImageFormat::ARGB, crate::DST_STRIDE_RGBA),
texture: std::ptr::null_mut(),
recorder: Default::default(),
record: false,
_display,
@@ -1043,13 +1051,18 @@ impl VideoHandler {
pub fn handle_frame(
&mut self,
vf: VideoFrame,
pixelbuffer: &mut bool,
chroma: &mut Option<Chroma>,
) -> ResultType<bool> {
match &vf.union {
Some(frame) => {
let res = self
.decoder
.handle_video_frame(frame, &mut self.rgb, chroma);
let res = self.decoder.handle_video_frame(
frame,
&mut self.rgb,
&mut self.texture,
pixelbuffer,
chroma,
);
if self.record {
self.recorder
.lock()
@@ -1065,7 +1078,11 @@ impl VideoHandler {
/// Reset the decoder.
pub fn reset(&mut self) {
self.decoder = Decoder::new();
#[cfg(all(feature = "flutter", feature = "gpucodec"))]
let luid = crate::flutter::get_adapter_luid();
#[cfg(not(all(feature = "flutter", feature = "gpucodec")))]
let luid = None;
self.decoder = Decoder::new(luid);
}
/// Start or stop screen record.
@@ -1113,6 +1130,7 @@ pub struct LoginConfigHandler {
pub save_ab_password_to_recent: bool, // true: connected with ab password
pub other_server: Option<(String, String, String)>,
pub custom_fps: Arc<Mutex<Option<usize>>>,
pub adapter_luid: Option<i64>,
}
impl Deref for LoginConfigHandler {
@@ -1136,6 +1154,7 @@ impl LoginConfigHandler {
conn_type: ConnType,
switch_uuid: Option<String>,
mut force_relay: bool,
adapter_luid: Option<i64>,
) {
let mut id = id;
if id.contains("@") {
@@ -1197,6 +1216,7 @@ impl LoginConfigHandler {
self.direct = None;
self.received = false;
self.switch_uuid = switch_uuid;
self.adapter_luid = adapter_luid;
}
/// Check if the client should auto login.
@@ -1536,7 +1556,11 @@ impl LoginConfigHandler {
n += 1;
}
msg.supported_decoding =
hbb_common::protobuf::MessageField::some(Decoder::supported_decodings(Some(&self.id)));
hbb_common::protobuf::MessageField::some(Decoder::supported_decodings(
Some(&self.id),
cfg!(feature = "flutter"),
self.adapter_luid,
));
n += 1;
if n > 0 {
@@ -1842,6 +1866,7 @@ impl LoginConfigHandler {
// no matter if change, for update file time
self.save_config(config);
self.supported_encoding = pi.encoding.clone().unwrap_or_default();
log::info!("peer info supported_encoding:{:?}", self.supported_encoding);
}
pub fn get_remote_dir(&self) -> String {
@@ -1915,8 +1940,12 @@ impl LoginConfigHandler {
msg_out
}
pub fn change_prefer_codec(&self) -> Message {
let decoding = scrap::codec::Decoder::supported_decodings(Some(&self.id));
pub fn update_supported_decodings(&self) -> Message {
let decoding = scrap::codec::Decoder::supported_decodings(
Some(&self.id),
cfg!(feature = "flutter"),
self.adapter_luid,
);
let mut misc = Misc::new();
misc.set_option(OptionMessage {
supported_decoding: hbb_common::protobuf::MessageField::some(decoding),
@@ -1927,6 +1956,44 @@ impl LoginConfigHandler {
msg_out
}
fn real_supported_decodings(
&self,
handler_controller_map: &Vec<VideoHandlerController>,
) -> Data {
let abilities: Vec<CodecAbility> = handler_controller_map
.iter()
.map(|h| h.handler.decoder.exist_codecs(cfg!(feature = "flutter")))
.collect();
let all = |ability: fn(&CodecAbility) -> bool| -> i32 {
if abilities.iter().all(|d| ability(d)) {
1
} else {
0
}
};
let decoding = scrap::codec::Decoder::supported_decodings(
Some(&self.id),
cfg!(feature = "flutter"),
self.adapter_luid,
);
let decoding = SupportedDecoding {
ability_vp8: all(|e| e.vp8),
ability_vp9: all(|e| e.vp9),
ability_av1: all(|e| e.av1),
ability_h264: all(|e| e.h264),
ability_h265: all(|e| e.h265),
..decoding
};
let mut misc = Misc::new();
misc.set_option(OptionMessage {
supported_decoding: hbb_common::protobuf::MessageField::some(decoding),
..Default::default()
});
let mut msg_out = Message::new();
msg_out.set_misc(misc);
Data::Message(msg_out)
}
pub fn restart_remote_device(&self) -> Message {
let mut misc = Misc::new();
misc.set_restart_remote_device(true);
@@ -1972,13 +2039,14 @@ pub fn start_video_audio_threads<F, T>(
Arc<RwLock<Option<Chroma>>>,
)
where
F: 'static + FnMut(usize, &mut scrap::ImageRgb) + Send,
F: 'static + FnMut(usize, &mut scrap::ImageRgb, *mut c_void, bool) + Send,
T: InvokeUiSession,
{
let (video_sender, video_receiver) = mpsc::channel::<MediaData>();
let video_queue_map: Arc<RwLock<HashMap<usize, ArrayQueue<VideoFrame>>>> = Default::default();
let video_queue_map_cloned = video_queue_map.clone();
let mut video_callback = video_callback;
let fps_map = Arc::new(RwLock::new(HashMap::new()));
let decode_fps_map = fps_map.clone();
let chroma = Arc::new(RwLock::new(None));
@@ -2018,6 +2086,7 @@ where
};
let display = vf.display as usize;
let start = std::time::Instant::now();
let mut created_new_handler = false;
if handler_controller_map.len() <= display {
for _i in handler_controller_map.len()..=display {
handler_controller_map.push(VideoHandlerController {
@@ -2026,13 +2095,33 @@ where
duration: std::time::Duration::ZERO,
skip_beginning: 0,
});
created_new_handler = true;
}
}
if created_new_handler {
session.send(
session
.lc
.read()
.unwrap()
.real_supported_decodings(&handler_controller_map),
);
}
if let Some(handler_controller) = handler_controller_map.get_mut(display) {
let mut pixelbuffer = true;
let mut tmp_chroma = None;
match handler_controller.handler.handle_frame(vf, &mut tmp_chroma) {
match handler_controller.handler.handle_frame(
vf,
&mut pixelbuffer,
&mut tmp_chroma,
) {
Ok(true) => {
video_callback(display, &mut handler_controller.handler.rgb);
video_callback(
display,
&mut handler_controller.handler.rgb,
handler_controller.handler.texture,
pixelbuffer,
);
// chroma
if tmp_chroma.is_some() && last_chroma != tmp_chroma {
@@ -2085,6 +2174,13 @@ where
MediaData::Reset(display) => {
if let Some(handler_controler) = handler_controller_map.get_mut(display) {
handler_controler.handler.reset();
session.send(
session
.lc
.read()
.unwrap()
.real_supported_decodings(&handler_controller_map),
);
}
}
MediaData::RecordScreen(start, display, w, h, id) => {