This commit is contained in:
kageru 2019-06-02 15:31:27 +02:00
parent b4eb5d8399
commit 9236534dab
Signed by: kageru
GPG Key ID: 8282A2BEA4ADA3D2
3 changed files with 63 additions and 39 deletions

View File

@ -1,17 +1,17 @@
use failure::Error; use failure::Error;
use num::Integer; use num::Integer;
use rand::distributions::Uniform;
use rand::Rng; use rand::Rng;
use rand_xorshift::XorShiftRng;
use vapoursynth::api::API; use vapoursynth::api::API;
use vapoursynth::core::CoreRef; use vapoursynth::core::CoreRef;
use vapoursynth::frame::{FrameRef, FrameRefMut}; use vapoursynth::frame::{FrameRef, FrameRefMut};
use vapoursynth::node::Node; use vapoursynth::node::Node;
use vapoursynth::plugins::{Filter, FrameContext}; use vapoursynth::plugins::{Filter, FrameContext};
use vapoursynth::video_info::VideoInfo; use vapoursynth::video_info::VideoInfo;
use rand::distributions::Uniform;
use rand_xorshift::XorShiftRng;
pub struct Grain<'core> { pub struct Grain<'core> {
pub source: Node<'core> pub source: Node<'core>,
} }
#[inline] #[inline]
@ -42,9 +42,9 @@ impl<'core> Filter<'core> for Grain<'core> {
context: FrameContext, context: FrameContext,
n: usize, n: usize,
) -> Result<FrameRef<'core>, Error> { ) -> Result<FrameRef<'core>, Error> {
let frame = self.source let frame = self.source.get_frame_filter(context, n).ok_or_else(|| {
.get_frame_filter(context, n) format_err!("Could not retrieve source frame. This shouldn’t happen.")
.ok_or_else(|| format_err!("Could not retrieve source frame. This shouldn’t happen."))?; })?;
let var = 20i16; let var = 20i16;
// these have to be defined explicitly for lifetime reasons // these have to be defined explicitly for lifetime reasons
//let mut rng = thread_rng(); //let mut rng = thread_rng();

View File

@ -8,23 +8,23 @@ extern crate vapoursynth;
mod grain; mod grain;
mod mask; mod mask;
use self::mask::Mask;
use self::grain::Grain; use self::grain::Grain;
use self::mask::Mask;
use failure::Error; use failure::Error;
use vapoursynth::api::API; use vapoursynth::api::API;
use vapoursynth::core::CoreRef; use vapoursynth::core::CoreRef;
use vapoursynth::format::SampleType;
use vapoursynth::frame::{FrameRef, FrameRefMut}; use vapoursynth::frame::{FrameRef, FrameRefMut};
use vapoursynth::map::Map; use vapoursynth::map::Map;
use vapoursynth::node::Node; use vapoursynth::node::Node;
use vapoursynth::plugins::{Filter, FilterArgument, FrameContext, Metadata}; use vapoursynth::plugins::{Filter, FilterArgument, FrameContext, Metadata};
use vapoursynth::video_info::{VideoInfo, Property}; use vapoursynth::video_info::{Property, VideoInfo};
use vapoursynth::format::SampleType;
pub const PLUGIN_NAME: &str = "adaptivegrain"; pub const PLUGIN_NAME: &str = "adaptivegrain";
pub const PLUGIN_IDENTIFIER: &str = "moe.kageru.adaptivegrain"; pub const PLUGIN_IDENTIFIER: &str = "moe.kageru.adaptivegrain";
struct AdaptiveGrain<'core> { struct AdaptiveGrain<'core> {
source: Node<'core> source: Node<'core>,
} }
impl<'core> Filter<'core> for AdaptiveGrain<'core> { impl<'core> Filter<'core> for AdaptiveGrain<'core> {
@ -50,12 +50,15 @@ impl<'core> Filter<'core> for AdaptiveGrain<'core> {
context: FrameContext, context: FrameContext,
n: usize, n: usize,
) -> Result<FrameRef<'core>, Error> { ) -> Result<FrameRef<'core>, Error> {
let frame = self.source let frame = self.source.get_frame_filter(context, n).ok_or_else(|| {
.get_frame_filter(context, n) format_err!("Could not retrieve source frame. This shouldn’t happen.")
.ok_or_else(|| format_err!("Could not retrieve source frame. This shouldn’t happen."))?; })?;
let average = match frame.props().get::<f64>("PlaneStatsAverage") { let average = match frame.props().get::<f64>("PlaneStatsAverage") {
Ok(average) => (average * 256.0) as u8, Ok(average) => (average * 256.0) as u8,
Err(_) => panic!(PLUGIN_NAME.to_owned() + ": You need to run std.PlaneStats on the clip before calling this function.") Err(_) => panic!(
PLUGIN_NAME.to_owned()
+ ": You need to run std.PlaneStats on the clip before calling this function."
),
}; };
let mut frame = FrameRefMut::copy_of(core, &frame); let mut frame = FrameRefMut::copy_of(core, &frame);

View File

@ -1,14 +1,14 @@
use failure::Error;
use super::PLUGIN_NAME; use super::PLUGIN_NAME;
use failure::Error;
use std::fmt::Debug;
use vapoursynth::api::API; use vapoursynth::api::API;
use vapoursynth::core::CoreRef; use vapoursynth::core::CoreRef;
use vapoursynth::format::ColorFamily;
use vapoursynth::frame::{FrameRef, FrameRefMut}; use vapoursynth::frame::{FrameRef, FrameRefMut};
use vapoursynth::node::Node; use vapoursynth::node::Node;
use vapoursynth::plugins::{Filter, FrameContext}; use vapoursynth::plugins::{Filter, FrameContext};
use vapoursynth::video_info::{VideoInfo, Property}; use vapoursynth::video_info::{Property, VideoInfo};
use vapoursynth::format::ColorFamily; use std::hint::unreachable_unchecked;
use std::fmt::Debug;
pub struct Mask<'core> { pub struct Mask<'core> {
pub source: Node<'core>, pub source: Node<'core>,
@ -17,7 +17,8 @@ pub struct Mask<'core> {
lazy_static! { lazy_static! {
static ref FLOAT_RANGE: Vec<f32> = { static ref FLOAT_RANGE: Vec<f32> = {
[0f32; 1000].iter() [0f32; 1000]
.iter()
.enumerate() .enumerate()
.map(|(i, _f)| (i as f32) * 0.001) .map(|(i, _f)| (i as f32) * 0.001)
.collect::<Vec<_>>() .collect::<Vec<_>>()
@ -26,14 +27,17 @@ lazy_static! {
#[inline] #[inline]
fn get_mask_value(x: f32, y: f32, luma_scaling: f32) -> f32 { fn get_mask_value(x: f32, y: f32, luma_scaling: f32) -> f32 {
f32::powf(1.0 - (x * (1.124 + x * (-9.466 + x * (36.624 + x * (-45.47 + x * 18.188))))), (y * y) * luma_scaling) f32::powf(
1.0 - (x * (1.124 + x * (-9.466 + x * (36.624 + x * (-45.47 + x * 18.188))))),
(y * y) * luma_scaling,
)
} }
#[inline] #[inline]
fn from_property<T: Debug + Clone + Copy + Eq + PartialEq>(prop: Property<T>) -> T { fn from_property<T: Debug + Clone + Copy + Eq + PartialEq>(prop: Property<T>) -> T {
match prop { match prop {
Property::Constant(p) => p, Property::Constant(p) => p,
Property::Variable => panic!() Property::Variable => unreachable!(),
} }
} }
@ -41,17 +45,21 @@ impl<'core> Filter<'core> for Mask<'core> {
fn video_info(&self, _api: API, _core: CoreRef<'core>) -> Vec<VideoInfo<'core>> { fn video_info(&self, _api: API, _core: CoreRef<'core>) -> Vec<VideoInfo<'core>> {
let info = self.source.info(); let info = self.source.info();
let format = match info.format { let format = match info.format {
Property::Variable => panic!("adaptivegrain: only constant format input supported"), Property::Variable => unreachable!(),
Property::Constant(format) => format Property::Constant(format) => format,
}; };
vec![VideoInfo { vec![VideoInfo {
format: Property::Constant(_core.register_format( format: Property::Constant(
ColorFamily::Gray, _core
format.sample_type(), .register_format(
format.bits_per_sample(), ColorFamily::Gray,
0, format.sample_type(),
0, format.bits_per_sample(),
).unwrap()), 0,
0,
)
.unwrap(),
),
flags: info.flags, flags: info.flags,
framerate: info.framerate, framerate: info.framerate,
num_frames: info.num_frames, num_frames: info.num_frames,
@ -80,21 +88,34 @@ impl<'core> Filter<'core> for Mask<'core> {
let new_format = from_property(self.video_info(_api, core)[0].format); let new_format = from_property(self.video_info(_api, core)[0].format);
let mut frame = unsafe { let mut frame = unsafe {
FrameRefMut::new_uninitialized( FrameRefMut::new_uninitialized(
core, None, new_format, from_property(self.source.info().resolution)) core,
None,
new_format,
from_property(self.source.info().resolution),
)
}; };
let src_frame = self.source let src_frame = self.source.get_frame_filter(context, n).ok_or_else(|| {
.get_frame_filter(context, n) format_err!("Could not retrieve source frame. This shouldn’t happen.")
.ok_or_else(|| format_err!("Could not retrieve source frame. This shouldn’t happen."))?; })?;
let average = match src_frame.props().get::<f64>("PlaneStatsAverage") { let average = match src_frame.props().get::<f64>("PlaneStatsAverage") {
Ok(average) => average as f32, Ok(average) => average as f32,
Err(_) => panic!(format!("{}: you need to run std.PlaneStats on the clip before calling this function.", PLUGIN_NAME)) Err(_) => panic!(format!(
"{}: you need to run std.PlaneStats on the clip before calling this function.",
PLUGIN_NAME
)),
}; };
let lut: Vec<f32> = FLOAT_RANGE.iter().map(|x| get_mask_value(*x, average, self.luma_scaling)).collect(); let lut: Vec<f32> = FLOAT_RANGE
.iter()
.map(|x| get_mask_value(*x, average, self.luma_scaling))
.collect();
for row in 0..frame.height(0) { for row in 0..frame.height(0) {
for (pixel, src_pixel) in frame.plane_row_mut::<f32>(0, row).iter_mut() for (pixel, src_pixel) in frame
.zip(src_frame.plane_row::<f32>(0, row).iter()) { .plane_row_mut::<f32>(0, row)
.iter_mut()
.zip(src_frame.plane_row::<f32>(0, row).iter())
{
*pixel = lut[(src_pixel * 1000f32) as usize]; *pixel = lut[(src_pixel * 1000f32) as usize];
} }
} }