video/h263: Add a deblocking filter as a postprocessing step

This commit is contained in:
TÖRÖK Attila 2023-07-14 14:17:22 +02:00 committed by Nathan Adams
parent 765ceb70a0
commit 39e51a7dcf
4 changed files with 70 additions and 17 deletions

19
Cargo.lock generated
View File

@ -2069,6 +2069,15 @@ dependencies = [
"thiserror",
]
[[package]]
name = "h263-rs-deblock"
version = "0.1.0"
source = "git+https://github.com/ruffle-rs/h263-rs?rev=128cdbd85455d19783c88927bb535e8a26fe5220#128cdbd85455d19783c88927bb535e8a26fe5220"
dependencies = [
"itertools",
"wide",
]
[[package]]
name = "h263-rs-yuv"
version = "0.1.0"
@ -2363,6 +2372,15 @@ dependencies = [
"waker-fn",
]
[[package]]
name = "itertools"
version = "0.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
dependencies = [
"either",
]
[[package]]
name = "itoa"
version = "1.0.8"
@ -4030,6 +4048,7 @@ dependencies = [
"flate2",
"generational-arena",
"h263-rs",
"h263-rs-deblock",
"log",
"nihav_codec_support",
"nihav_core",

View File

@ -17,12 +17,13 @@ flate2 = "1.0.26"
log = "0.4"
h263-rs = { git = "https://github.com/ruffle-rs/h263-rs", rev = "128cdbd85455d19783c88927bb535e8a26fe5220", optional = true }
h263-rs-deblock = { git = "https://github.com/ruffle-rs/h263-rs", rev = "128cdbd85455d19783c88927bb535e8a26fe5220", optional = true }
nihav_core = { git = "https://github.com/ruffle-rs/nihav-vp6", rev = "9416fcc9fc8aab8f4681aa9093b42922214abbd3", optional = true }
nihav_codec_support = { git = "https://github.com/ruffle-rs/nihav-vp6", rev = "9416fcc9fc8aab8f4681aa9093b42922214abbd3", optional = true }
nihav_duck = { git = "https://github.com/ruffle-rs/nihav-vp6", rev = "9416fcc9fc8aab8f4681aa9093b42922214abbd3", optional = true }
[features]
default = ["h263", "vp6", "screenvideo"]
h263 = ["h263-rs"]
h263 = ["h263-rs", "h263-rs-deblock"]
vp6 = ["nihav_core", "nihav_codec_support", "nihav_duck"]
screenvideo = []

View File

@ -35,11 +35,11 @@ impl VideoBackend for SoftwareVideoBackend {
_num_frames: u32,
size: (u16, u16),
codec: VideoCodec,
_filter: VideoDeblocking,
filter: VideoDeblocking,
) -> Result<VideoStreamHandle, Error> {
let decoder: Box<dyn VideoDecoder> = match codec {
#[cfg(feature = "h263")]
VideoCodec::H263 => Box::new(crate::decoder::h263::H263Decoder::new()),
VideoCodec::H263 => Box::new(crate::decoder::h263::H263Decoder::new(filter)),
#[cfg(feature = "vp6")]
VideoCodec::Vp6 => Box::new(crate::decoder::vp6::Vp6Decoder::new(false, size)),
#[cfg(feature = "vp6")]

View File

@ -1,9 +1,11 @@
use crate::decoder::VideoDecoder;
use h263_rs::parser::H263Reader;
use h263_rs::{DecoderOption, H263State, PictureTypeCode};
use h263_rs::{DecoderOption, H263State, PictureOption, PictureTypeCode};
use h263_rs_deblock::deblock::{deblock, QUANT_TO_STRENGTH};
use ruffle_render::bitmap::BitmapFormat;
use ruffle_video::error::Error;
use ruffle_video::frame::{DecodedFrame, EncodedFrame, FrameDependency};
use swf::VideoDeblocking;
#[derive(thiserror::Error, Debug)]
pub enum H263Error {
@ -27,11 +29,14 @@ impl From<H263Error> for Error {
}
/// H263 video decoder.
pub struct H263Decoder(H263State);
pub struct H263Decoder(H263State, VideoDeblocking);
impl H263Decoder {
pub fn new() -> Self {
Self(H263State::new(DecoderOption::SORENSON_SPARK_BITSTREAM))
pub fn new(deblock: VideoDeblocking) -> Self {
Self(
H263State::new(DecoderOption::SORENSON_SPARK_BITSTREAM),
deblock,
)
}
}
@ -70,9 +75,36 @@ impl VideoDecoder for H263Decoder {
.ok_or(H263Error::MissingWidthHeight)?;
let (y, b, r) = picture.as_yuv();
let mut data = y.to_vec();
data.extend(b);
data.extend(r);
let hdr = picture.as_header();
if self.1 == VideoDeblocking::Level1
|| (self.1 == VideoDeblocking::UseVideoPacketValue
&& hdr.options.contains(PictureOption::USE_DEBLOCKER))
{
let chroma_width = picture.chroma_samples_per_row();
let quantizer = hdr.quantizer as usize;
let strength = QUANT_TO_STRENGTH[quantizer];
let y = deblock(y, width as usize, strength);
let b = deblock(b, chroma_width, strength);
let r = deblock(r, chroma_width, strength);
let mut data = Vec::with_capacity(y.len() + b.len() + r.len());
data.extend_from_slice(&y);
data.extend_from_slice(&b);
data.extend_from_slice(&r);
Ok(DecodedFrame::new(
width as u32,
height as u32,
BitmapFormat::Yuv420p,
data,
))
} else {
let mut data = Vec::with_capacity(y.len() + b.len() + r.len());
data.extend_from_slice(y);
data.extend_from_slice(b);
data.extend_from_slice(r);
Ok(DecodedFrame::new(
width as u32,
@ -82,9 +114,10 @@ impl VideoDecoder for H263Decoder {
))
}
}
}
impl Default for H263Decoder {
fn default() -> Self {
Self::new()
Self::new(VideoDeblocking::UseVideoPacketValue)
}
}