video/external: Make OpenH264 support optional by adding the `openh264` feature
And enable it in desktop and tests.
This commit is contained in:
parent
0e1d500654
commit
8ad1c1069c
|
@ -23,7 +23,7 @@ ruffle_core = { path = "../core", features = ["audio", "clap", "mp3", "nellymose
|
||||||
ruffle_render = { path = "../render", features = ["clap"] }
|
ruffle_render = { path = "../render", features = ["clap"] }
|
||||||
ruffle_render_wgpu = { path = "../render/wgpu", features = ["clap"] }
|
ruffle_render_wgpu = { path = "../render/wgpu", features = ["clap"] }
|
||||||
ruffle_video_software = { path = "../video/software", optional = true }
|
ruffle_video_software = { path = "../video/software", optional = true }
|
||||||
ruffle_video_external = { path = "../video/external", optional = true }
|
ruffle_video_external = { path = "../video/external", features = ["openh264"], optional = true }
|
||||||
ruffle_frontend_utils = { path = "../frontend-utils", features = ["cpal"] }
|
ruffle_frontend_utils = { path = "../frontend-utils", features = ["cpal"] }
|
||||||
tracing = { workspace = true }
|
tracing = { workspace = true }
|
||||||
tracing-subscriber = { workspace = true }
|
tracing-subscriber = { workspace = true }
|
||||||
|
|
|
@ -234,15 +234,14 @@ impl ActivePlayer {
|
||||||
let openh264 = tokio::task::block_in_place(|| {
|
let openh264 = tokio::task::block_in_place(|| {
|
||||||
OpenH264Codec::load(&opt.cache_directory.join("video"))
|
OpenH264Codec::load(&opt.cache_directory.join("video"))
|
||||||
});
|
});
|
||||||
let openh264 = match openh264 {
|
let backend = match openh264 {
|
||||||
Ok(codec) => Some(codec),
|
Ok(codec) => ExternalVideoBackend::new_with_openh264(codec),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
tracing::error!("Failed to load OpenH264: {}", e);
|
tracing::error!("Failed to load OpenH264: {}", e);
|
||||||
None
|
ExternalVideoBackend::new()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
builder = builder.with_video(backend);
|
||||||
builder = builder.with_video(ExternalVideoBackend::new(openh264));
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
#[cfg(feature = "software_video")]
|
#[cfg(feature = "software_video")]
|
||||||
|
|
|
@ -16,7 +16,7 @@ ruffle_render = { path = "../../render", features = ["serde"] }
|
||||||
ruffle_input_format = { path = "../input-format" }
|
ruffle_input_format = { path = "../input-format" }
|
||||||
ruffle_socket_format = { path = "../socket-format" }
|
ruffle_socket_format = { path = "../socket-format" }
|
||||||
ruffle_video_software = { path = "../../video/software", optional = true }
|
ruffle_video_software = { path = "../../video/software", optional = true }
|
||||||
ruffle_video_external = { path = "../../video/external", optional = true }
|
ruffle_video_external = { path = "../../video/external", features = ["openh264"], optional = true }
|
||||||
image = { workspace = true, features = ["png"] }
|
image = { workspace = true, features = ["png"] }
|
||||||
regex = "1.10.6"
|
regex = "1.10.6"
|
||||||
url = { workspace = true }
|
url = { workspace = true }
|
||||||
|
|
|
@ -187,7 +187,7 @@ impl PlayerOptions {
|
||||||
.map_err(|e| anyhow!("Couldn't load OpenH264: {}", e))?;
|
.map_err(|e| anyhow!("Couldn't load OpenH264: {}", e))?;
|
||||||
|
|
||||||
player_builder =
|
player_builder =
|
||||||
player_builder.with_video(ExternalVideoBackend::new(Some(openh264)));
|
player_builder.with_video(ExternalVideoBackend::new_with_openh264(openh264));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(
|
#[cfg(all(
|
||||||
|
|
|
@ -17,9 +17,12 @@ ruffle_video_software = { path = "../software" }
|
||||||
thiserror = { workspace = true }
|
thiserror = { workspace = true }
|
||||||
|
|
||||||
# Needed for OpenH264:
|
# Needed for OpenH264:
|
||||||
libloading = "0.8.5"
|
libloading = { version = "0.8.5", optional = true }
|
||||||
reqwest = { version = "0.12.7", default-features = false, features = ["blocking"] }
|
reqwest = { version = "0.12.7", default-features = false, features = ["blocking"], optional = true }
|
||||||
hex = "0.4.3"
|
hex = { version = "0.4.3", optional = true }
|
||||||
bzip2 = { version = "0.4.4", features = ["static"] }
|
bzip2 = { version = "0.4.4", features = ["static"], optional = true }
|
||||||
tempfile = "3.12.0"
|
tempfile = { version = "3.12.0", optional = true }
|
||||||
sha2 = "0.10.8"
|
sha2 = { version = "0.10.8", optional = true }
|
||||||
|
|
||||||
|
[features]
|
||||||
|
openh264 = ["libloading", "reqwest", "hex", "bzip2", "tempfile", "sha2"]
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#[cfg(feature = "openh264")]
|
||||||
use crate::decoder::openh264::OpenH264Codec;
|
use crate::decoder::openh264::OpenH264Codec;
|
||||||
use crate::decoder::VideoDecoder;
|
use crate::decoder::VideoDecoder;
|
||||||
|
|
||||||
|
@ -26,21 +27,42 @@ enum ProxyOrStream {
|
||||||
/// except for H.264, for which it uses an external decoder.
|
/// except for H.264, for which it uses an external decoder.
|
||||||
pub struct ExternalVideoBackend {
|
pub struct ExternalVideoBackend {
|
||||||
streams: SlotMap<VideoStreamHandle, ProxyOrStream>,
|
streams: SlotMap<VideoStreamHandle, ProxyOrStream>,
|
||||||
|
#[cfg(feature = "openh264")]
|
||||||
openh264_codec: Option<OpenH264Codec>,
|
openh264_codec: Option<OpenH264Codec>,
|
||||||
software: SoftwareVideoBackend,
|
software: SoftwareVideoBackend,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for ExternalVideoBackend {
|
impl Default for ExternalVideoBackend {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self::new(None)
|
Self::new()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExternalVideoBackend {
|
impl ExternalVideoBackend {
|
||||||
pub fn new(openh264_codec: Option<OpenH264Codec>) -> Self {
|
fn make_decoder(&mut self) -> Result<Box<dyn VideoDecoder>, Error> {
|
||||||
|
#[cfg(feature = "openh264")]
|
||||||
|
if let Some(h264_codec) = self.openh264_codec.as_ref() {
|
||||||
|
let decoder = Box::new(crate::decoder::openh264::H264Decoder::new(h264_codec));
|
||||||
|
return Ok(decoder);
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(Error::DecoderError("No OpenH264".into()))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
streams: SlotMap::with_key(),
|
streams: SlotMap::with_key(),
|
||||||
openh264_codec,
|
#[cfg(feature = "openh264")]
|
||||||
|
openh264_codec: None,
|
||||||
|
software: SoftwareVideoBackend::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "openh264")]
|
||||||
|
pub fn new_with_openh264(openh264_codec: OpenH264Codec) -> Self {
|
||||||
|
Self {
|
||||||
|
streams: SlotMap::with_key(),
|
||||||
|
openh264_codec: Some(openh264_codec),
|
||||||
software: SoftwareVideoBackend::new(),
|
software: SoftwareVideoBackend::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,13 +79,9 @@ impl VideoBackend for ExternalVideoBackend {
|
||||||
filter: VideoDeblocking,
|
filter: VideoDeblocking,
|
||||||
) -> Result<VideoStreamHandle, Error> {
|
) -> Result<VideoStreamHandle, Error> {
|
||||||
let proxy_or_stream = if codec == VideoCodec::H264 {
|
let proxy_or_stream = if codec == VideoCodec::H264 {
|
||||||
if let Some(h264_codec) = self.openh264_codec.as_ref() {
|
let decoder = self.make_decoder()?;
|
||||||
let decoder = Box::new(crate::decoder::openh264::H264Decoder::new(h264_codec));
|
|
||||||
let stream = VideoStream::new(decoder);
|
let stream = VideoStream::new(decoder);
|
||||||
ProxyOrStream::Owned(stream)
|
ProxyOrStream::Owned(stream)
|
||||||
} else {
|
|
||||||
return Err(Error::DecoderError("No OpenH264".into()));
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
ProxyOrStream::Proxied(
|
ProxyOrStream::Proxied(
|
||||||
self.software
|
self.software
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
// bindgen ../openh264/codec/api/wels/codec_api.h --no-prepend-enum-name \
|
// bindgen ../openh264/codec/api/wels/codec_api.h --no-prepend-enum-name \
|
||||||
// --dynamic-loading OpenH264 -o openh264_sys.rs
|
// --dynamic-loading OpenH264 -o openh264_sys.rs
|
||||||
|
#[cfg(feature = "openh264")]
|
||||||
#[allow(non_upper_case_globals)]
|
#[allow(non_upper_case_globals)]
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
mod openh264_sys;
|
mod openh264_sys;
|
||||||
|
|
||||||
|
#[cfg(feature = "openh264")]
|
||||||
pub mod openh264;
|
pub mod openh264;
|
||||||
|
|
||||||
pub use ruffle_video_software::decoder::VideoDecoder;
|
pub use ruffle_video_software::decoder::VideoDecoder;
|
||||||
|
|
Loading…
Reference in New Issue