scrap: ensure video_handler's creation before client start

Signed-off-by: 21pages <pages21@163.com>
This commit is contained in:
21pages 2022-06-09 17:14:26 +08:00
parent 2a91fb842d
commit feaadcfc96
3 changed files with 72 additions and 45 deletions

View File

@ -23,8 +23,10 @@ use hbb_common::{
#[cfg(feature = "hwcodec")] #[cfg(feature = "hwcodec")]
lazy_static::lazy_static! { lazy_static::lazy_static! {
static ref VIDEO_CODEC_STATES: Arc<Mutex<HashMap<i32, VideoCodecState>>> = Default::default(); static ref PEER_DECODER_STATES: Arc<Mutex<HashMap<i32, VideoCodecState>>> = Default::default();
static ref MY_DECODER_STATE: Arc<Mutex<VideoCodecState>> = Default::default();
} }
const SCORE_VPX: i32 = 90;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct HwEncoderConfig { pub struct HwEncoderConfig {
@ -96,9 +98,15 @@ impl Encoder {
}), }),
#[cfg(feature = "hwcodec")] #[cfg(feature = "hwcodec")]
EncoderCfg::HW(_) => Ok(Encoder { EncoderCfg::HW(_) => match HwEncoder::new(config) {
codec: Box::new(HwEncoder::new(config)?), Ok(hw) => Ok(Encoder {
codec: Box::new(hw),
}), }),
Err(e) => {
HwEncoder::best(true);
Err(e)
}
},
#[cfg(not(feature = "hwcodec"))] #[cfg(not(feature = "hwcodec"))]
_ => Err(anyhow!("unsupported encoder type")), _ => Err(anyhow!("unsupported encoder type")),
} }
@ -109,7 +117,7 @@ impl Encoder {
log::info!("update video encoder:{:?}", update); log::info!("update video encoder:{:?}", update);
#[cfg(feature = "hwcodec")] #[cfg(feature = "hwcodec")]
{ {
let mut states = VIDEO_CODEC_STATES.lock().unwrap(); let mut states = PEER_DECODER_STATES.lock().unwrap();
match update { match update {
EncoderUpdate::State(state) => { EncoderUpdate::State(state) => {
states.insert(id, state); states.insert(id, state);
@ -125,14 +133,14 @@ impl Encoder {
} }
let current_encoder_name = HwEncoder::current_name(); let current_encoder_name = HwEncoder::current_name();
if states.len() > 0 { if states.len() > 0 {
let best = HwEncoder::best(); let best = HwEncoder::best(false);
let enabled_h264 = let enabled_h264 =
best.h264.is_some() && states.len() > 0 && states.iter().all(|(_, s)| s.H264); best.h264.is_some() && states.len() > 0 && states.iter().all(|(_, s)| s.H264);
let enabled_h265 = let enabled_h265 =
best.h265.is_some() && states.len() > 0 && states.iter().all(|(_, s)| s.H265); best.h265.is_some() && states.len() > 0 && states.iter().all(|(_, s)| s.H265);
// score encoder // score encoder
let mut score_vpx = 90; let mut score_vpx = SCORE_VPX;
let mut score_h264 = best.h264.as_ref().map_or(0, |c| c.score); let mut score_h264 = best.h264.as_ref().map_or(0, |c| c.score);
let mut score_h265 = best.h265.as_ref().map_or(0, |c| c.score); let mut score_h265 = best.h265.as_ref().map_or(0, |c| c.score);
@ -181,33 +189,50 @@ impl Encoder {
} }
} }
impl Decoder {
// TODO
pub fn video_codec_state() -> VideoCodecState {
let mut state = VideoCodecState::default();
state.ScoreVpx = 90;
#[cfg(feature = "hwcodec")] #[cfg(feature = "hwcodec")]
{ impl Drop for Decoder {
let best = super::hwcodec::HwDecoder::best(false); fn drop(&mut self) {
state.H264 = best.h264.is_some(); *MY_DECODER_STATE.lock().unwrap() = VideoCodecState {
state.ScoreH264 = best.h264.map_or(0, |c| c.score); ScoreVpx: SCORE_VPX,
state.H265 = best.h265.is_some(); ..Default::default()
state.ScoreH265 = best.h265.map_or(0, |c| c.score); };
}
} }
state impl Decoder {
pub fn video_codec_state() -> VideoCodecState {
// video_codec_state is mainted by creation and destruction of Decoder.
// It has been ensured to use after Decoder's creation.
#[cfg(feature = "hwcodec")]
return MY_DECODER_STATE.lock().unwrap().clone();
#[cfg(not(feature = "hwcodec"))]
VideoCodecState {
ScoreVpx: SCORE_VPX,
..Default::default()
}
} }
pub fn new(config: DecoderCfg) -> Decoder { pub fn new(config: DecoderCfg) -> Decoder {
let vpx = VpxDecoder::new(config.vpx).unwrap(); let vpx = VpxDecoder::new(config.vpx).unwrap();
Decoder { let decoder = Decoder {
vpx, vpx,
#[cfg(feature = "hwcodec")] #[cfg(feature = "hwcodec")]
hw: HwDecoder::new_decoders(), hw: HwDecoder::new_decoders(),
#[cfg(feature = "hwcodec")] #[cfg(feature = "hwcodec")]
i420: vec![], i420: vec![],
};
#[cfg(feature = "hwcodec")]
{
let mut state = MY_DECODER_STATE.lock().unwrap();
state.ScoreVpx = SCORE_VPX;
state.H264 = decoder.hw.h264.is_some();
state.ScoreH264 = decoder.hw.h264.as_ref().map_or(0, |d| d.info.score);
state.H265 = decoder.hw.h265.is_some();
state.ScoreH265 = decoder.hw.h265.as_ref().map_or(0, |d| d.info.score);
} }
decoder
} }
pub fn handle_video_frame( pub fn handle_video_frame(

View File

@ -137,11 +137,13 @@ impl EncoderApi for HwEncoder {
} }
impl HwEncoder { impl HwEncoder {
pub fn best() -> CodecInfos { pub fn best(force_reset: bool) -> CodecInfos {
let key = "bestHwEncoders"; let key = "bestHwEncoders";
match get_config(key) {
Ok(config) => config, let config = get_config(key);
Err(_) => { if !force_reset && config.is_ok() {
config.unwrap()
} else {
let ctx = EncodeContext { let ctx = EncodeContext {
name: String::from(""), name: String::from(""),
width: 1920, width: 1920,
@ -161,7 +163,6 @@ impl HwEncoder {
encoders encoders
} }
} }
}
pub fn current_name() -> Arc<Mutex<Option<String>>> { pub fn current_name() -> Arc<Mutex<Option<String>>> {
HW_ENCODER_NAME.clone() HW_ENCODER_NAME.clone()
@ -234,7 +235,7 @@ pub struct HwDecoders {
impl HwDecoder { impl HwDecoder {
/// H264, H265 decoder info with the highest score. /// H264, H265 decoder info with the highest score.
pub fn best(force_reset: bool) -> CodecInfos { fn best(force_reset: bool) -> CodecInfos {
let key = "bestHwDecoders"; let key = "bestHwDecoders";
let config = get_config(key); let config = get_config(key);
if !force_reset && config.is_ok() { if !force_reset && config.is_ok() {
@ -268,7 +269,6 @@ impl HwDecoder {
} }
if fail { if fail {
HwDecoder::best(true); HwDecoder::best(true);
// TODO: notify encoder
} }
if h264.is_some() { if h264.is_some() {

View File

@ -1159,9 +1159,11 @@ where
let latency_controller = LatencyController::new(); let latency_controller = LatencyController::new();
let latency_controller_cl = latency_controller.clone(); let latency_controller_cl = latency_controller.clone();
// Create video_handler out of the thread below to ensure that the handler exists before client start.
// It will take a few tenths of a second for the first time, and then tens of milliseconds.
let mut video_handler = VideoHandler::new(latency_controller);
std::thread::spawn(move || { std::thread::spawn(move || {
let mut video_handler = VideoHandler::new(latency_controller);
loop { loop {
if let Ok(data) = video_receiver.recv() { if let Ok(data) = video_receiver.recv() {
match data { match data {