video: Add "external" video backend

This commit is contained in:
TÖRÖK Attila 2023-12-21 12:58:57 +01:00 committed by Nathan Adams
parent c462c7b1d4
commit fe2a264a93
6 changed files with 167 additions and 0 deletions

11
Cargo.lock generated
View File

@ -4537,6 +4537,17 @@ dependencies = [
"thiserror", "thiserror",
] ]
[[package]]
name = "ruffle_video_external"
version = "0.1.0"
dependencies = [
"ruffle_render",
"ruffle_video",
"ruffle_video_software",
"slotmap",
"swf",
]
[[package]] [[package]]
name = "ruffle_video_software" name = "ruffle_video_software"
version = "0.1.0" version = "0.1.0"

View File

@ -26,6 +26,7 @@ members = [
"video", "video",
"video/software", "video/software",
"video/external",
"tests", "tests",
"tests/input-format", "tests/input-format",

15
video/external/Cargo.toml vendored Normal file
View File

@ -0,0 +1,15 @@
[package]
name = "ruffle_video_external"
authors.workspace = true
edition.workspace = true
homepage.workspace = true
license.workspace = true
repository.workspace = true
version.workspace = true
[dependencies]
ruffle_render = { path = "../../render" }
ruffle_video = { path = ".." }
swf = { path = "../../swf" }
slotmap = { workspace = true }
ruffle_video_software = { path = "../software" }

137
video/external/src/backend.rs vendored Normal file
View File

@ -0,0 +1,137 @@
use crate::decoder::VideoDecoder;
use ruffle_render::backend::RenderBackend;
use ruffle_render::bitmap::{BitmapHandle, BitmapInfo, PixelRegion};
use ruffle_video::backend::VideoBackend;
use ruffle_video::error::Error;
use ruffle_video::frame::{EncodedFrame, FrameDependency};
use ruffle_video::VideoStreamHandle;
use ruffle_video_software::backend::SoftwareVideoBackend;
use slotmap::SlotMap;
use swf::{VideoCodec, VideoDeblocking};
enum ProxyOrStream {
/// These streams are passed through to the wrapped software
/// backend, accessed using the stored ("inner") handle,
/// which is completely internal to this backend.
Proxied(VideoStreamHandle),
/// These streams are handled by this backend directly.
Owned(VideoStream),
}
/// A video backend that falls back to the software backend for most codecs,
/// except for H.264, for which it uses an external decoder.
pub struct ExternalVideoBackend {
streams: SlotMap<VideoStreamHandle, ProxyOrStream>,
software: SoftwareVideoBackend,
}
impl Default for ExternalVideoBackend {
fn default() -> Self {
Self::new()
}
}
impl ExternalVideoBackend {
pub fn new() -> Self {
Self {
streams: SlotMap::with_key(),
software: SoftwareVideoBackend::new(),
}
}
}
// NOTE: The stream handles coming in through this API must not be
// conflated with the ones stored in `streams` as `Proxied`.
impl VideoBackend for ExternalVideoBackend {
fn register_video_stream(
&mut self,
num_frames: u32,
size: (u16, u16),
codec: VideoCodec,
filter: VideoDeblocking,
) -> Result<VideoStreamHandle, Error> {
let proxy_or_stream = if codec == VideoCodec::H264 {
todo!();
} else {
ProxyOrStream::Proxied(
self.software
.register_video_stream(num_frames, size, codec, filter)?,
)
};
Ok(self.streams.insert(proxy_or_stream))
}
fn preload_video_stream_frame(
&mut self,
stream: VideoStreamHandle,
encoded_frame: EncodedFrame<'_>,
) -> Result<FrameDependency, Error> {
let stream = self
.streams
.get_mut(stream)
.ok_or(Error::VideoStreamIsNotRegistered)?;
match stream {
ProxyOrStream::Proxied(handle) => self
.software
.preload_video_stream_frame(*handle, encoded_frame),
ProxyOrStream::Owned(stream) => stream.decoder.preload_frame(encoded_frame),
}
}
fn decode_video_stream_frame(
&mut self,
stream: VideoStreamHandle,
encoded_frame: EncodedFrame<'_>,
renderer: &mut dyn RenderBackend,
) -> Result<BitmapInfo, Error> {
let stream = self
.streams
.get_mut(stream)
.ok_or(Error::VideoStreamIsNotRegistered)?;
match stream {
ProxyOrStream::Proxied(handle) => {
self.software
.decode_video_stream_frame(*handle, encoded_frame, renderer)
}
ProxyOrStream::Owned(stream) => {
let frame = stream.decoder.decode_frame(encoded_frame)?;
let w = frame.width();
let h = frame.height();
let handle = if let Some(bitmap) = stream.bitmap.clone() {
renderer.update_texture(&bitmap, frame, PixelRegion::for_whole_size(w, h))?;
bitmap
} else {
renderer.register_bitmap(frame)?
};
stream.bitmap = Some(handle.clone());
Ok(BitmapInfo {
handle,
width: w as u16,
height: h as u16,
})
}
}
}
}
/// A single preloaded video stream.
pub struct VideoStream {
bitmap: Option<BitmapHandle>,
decoder: Box<dyn VideoDecoder>,
}
impl VideoStream {
fn new(decoder: Box<dyn VideoDecoder>) -> Self {
Self {
decoder,
bitmap: None,
}
}
}

1
video/external/src/decoder.rs vendored Normal file
View File

@ -0,0 +1 @@
pub use ruffle_video_software::decoder::VideoDecoder;

2
video/external/src/lib.rs vendored Normal file
View File

@ -0,0 +1,2 @@
pub mod backend;
pub mod decoder;