scrap: ensure video_handler's creation before client start
Signed-off-by: 21pages <pages21@163.com>
This commit is contained in:
parent
2a91fb842d
commit
feaadcfc96
@ -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 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "hwcodec")]
|
||||||
|
impl Drop for Decoder {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
*MY_DECODER_STATE.lock().unwrap() = VideoCodecState {
|
||||||
|
ScoreVpx: SCORE_VPX,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Decoder {
|
impl Decoder {
|
||||||
// TODO
|
|
||||||
pub fn video_codec_state() -> VideoCodecState {
|
pub fn video_codec_state() -> VideoCodecState {
|
||||||
let mut state = VideoCodecState::default();
|
// video_codec_state is mainted by creation and destruction of Decoder.
|
||||||
state.ScoreVpx = 90;
|
// It has been ensured to use after Decoder's creation.
|
||||||
|
|
||||||
#[cfg(feature = "hwcodec")]
|
#[cfg(feature = "hwcodec")]
|
||||||
{
|
return MY_DECODER_STATE.lock().unwrap().clone();
|
||||||
let best = super::hwcodec::HwDecoder::best(false);
|
#[cfg(not(feature = "hwcodec"))]
|
||||||
state.H264 = best.h264.is_some();
|
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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(
|
||||||
|
@ -137,29 +137,30 @@ 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() {
|
||||||
let ctx = EncodeContext {
|
config.unwrap()
|
||||||
name: String::from(""),
|
} else {
|
||||||
width: 1920,
|
let ctx = EncodeContext {
|
||||||
height: 1080,
|
name: String::from(""),
|
||||||
pixfmt: DEFAULT_PIXFMT,
|
width: 1920,
|
||||||
align: HW_STRIDE_ALIGN as _,
|
height: 1080,
|
||||||
bitrate: 0,
|
pixfmt: DEFAULT_PIXFMT,
|
||||||
timebase: DEFAULT_TIME_BASE,
|
align: HW_STRIDE_ALIGN as _,
|
||||||
gop: DEFAULT_GOP,
|
bitrate: 0,
|
||||||
quality: DEFAULT_HW_QUALITY,
|
timebase: DEFAULT_TIME_BASE,
|
||||||
rc: DEFAULT_RC,
|
gop: DEFAULT_GOP,
|
||||||
};
|
quality: DEFAULT_HW_QUALITY,
|
||||||
let encoders = CodecInfo::score(Encoder::avaliable_encoders(ctx));
|
rc: DEFAULT_RC,
|
||||||
let _ = set_config(key, &encoders)
|
};
|
||||||
.map_err(|e| log::error!("{:?}", e))
|
let encoders = CodecInfo::score(Encoder::avaliable_encoders(ctx));
|
||||||
.ok();
|
let _ = set_config(key, &encoders)
|
||||||
encoders
|
.map_err(|e| log::error!("{:?}", e))
|
||||||
}
|
.ok();
|
||||||
|
encoders
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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() {
|
||||||
|
@ -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 {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user