diff options
Diffstat (limited to 'src/post/deinterlace/plugins/greedy2frame.c')
-rw-r--r-- | src/post/deinterlace/plugins/greedy2frame.c | 198 |
1 files changed, 198 insertions, 0 deletions
diff --git a/src/post/deinterlace/plugins/greedy2frame.c b/src/post/deinterlace/plugins/greedy2frame.c new file mode 100644 index 000000000..00c9b34cb --- /dev/null +++ b/src/post/deinterlace/plugins/greedy2frame.c @@ -0,0 +1,198 @@ +/** + * Copyright (c) 2000 John Adcock, Tom Barry, Steve Grimm All rights reserved. + * mmx.h port copyright (c) 2002 Billy Biggs <vektor@dumbterm.net>. + * + * This code is ported from DScaler: http://deinterlace.sf.net/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include <stdio.h> +#include <stdint.h> + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "attributes.h" +#include "xineutils.h" +#include "deinterlace.h" +#include "speedtools.h" +#include "speedy.h" + +static int GreedyTwoFrameThreshold = 4; +static int GreedyTwoFrameThreshold2 = 8; + +static void deinterlace_greedytwoframe_packed422_scanline_mmxext( uint8_t *output, + deinterlace_scanline_data_t *data, + int width ) +{ +#ifdef ARCH_X86 + const mmx_t Mask = { 0x7f7f7f7f7f7f7f7fULL }; + const mmx_t DwordOne = { 0x0000000100000001ULL }; + const mmx_t DwordTwo = { 0x0000000200000002ULL }; + mmx_t qwGreedyTwoFrameThreshold; + uint8_t *m0 = data->m0; + uint8_t *t1 = data->t1; + uint8_t *b1 = data->b1; + uint8_t *m2 = data->m2; + uint8_t *t3 = data->t1; + uint8_t *b3 = data->b1; + + qwGreedyTwoFrameThreshold.b[ 0 ] = GreedyTwoFrameThreshold; + qwGreedyTwoFrameThreshold.b[ 1 ] = GreedyTwoFrameThreshold2; + qwGreedyTwoFrameThreshold.b[ 2 ] = GreedyTwoFrameThreshold; + qwGreedyTwoFrameThreshold.b[ 4 ] = GreedyTwoFrameThreshold; + qwGreedyTwoFrameThreshold.b[ 6 ] = GreedyTwoFrameThreshold; + + width /= 4; + while( width-- ) { + movq_m2r( *m0, mm0 ); + movq_m2r( *t1, mm1 ); + movq_m2r( *b1, mm3 ); + movq_m2r( *m2, mm2 ); + + // Average T1 and B1 so we can do interpolated bobbing if we bob onto T1. + movq_r2r( mm3, mm7 ); // mm7 = B1 + pavgb_r2r( mm1, mm7 ); + + // calculate |M1-M0| put result in mm4 need to keep mm0 intact + // if we have a good processor then make mm0 the average of M1 and M0 + // which should make weave look better when there is small amounts of + // movement + movq_r2r( mm0, mm4 ); + movq_r2r( mm2, mm5 ); + psubusb_r2r( mm2, mm4 ); + psubusb_r2r( mm0, mm5 ); + por_r2r( mm5, mm4 ); + psrlw_i2r( 1, mm4 ); + pavgb_r2r( mm2, mm0 ); + pand_r2r( mm6, mm4 ); + + // if |M1-M0| > Threshold we want dword worth of twos + pcmpgtb_m2r( qwGreedyTwoFrameThreshold, mm4 ); + pand_m2r( Mask, mm4 ); // get rid of any sign bit + pcmpgtd_m2r( DwordOne, mm4 ); // do we want to bob + pandn_m2r( DwordTwo, mm4 ); + + movq_m2r( *t3, mm2 ); // mm2 = T0 + + // calculate |T1-T0| put result in mm5 + movq_r2r( mm2, mm5 ); + psubusb_r2r( mm1, mm5 ); + psubusb_r2r( mm2, mm1 ); + por_r2r( mm1, mm5 ); + psrlw_i2r( 1, mm5 ); + pand_r2r( mm6, mm5 ); + + // if |T1-T0| > Threshold we want dword worth of ones + pcmpgtb_m2r( qwGreedyTwoFrameThreshold, mm5 ); + pand_r2r( mm6, mm5 ); // get rid of any sign bit + pcmpgtd_m2r( DwordOne, mm5 ); + pandn_m2r( DwordOne, mm5 ); + paddd_r2r( mm5, mm4 ); + + movq_m2r( *b3, mm2 ); // B0 + + // calculate |B1-B0| put result in mm5 + movq_r2r( mm2, mm5 ); + psubusb_r2r( mm3, mm5 ); + psubusb_r2r( mm2, mm3 ); + por_r2r( mm3, mm5 ); + psrlw_i2r( 1, mm5 ); + pand_r2r( mm6, mm5 ); + + // if |B1-B0| > Threshold we want dword worth of ones + pcmpgtb_m2r( qwGreedyTwoFrameThreshold, mm5 ); + pand_r2r( mm6, mm5 ); // get rid of any sign bit + pcmpgtd_m2r( DwordOne, mm5 ); + pandn_m2r( DwordOne, mm5 ); + paddd_r2r( mm5, mm4 ); + + pcmpgtd_m2r( DwordTwo, mm4 ); + + movq_r2r( mm4, mm5 ); + // mm4 now is 1 where we want to weave and 0 where we want to bob + pand_r2r( mm0, mm4 ); + pandn_r2r( mm7, mm5 ); + por_r2r( mm5, mm4 ); + + movq_r2m( mm4, *output ); + + // Advance to the next set of pixels. + output += 8; + m0 += 8; + t1 += 8; + b1 += 8; + m2 += 8; + t3 += 8; + b3 += 8; + } + sfence(); + emms(); +#endif +} + +static void copy_scanline( uint8_t *output, + deinterlace_scanline_data_t *data, + int width ) +{ + blit_packed422_scanline( output, data->m1, width ); +} + + +static deinterlace_setting_t settings[] = +{ + { + "Greedy 2 Frame Luma Threshold", + SETTING_SLIDER, + &GreedyTwoFrameThreshold, + 4, 0, 128, 1, + 0 + }, + { + "Greedy 2 Frame Chroma Threshold", + SETTING_SLIDER, + &GreedyTwoFrameThreshold2, + 8, 0, 128, 1, + 0 + } +}; + +static deinterlace_method_t greedymethod = +{ + DEINTERLACE_PLUGIN_API_VERSION, + "Greedy - 2-frame (DScaler)", + "Greedy2Frame", + 4, + MM_ACCEL_X86_MMXEXT, + 0, + 2, + settings, + 1, + copy_scanline, + deinterlace_greedytwoframe_packed422_scanline_mmxext, + 0 +}; + +#ifdef BUILD_TVTIME_PLUGINS +void deinterlace_plugin_init( void ) +#else +void greedy2frame_plugin_init( void ) +#endif +{ + register_deinterlace_method( &greedymethod ); +} + |