video/h263: Add a deblocking filter as a postprocessing step
This commit is contained in:
parent
765ceb70a0
commit
39e51a7dcf
|
@ -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",
|
||||
|
|
|
@ -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 = []
|
||||
|
|
|
@ -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")]
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue