linearblend.c

来自「linux下的MPEG1」· C语言 代码 · 共 363 行

C
363
字号
/** * Linear blend deinterlacing plugin.  The idea for this algorithm came * from the linear blend deinterlacer which originated in the mplayer * sources. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */#ifdef HAVE_CONFIG_H# include "config.h"#endif#include <stdio.h>#if HAVE_INTTYPES_H#include <inttypes.h>#else#include <stdint.h>#endif#include "attributes.h"#include "xineutils.h"#include "speedtools.h"#include "speedy.h"#include "deinterlace.h"#include "plugins.h"static const char linearblendmethod_help[] =  "Avoids flicker by blurring consecutive frames of input.  Use this if "  "you want to run your monitor at an arbitrary refresh rate and not use "  "much CPU, and are willing to sacrifice detail.\n"  "\n"  "Temporal mode evenly blurs content for least flicker, but with visible "  "trails on fast motion. From the linear blend deinterlacer in mplayer.";static void deinterlace_scanline_linear_blend( uint8_t *output,                                               deinterlace_scanline_data_t *data,                                               int width ){    uint8_t *t0 = data->t0;    uint8_t *b0 = data->b0;    uint8_t *m1 = data->m1;#if defined(ARCH_X86) || defined(ARCH_X86_64)    int i;    // Get width in bytes.    width *= 2;    i = width / 8;    width -= i * 8;    pxor_r2r( mm7, mm7 );    while( i-- ) {        movd_m2r( *t0, mm0 );        movd_m2r( *b0, mm1 );        movd_m2r( *m1, mm2 );        movd_m2r( *(t0+4), mm3 );        movd_m2r( *(b0+4), mm4 );        movd_m2r( *(m1+4), mm5 );        punpcklbw_r2r( mm7, mm0 );        punpcklbw_r2r( mm7, mm1 );        punpcklbw_r2r( mm7, mm2 );        punpcklbw_r2r( mm7, mm3 );        punpcklbw_r2r( mm7, mm4 );        punpcklbw_r2r( mm7, mm5 );        psllw_i2r( 1, mm2 );        psllw_i2r( 1, mm5 );        paddw_r2r( mm0, mm2 );        paddw_r2r( mm3, mm5 );        paddw_r2r( mm1, mm2 );        paddw_r2r( mm4, mm5 );        psrlw_i2r( 2, mm2 );        psrlw_i2r( 2, mm5 );        packuswb_r2r( mm2, mm2 );        packuswb_r2r( mm5, mm5 );        movd_r2m( mm2, *output );        movd_r2m( mm5, *(output+4) );        output += 8;        t0 += 8;        b0 += 8;        m1 += 8;    }    while( width-- ) {        *output++ = (*t0++ + *b0++ + (*m1++ << 1)) >> 2;    }    emms();#else    width *= 2;    while( width-- ) {        *output++ = (*t0++ + *b0++ + (*m1++ << 1)) >> 2;    }#endif}static void deinterlace_scanline_linear_blend2( uint8_t *output,                                                deinterlace_scanline_data_t *data,                                                int width ){    uint8_t *m0 = data->m0;    uint8_t *t1 = data->t1;    uint8_t *b1 = data->b1;#if defined(ARCH_X86) || defined(ARCH_X86_64)    int i;    // Get width in bytes.    width *= 2;    i = width / 8;    width -= i * 8;    pxor_r2r( mm7, mm7 );    while( i-- ) {        movd_m2r( *t1, mm0 );        movd_m2r( *b1, mm1 );        movd_m2r( *m0, mm2 );        movd_m2r( *(t1+4), mm3 );        movd_m2r( *(b1+4), mm4 );        movd_m2r( *(m0+4), mm5 );        punpcklbw_r2r( mm7, mm0 );        punpcklbw_r2r( mm7, mm1 );        punpcklbw_r2r( mm7, mm2 );        punpcklbw_r2r( mm7, mm3 );        punpcklbw_r2r( mm7, mm4 );        punpcklbw_r2r( mm7, mm5 );        psllw_i2r( 1, mm2 );        psllw_i2r( 1, mm5 );        paddw_r2r( mm0, mm2 );        paddw_r2r( mm3, mm5 );        paddw_r2r( mm1, mm2 );        paddw_r2r( mm4, mm5 );        psrlw_i2r( 2, mm2 );        psrlw_i2r( 2, mm5 );        packuswb_r2r( mm2, mm2 );        packuswb_r2r( mm5, mm5 );        movd_r2m( mm2, *output );        movd_r2m( mm5, *(output+4) );        output += 8;        t1 += 8;        b1 += 8;        m0 += 8;    }    while( width-- ) {        *output++ = (*t1++ + *b1++ + (*m0++ << 1)) >> 2;    }    emms();#else    width *= 2;    while( width-- ) {        *output++ = (*t1++ + *b1++ + (*m0++ << 1)) >> 2;    }#endif}#if defined(ARCH_X86) || defined(ARCH_X86_64)/* MMXEXT version is about 15% faster with Athlon XP [MF] */static void deinterlace_scanline_linear_blend_mmxext( uint8_t *output,                                               deinterlace_scanline_data_t *data,                                               int width ){    uint8_t *t0 = data->t0;    uint8_t *b0 = data->b0;    uint8_t *m1 = data->m1;    int i;    static mmx_t high_mask = {ub:{0xff,0xff,0xff,0xff,0,0,0,0}};    READ_PREFETCH_2048( t0 );    READ_PREFETCH_2048( b0 );    READ_PREFETCH_2048( m1 );    // Get width in bytes.    width *= 2;    i = width / 8;    width -= i * 8;    movd_m2r( high_mask, mm6 );    pxor_r2r( mm7, mm7 );    while( i-- ) {        movd_m2r( *t0, mm0 );        movd_m2r( *b0, mm1 );        movd_m2r( *m1, mm2 );        movd_m2r( *(t0+4), mm3 );        movd_m2r( *(b0+4), mm4 );        movd_m2r( *(m1+4), mm5 );        punpcklbw_r2r( mm7, mm0 );        punpcklbw_r2r( mm7, mm1 );        punpcklbw_r2r( mm7, mm2 );        punpcklbw_r2r( mm7, mm3 );        punpcklbw_r2r( mm7, mm4 );        punpcklbw_r2r( mm7, mm5 );        psllw_i2r( 1, mm2 );        psllw_i2r( 1, mm5 );        paddw_r2r( mm0, mm2 );        paddw_r2r( mm3, mm5 );        paddw_r2r( mm1, mm2 );        paddw_r2r( mm4, mm5 );        psrlw_i2r( 2, mm2 );        psrlw_i2r( 2, mm5 );        packuswb_r2r( mm2, mm2 );        packuswb_r2r( mm5, mm5 );        psllq_i2r( 32, mm5 );        pand_r2r( mm6, mm2 );        por_r2r( mm2, mm5 );        movntq_r2m( mm5, *output );        output += 8;        t0 += 8;        b0 += 8;        m1 += 8;    }    while( width-- ) {        *output++ = (*t0++ + *b0++ + (*m1++ << 1)) >> 2;    }    sfence();    emms();}static void deinterlace_scanline_linear_blend2_mmxext( uint8_t *output,                                                deinterlace_scanline_data_t *data,                                                int width ){    uint8_t *m0 = data->m0;    uint8_t *t1 = data->t1;    uint8_t *b1 = data->b1;    int i;     READ_PREFETCH_2048( t1 );    READ_PREFETCH_2048( b1 );    READ_PREFETCH_2048( m0 );    // Get width in bytes.    width *= 2;    i = width / 8;    width -= i * 8;    pxor_r2r( mm7, mm7 );    while( i-- ) {        movd_m2r( *t1, mm0 );        movd_m2r( *b1, mm1 );        movd_m2r( *m0, mm2 );        movd_m2r( *(t1+4), mm3 );        movd_m2r( *(b1+4), mm4 );        movd_m2r( *(m0+4), mm5 );        punpcklbw_r2r( mm7, mm0 );        punpcklbw_r2r( mm7, mm1 );        punpcklbw_r2r( mm7, mm2 );        punpcklbw_r2r( mm7, mm3 );        punpcklbw_r2r( mm7, mm4 );        punpcklbw_r2r( mm7, mm5 );        psllw_i2r( 1, mm2 );        psllw_i2r( 1, mm5 );        paddw_r2r( mm0, mm2 );        paddw_r2r( mm3, mm5 );        paddw_r2r( mm1, mm2 );        paddw_r2r( mm4, mm5 );        psrlw_i2r( 2, mm2 );        psrlw_i2r( 2, mm5 );        packuswb_r2r( mm2, mm2 );        packuswb_r2r( mm5, mm5 );        psllq_i2r( 32, mm5 );        pand_r2r( mm6, mm2 );        por_r2r( mm2, mm5 );        movntq_r2m( mm5, *output );        output += 8;        t1 += 8;        b1 += 8;        m0 += 8;    }    while( width-- ) {        *output++ = (*t1++ + *b1++ + (*m0++ << 1)) >> 2;    }    sfence();    emms();}static deinterlace_method_t linearblendmethod_mmxext ={    "Linear Blend (mplayer)",    "LinearBlend",    2,    MM_ACCEL_X86_MMXEXT,    0,    1,    deinterlace_scanline_linear_blend_mmxext,    deinterlace_scanline_linear_blend2_mmxext,    0,    0,    linearblendmethod_help};#endifstatic deinterlace_method_t linearblendmethod ={    "Linear Blend (mplayer)",    "LinearBlend",/*    "Blur: Temporal",    "BlurTemporal",*/    2,#if defined(ARCH_X86) || defined(ARCH_X86_64)    MM_ACCEL_X86_MMX,#else    0,#endif    0,    1,    deinterlace_scanline_linear_blend,    deinterlace_scanline_linear_blend2,    0,    0,    linearblendmethod_help};deinterlace_method_t *linearblend_get_method( void ){#if defined(ARCH_X86) || defined(ARCH_X86_64)    if( xine_mm_accel() & MM_ACCEL_X86_MMXEXT )      return &linearblendmethod_mmxext;    else#endif      return &linearblendmethod;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?