X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fvideo_filter%2Fchain.c;h=1c295bba856d842c800c93b2bf8f014177a23150;hb=ea93da268c6617a0c5c98a2125b9aa27eba19d6d;hp=dd65f08c141dec4f21242c5d2d5ae928e072cfad;hpb=3223bb48e69376664842115be49c4550c4506eaa;p=vlc diff --git a/modules/video_filter/chain.c b/modules/video_filter/chain.c index dd65f08c14..1c295bba85 100644 --- a/modules/video_filter/chain.c +++ b/modules/video_filter/chain.c @@ -32,33 +32,32 @@ #include #include #include -#include - -/***************************************************************************** - * Local and extern prototypes. - *****************************************************************************/ -static int Activate ( vlc_object_t * ); -static void Destroy ( vlc_object_t * ); -static picture_t *Chain( filter_t *, picture_t * ); /***************************************************************************** * Module descriptor *****************************************************************************/ +static int Activate ( vlc_object_t * ); +static void Destroy ( vlc_object_t * ); + vlc_module_begin(); set_description( N_("Video filtering using a chain of video filter modules") ); set_capability( "video filter2", 1 ); set_callbacks( Activate, Destroy ); vlc_module_end(); -#define MAX_FILTERS 4 +/***************************************************************************** + * Local prototypes. + *****************************************************************************/ +static picture_t *Chain ( filter_t *, picture_t * ); +static int BufferAllocationInit ( filter_t *, void * ); + +static int BuildChromaResize( filter_t * ); +static int BuildChromaChain( filter_t *p_filter ); -struct filter_sys_t -{ - filter_t *p_filter1; /* conversion from fmt_in to fmr_mid */ - filter_t *p_filter2; /* conversion from fmt_mid to fmt_out */ - picture_t *p_tmp; /* temporary picture buffer */ - video_format_t fmt_mid; -}; +static int CreateChain( filter_chain_t *p_chain, es_format_t *p_fmt_mid ); +static void EsFormatMergeSize( es_format_t *p_dst, + const es_format_t *p_base, + const es_format_t *p_size ); static const vlc_fourcc_t pi_allowed_chromas[] = { VLC_FOURCC('I','4','2','0'), @@ -68,181 +67,202 @@ static const vlc_fourcc_t pi_allowed_chromas[] = { 0 }; -static picture_t *get_pic( filter_t *p_filter ) +struct filter_sys_t { - picture_t *p_pic = (picture_t *)p_filter->p_owner; - p_filter->p_owner = NULL; - return p_pic; -} + filter_chain_t *p_chain; +}; -/* FIXME: this is almost like DeleteFilter in src/misc/image.c */ -static void DeleteFilter( filter_t *p_filter ) -{ - vlc_object_detach( p_filter ); - if( p_filter->p_module ) module_Unneed( p_filter, p_filter->p_module ); - vlc_object_release( p_filter ); -} +#define CHAIN_LEVEL_MAX 4 -/* FIXME: this is almost like CreateFilter in src/misc/image.c */ -static filter_t *CreateFilter( vlc_object_t *p_this, video_format_t *fmt_in, - video_format_t *fmt_out ) +/***************************************************************************** + * Activate: allocate a chroma function + ***************************************************************************** + * This function allocates and initializes a chroma function + *****************************************************************************/ +static int Activate( vlc_object_t *p_this ) { - filter_t *p_filter = vlc_object_create( p_this, VLC_OBJECT_FILTER ); - vlc_object_attach( p_filter, p_this ); + filter_t *p_filter = (filter_t *)p_this; + filter_sys_t *p_sys; + int i_ret; - p_filter->pf_vout_buffer_new = get_pic; + const bool b_chroma = p_filter->fmt_in.video.i_chroma != p_filter->fmt_out.video.i_chroma; + const bool b_resize = p_filter->fmt_in.video.i_width != p_filter->fmt_out.video.i_width || + p_filter->fmt_in.video.i_height != p_filter->fmt_out.video.i_height; - p_filter->fmt_in = *fmt_in; - p_filter->fmt_out = *fmt_out; + /* XXX Remove check on b_resize to build chroma chain (untested) */ + if( !b_chroma || !b_resize ) + return VLC_EGENERIC; - p_filter->p_module = module_Need( p_filter, "video filter2", NULL, 0 ); + p_sys = p_filter->p_sys = malloc( sizeof( *p_sys ) ); + if( !p_sys ) + return VLC_ENOMEM; + + memset( p_sys, 0, sizeof( *p_sys ) ); - if( !p_filter->p_module ) + p_sys->p_chain = filter_chain_New( p_filter, "video filter2", false, BufferAllocationInit, NULL, p_filter ); + if( !p_sys->p_chain ) { - DeleteFilter( p_filter ); - return NULL; + free( p_sys ); + return VLC_EGENERIC; } + filter_chain_Reset( p_sys->p_chain, &p_filter->fmt_in, &p_filter->fmt_out ); - return p_filter; -} + if( b_chroma && b_resize ) + i_ret = BuildChromaResize( p_filter ); + else if( b_chroma ) + i_ret = BuildChromaChain( p_filter ); + else + i_ret = VLC_EGENERIC; -static int CreateChain( vlc_object_t *p_this, filter_sys_t *p_sys ) -{ - p_sys->p_filter1 = CreateFilter( p_this, &p_filter->fmt_in.video, - &p_sys->fmt_mid ); - if( p_sys->p_filter1 ) + if( i_ret ) { - p_sys->p_filter2 = CreateFilter( p_this, &p_sys->fmt_mid, - &p_filter->fmt_out.video ); - if( p_sys->p_filter2 ) - return VLC_SUCCESS; - DeleteFilter( p_sys->p_filter1 ); + /* Hum ... looks like this really isn't going to work. Too bad. */ + filter_chain_Delete( p_sys->p_chain ); + free( p_sys ); + return VLC_EGENERIC; } - return VLC_EGENERIC; + /* */ + p_filter->pf_video_filter = Chain; + return VLC_SUCCESS; +} + +static void Destroy( vlc_object_t *p_this ) +{ + filter_t *p_filter = (filter_t *)p_this; + filter_chain_Delete( p_filter->p_sys->p_chain ); + free( p_filter->p_sys ); } /***************************************************************************** - * Activate: allocate a chroma function - ***************************************************************************** - * This function allocates and initializes a chroma function + * Chain *****************************************************************************/ -static int Activate( vlc_object_t *p_this ) +static picture_t *Chain( filter_t *p_filter, picture_t *p_pic ) { - filter_t *p_filter = (filter_t *)p_this; - static int hack = 0; /* FIXME */ + return filter_chain_VideoFilter( p_filter->p_sys->p_chain, p_pic ); +} - if( p_filter->fmt_in.video.i_chroma == p_filter->fmt_out.video.i_chroma ) - return VLC_EGENERIC; +/***************************************************************************** + * Builders + *****************************************************************************/ +static int BuildChromaResize( filter_t *p_filter ) +{ + filter_sys_t *p_sys = p_filter->p_sys; + es_format_t fmt_mid; + int i_ret; + + /* Lets try resizing and then doing the chroma conversion */ + msg_Dbg( p_filter, "Trying to build resize+chroma" ); + EsFormatMergeSize( &fmt_mid, &p_filter->fmt_in, &p_filter->fmt_out ); + i_ret = CreateChain( p_sys->p_chain, &fmt_mid ); + es_format_Clean( &fmt_mid ); + if( i_ret == VLC_SUCCESS ) + return VLC_SUCCESS; + + /* Lets try it the other way arround (chroma and then resize) */ + msg_Dbg( p_filter, "Trying to build chroma+resize" ); + EsFormatMergeSize( &fmt_mid, &p_filter->fmt_out, &p_filter->fmt_in ); + i_ret = CreateChain( p_sys->p_chain, &fmt_mid ); + es_format_Clean( &fmt_mid ); + if( i_ret == VLC_SUCCESS ) + return VLC_SUCCESS; + + return VLC_EGENERIC; +} + +static int BuildChromaChain( filter_t *p_filter ) +{ + filter_sys_t *p_sys = p_filter->p_sys; + es_format_t fmt_mid; + int i_ret; + int i; - hack++; - if( hack >= MAX_FILTERS ) + /* We have to protect ourself against a too high recursion */ + const char *psz_option = MODULE_STRING"-level"; + bool b_first = !var_Type( p_filter, psz_option ); + + if( var_Create( p_filter, MODULE_STRING"-level", VLC_VAR_INTEGER | (b_first ? VLC_VAR_DOINHERIT : 0 ) ) ) { - msg_Err( p_this, "Preventing chain filter reccursion (already %d long)", - hack ); + msg_Err( p_filter, "Failed to create %s variable\n", psz_option ); return VLC_EGENERIC; } - - filter_sys_t *p_sys = (filter_sys_t *)malloc( sizeof( filter_sys_t ) ); - if( !p_sys ) + int i_level = var_GetInteger( p_filter, psz_option ); + if( i_level >= CHAIN_LEVEL_MAX ) { - hack--; - return VLC_ENOMEM; + msg_Err( p_filter, "Too high level of recursion (%d)\n", i_level ); + return VLC_EGENERIC; } - memset( p_sys, 0, sizeof( filter_sys_t ) ); - p_filter->p_sys = p_sys; + var_SetInteger( p_filter, psz_option, i_level + 1 ); - if( p_filter->fmt_in.i_width != p_filter->fmt_out.i_width || - p_filter->fmt_in.i_height != p_filter->fmt_out.i_height || - p_filter->fmt_in.i_visible_width != p_filter->fmt_out.i_visible_width || - p_filter->fmt_in.i_visible_height != p_filter->fmt_out.i_visible_height ) + /* Now try chroma format list */ + for( i = 0; pi_allowed_chromas[i]; i++ ) { - /* Lets try resizing and then doing the chroma conversion */ - p_sys->fmt_mid = p_filter->fmt_out.video; - p_sys->fmt_mid.i_chroma = p_filter->fmt_in.video.i_chroma; - if( CreateChain( p_this, p_sys ) == VLC_SUCCESS ) - return VLC_SUCCESS; + const vlc_fourcc_t i_chroma = pi_allowed_chromas[i]; + + msg_Dbg( p_filter, "Trying to use chroma %4.4s as middle man", + (char*)&i_chroma ); + + es_format_Copy( &fmt_mid, &p_filter->fmt_in ); + fmt_mid.video.i_chroma = i_chroma; + + i_ret = CreateChain( p_sys->p_chain, &fmt_mid ); + es_format_Clean( &fmt_mid ); - /* Lets try it the other way arround (chroma and then resize) */ - p_sys->fmt_mid = p_filter->fmt_in.video; - p_sys->fmt_mid.i_chroma = p_filter->fmt_out.video.i_chroma; - if( CreateChain( p_this, p_sys ) == VLC_SUCCESS ) + if( i_ret == VLC_SUCCESS ) return VLC_SUCCESS; } - else - { - /* Lets try doing a chroma chain */ - int i; - p_sys->fmt_mid = p_filter->fmt_in.video; - for( i = 0; pi_allowed_chomas[i]; i++ ) - { - p_sys->fmt_mid.i_chroma = pi_allowed_chromas[i]; - if( CreateChain( p_this, p_sys ) == VLC_SUCCESS ) - return VLC_SUCCESS; - } - } - - /* Hum ... looks like this really isn't going to work. Too bad. */ - free( p_sys ); - hack--; return VLC_EGENERIC; } -static void Destroy( vlc_object_t *p_this ) +/***************************************************************************** + * Buffer management + *****************************************************************************/ +static picture_t *BufferNew( filter_t *p_filter ) { - filter_t *p_filter = (filter_t *)p_this; + filter_t *p_parent = (filter_t*)p_filter->p_owner; - DeleteFilter( p_filter->p_sys->filter1 ); - DeleteFilter( p_filter->p_sys->filter2 ); - - if( p_filter->p_sys->p_tmp ) - { - free( p_filter->p_sys->p_tmp->p_data_orig ); - free( p_filter->p_sys->p_tmp ); - } + return p_parent->pf_vout_buffer_new( p_parent ); +} +static void BufferDel( filter_t *p_filter, picture_t *p_pic ) +{ + filter_t *p_parent = (filter_t*)p_filter->p_owner; - free( p_filter->p_sys ); + p_parent->pf_vout_buffer_del( p_parent, p_pic ); +} +static int BufferAllocationInit ( filter_t *p_filter, void *p_data ) +{ + p_filter->pf_vout_buffer_new = BufferNew; + p_filter->pf_vout_buffer_del = BufferDel; + p_filter->p_owner = p_data; + return VLC_SUCCESS; } /***************************************************************************** - * Chain + * *****************************************************************************/ -static picture_t *Chain( filter_t *p_filter, picture_t *p_pic ) +static int CreateChain( filter_chain_t *p_chain, es_format_t *p_fmt_mid ) { - picture_t *p_outpic = p_filter->pf_vout_buffer_new( p_filter ); - if( !p_outpic ) + filter_t *p_filter1; + if( !( p_filter1 = + filter_chain_AppendFilter( p_chain, NULL, NULL, NULL, p_fmt_mid )) ) + return VLC_EGENERIC; + if( !filter_chain_AppendFilter( p_chain, NULL, NULL, p_fmt_mid, NULL ) ) { - msg_Warn( p_filter, "can't get output picture" ); - if( p_pic->pf_release ) - p_pic->pf_release( p_pic ); - return NULL; + filter_chain_DeleteFilter( p_chain, p_filter1 ); + return VLC_EGENERIC; } + return VLC_SUCCESS; +} +static void EsFormatMergeSize( es_format_t *p_dst, + const es_format_t *p_base, + const es_format_t *p_size ) +{ + es_format_Copy( p_dst, p_base ); - if( !p_sys->p_tmp ) - { - picture_t *p_tmp = malloc( sizeof( picture_t ) ); - if( !p_tmp ) - return NULL; - vout_AllocatePicture( VLC_OBJECT( p_vout ), p_tmp, - p_sys->fmt_mid.i_chroma, - p_sys->fmt_mid.i_width, - p_sys->fmt_mid.i_height, - p_sys->fmt_mid.i_aspect ); - p_sys->p_tmp = p_tmp; - p_tmp->pf_release = NULL; - p_tmp->i_status = RESERVED_PICTURE; - p_tmp->p_sys = NULL; - } + p_dst->video.i_width = p_size->video.i_width; + p_dst->video.i_height = p_size->video.i_height; - p_sys->p_filter1->p_owner = (filter_owner_sys_t*)p_sys->p_tmp; - if( !p_sys->p_filter1->pf_video_filter( p_sys->p_filter1, p_pic ) ) - { - if( p_pic->pf_release ) - p_pic->pf_release( p_pic ); - return NULL; - } - if( p_pic->pf_release ) - p_pic->pf_release( p_pic ); - p_sys->p_filter2->p_owner = (filter_owner_sys_t*)p_outpic; - return p_sys->p_filter2->pf_video_filter( p_sys->p_filter2, p_sys->p_tmp ); + p_dst->video.i_visible_width = p_size->video.i_visible_width; + p_dst->video.i_visible_height = p_size->video.i_visible_height; } +