2019-05-30 13:06:53 +02:00
#[ macro_use ]
extern crate failure ;
#[ macro_use ]
2019-06-01 08:55:47 +02:00
extern crate lazy_static ;
#[ macro_use ]
2019-05-30 13:06:53 +02:00
extern crate vapoursynth ;
2019-06-01 08:55:47 +02:00
mod grain ;
mod mask ;
use self ::grain ::Grain ;
2019-06-02 15:31:27 +02:00
use self ::mask ::Mask ;
2019-06-01 08:55:47 +02:00
use failure ::Error ;
use vapoursynth ::api ::API ;
2019-05-30 13:06:53 +02:00
use vapoursynth ::core ::CoreRef ;
2019-06-02 15:31:27 +02:00
use vapoursynth ::format ::SampleType ;
2019-06-01 08:55:47 +02:00
use vapoursynth ::frame ::{ FrameRef , FrameRefMut } ;
2019-05-30 13:06:53 +02:00
use vapoursynth ::map ::Map ;
use vapoursynth ::node ::Node ;
use vapoursynth ::plugins ::{ Filter , FilterArgument , FrameContext , Metadata } ;
2019-06-02 15:31:27 +02:00
use vapoursynth ::video_info ::{ Property , VideoInfo } ;
2019-05-30 13:06:53 +02:00
2019-06-01 08:55:47 +02:00
pub const PLUGIN_NAME : & str = " adaptivegrain " ;
pub const PLUGIN_IDENTIFIER : & str = " moe.kageru.adaptivegrain " ;
2019-05-30 13:06:53 +02:00
struct AdaptiveGrain < ' core > {
2019-06-02 15:31:27 +02:00
source : Node < ' core > ,
2019-05-30 13:06:53 +02:00
}
impl < ' core > Filter < ' core > for AdaptiveGrain < ' core > {
fn video_info ( & self , _api : API , _core : CoreRef < ' core > ) -> Vec < VideoInfo < ' core > > {
vec! [ self . source . info ( ) ]
}
fn get_frame_initial (
& self ,
_api : API ,
_core : CoreRef < ' core > ,
context : FrameContext ,
n : usize ,
) -> Result < Option < FrameRef < ' core > > , Error > {
self . source . request_frame_filter ( context , n ) ;
Ok ( None )
}
fn get_frame (
& self ,
_api : API ,
core : CoreRef < ' core > ,
context : FrameContext ,
n : usize ,
) -> Result < FrameRef < ' core > , Error > {
2019-06-02 15:31:27 +02:00
let frame = self . source . get_frame_filter ( context , n ) . ok_or_else ( | | {
format_err! ( " Could not retrieve source frame. This shouldn’t happen. " )
} ) ? ;
2019-05-30 13:06:53 +02:00
let average = match frame . props ( ) . get ::< f64 > ( " PlaneStatsAverage " ) {
Ok ( average ) = > ( average * 256.0 ) as u8 ,
2019-06-02 15:31:27 +02:00
Err ( _ ) = > panic! (
PLUGIN_NAME . to_owned ( )
+ " : You need to run std.PlaneStats on the clip before calling this function. "
) ,
2019-05-30 13:06:53 +02:00
} ;
let mut frame = FrameRefMut ::copy_of ( core , & frame ) ;
for plane in 0 .. frame . format ( ) . plane_count ( ) {
for row in 0 .. frame . height ( plane ) {
for pixel in frame . plane_row_mut ::< u8 > ( plane , row ) {
* pixel = average ;
}
}
}
Ok ( frame . into ( ) )
}
}
make_filter_function! {
AdaptiveGrainFunction , " AdaptiveGrain "
fn create_adaptivegrain < ' core > (
_api : API ,
_core : CoreRef < ' core > ,
clip : Node < ' core > ,
2019-06-02 14:43:53 +02:00
) -> Result < Option < Box < dyn Filter < ' core > + ' core > > , Error > {
2019-05-30 13:06:53 +02:00
Ok ( Some ( Box ::new ( AdaptiveGrain { source : clip } ) ) )
}
}
2019-06-01 08:55:47 +02:00
make_filter_function! {
GrainFunction , " Grain "
fn create_grain < ' core > (
_api : API ,
_core : CoreRef < ' core > ,
clip : Node < ' core > ,
2019-06-02 14:43:53 +02:00
) -> Result < Option < Box < dyn Filter < ' core > + ' core > > , Error > {
2019-06-01 08:55:47 +02:00
Ok ( Some ( Box ::new ( Grain { source : clip } ) ) )
}
}
make_filter_function! {
MaskFunction , " Mask "
fn create_mask < ' core > (
_api : API ,
_core : CoreRef < ' core > ,
clip : Node < ' core > ,
luma_scaling : Option < f64 >
2019-06-02 14:43:53 +02:00
) -> Result < Option < Box < dyn Filter < ' core > + ' core > > , Error > {
2019-06-01 08:55:47 +02:00
let luma_scaling = match luma_scaling {
Some ( i ) = > i as f32 ,
None = > 10.0
} ;
2019-06-02 14:43:53 +02:00
if let Property ::Constant ( format ) = clip . info ( ) . format {
2019-06-02 22:44:52 +02:00
if ! ( format . sample_type ( ) = = SampleType ::Float & & format . bits_per_sample ( ) ! = 32 ) {
2019-06-02 14:43:53 +02:00
return Ok ( Some ( Box ::new ( Mask {
source : clip ,
luma_scaling
} ) ) ) ;
2019-06-02 22:44:52 +02:00
} else {
bail! ( " Half precision float input is not supported " ) ;
2019-06-02 14:43:53 +02:00
}
}
2019-06-02 22:44:52 +02:00
bail! ( " Variable format input is not supported " )
2019-06-01 08:55:47 +02:00
}
}
2019-05-30 13:06:53 +02:00
export_vapoursynth_plugin! {
Metadata {
identifier : PLUGIN_IDENTIFIER ,
namespace : " adg " ,
name : " Adaptive grain " ,
read_only : false ,
} ,
[
2019-06-02 14:43:53 +02:00
//AdaptiveGrainFunction::new(),
//GrainFunction::new(),
2019-06-01 08:55:47 +02:00
MaskFunction ::new ( )
2019-05-30 13:06:53 +02:00
]
}
#[ cfg(test) ]
mod tests {
#[ test ]
fn it_works ( ) {
assert_eq! ( 2 + 2 , 4 ) ;
}
}