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

View File

@ -137,29 +137,30 @@ impl EncoderApi for HwEncoder {
}
impl HwEncoder {
pub fn best() -> CodecInfos {
pub fn best(force_reset: bool) -> CodecInfos {
let key = "bestHwEncoders";
match get_config(key) {
Ok(config) => config,
Err(_) => {
let ctx = EncodeContext {
name: String::from(""),
width: 1920,
height: 1080,
pixfmt: DEFAULT_PIXFMT,
align: HW_STRIDE_ALIGN as _,
bitrate: 0,
timebase: DEFAULT_TIME_BASE,
gop: DEFAULT_GOP,
quality: DEFAULT_HW_QUALITY,
rc: DEFAULT_RC,
};
let encoders = CodecInfo::score(Encoder::avaliable_encoders(ctx));
let _ = set_config(key, &encoders)
.map_err(|e| log::error!("{:?}", e))
.ok();
encoders
}
let config = get_config(key);
if !force_reset && config.is_ok() {
config.unwrap()
} else {
let ctx = EncodeContext {
name: String::from(""),
width: 1920,
height: 1080,
pixfmt: DEFAULT_PIXFMT,
align: HW_STRIDE_ALIGN as _,
bitrate: 0,
timebase: DEFAULT_TIME_BASE,
gop: DEFAULT_GOP,
quality: DEFAULT_HW_QUALITY,
rc: DEFAULT_RC,
};
let encoders = CodecInfo::score(Encoder::avaliable_encoders(ctx));
let _ = set_config(key, &encoders)
.map_err(|e| log::error!("{:?}", e))
.ok();
encoders
}
}
@ -234,7 +235,7 @@ pub struct HwDecoders {
impl HwDecoder {
/// 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 config = get_config(key);
if !force_reset && config.is_ok() {
@ -268,7 +269,6 @@ impl HwDecoder {
}
if fail {
HwDecoder::best(true);
// TODO: notify encoder
}
if h264.is_some() {

View File

@ -1159,9 +1159,11 @@ where
let latency_controller = LatencyController::new();
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 || {
let mut video_handler = VideoHandler::new(latency_controller);
loop {
if let Ok(data) = video_receiver.recv() {
match data {