enable ffmpeg native h26x software decoders for all platforms (#7750)

* enable ffmpeg native h26x software decoders for all platforms

* h26x software decoders depend on hwcodec feature, so all platforms
  enable it, software h26x decoders are always available like vpx, no available check and no option
* ffmpeg:
	- build: mac arm64 build ffmpeg with my m1, others build with ci
	- version: win/linux use ffmpeg release/5.1, becaues higher version require higher nvidia driver,  other platforms use release/7.0
* test:
	- ios not test.
	- android: sometimes the screen will appear blurry, but it will recover after a while.
	- arm64 linux: test a example of hwcodec repo

Signed-off-by: 21pages <pages21@163.com>

* check hwcodec only when enabled and immediately when clicked enabled

Signed-off-by: 21pages <pages21@163.com>

---------

Signed-off-by: 21pages <pages21@163.com>
This commit is contained in:
21pages
2024-04-18 13:12:45 +08:00
committed by GitHub
parent 4e8cbe3db1
commit 4252b5e273
16 changed files with 106 additions and 39 deletions

View File

@@ -61,6 +61,5 @@ gstreamer-video = { version = "0.16", optional = true }
[dependencies.hwcodec]
git = "https://github.com/21pages/hwcodec"
optional = true
features = ["ffmpeg"]

View File

@@ -399,7 +399,7 @@ impl Decoder {
..Default::default()
};
#[cfg(feature = "hwcodec")]
if enable_hwcodec_option() {
{
let best = HwRamDecoder::best();
decoding.ability_h264 |= if best.h264.is_some() { 1 } else { 0 };
decoding.ability_h265 |= if best.h265.is_some() { 1 } else { 0 };
@@ -492,7 +492,7 @@ impl Decoder {
valid = h264_vram.is_some();
}
#[cfg(feature = "hwcodec")]
if !valid && enable_hwcodec_option() {
if !valid {
match HwRamDecoder::new(format) {
Ok(v) => h264_ram = Some(v),
Err(e) => log::error!("create H264 ram decoder failed: {}", e),
@@ -518,7 +518,7 @@ impl Decoder {
valid = h265_vram.is_some();
}
#[cfg(feature = "hwcodec")]
if !valid && enable_hwcodec_option() {
if !valid {
match HwRamDecoder::new(format) {
Ok(v) => h265_ram = Some(v),
Err(e) => log::error!("create H265 ram decoder failed: {}", e),
@@ -792,10 +792,13 @@ impl Decoder {
#[cfg(any(feature = "hwcodec", feature = "mediacodec"))]
pub fn enable_hwcodec_option() -> bool {
if let Some(v) = Config2::get().options.get("enable-hwcodec") {
return v != "N";
if cfg!(windows) || cfg!(target_os = "linux") || cfg!(feature = "mediacodec") {
if let Some(v) = Config2::get().options.get("enable-hwcodec") {
return v != "N";
}
return true; // default is true
}
return true; // default is true
false
}
#[cfg(feature = "vram")]
pub fn enable_vram_option() -> bool {

View File

@@ -1,9 +1,10 @@
use crate::{
codec::{base_bitrate, codec_thread_num, EncoderApi, EncoderCfg, Quality as Q},
codec::{
base_bitrate, codec_thread_num, enable_hwcodec_option, EncoderApi, EncoderCfg, Quality as Q,
},
hw, CodecFormat, EncodeInput, ImageFormat, ImageRgb, Pixfmt, HW_STRIDE_ALIGN,
};
use hbb_common::{
allow_err,
anyhow::{anyhow, bail, Context},
bytes::Bytes,
config::HwCodecConfig,
@@ -223,10 +224,18 @@ pub struct HwRamDecoder {
impl HwRamDecoder {
pub fn best() -> CodecInfos {
get_config().map(|c| c.d).unwrap_or(CodecInfos {
h264: None,
h265: None,
})
let mut info = CodecInfo::soft();
if enable_hwcodec_option() {
if let Ok(hw) = get_config().map(|c| c.d) {
if let Some(h264) = hw.h264 {
info.h264 = Some(h264);
}
if let Some(h265) = hw.h265 {
info.h265 = Some(h265);
}
}
}
info
}
pub fn new(format: CodecFormat) -> ResultType<Self> {
@@ -359,8 +368,8 @@ pub fn check_available_hwcodec() {
let vram = crate::vram::check_available_vram();
#[cfg(not(feature = "vram"))]
let vram = "".to_owned();
let encoders = CodecInfo::score(Encoder::available_encoders(ctx, Some(vram.clone())));
let decoders = CodecInfo::score(Decoder::available_decoders(Some(vram.clone())));
let encoders = CodecInfo::prioritized(Encoder::available_encoders(ctx, Some(vram.clone())));
let decoders = CodecInfo::prioritized(Decoder::available_decoders(Some(vram.clone())));
let ram = Available {
e: encoders,
d: decoders,
@@ -370,7 +379,12 @@ pub fn check_available_hwcodec() {
}
}
pub fn hwcodec_new_check_process() {
#[cfg(any(target_os = "windows", target_os = "linux"))]
pub fn start_check_process(force: bool) {
if !force && !enable_hwcodec_option() {
return;
}
use hbb_common::allow_err;
use std::sync::Once;
let f = || {
// Clear to avoid checking process errors
@@ -410,7 +424,11 @@ pub fn hwcodec_new_check_process() {
};
};
static ONCE: Once = Once::new();
ONCE.call_once(|| {
if force && ONCE.is_completed() {
std::thread::spawn(f);
});
} else {
ONCE.call_once(|| {
std::thread::spawn(f);
});
}
}