video: Add OpenH264Codec struct

This struct represents the OpenH264 codec and makes it possible to
reuse the reference to the OpenH264 library across decoders.
It also adds better error handling.
This commit is contained in:
Kamil Jarosz 2024-09-06 21:24:47 +02:00 committed by TÖRÖK Attila
parent 835d2eabaa
commit 1f26edd5b1
3 changed files with 51 additions and 0 deletions

1
Cargo.lock generated
View File

@ -4601,6 +4601,7 @@ dependencies = [
"slotmap",
"swf",
"tempfile",
"thiserror",
"tracing",
]

View File

@ -14,6 +14,7 @@ swf = { path = "../../swf" }
slotmap = { workspace = true }
tracing = { workspace = true }
ruffle_video_software = { path = "../software" }
thiserror = { workspace = true }
# Needed for OpenH264:
libloading = "0.8.5"

View File

@ -1,6 +1,8 @@
use core::slice;
use std::ffi::{c_int, c_uchar};
use std::fmt::Display;
use std::ptr;
use std::sync::Arc;
use crate::decoder::openh264_sys::{self, videoFormatI420, ISVCDecoder, OpenH264};
use crate::decoder::VideoDecoder;
@ -8,6 +10,53 @@ use crate::decoder::VideoDecoder;
use ruffle_render::bitmap::BitmapFormat;
use ruffle_video::error::Error;
use ruffle_video::frame::{DecodedFrame, EncodedFrame, FrameDependency};
use thiserror::Error;
#[derive(Debug, PartialEq, Eq)]
pub struct OpenH264Version(u32, u32, u32);
impl Display for OpenH264Version {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}.{}.{}", self.0, self.1, self.2)?;
Ok(())
}
}
#[derive(Debug, Error)]
pub enum OpenH264Error {
#[error("Error while loading OpenH264: {0}")]
LibraryLoadingError(#[from] ::libloading::Error),
#[error("OpenH264 version mismatch, expected {0}, was {1}")]
VersionMismatchError(OpenH264Version, OpenH264Version),
}
/// OpenH264 codec representation.
pub struct OpenH264Codec {
openh264: Arc<OpenH264>,
}
impl OpenH264Codec {
const VERSION: OpenH264Version = OpenH264Version(2, 4, 1);
pub fn new<P>(filename: P) -> Result<Self, OpenH264Error>
where
P: AsRef<::std::ffi::OsStr>,
{
let openh264 = unsafe { OpenH264::new(filename)? };
let version = unsafe { openh264.WelsGetCodecVersion() };
let version = OpenH264Version(version.uMajor, version.uMinor, version.uRevision);
if Self::VERSION != version {
return Err(OpenH264Error::VersionMismatchError(Self::VERSION, version));
}
Ok(Self {
openh264: Arc::new(openh264),
})
}
}
/// H264 video decoder.
pub struct H264Decoder {