video: Add "external" video backend
This commit is contained in:
parent
c462c7b1d4
commit
fe2a264a93
|
@ -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"
|
||||||
|
|
|
@ -26,6 +26,7 @@ members = [
|
||||||
|
|
||||||
"video",
|
"video",
|
||||||
"video/software",
|
"video/software",
|
||||||
|
"video/external",
|
||||||
|
|
||||||
"tests",
|
"tests",
|
||||||
"tests/input-format",
|
"tests/input-format",
|
||||||
|
|
|
@ -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" }
|
|
@ -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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
pub use ruffle_video_software::decoder::VideoDecoder;
|
|
@ -0,0 +1,2 @@
|
||||||
|
pub mod backend;
|
||||||
|
pub mod decoder;
|
Loading…
Reference in New Issue