@ -184,13 +184,15 @@ static AVFilterInOut *extract_inout(const char *label, AVFilterInOut **links)
{
{
AVFilterInOut * ret ;
AVFilterInOut * ret ;
while ( * links & & strcmp ( ( * links ) - > name , label ) )
while ( * links & & ( ! ( * links ) - > name | | strcmp ( ( * links ) - > name , label ) ) )
links = & ( ( * links ) - > next ) ;
links = & ( ( * links ) - > next ) ;
ret = * links ;
ret = * links ;
if ( ret )
if ( ret ) {
* links = ret - > next ;
* links = ret - > next ;
ret - > next = NULL ;
}
return ret ;
return ret ;
}
}
@ -201,6 +203,18 @@ static void insert_inout(AVFilterInOut **inouts, AVFilterInOut *element)
* inouts = element ;
* inouts = element ;
}
}
static void append_inout ( AVFilterInOut * * inouts , AVFilterInOut * * element )
{
while ( * inouts & & ( * inouts ) - > next )
inouts = & ( ( * inouts ) - > next ) ;
if ( ! * inouts )
* inouts = * element ;
else
( * inouts ) - > next = * element ;
* element = NULL ;
}
static int link_filter_inouts ( AVFilterContext * filt_ctx ,
static int link_filter_inouts ( AVFilterContext * filt_ctx ,
AVFilterInOut * * curr_inputs ,
AVFilterInOut * * curr_inputs ,
AVFilterInOut * * open_inputs , void * log_ctx )
AVFilterInOut * * open_inputs , void * log_ctx )
@ -209,14 +223,11 @@ static int link_filter_inouts(AVFilterContext *filt_ctx,
while ( pad - - ) {
while ( pad - - ) {
AVFilterInOut * p = * curr_inputs ;
AVFilterInOut * p = * curr_inputs ;
if ( ! p ) {
av_log ( log_ctx , AV_LOG_ERROR ,
" Not enough inputs specified for the \" %s \" filter. \n " ,
filt_ctx - > filter - > name ) ;
return AVERROR ( EINVAL ) ;
}
* curr_inputs = ( * curr_inputs ) - > next ;
if ( p )
* curr_inputs = ( * curr_inputs ) - > next ;
else if ( ! ( p = av_mallocz ( sizeof ( * p ) ) ) )
return AVERROR ( ENOMEM ) ;
if ( p - > filter_ctx ) {
if ( p - > filter_ctx ) {
if ( ( ret = link_filter ( p - > filter_ctx , p - > pad_idx , filt_ctx , pad , log_ctx ) ) < 0 )
if ( ( ret = link_filter ( p - > filter_ctx , p - > pad_idx , filt_ctx , pad , log_ctx ) ) < 0 )
@ -329,18 +340,22 @@ static int parse_outputs(const char **buf, AVFilterInOut **curr_inputs,
return pad ;
return pad ;
}
}
int avfilter_graph_parse ( AVFilterGraph * graph , const char * filters ,
# if FF_API_GRAPH_AVCLASS
AVFilterInOut * open_inputs ,
# define log_ctx graph
AVFilterInOut * open_outputs , void * log_ctx )
# else
# define log_ctx NULL
# endif
int avfilter_graph_parse2 ( AVFilterGraph * graph , const char * filters ,
AVFilterInOut * * inputs ,
AVFilterInOut * * outputs )
{
{
int index = 0 , ret ;
int index = 0 , ret ;
char chr = 0 ;
char chr = 0 ;
AVFilterInOut * curr_inputs = NULL ;
AVFilterInOut * curr_inputs = NULL , * open_inputs = NULL , * open_outputs = NULL ;
do {
do {
AVFilterContext * filter ;
AVFilterContext * filter ;
const char * filterchain = filters ;
filters + = strspn ( filters , WHITESPACES ) ;
filters + = strspn ( filters , WHITESPACES ) ;
if ( ( ret = parse_inputs ( & filters , & curr_inputs , & open_outputs , log_ctx ) ) < 0 )
if ( ( ret = parse_inputs ( & filters , & curr_inputs , & open_outputs , log_ctx ) ) < 0 )
@ -349,12 +364,6 @@ int avfilter_graph_parse(AVFilterGraph *graph, const char *filters,
if ( ( ret = parse_filter ( & filter , & filters , graph , index , log_ctx ) ) < 0 )
if ( ( ret = parse_filter ( & filter , & filters , graph , index , log_ctx ) ) < 0 )
goto fail ;
goto fail ;
if ( filter - > input_count = = 1 & & ! curr_inputs & & ! index ) {
/* First input can be omitted if it is "[in]" */
const char * tmp = " [in] " ;
if ( ( ret = parse_inputs ( & tmp , & curr_inputs , & open_outputs , log_ctx ) ) < 0 )
goto fail ;
}
if ( ( ret = link_filter_inouts ( filter , & curr_inputs , & open_inputs , log_ctx ) ) < 0 )
if ( ( ret = link_filter_inouts ( filter , & curr_inputs , & open_inputs , log_ctx ) ) < 0 )
goto fail ;
goto fail ;
@ -366,13 +375,8 @@ int avfilter_graph_parse(AVFilterGraph *graph, const char *filters,
filters + = strspn ( filters , WHITESPACES ) ;
filters + = strspn ( filters , WHITESPACES ) ;
chr = * filters + + ;
chr = * filters + + ;
if ( chr = = ' ; ' & & curr_inputs ) {
if ( chr = = ' ; ' & & curr_inputs )
av_log ( log_ctx , AV_LOG_ERROR ,
append_inout ( & open_outputs , & curr_inputs ) ;
" Invalid filterchain containing an unlabelled output pad: \" %s \" \n " ,
filterchain ) ;
ret = AVERROR ( EINVAL ) ;
goto fail ;
}
index + + ;
index + + ;
} while ( chr = = ' , ' | | chr = = ' ; ' ) ;
} while ( chr = = ' , ' | | chr = = ' ; ' ) ;
@ -384,14 +388,10 @@ int avfilter_graph_parse(AVFilterGraph *graph, const char *filters,
goto fail ;
goto fail ;
}
}
if ( open_inputs & & ! strcmp ( open_inputs - > name , " out " ) & & curr_inputs ) {
append_inout ( & open_outputs , & curr_inputs ) ;
/* Last output can be omitted if it is "[out]" */
const char * tmp = " [out] " ;
if ( ( ret = parse_outputs ( & tmp , & curr_inputs , & open_inputs , & open_outputs ,
log_ctx ) ) < 0 )
goto fail ;
}
* inputs = open_inputs ;
* outputs = open_outputs ;
return 0 ;
return 0 ;
fail :
fail :
@ -401,5 +401,73 @@ int avfilter_graph_parse(AVFilterGraph *graph, const char *filters,
free_inout ( open_inputs ) ;
free_inout ( open_inputs ) ;
free_inout ( open_outputs ) ;
free_inout ( open_outputs ) ;
free_inout ( curr_inputs ) ;
free_inout ( curr_inputs ) ;
* inputs = NULL ;
* outputs = NULL ;
return ret ;
}
# undef log_ctx
int avfilter_graph_parse ( AVFilterGraph * graph , const char * filters ,
AVFilterInOut * open_inputs ,
AVFilterInOut * open_outputs , void * log_ctx )
{
int ret ;
AVFilterInOut * cur , * match , * inputs = NULL , * outputs = NULL ;
if ( ( ret = avfilter_graph_parse2 ( graph , filters , & inputs , & outputs ) ) < 0 )
goto fail ;
/* First input can be omitted if it is "[in]" */
if ( inputs & & ! inputs - > name )
inputs - > name = av_strdup ( " in " ) ;
for ( cur = inputs ; cur ; cur = cur - > next ) {
if ( ! cur - > name ) {
av_log ( log_ctx , AV_LOG_ERROR ,
" Not enough inputs specified for the \" %s \" filter. \n " ,
cur - > filter_ctx - > filter - > name ) ;
ret = AVERROR ( EINVAL ) ;
goto fail ;
}
if ( ! ( match = extract_inout ( cur - > name , & open_outputs ) ) )
continue ;
ret = avfilter_link ( match - > filter_ctx , match - > pad_idx ,
cur - > filter_ctx , cur - > pad_idx ) ;
free_inout ( match ) ;
if ( ret < 0 )
goto fail ;
}
/* Last output can be omitted if it is "[out]" */
if ( outputs & & ! outputs - > name )
outputs - > name = av_strdup ( " out " ) ;
for ( cur = outputs ; cur ; cur = cur - > next ) {
if ( ! cur - > name ) {
av_log ( log_ctx , AV_LOG_ERROR ,
" Invalid filterchain containing an unlabelled output pad: \" %s \" \n " ,
filters ) ;
ret = AVERROR ( EINVAL ) ;
goto fail ;
}
if ( ! ( match = extract_inout ( cur - > name , & open_inputs ) ) )
continue ;
ret = avfilter_link ( cur - > filter_ctx , cur - > pad_idx ,
match - > filter_ctx , match - > pad_idx ) ;
free_inout ( match ) ;
if ( ret < 0 )
goto fail ;
}
fail :
if ( ret < 0 ) {
for ( ; graph - > filter_count > 0 ; graph - > filter_count - - )
avfilter_free ( graph - > filters [ graph - > filter_count - 1 ] ) ;
av_freep ( & graph - > filters ) ;
}
free_inout ( inputs ) ;
free_inout ( outputs ) ;
free_inout ( open_inputs ) ;
free_inout ( open_outputs ) ;
return ret ;
return ret ;
}
}