Commit 313acca3 authored by gbazin's avatar gbazin
Browse files

* modules/codec/ffmpeg/postprocessing: removed deprecated postprocessing code.

parent b15eda88
......@@ -4138,7 +4138,6 @@ AC_CONFIG_FILES([
modules/codec/cmml/Makefile
modules/codec/dmo/Makefile
modules/codec/ffmpeg/Makefile
modules/codec/ffmpeg/postprocessing/Makefile
modules/codec/ogt/Makefile
modules/codec/spudec/Makefile
modules/control/Makefile
......
SOURCES_postprocessing_c = \
postprocessing.c \
postprocessing_c.c \
$(NULL)
SOURCES_postprocessing_mmx = \
postprocessing.c \
postprocessing_mmx.c \
$(NULL)
SOURCES_postprocessing_mmxext = \
postprocessing.c \
postprocessing_mmxext.c \
$(NULL)
noinst_HEADERS += \
postprocessing.h \
postprocessing_common.h \
$(NULL)
/*****************************************************************************
* postprocessing.c
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
* $Id$
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
*
* 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 of the License, 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, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include <stdlib.h>
#include <string.h>
#include <vlc/vlc.h>
#include <vlc/vout.h>
#include "postprocessing.h"
#include "postprocessing_common.h"
static int Open ( vlc_object_t *p_this );
static uint32_t pp_getmode( int i_quality, int b_autolevel );
static int pp_postprocess( picture_t *,
QT_STORE_T *, unsigned int,
unsigned int i_mode );
/*****************************************************************************
* Module descriptor
*****************************************************************************/
vlc_module_begin();
#ifdef MODULE_NAME_IS_postprocessing_c
set_description( _("C post processing") );
set_capability( "postprocessing", 50 );
add_shortcut( "c" );
#elif defined( MODULE_NAME_IS_postprocessing_mmx )
set_description( _("MMX post processing") );
set_capability( "postprocessing", 100 );
add_requirement( MMX );
add_shortcut( "mmx" );
#elif defined( MODULE_NAME_IS_postprocessing_mmxext )
set_description( _("MMX EXT post processing") );
set_capability( "postprocessing", 150 );
add_requirement( MMXEXT );
add_shortcut( "mmxext" );
add_shortcut( "mmx2" );
#endif
set_callbacks( Open, NULL );
vlc_module_end();
/*****************************************************************************
* Module initializer
*****************************************************************************/
static int Open ( vlc_object_t *p_this )
{
postprocessing_t *p_pp = (postprocessing_t *)p_this;
p_pp->pf_getmode = pp_getmode;
p_pp->pf_postprocess = pp_postprocess;
return VLC_SUCCESS;
}
static uint32_t pp_getmode( int i_quality, int b_autolevel )
{
uint32_t i_mode;
i_quality = i_quality < 0 ? 0 : i_quality;
i_quality = i_quality > 6 ? 6 : i_quality;
switch( i_quality )
{
case( 0 ):
i_mode = 0;
break;
case( 1 ):
i_mode = PP_DEBLOCK_Y_H;
break;
case( 2 ):
i_mode = PP_DEBLOCK_Y_H|PP_DEBLOCK_Y_V;
break;
case( 3 ):
i_mode = PP_DEBLOCK_Y_H|PP_DEBLOCK_Y_V|
PP_DEBLOCK_C_H;
break;
case( 4 ):
i_mode = PP_DEBLOCK_Y_H|PP_DEBLOCK_Y_V|
PP_DEBLOCK_C_H|PP_DEBLOCK_C_V;
break;
case( 5 ):
i_mode = PP_DEBLOCK_Y_H|PP_DEBLOCK_Y_V|
PP_DEBLOCK_C_H|PP_DEBLOCK_C_V|
PP_DERING_Y;
break;
case( 6 ):
i_mode = PP_DEBLOCK_Y_H|PP_DEBLOCK_Y_V|
PP_DEBLOCK_C_H|PP_DEBLOCK_C_V|
PP_DERING_Y|PP_DERING_C;
break;
default:
i_mode = 0;
}
if( b_autolevel )
{
i_mode |= PP_AUTOLEVEL;
}
return( i_mode );
}
/*****************************************************************************
* pp_postprocess : make post-filter as defined in MPEG4-ISO
*****************************************************************************
*****************************************************************************/
static int pp_postprocess( picture_t *p_pic,
QT_STORE_T *p_QP_store, unsigned int i_QP_stride,
unsigned int i_mode )
{
/* Some sanity checks */
/* if( ( p_pic->i_height&0x0f )||( p_pic->i_width&0x0f )||*/
if( ( p_pic->p_heap->i_chroma != VLC_FOURCC( 'I', '4', '2', '0' ) )&&
( p_pic->p_heap->i_chroma != VLC_FOURCC( 'Y', 'V', '1', '2' ) ) )
{
return( PP_ERR_INVALID_PICTURE );
}
if( ( !p_QP_store )||( i_QP_stride < p_pic->p_heap->i_width >> 4 ) )
{
return( PP_ERR_INVALID_QP );
}
/* First do vertical deblocking and then horizontal */
/* Luminance */
if( i_mode&PP_DEBLOCK_Y_V )
{
E_( pp_deblock_V )( p_pic->Y_PIXELS,
p_pic->p_heap->i_width, p_pic->p_heap->i_height, p_pic->Y_PITCH,
p_QP_store, i_QP_stride,
0 );
}
if( i_mode&PP_DEBLOCK_Y_H )
{
E_( pp_deblock_H )( p_pic->Y_PIXELS,
p_pic->p_heap->i_width, p_pic->p_heap->i_height, p_pic->Y_PITCH,
p_QP_store, i_QP_stride,
0 );
}
/* Chrominance */
if( i_mode&PP_DEBLOCK_C_V )
{
E_( pp_deblock_V )( p_pic->U_PIXELS,
p_pic->p_heap->i_width >> 1, p_pic->p_heap->i_height >> 1,
p_pic->U_PITCH,
p_QP_store, i_QP_stride,
1 );
E_( pp_deblock_V )( p_pic->V_PIXELS,
p_pic->p_heap->i_width >> 1, p_pic->p_heap->i_height >> 1,
p_pic->V_PITCH,
p_QP_store, i_QP_stride,
1 );
}
if( i_mode&PP_DEBLOCK_C_H )
{
E_( pp_deblock_H )( p_pic->U_PIXELS,
p_pic->p_heap->i_width >> 1, p_pic->p_heap->i_height >> 1,
p_pic->U_PITCH,
p_QP_store, i_QP_stride,
1 );
E_( pp_deblock_H )( p_pic->V_PIXELS,
p_pic->p_heap->i_width >> 1, p_pic->p_heap->i_height >> 1,
p_pic->V_PITCH,
p_QP_store, i_QP_stride,
1 );
}
/* After deblocking do dering */
/* TODO check for min size */
if( i_mode&PP_DERING_Y )
{
E_( pp_dering_Y )( p_pic->Y_PIXELS,
p_pic->p_heap->i_width, p_pic->p_heap->i_height,
p_pic->Y_PITCH,
p_QP_store, i_QP_stride );
}
if( i_mode&PP_DERING_C )
{
E_( pp_dering_C )( p_pic->U_PIXELS,
p_pic->p_heap->i_width >> 1, p_pic->p_heap->i_height >> 1,
p_pic->U_PITCH,
p_QP_store, i_QP_stride );
E_( pp_dering_C )( p_pic->V_PIXELS,
p_pic->p_heap->i_width >> 1, p_pic->p_heap->i_height >> 1,
p_pic->V_PITCH,
p_QP_store, i_QP_stride );
}
#if defined( MODULE_NAME_IS_postprocessing_mmx )||defined( MODULE_NAME_IS_postprocessing_mmxext )
/* We have used MMX so return to safe FPU state */
__asm__ __volatile__ ( "emms" );
#endif
return( PP_ERR_OK );
}
/*****************************************************************************
* postprocessing.h
*****************************************************************************
* Copyright (C) 2001 VideoLAN
* $Id: postprocessing.h,v 1.3 2003/10/25 00:49:14 sam Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
*
* 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 of the License, 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, USA.
*****************************************************************************/
#define QT_STORE_T int8_t
/* postprocessing available using to create i_mode */
#define PP_DEBLOCK_Y_H 0x00000001
#define PP_DEBLOCK_Y_V 0x00000002
#define PP_DEBLOCK_C_H 0x00000004
#define PP_DEBLOCK_C_V 0x00000008
#define PP_DERING_Y 0x00000010
#define PP_DERING_C 0x00000020
#define PP_AUTOLEVEL 0x80000000
/* error code, not really used */
#define PP_ERR_OK 0 /* no problem */
#define PP_ERR_INVALID_PICTURE 1 /* wrong picture size or chroma */
#define PP_ERR_INVALID_QP 2 /* need valid QP to make the postprocess */
#define PP_ERR_UNKNOWN 255
typedef struct postprocessing_s
{
VLC_COMMON_MEMBERS
module_t * p_module;
uint32_t (*pf_getmode)( int i_quality, int b_autolevel );
int (*pf_postprocess)( picture_t *p_pic,
QT_STORE_T *p_QP_store, unsigned int i_QP_stride,
unsigned int i_mode );
} postprocessing_t;
/*****************************************************************************
* postprocessing_c.c: Post Processing plugin in C
*****************************************************************************
* Copyright (C) 2001 VideoLAN
* $Id: postprocessing_c.c,v 1.2 2002/12/06 16:34:05 sam Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
*
* 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 of the License, 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, USA.
*****************************************************************************/
#include <vlc/vlc.h> /* only use uint8_t, uint32_t .... */
#include "postprocessing.h"
#include "postprocessing_common.h"
/*****************************************************************************
*
* Internals functions common to pp_deblock_V and pp_deblock_H
*
*****************************************************************************/
/****************************************************************************
* pp_deblock_isDC_mode : Check if we will use DC mode or Default mode
****************************************************************************
* Use constant PP_THR1 and PP_THR2 ( PP_2xTHR1 )
*
* Called for for each pixel on a boundary block when doing deblocking
* so need to be fast ...
*
****************************************************************************/
static inline int pp_deblock_isDC_mode( uint8_t *p_v )
{
unsigned int i_eq_cnt;
/* algo : if ( | v[i] -v[i+1] | <= PP_THR1 ) { i_eq_cnt++; } */
i_eq_cnt = 0;
if(( ( p_v[0] - p_v[1] + PP_THR1 )&0xffff )<= PP_2xTHR1 ) i_eq_cnt++;
if(( ( p_v[1] - p_v[2] + PP_THR1 )&0xffff )<= PP_2xTHR1 ) i_eq_cnt++;
if(( ( p_v[2] - p_v[3] + PP_THR1 )&0xffff )<= PP_2xTHR1 ) i_eq_cnt++;
if(( ( p_v[3] - p_v[4] + PP_THR1 )&0xffff )<= PP_2xTHR1 ) i_eq_cnt++;
if(( ( p_v[4] - p_v[5] + PP_THR1 )&0xffff )<= PP_2xTHR1 ) i_eq_cnt++;
if(( ( p_v[5] - p_v[6] + PP_THR1 )&0xffff )<= PP_2xTHR1 ) i_eq_cnt++;
if(( ( p_v[6] - p_v[7] + PP_THR1 )&0xffff )<= PP_2xTHR1 ) i_eq_cnt++;
if(( ( p_v[7] - p_v[8] + PP_THR1 )&0xffff )<= PP_2xTHR1 ) i_eq_cnt++;
if(( ( p_v[8] - p_v[9] + PP_THR1 )&0xffff )<= PP_2xTHR1 ) i_eq_cnt++;
#if 0
int i;
for( i =0; i < 9; i++ )
{
if(( ( p_v[i] - p_v[i+1] + PP_THR1 )&0xffff )<= PP_2xTHR1 )
{
i_eq_cnt++;
}
}
#endif
return( (i_eq_cnt >= PP_THR2 ) ? 1 : 0 );
}
static inline int pp_deblock_isMinMaxOk( uint8_t *p_v, int i_QP )
{
int i_max, i_min;
i_min = i_max = p_v[1];
if( i_max < p_v[1] ) i_max = p_v[1];
if( i_min > p_v[1] ) i_min = p_v[1];
if( i_max < p_v[2] ) i_max = p_v[2];
if( i_min > p_v[2] ) i_min = p_v[2];
if( i_max < p_v[3] ) i_max = p_v[3];
if( i_min > p_v[3] ) i_min = p_v[3];
if( i_max < p_v[4] ) i_max = p_v[4];
if( i_min > p_v[4] ) i_min = p_v[4];
if( i_max < p_v[5] ) i_max = p_v[5];
if( i_min > p_v[5] ) i_min = p_v[5];
if( i_max < p_v[6] ) i_max = p_v[6];
if( i_min > p_v[6] ) i_min = p_v[6];
if( i_max < p_v[7] ) i_max = p_v[7];
if( i_min > p_v[7] ) i_min = p_v[7];
if( i_max < p_v[8] ) i_max = p_v[8];
if( i_min > p_v[8] ) i_min = p_v[8];
#if 0
int i;
int i_range;
for( i = 2; i < 9; i++ )
{
if( i_max < p_v[i] ) i_max = p_v[i];
if( i_min > p_v[i] ) i_min = p_v[i];
}
i_range = i_max - i_min;
#endif
return( i_max - i_min < 2*i_QP ? 1 : 0 );
}
static inline void pp_deblock_DefaultMode( uint8_t i_v[10], int i_stride,
int i_QP )
{
int d, i_delta;
int a3x0, a3x0_, a3x1, a3x2;
int b_neg;
/* d = CLIP( 5(a3x0' - a3x0)//8, 0, (v4-v5)/2 ).d( abs(a3x0) < QP ) */
/* First calculate a3x0 */
a3x0 = 2 * ( i_v[3] - i_v[6] ) + 5 *( i_v[5] - i_v[4] );
if( a3x0 < 0 )
{
b_neg = 1;
a3x0 = -a3x0;
}
else
{
b_neg = 0;
}
/* XXX Now a3x0 is abs( a3x0 ) */
if( ( a3x0 < 8 * i_QP )&&( a3x0 != 0 ) ) /* |a3x0| < 8*i_QP */
{
/* calculate a3x1 et a3x2 */
a3x1 = 2 * ( i_v[1] - i_v[4] ) + 5 * ( i_v[3] - i_v[2] );
a3x2 = 2 * ( i_v[5] - i_v[8] ) + 5 * ( i_v[7] - i_v[6] );
if( a3x1 < 0) a3x1 = -a3x1; /* abs( a3x1 ) */
if( a3x2 < 0) a3x2 = -a3x2; /* abs( a3x2 ) */
a3x0_ = PP_MIN3( a3x0, a3x1, a3x2 );
d = 5 *( a3x0 - a3x0_ ) / 8; /* always > 0 */
i_delta = ( i_v[4] - i_v[5] ) / 2;
/* clip into [0, i_delta] or [i_delta, 0] */
if( i_delta < 0 )
{
if( !b_neg ) /* since true d has sgn(d) = - sgn( a3x0 ) */
{
d = -d;
if( d < i_delta ) d = i_delta;
i_v[4] -= d;
i_v[5] += d;
}
}
else
{
if( b_neg )
{
if( d > i_delta ) d = i_delta;
i_v[4] -= d;
i_v[5] += d;
}
}
}
}
static inline void pp_deblock_DCMode( uint8_t *p_v, /* = int i_v[10] */
int i_QP )
{
int v[10];
int i;
int i_p0, i_p9;
i_p0 = PP_ABS( p_v[1] - p_v[0] ) < i_QP ? p_v[0] : p_v[1];
i_p9 = PP_ABS( p_v[8] - p_v[9] ) < i_QP ? p_v[9] : p_v[8];
for( i = 1; i < 9; i++ )
{
v[i] = p_v[i]; /* save 8 pix that will be modified */
}
p_v[1] = ( 6 * i_p0 + 4 * v[1]
+ 2 *( v[2] + v[3]) + v[4] + v[5]) >> 4;
p_v[2] = ( 4 * i_p0 + 2 * v[1] + 4 * v[2]
+ 2 *( v[3] + v[4]) + v[5] + v[6]) >> 4;
p_v[3] = ( 2 * i_p0 + 2 * (v[1] + v[2]) + 4 * v[3]
+ 2 *( v[4] + v[5]) + v[6] + v[7]) >> 4;
p_v[4] = ( i_p0 + v[1] + 2 * (v[2] + v[3]) + 4 * v[4]
+ 2 *( v[5] + v[6]) + v[7] + v[8]) >> 4;
p_v[5] = ( v[1] + v[2] + 2 * (v[3] + v[4]) + 4 * v[5]
+ 2 *( v[6] + v[7]) + v[8] + i_p9) >> 4;
p_v[6] = ( v[2] + v[3] + 2 * (v[4] + v[5]) + 4 * v[6]
+ 2 *( v[7] + v[8]) + 2 * i_p9) >> 4;
p_v[7] = ( v[3] + v[4] + 2 * (v[5] + v[6]) + 4 * v[7]
+ 2 * v[8] + 4 * i_p9) >> 4;
p_v[8] = ( v[4] + v[5] + 2 * (v[6] + v[7]) + 4 * v[8]
+ 6 * i_p9) >> 4;
}
/*****************************************************************************/
/*---------------------------------------------------------------------------*/
/* */
/* ---------- filter Vertical lines so follow horizontal edges -------- */
/* */
/*---------------------------------------------------------------------------*/
/*****************************************************************************/
void E_( pp_deblock_V )( uint8_t *p_plane,
int i_width, int i_height, int i_stride,
QT_STORE_T *p_QP_store, int i_QP_stride,
int b_chroma )
{
int x, y, i;
uint8_t *p_v;
int i_QP_scale; /* use to do ( ? >> i_QP_scale ) */
int i_QP;
uint8_t i_v[10];
i_QP_scale = b_chroma ? 5 : 4 ;
for( y = 8; y < i_height - 4; y += 8 )
{
p_v = p_plane + ( y - 5 )* i_stride;
for( x = 0; x < i_width; x++ )
{
/* First get 10 vert pix to use them without i_stride */
for( i = 0; i < 10; i++ )
{
i_v[i] = p_v[i*i_stride + x];
}
i_QP = p_QP_store[(y>>i_QP_scale)*i_QP_stride+
(x>>i_QP_scale)];
/* XXX QP is for v5 */
if( pp_deblock_isDC_mode( i_v ) )
{
if( pp_deblock_isMinMaxOk( i_v, i_QP ) )
{
pp_deblock_DCMode( i_v, i_QP );
}
}
else
{
pp_deblock_DefaultMode( i_v, i_stride, i_QP );
}
/* Copy back, XXX only 1-8 were modified */
for( i = 1; i < 9; i++ )
{
p_v[i*i_stride + x] = i_v[i];
}
}
}
return;
}