video: Reuse OpenH264 across decoders and load early

By using the H264Codec struct, we can load OpenH264 early
and reuse its instance for all decoders.
This commit is contained in:
Kamil Jarosz 2024-09-06 21:30:37 +02:00 committed by TÖRÖK Attila
parent 1f26edd5b1
commit 7f8beeb1e5
2 changed files with 17 additions and 18 deletions

View File

@ -1,3 +1,4 @@
use crate::decoder::openh264::OpenH264Codec;
use crate::decoder::VideoDecoder;
use bzip2::read::BzDecoder;
use ruffle_render::backend::RenderBackend;
@ -28,7 +29,7 @@ enum ProxyOrStream {
/// except for H.264, for which it uses an external decoder.
pub struct ExternalVideoBackend {
streams: SlotMap<VideoStreamHandle, ProxyOrStream>,
openh264_lib_filepath: Option<PathBuf>,
openh264_codec: Option<OpenH264Codec>,
software: SoftwareVideoBackend,
}
@ -123,9 +124,18 @@ impl ExternalVideoBackend {
}
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
};
Self {
streams: SlotMap::with_key(),
openh264_lib_filepath,
openh264_codec: h264_codec,
software: SoftwareVideoBackend::new(),
}
}
@ -142,10 +152,8 @@ impl VideoBackend for ExternalVideoBackend {
filter: VideoDeblocking,
) -> Result<VideoStreamHandle, Error> {
let proxy_or_stream = if codec == VideoCodec::H264 {
let openh264 = &self.openh264_lib_filepath;
if let Some(openh264) = openh264 {
tracing::info!("Using OpenH264 at {:?}", openh264);
let decoder = Box::new(crate::decoder::openh264::H264Decoder::new(openh264));
if let Some(h264_codec) = self.openh264_codec.as_ref() {
let decoder = Box::new(crate::decoder::openh264::H264Decoder::new(h264_codec));
let stream = VideoStream::new(decoder);
ProxyOrStream::Owned(stream)
} else {

View File

@ -63,26 +63,17 @@ pub struct H264Decoder {
/// How many bytes are used to store the length of the NALU (1, 2, 3, or 4).
length_size: u8,
openh264: OpenH264,
openh264: Arc<OpenH264>,
decoder: *mut ISVCDecoder,
}
impl H264Decoder {
/// `extradata` should hold "AVCC (MP4) format" decoder configuration, including PPS and SPS.
/// Make sure it has any start code emulation prevention "three bytes" removed.
pub fn new(openh264_lib_filename: &std::path::Path) -> Self {
pub fn new(h264: &OpenH264Codec) -> Self {
let openh264 = h264.openh264.clone();
let mut decoder: *mut ISVCDecoder = ptr::null_mut();
unsafe {
let openh264 = OpenH264::new(openh264_lib_filename).unwrap();
let version = openh264.WelsGetCodecVersion();
assert_eq!(
(version.uMajor, version.uMinor, version.uRevision),
(2, 4, 1),
"Unexpected OpenH264 version"
);
openh264.WelsCreateDecoder(&mut decoder);
let decoder_vtbl = (*decoder).as_ref().unwrap();