Skip to content

Commit

Permalink
video: Prefer loading system OpenH264 library to downloading it
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
kjarosh committed Sep 12, 2024
1 parent d2ea5bb commit ac209f9
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 20 deletions.
10 changes: 5 additions & 5 deletions desktop/src/player.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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")]
Expand Down
6 changes: 3 additions & 3 deletions tests/framework/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
46 changes: 34 additions & 12 deletions video/external/src/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ enum ProxyOrStream {
}

struct OpenH264Data {
local_filenames: Vec<&'static str>,
download_filename: &'static str,
download_sha256: &'static str,
}
Expand All @@ -49,6 +50,12 @@ 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"],
// TODO: investigate other OSes
_ => vec![],
};

// Source: https://github.com/cisco/openh264/releases/tag/v2.4.1
let (download_filename, download_sha256) = match (OS, ARCH) {
("linux", "x86") => (
Expand Down Expand Up @@ -87,17 +94,19 @@ impl ExternalVideoBackend {
};

Ok(OpenH264Data {
local_filenames,
download_filename,
download_sha256,
})
}

pub fn get_openh264() -> Result<PathBuf, Box<dyn std::error::Error>> {
fn download_openh264(
openh264_data: &OpenH264Data,
) -> Result<PathBuf, Box<dyn std::error::Error>> {
// 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,
Expand Down Expand Up @@ -140,19 +149,32 @@ impl ExternalVideoBackend {
Ok(filepath)
}

pub fn new(openh264_lib_filepath: Option<PathBuf>) -> Self {
let h264_codec = if let Some(openh264_lib_filepath) = openh264_lib_filepath {
tracing::info!("Using OpenH264 at {:?}", openh264_lib_filepath);
OpenH264Codec::new(&openh264_lib_filepath)
.inspect_err(|err| tracing::error!("Error loading OpenH264: {:?}", err))
.ok()
} else {
None
};
pub fn load_openh264() -> Result<OpenH264Codec, Box<dyn std::error::Error>> {
let openh264_data = Self::get_openh264_data()?;

for filename in &openh264_data.local_filenames {
match OpenH264Codec::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(OpenH264Codec::new(&filename)?)
}

pub fn new(openh264_codec: Option<OpenH264Codec>) -> Self {
Self {
streams: SlotMap::with_key(),
openh264_codec: h264_codec,
openh264_codec,
software: SoftwareVideoBackend::new(),
}
}
Expand Down

0 comments on commit ac209f9

Please sign in to comment.