From 869e87c98faac93b72f5f00f63e18858d0f1f25d Mon Sep 17 00:00:00 2001 From: Kamil Jarosz Date: Fri, 6 Sep 2024 23:24:16 +0200 Subject: [PATCH] video: Prefer loading system OpenH264 library to downloading it Some systems do have OpenH264 installed and in order to get rid of the delay caused by downloading the library (and needlessly downloading it in the first place), an attempt is made first to load OpenH264 as a system library. When loading fails (or version is mismatched), only then Ruffle downloads OpenH264 and uses that version of the library. --- desktop/src/player.rs | 10 ++++---- tests/framework/src/options.rs | 6 ++--- video/external/src/backend.rs | 43 +++++++++++++++++++++++++--------- 3 files changed, 40 insertions(+), 19 deletions(-) diff --git a/desktop/src/player.rs b/desktop/src/player.rs index dd32d6daf3e45..74a6082a473ec 100644 --- a/desktop/src/player.rs +++ b/desktop/src/player.rs @@ -224,16 +224,16 @@ impl ActivePlayer { #[cfg(feature = "external_video")] { use ruffle_video_external::backend::ExternalVideoBackend; - let path = tokio::task::block_in_place(ExternalVideoBackend::get_openh264); - let openh264_path = match path { - Ok(path) => Some(path), + let h264_codec = tokio::task::block_in_place(ExternalVideoBackend::load_openh264); + let h264_codec = match h264_codec { + Ok(codec) => Some(codec), Err(e) => { - tracing::error!("Couldn't get OpenH264: {}", e); + tracing::error!("Failed to load OpenH264: {}", e); None } }; - builder = builder.with_video(ExternalVideoBackend::new(openh264_path)); + builder = builder.with_video(ExternalVideoBackend::new(h264_codec)); } } else { #[cfg(feature = "software_video")] diff --git a/tests/framework/src/options.rs b/tests/framework/src/options.rs index 068abaf38825b..b837c9f666402 100644 --- a/tests/framework/src/options.rs +++ b/tests/framework/src/options.rs @@ -178,11 +178,11 @@ impl PlayerOptions { #[cfg(feature = "ruffle_video_external")] { use ruffle_video_external::backend::ExternalVideoBackend; - let openh264_path = ExternalVideoBackend::get_openh264() - .map_err(|e| anyhow!("Couldn't get OpenH264: {}", e))?; + let openh264 = ExternalVideoBackend::load_openh264() + .map_err(|e| anyhow!("Couldn't load OpenH264: {}", e))?; player_builder = - player_builder.with_video(ExternalVideoBackend::new(Some(openh264_path))); + player_builder.with_video(ExternalVideoBackend::new(Some(openh264))); } #[cfg(all( diff --git a/video/external/src/backend.rs b/video/external/src/backend.rs index 56c766f1c8679..dac55ade9b927 100644 --- a/video/external/src/backend.rs +++ b/video/external/src/backend.rs @@ -26,6 +26,7 @@ enum ProxyOrStream { } struct OpenH264Data { + local_filenames: Vec<&'static str>, download_filename: &'static str, download_sha256: &'static str, } @@ -49,6 +50,11 @@ impl ExternalVideoBackend { const OS: &str = std::env::consts::OS; const ARCH: &str = std::env::consts::ARCH; + let local_filenames = match OS { + "linux" => vec!["libopenh264.so.7", "libopenh264.so.2.4.1", "libopenh264.so"], + _ => vec![], + }; + // Source: https://github.com/cisco/openh264/releases/tag/v2.4.1 let (download_filename, download_sha256) = match (OS, ARCH) { ("linux", "x86") => ( @@ -87,17 +93,19 @@ impl ExternalVideoBackend { }; Ok(OpenH264Data { + local_filenames, download_filename, download_sha256, }) } - pub fn get_openh264() -> Result> { + fn download_openh264( + openh264_data: &OpenH264Data, + ) -> Result> { // See the license at: https://www.openh264.org/BINARY_LICENSE.txt const URL_BASE: &str = "http://ciscobinary.openh264.org/"; const URL_SUFFIX: &str = ".bz2"; - let openh264_data = Self::get_openh264_data()?; let (filename, sha256sum) = ( openh264_data.download_filename, openh264_data.download_sha256, @@ -140,16 +148,29 @@ impl ExternalVideoBackend { Ok(filepath) } - pub fn new(openh264_lib_filepath: Option) -> Self { - let h264_codec = if let Some(openh264_lib_filepath) = openh264_lib_filepath { - tracing::info!("Using OpenH264 at {:?}", openh264_lib_filepath); - H264Codec::new(&openh264_lib_filepath) - .inspect_err(|err| tracing::error!("Error loading OpenH264: {:?}", err)) - .ok() - } else { - None - }; + pub fn load_openh264() -> Result> { + let openh264_data = Self::get_openh264_data()?; + + for filename in &openh264_data.local_filenames { + match H264Codec::new(filename) { + Ok(codec) => return Ok(codec), + Err(err) => { + tracing::warn!( + "Failed to load system OpenH264 library {}: {}", + filename, + err + ); + } + } + } + + tracing::info!("Downloading OpenH264 library"); + let filename = Self::download_openh264(&openh264_data)?; + tracing::info!("Using OpenH264 at {:?}", filename); + Ok(H264Codec::new(&filename)?) + } + pub fn new(h264_codec: Option) -> Self { Self { streams: SlotMap::with_key(), h264_codec,