X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fvideo_filter%2Fpostproc.c;h=cf31d806381064a409158001d1cfa53ef156b084;hb=1c7c0c9f95b8df3141121736e22c212173a10860;hp=e05d773beae374eb468cd71ee225b31c829d298f;hpb=4b00ff6ec805784d3b136591f0a4cf460ac36af9;p=vlc diff --git a/modules/video_filter/postproc.c b/modules/video_filter/postproc.c index e05d773bea..cf31d80638 100644 --- a/modules/video_filter/postproc.c +++ b/modules/video_filter/postproc.c @@ -1,7 +1,7 @@ /***************************************************************************** * postproc.c: video postprocessing using libpostproc ***************************************************************************** - * Copyright (C) 1999-2008 the VideoLAN team + * Copyright (C) 1999-2009 the VideoLAN team * $Id$ * * Authors: Laurent Aimar @@ -29,7 +29,8 @@ #include #include -#include +#include +#include #include "filter_picture.h" @@ -63,32 +64,33 @@ static int PPNameCallback( vlc_object_t *, char const *, "better looking pictures." ) #define NAME_TEXT N_("FFmpeg post processing filter chains") -/* defined by libpostproc */ -#define NAME_LONGTEXT pp_help +#define NAME_LONGTEXT NAME_TEXT #define FILTER_PREFIX "postproc-" /***************************************************************************** * Module descriptor *****************************************************************************/ -vlc_module_begin(); - set_description( N_("Video post processing filter") ); - add_shortcut( "postprocess" ); /* name is "postproc" */ - add_shortcut( "pp" ); - set_category( CAT_VIDEO ); - set_subcategory( SUBCAT_VIDEO_VFILTER ); +vlc_module_begin () + set_description( N_("Video post processing filter") ) + set_shortname( N_("Postproc" ) ) + add_shortcut( "postprocess" ) /* name is "postproc" */ + add_shortcut( "pp" ) + set_category( CAT_VIDEO ) + set_subcategory( SUBCAT_VIDEO_VFILTER ) - set_capability( "video filter2", 0 ); + set_capability( "video filter2", 0 ) - set_callbacks( OpenPostproc, ClosePostproc ); + set_callbacks( OpenPostproc, ClosePostproc ) add_integer_with_range( FILTER_PREFIX "q", PP_QUALITY_MAX, 0, - PP_QUALITY_MAX, NULL, Q_TEXT, Q_LONGTEXT, false ); - add_deprecated_alias( "ffmpeg-pp-q" ); + PP_QUALITY_MAX, NULL, Q_TEXT, Q_LONGTEXT, false ) + add_deprecated_alias( "ffmpeg-pp-q" ) + change_safe() add_string( FILTER_PREFIX "name", "default", NULL, NAME_TEXT, - NAME_LONGTEXT, true ); - add_deprecated_alias( "ffmpeg-pp-name" ); -vlc_module_end(); + NAME_LONGTEXT, true ) + add_deprecated_alias( "ffmpeg-pp-name" ) +vlc_module_end () static const char *const ppsz_filter_options[] = { "q", "name", NULL @@ -99,10 +101,18 @@ static const char *const ppsz_filter_options[] = { *****************************************************************************/ struct filter_sys_t { - pp_context_t *pp_context; /* Never changes after init */ - pp_mode_t *pp_mode; /* Set to NULL if post processing is disabled */ + /* Never changes after init */ + pp_context_t *pp_context; - vlc_mutex_t lock; /* Lock when using or changing pp_mode */ + /* Set to NULL if post processing is disabled */ + pp_mode_t *pp_mode; + + /* Set to true if previous pic had a quant matrix + (used to prevent spamming warning messages) */ + bool b_had_matrix; + + /* Lock when using or changing pp_mode */ + vlc_mutex_t lock; }; @@ -137,26 +147,28 @@ static int OpenPostproc( vlc_object_t *p_this ) switch( p_filter->fmt_in.video.i_chroma ) { - case VLC_FOURCC('I','4','4','4'): - case VLC_FOURCC('J','4','4','4'): + case VLC_CODEC_I444: + case VLC_CODEC_J444: + /* case VLC_CODEC_YUVA: + FIXME: Should work but alpha plane needs to be copied manually and + I'm kind of feeling too lazy to write the code to do that ATM + (i_pitch vs i_visible_pitch...). */ i_flags |= PP_FORMAT_444; break; - case VLC_FOURCC('I','4','2','2'): - case VLC_FOURCC('J','4','2','2'): + case VLC_CODEC_I422: + case VLC_CODEC_J422: i_flags |= PP_FORMAT_422; break; - case VLC_FOURCC('I','4','1','1'): + case VLC_CODEC_I411: i_flags |= PP_FORMAT_411; break; - case VLC_FOURCC('I','4','2','0'): - case VLC_FOURCC('I','Y','U','V'): - case VLC_FOURCC('J','4','2','0'): - case VLC_FOURCC('Y','V','1','2'): - /* case VLC_FOURCC('Y','U','V','A'): FIXME Should work but alpha plane needs to be copied manually and I'm kind of feeling too lazy to write the code to do that ATM (i_pitch vs i_visible_pitch...). */ + case VLC_CODEC_I420: + case VLC_CODEC_J420: + case VLC_CODEC_YV12: i_flags |= PP_FORMAT_420; break; default: - msg_Err( p_filter, "Unsupported input chroma (%4s)", + msg_Err( p_filter, "Unsupported input chroma (%4.4s)", (char*)&p_filter->fmt_in.video.i_chroma ); return VLC_EGENERIC; } @@ -178,23 +190,20 @@ static int OpenPostproc( vlc_object_t *p_this ) config_ChainParse( p_filter, FILTER_PREFIX, ppsz_filter_options, p_filter->p_cfg ); - var_Create( p_filter, FILTER_PREFIX "q", - VLC_VAR_INTEGER | VLC_VAR_HASCHOICE | VLC_VAR_DOINHERIT | - VLC_VAR_ISCOMMAND ); - var_Change( p_filter, FILTER_PREFIX "q", VLC_VAR_SETISCOMMAND, NULL, NULL ); /* For some obscure reason the VLC_VAR_ISCOMMAND isn't taken into account in during var_Create */ - var_AddCallback( p_filter, FILTER_PREFIX "q", PPQCallback, NULL ); + var_Create( p_filter, FILTER_PREFIX "q", VLC_VAR_INTEGER | + VLC_VAR_HASCHOICE | VLC_VAR_DOINHERIT | VLC_VAR_ISCOMMAND ); + text.psz_string = _("Post processing"); var_Change( p_filter, FILTER_PREFIX "q", VLC_VAR_SETTEXT, &text, NULL ); var_Get( p_filter, FILTER_PREFIX "q", &val_orig ); var_Change( p_filter, FILTER_PREFIX "q", VLC_VAR_DELCHOICE, &val_orig, NULL ); - val.psz_string = var_CreateGetNonEmptyStringCommand( - p_filter, FILTER_PREFIX "name" ); - var_AddCallback( p_filter, FILTER_PREFIX "name", PPNameCallback, NULL ); + val.psz_string = var_GetNonEmptyString( p_filter, FILTER_PREFIX "name" ); if( val_orig.i_int ) { - p_sys->pp_mode = pp_get_mode_by_name_and_quality( val.psz_string?: + p_sys->pp_mode = pp_get_mode_by_name_and_quality( val.psz_string ? + val.psz_string : "default", val_orig.i_int ); @@ -202,7 +211,6 @@ static int OpenPostproc( vlc_object_t *p_this ) { msg_Err( p_filter, "Error while creating post processing mode." ); free( val.psz_string ); - var_Destroy( p_filter, FILTER_PREFIX "q" ); pp_free_context( p_sys->pp_context ); free( p_sys ); return VLC_EGENERIC; @@ -237,7 +245,12 @@ static int OpenPostproc( vlc_object_t *p_this ) vlc_mutex_init( &p_sys->lock ); + /* Add the callback at the end to prevent crashes */ + var_AddCallback( p_filter, FILTER_PREFIX "q", PPQCallback, NULL ); + var_AddCallback( p_filter, FILTER_PREFIX "name", PPNameCallback, NULL ); + p_filter->pf_video_filter = PostprocPict; + p_sys->b_had_matrix = true; return VLC_SUCCESS; } @@ -249,6 +262,12 @@ static void ClosePostproc( vlc_object_t *p_this ) { filter_t *p_filter = (filter_t *)p_this; filter_sys_t *p_sys = p_filter->p_sys; + + /* delete the callback before destroying the mutex */ + var_DelCallback( p_filter, FILTER_PREFIX "q", PPQCallback, NULL ); + var_DelCallback( p_filter, FILTER_PREFIX "name", PPNameCallback, NULL ); + + /* Destroy the resources */ vlc_mutex_destroy( &p_sys->lock ); pp_free_context( p_sys->pp_context ); if( p_sys->pp_mode ) pp_free_mode( p_sys->pp_mode ); @@ -267,21 +286,23 @@ static picture_t *PostprocPict( filter_t *p_filter, picture_t *p_pic ) int i_plane; int i_src_stride[3], i_dst_stride[3]; - vlc_mutex_lock( &p_sys->lock ); /* Lock to prevent issues if pp_mode is changed */ - if( !p_sys->pp_mode ) - { - vlc_mutex_unlock( &p_sys->lock ); - return p_pic; - } - picture_t *p_outpic = filter_NewPicture( p_filter ); if( !p_outpic ) { picture_Release( p_pic ); - vlc_mutex_unlock( &p_sys->lock ); return NULL; } + /* Lock to prevent issues if pp_mode is changed */ + vlc_mutex_lock( &p_sys->lock ); + if( !p_sys->pp_mode ) + { + vlc_mutex_unlock( &p_sys->lock ); + picture_CopyPixels( p_outpic, p_pic ); + return CopyInfoAndRelease( p_outpic, p_pic ); + } + + for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ ) { src[i_plane] = p_pic->p[i_plane].p_pixels; @@ -293,20 +314,29 @@ static picture_t *PostprocPict( filter_t *p_filter, picture_t *p_pic ) i_dst_stride[i_plane] = p_outpic->p[i_plane].i_pitch; } + if( !p_pic->p_q && p_sys->b_had_matrix ) + { + msg_Warn( p_filter, "Quantification table was not set by video decoder. Postprocessing won't look good." ); + p_sys->b_had_matrix = false; + } + else if( p_pic->p_q ) + { + p_sys->b_had_matrix = true; + } + pp_postprocess( src, i_src_stride, dst, i_dst_stride, p_filter->fmt_in.video.i_width, p_filter->fmt_in.video.i_height, - NULL /* FIXME ? works by selecting a default table. But maybe setting our own might help improve post processing quality ... */, - 0 /* FIXME */, + p_pic->p_q, p_pic->i_qstride, p_sys->pp_mode, p_sys->pp_context, - PP_PICT_TYPE_QP2 /* FIXME ? This should be set only for mpeg2 type codecs if I understand correctly. */ ); + p_pic->i_qtype == QTYPE_MPEG2 ? PP_PICT_TYPE_QP2 : 0 ); vlc_mutex_unlock( &p_sys->lock ); return CopyInfoAndRelease( p_outpic, p_pic ); } /***************************************************************************** - * + * PPChangeMode: change the current mode and quality *****************************************************************************/ static void PPChangeMode( filter_t *p_filter, const char *psz_name, int i_quality ) @@ -315,7 +345,8 @@ static void PPChangeMode( filter_t *p_filter, const char *psz_name, vlc_mutex_lock( &p_sys->lock ); if( i_quality > 0 ) { - pp_mode_t *pp_mode = pp_get_mode_by_name_and_quality( psz_name?: + pp_mode_t *pp_mode = pp_get_mode_by_name_and_quality( psz_name ? + psz_name : "default", i_quality ); if( pp_mode ) @@ -354,6 +385,7 @@ static int PPNameCallback( vlc_object_t *p_this, const char *psz_var, filter_t *p_filter = (filter_t *)p_this; int i_quality = var_GetInteger( p_filter, FILTER_PREFIX "q" ); - PPChangeMode( p_filter, *newval.psz_string?newval.psz_string:NULL, i_quality ); + PPChangeMode( p_filter, *newval.psz_string ? newval.psz_string : NULL, + i_quality ); return VLC_SUCCESS; }