@ -61,8 +61,8 @@ static const AVOption interlace_options[] = {
AVFILTER_DEFINE_CLASS ( interlace ) ;
static void lowpass_line_c ( uint8_t * dstp , ptrdiff_t linesize ,
const uint8_t * srcp ,
ptrdiff_t mref , ptrdiff_t pref )
const uint8_t * srcp , ptrdiff_t mref ,
ptrdiff_t pref , int clip_max )
{
const uint8_t * srcp_above = srcp + mref ;
const uint8_t * srcp_below = srcp + pref ;
@ -75,9 +75,28 @@ static void lowpass_line_c(uint8_t *dstp, ptrdiff_t linesize,
}
}
static void lowpass_line_c_16 ( uint8_t * dst8 , ptrdiff_t linesize ,
const uint8_t * src8 , ptrdiff_t mref ,
ptrdiff_t pref , int clip_max )
{
uint16_t * dstp = ( uint16_t * ) dst8 ;
const uint16_t * srcp = ( const uint16_t * ) src8 ;
const uint16_t * srcp_above = srcp + mref / 2 ;
const uint16_t * srcp_below = srcp + pref / 2 ;
int i , src_x ;
for ( i = 0 ; i < linesize ; i + + ) {
// this calculation is an integer representation of
// '0.5 * current + 0.25 * above + 0.25 * below'
// '1 +' is for rounding.
src_x = av_le2ne16 ( srcp [ i ] ) < < 1 ;
dstp [ i ] = av_le2ne16 ( ( 1 + src_x + av_le2ne16 ( srcp_above [ i ] )
+ av_le2ne16 ( srcp_below [ i ] ) ) > > 2 ) ;
}
}
static void lowpass_line_complex_c ( uint8_t * dstp , ptrdiff_t linesize ,
const uint8_t * srcp ,
ptrdiff_t mref , ptrdiff_t pref )
const uint8_t * srcp , ptrdiff_t mref ,
ptrdiff_t pref , int clip_max )
{
const uint8_t * srcp_above = srcp + mref ;
const uint8_t * srcp_below = srcp + pref ;
@ -103,11 +122,51 @@ static void lowpass_line_complex_c(uint8_t *dstp, ptrdiff_t linesize,
}
}
static void lowpass_line_complex_c_16 ( uint8_t * dst8 , ptrdiff_t linesize ,
const uint8_t * src8 , ptrdiff_t mref ,
ptrdiff_t pref , int clip_max )
{
uint16_t * dstp = ( uint16_t * ) dst8 ;
const uint16_t * srcp = ( const uint16_t * ) src8 ;
const uint16_t * srcp_above = srcp + mref / 2 ;
const uint16_t * srcp_below = srcp + pref / 2 ;
const uint16_t * srcp_above2 = srcp + mref ;
const uint16_t * srcp_below2 = srcp + pref ;
int i , dst_le , src_le , src_x , src_ab ;
for ( i = 0 ; i < linesize ; i + + ) {
// this calculation is an integer representation of
// '0.75 * current + 0.25 * above + 0.25 * below - 0.125 * above2 - 0.125 * below2'
// '4 +' is for rounding.
src_le = av_le2ne16 ( srcp [ i ] ) ;
src_x = src_le < < 1 ;
src_ab = av_le2ne16 ( srcp_above [ i ] ) + av_le2ne16 ( srcp_below [ i ] ) ;
dst_le = av_clip ( ( 4 + ( ( src_le + src_x + src_ab ) < < 1 )
- av_le2ne16 ( srcp_above2 [ i ] )
- av_le2ne16 ( srcp_below2 [ i ] ) ) > > 3 , 0 , clip_max ) ;
// Prevent over-sharpening:
// dst must not exceed src when the average of above and below
// is less than src. And the other way around.
if ( src_ab > src_x ) {
if ( dst_le < src_le )
dstp [ i ] = av_le2ne16 ( src_le ) ;
else
dstp [ i ] = av_le2ne16 ( dst_le ) ;
} else if ( dst_le > src_le ) {
dstp [ i ] = av_le2ne16 ( src_le ) ;
} else
dstp [ i ] = av_le2ne16 ( dst_le ) ;
}
}
static const enum AVPixelFormat formats_supported [ ] = {
AV_PIX_FMT_YUV420P , AV_PIX_FMT_YUV422P , AV_PIX_FMT_YUV444P ,
AV_PIX_FMT_YUV444P , AV_PIX_FMT_YUV410P , AV_PIX_FMT_YUVA420P ,
AV_PIX_FMT_GRAY8 , AV_PIX_FMT_YUVJ420P , AV_PIX_FMT_YUVJ422P ,
AV_PIX_FMT_YUVJ444P , AV_PIX_FMT_YUVJ440P , AV_PIX_FMT_NONE
AV_PIX_FMT_YUV410P , AV_PIX_FMT_YUV411P ,
AV_PIX_FMT_YUV420P , AV_PIX_FMT_YUV422P , AV_PIX_FMT_YUV444P ,
AV_PIX_FMT_YUV420P10LE , AV_PIX_FMT_YUV422P10LE , AV_PIX_FMT_YUV444P10LE ,
AV_PIX_FMT_YUV420P12LE , AV_PIX_FMT_YUV422P12LE , AV_PIX_FMT_YUV444P12LE ,
AV_PIX_FMT_YUVA420P , AV_PIX_FMT_YUVA422P , AV_PIX_FMT_YUVA444P ,
AV_PIX_FMT_YUVA420P10LE , AV_PIX_FMT_YUVA422P10LE , AV_PIX_FMT_YUVA444P10LE ,
AV_PIX_FMT_GRAY8 , AV_PIX_FMT_YUVJ420P , AV_PIX_FMT_YUVJ422P ,
AV_PIX_FMT_YUVJ444P , AV_PIX_FMT_YUVJ440P , AV_PIX_FMT_NONE
} ;
static int query_formats ( AVFilterContext * ctx )
@ -150,12 +209,19 @@ static int config_out_props(AVFilterLink *outlink)
outlink - > time_base . num * = 2 ;
outlink - > frame_rate . den * = 2 ;
s - > csp = av_pix_fmt_desc_get ( outlink - > format ) ;
if ( s - > lowpass ) {
if ( s - > lowpass = = VLPF_LIN )
s - > lowpass_line = lowpass_line_c ;
else if ( s - > lowpass = = VLPF_CMP )
s - > lowpass_line = lowpass_line_complex_c ;
if ( s - > lowpass = = VLPF_LIN ) {
if ( s - > csp - > comp [ 0 ] . depth > 8 )
s - > lowpass_line = lowpass_line_c_16 ;
else
s - > lowpass_line = lowpass_line_c ;
} else if ( s - > lowpass = = VLPF_CMP ) {
if ( s - > csp - > comp [ 0 ] . depth > 8 )
s - > lowpass_line = lowpass_line_complex_c_16 ;
else
s - > lowpass_line = lowpass_line_complex_c ;
}
if ( ARCH_X86 )
ff_interlace_init_x86 ( s ) ;
}
@ -183,6 +249,7 @@ static void copy_picture_field(InterlaceContext *s,
const uint8_t * srcp = src_frame - > data [ plane ] ;
int srcp_linesize = src_frame - > linesize [ plane ] * 2 ;
int dstp_linesize = dst_frame - > linesize [ plane ] * 2 ;
int clip_max = ( 1 < < s - > csp - > comp [ plane ] . depth ) - 1 ;
av_assert0 ( cols > = 0 | | lines > = 0 ) ;
@ -202,11 +269,13 @@ static void copy_picture_field(InterlaceContext *s,
mref = 0 ;
else if ( j < = ( 1 + x ) )
pref = 0 ;
s - > lowpass_line ( dstp , cols , srcp , mref , pref ) ;
s - > lowpass_line ( dstp , cols , srcp , mref , pref , clip_max ) ;
dstp + = dstp_linesize ;
srcp + = srcp_linesize ;
}
} else {
if ( s - > csp - > comp [ plane ] . depth > 8 )
cols * = 2 ;
av_image_copy_plane ( dstp , dstp_linesize , srcp , srcp_linesize , cols , lines ) ;
}
}