@ -147,6 +147,13 @@ static void avconv_cleanup(int ret)
FilterGraph * fg = filtergraphs [ i ] ;
avfilter_graph_free ( & fg - > graph ) ;
for ( j = 0 ; j < fg - > nb_inputs ; j + + ) {
while ( av_fifo_size ( fg - > inputs [ j ] - > frame_queue ) ) {
AVFrame * frame ;
av_fifo_generic_read ( fg - > inputs [ j ] - > frame_queue , & frame ,
sizeof ( frame ) , NULL ) ;
av_frame_free ( & frame ) ;
}
av_fifo_free ( fg - > inputs [ j ] - > frame_queue ) ;
av_buffer_unref ( & fg - > inputs [ j ] - > hw_frames_ctx ) ;
av_freep ( & fg - > inputs [ j ] - > name ) ;
av_freep ( & fg - > inputs [ j ] ) ;
@ -656,6 +663,8 @@ FF_ENABLE_DEPRECATION_WARNINGS
}
}
static int init_output_stream ( OutputStream * ost , char * error , int error_len ) ;
/*
* Read one frame for lavfi output for ost and encode it .
*/
@ -670,6 +679,16 @@ static int poll_filter(OutputStream *ost)
}
filtered_frame = ost - > filtered_frame ;
if ( ! ost - > initialized ) {
char error [ 1024 ] ;
ret = init_output_stream ( ost , error , sizeof ( error ) ) ;
if ( ret < 0 ) {
av_log ( NULL , AV_LOG_ERROR , " Error initializing output stream %d:%d -- %s \n " ,
ost - > file_index , ost - > index , error ) ;
exit_program ( 1 ) ;
}
}
if ( ost - > enc - > type = = AVMEDIA_TYPE_AUDIO & &
! ( ost - > enc - > capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE ) )
ret = av_buffersink_get_samples ( ost - > filter - > filter , filtered_frame ,
@ -745,7 +764,8 @@ static int poll_filters(void)
for ( i = 0 ; i < nb_output_streams ; i + + ) {
int64_t pts = output_streams [ i ] - > sync_opts ;
if ( ! output_streams [ i ] - > filter | | output_streams [ i ] - > finished )
if ( ! output_streams [ i ] - > filter | | output_streams [ i ] - > finished | |
! output_streams [ i ] - > filter - > graph - > graph )
continue ;
pts = av_rescale_q ( pts , output_streams [ i ] - > enc_ctx - > time_base ,
@ -1150,6 +1170,89 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p
output_packet ( of , & opkt , ost ) ;
}
static int ifilter_send_frame ( InputFilter * ifilter , AVFrame * frame )
{
FilterGraph * fg = ifilter - > graph ;
int need_reinit , ret , i ;
/* determine if the parameters for this input changed */
need_reinit = ifilter - > format ! = frame - > format ;
if ( ! ! ifilter - > hw_frames_ctx ! = ! ! frame - > hw_frames_ctx | |
( ifilter - > hw_frames_ctx & & ifilter - > hw_frames_ctx - > data ! = frame - > hw_frames_ctx - > data ) )
need_reinit = 1 ;
switch ( ifilter - > ist - > st - > codecpar - > codec_type ) {
case AVMEDIA_TYPE_AUDIO :
need_reinit | = ifilter - > sample_rate ! = frame - > sample_rate | |
ifilter - > channel_layout ! = frame - > channel_layout ;
break ;
case AVMEDIA_TYPE_VIDEO :
need_reinit | = ifilter - > width ! = frame - > width | |
ifilter - > height ! = frame - > height ;
break ;
}
if ( need_reinit ) {
ret = ifilter_parameters_from_frame ( ifilter , frame ) ;
if ( ret < 0 )
return ret ;
}
/* (re)init the graph if possible, otherwise buffer the frame and return */
if ( need_reinit | | ! fg - > graph ) {
for ( i = 0 ; i < fg - > nb_inputs ; i + + ) {
if ( fg - > inputs [ i ] - > format < 0 ) {
AVFrame * tmp = av_frame_clone ( frame ) ;
if ( ! tmp )
return AVERROR ( ENOMEM ) ;
av_frame_unref ( frame ) ;
if ( ! av_fifo_space ( ifilter - > frame_queue ) ) {
ret = av_fifo_realloc2 ( ifilter - > frame_queue , 2 * av_fifo_size ( ifilter - > frame_queue ) ) ;
if ( ret < 0 )
return ret ;
}
av_fifo_generic_write ( ifilter - > frame_queue , & tmp , sizeof ( tmp ) , NULL ) ;
return 0 ;
}
}
ret = poll_filters ( ) ;
if ( ret < 0 & & ret ! = AVERROR_EOF ) {
char errbuf [ 128 ] ;
av_strerror ( ret , errbuf , sizeof ( errbuf ) ) ;
av_log ( NULL , AV_LOG_ERROR , " Error while filtering: %s \n " , errbuf ) ;
return ret ;
}
ret = configure_filtergraph ( fg ) ;
if ( ret < 0 ) {
av_log ( NULL , AV_LOG_ERROR , " Error reinitializing filters! \n " ) ;
return ret ;
}
for ( i = 0 ; i < fg - > nb_inputs ; i + + ) {
while ( av_fifo_size ( fg - > inputs [ i ] - > frame_queue ) ) {
AVFrame * tmp ;
av_fifo_generic_read ( fg - > inputs [ i ] - > frame_queue , & tmp , sizeof ( tmp ) , NULL ) ;
ret = av_buffersrc_add_frame ( fg - > inputs [ i ] - > filter , tmp ) ;
av_frame_free ( & tmp ) ;
if ( ret < 0 )
return ret ;
}
}
}
ret = av_buffersrc_add_frame ( ifilter - > filter , frame ) ;
if ( ret < 0 ) {
av_log ( NULL , AV_LOG_ERROR , " Error while filtering \n " ) ;
return ret ;
}
return 0 ;
}
// This does not quite work like avcodec_decode_audio4/avcodec_decode_video2.
// There is the following difference: if you got a frame, you must call
// it again with pkt=NULL. pkt==NULL is treated differently from pkt.size==0
@ -1199,7 +1302,7 @@ static int decode_audio(InputStream *ist, AVPacket *pkt, int *got_output)
{
AVFrame * decoded_frame , * f ;
AVCodecContext * avctx = ist - > dec_ctx ;
int i , ret , err = 0 , resample_changed ;
int i , ret , err = 0 ;
if ( ! ist - > decoded_frame & & ! ( ist - > decoded_frame = av_frame_alloc ( ) ) )
return AVERROR ( ENOMEM ) ;
@ -1222,57 +1325,6 @@ static int decode_audio(InputStream *ist, AVPacket *pkt, int *got_output)
decoded_frame - > pts = pkt - > pts ;
}
resample_changed = ist - > resample_sample_fmt ! = decoded_frame - > format | |
ist - > resample_channels ! = avctx - > channels | |
ist - > resample_channel_layout ! = decoded_frame - > channel_layout | |
ist - > resample_sample_rate ! = decoded_frame - > sample_rate ;
if ( resample_changed ) {
char layout1 [ 64 ] , layout2 [ 64 ] ;
if ( ! guess_input_channel_layout ( ist ) ) {
av_log ( NULL , AV_LOG_FATAL , " Unable to find default channel "
" layout for Input Stream #%d.%d \n " , ist - > file_index ,
ist - > st - > index ) ;
exit_program ( 1 ) ;
}
decoded_frame - > channel_layout = avctx - > channel_layout ;
av_get_channel_layout_string ( layout1 , sizeof ( layout1 ) , ist - > resample_channels ,
ist - > resample_channel_layout ) ;
av_get_channel_layout_string ( layout2 , sizeof ( layout2 ) , avctx - > channels ,
decoded_frame - > channel_layout ) ;
av_log ( NULL , AV_LOG_INFO ,
" Input stream #%d:%d frame changed from rate:%d fmt:%s ch:%d chl:%s to rate:%d fmt:%s ch:%d chl:%s \n " ,
ist - > file_index , ist - > st - > index ,
ist - > resample_sample_rate , av_get_sample_fmt_name ( ist - > resample_sample_fmt ) ,
ist - > resample_channels , layout1 ,
decoded_frame - > sample_rate , av_get_sample_fmt_name ( decoded_frame - > format ) ,
avctx - > channels , layout2 ) ;
ist - > resample_sample_fmt = decoded_frame - > format ;
ist - > resample_sample_rate = decoded_frame - > sample_rate ;
ist - > resample_channel_layout = decoded_frame - > channel_layout ;
ist - > resample_channels = avctx - > channels ;
for ( i = 0 ; i < ist - > nb_filters ; i + + ) {
err = ifilter_parameters_from_frame ( ist - > filters [ i ] , decoded_frame ) ;
if ( err < 0 ) {
av_log ( NULL , AV_LOG_ERROR ,
" Error reconfiguring input stream %d:%d filter %d \n " ,
ist - > file_index , ist - > st - > index , i ) ;
goto fail ;
}
}
for ( i = 0 ; i < nb_filtergraphs ; i + + )
if ( ist_in_filtergraph ( filtergraphs [ i ] , ist ) & &
configure_filtergraph ( filtergraphs [ i ] ) < 0 ) {
av_log ( NULL , AV_LOG_FATAL , " Error reinitializing filters! \n " ) ;
exit_program ( 1 ) ;
}
}
if ( decoded_frame - > pts ! = AV_NOPTS_VALUE )
decoded_frame - > pts = av_rescale_q ( decoded_frame - > pts ,
ist - > st - > time_base ,
@ -1287,12 +1339,11 @@ static int decode_audio(InputStream *ist, AVPacket *pkt, int *got_output)
} else
f = decoded_frame ;
err = av_buffersrc_ad d_frame( ist - > filters [ i ] - > filter , f ) ;
err = ifilter_sen d_frame( ist - > filters [ i ] , f ) ;
if ( err < 0 )
break ;
}
fail :
av_frame_unref ( ist - > filter_frame ) ;
av_frame_unref ( decoded_frame ) ;
return err < 0 ? err : ret ;
@ -1301,7 +1352,7 @@ fail:
static int decode_video ( InputStream * ist , AVPacket * pkt , int * got_output )
{
AVFrame * decoded_frame , * f ;
int i , ret = 0 , err = 0 , resample_changed ;
int i , ret = 0 , err = 0 ;
if ( ! ist - > decoded_frame & & ! ( ist - > decoded_frame = av_frame_alloc ( ) ) )
return AVERROR ( ENOMEM ) ;
@ -1328,46 +1379,6 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output)
if ( ist - > st - > sample_aspect_ratio . num )
decoded_frame - > sample_aspect_ratio = ist - > st - > sample_aspect_ratio ;
resample_changed = ist - > resample_width ! = decoded_frame - > width | |
ist - > resample_height ! = decoded_frame - > height | |
ist - > resample_pix_fmt ! = decoded_frame - > format ;
if ( resample_changed ) {
av_log ( NULL , AV_LOG_INFO ,
" Input stream #%d:%d frame changed from size:%dx%d fmt:%s to size:%dx%d fmt:%s \n " ,
ist - > file_index , ist - > st - > index ,
ist - > resample_width , ist - > resample_height , av_get_pix_fmt_name ( ist - > resample_pix_fmt ) ,
decoded_frame - > width , decoded_frame - > height , av_get_pix_fmt_name ( decoded_frame - > format ) ) ;
ret = poll_filters ( ) ;
if ( ret < 0 & & ret ! = AVERROR_EOF ) {
char errbuf [ 128 ] ;
av_strerror ( ret , errbuf , sizeof ( errbuf ) ) ;
av_log ( NULL , AV_LOG_ERROR , " Error while filtering: %s \n " , errbuf ) ;
}
ist - > resample_width = decoded_frame - > width ;
ist - > resample_height = decoded_frame - > height ;
ist - > resample_pix_fmt = decoded_frame - > format ;
for ( i = 0 ; i < ist - > nb_filters ; i + + ) {
err = ifilter_parameters_from_frame ( ist - > filters [ i ] , decoded_frame ) ;
if ( err < 0 ) {
av_log ( NULL , AV_LOG_ERROR ,
" Error reconfiguring input stream %d:%d filter %d \n " ,
ist - > file_index , ist - > st - > index , i ) ;
goto fail ;
}
}
for ( i = 0 ; i < nb_filtergraphs ; i + + )
if ( ist_in_filtergraph ( filtergraphs [ i ] , ist ) & &
configure_filtergraph ( filtergraphs [ i ] ) < 0 ) {
av_log ( NULL , AV_LOG_FATAL , " Error reinitializing filters! \n " ) ;
exit_program ( 1 ) ;
}
}
for ( i = 0 ; i < ist - > nb_filters ; i + + ) {
if ( i < ist - > nb_filters - 1 ) {
f = ist - > filter_frame ;
@ -1377,7 +1388,7 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output)
} else
f = decoded_frame ;
err = av_buffersrc_ad d_frame( ist - > filters [ i ] - > filter , f ) ;
err = ifilter_sen d_frame( ist - > filters [ i ] , f ) ;
if ( err < 0 )
break ;
}
@ -1415,11 +1426,18 @@ static int transcode_subtitles(InputStream *ist, AVPacket *pkt, int *got_output)
static int send_filter_eof ( InputStream * ist )
{
int i , ret ;
int i , j , ret ;
for ( i = 0 ; i < ist - > nb_filters ; i + + ) {
ret = av_buffersrc_add_frame ( ist - > filters [ i ] - > filter , NULL ) ;
if ( ret < 0 )
return ret ;
if ( ist - > filters [ i ] - > filter ) {
ret = av_buffersrc_add_frame ( ist - > filters [ i ] - > filter , NULL ) ;
if ( ret < 0 )
return ret ;
} else {
// the filtergraph was never configured
FilterGraph * fg = ist - > filters [ i ] - > graph ;
for ( j = 0 ; j < fg - > nb_outputs ; j + + )
finish_output_stream ( fg - > outputs [ j ] - > ost ) ;
}
}
return 0 ;
}
@ -1618,17 +1636,9 @@ static int get_buffer(AVCodecContext *s, AVFrame *frame, int flags)
static int init_input_stream ( int ist_index , char * error , int error_len )
{
int i , ret ;
int ret ;
InputStream * ist = input_streams [ ist_index ] ;
for ( i = 0 ; i < ist - > nb_filters ; i + + ) {
ret = ifilter_parameters_from_decoder ( ist - > filters [ i ] , ist - > dec_ctx ) ;
if ( ret < 0 ) {
av_log ( NULL , AV_LOG_FATAL , " Error initializing filter input \n " ) ;
return ret ;
}
}
if ( ist - > decoding_needed ) {
AVCodec * codec = ist - > dec ;
if ( ! codec ) {
@ -1959,17 +1969,6 @@ static int init_output_stream_encode(OutputStream *ost)
enc_ctx - > chroma_sample_location = dec_ctx - > chroma_sample_location ;
}
if ( ( enc_ctx - > codec_type = = AVMEDIA_TYPE_VIDEO | |
enc_ctx - > codec_type = = AVMEDIA_TYPE_AUDIO ) & &
filtergraph_is_simple ( ost - > filter - > graph ) ) {
FilterGraph * fg = ost - > filter - > graph ;
if ( configure_filtergraph ( fg ) ) {
av_log ( NULL , AV_LOG_FATAL , " Error opening filters! \n " ) ;
exit_program ( 1 ) ;
}
}
switch ( enc_ctx - > codec_type ) {
case AVMEDIA_TYPE_AUDIO :
enc_ctx - > sample_fmt = ost - > filter - > filter - > inputs [ 0 ] - > format ;
@ -2142,6 +2141,10 @@ static int transcode_init(void)
/* open each encoder */
for ( i = 0 ; i < nb_output_streams ; i + + ) {
// skip streams fed from filtergraphs until we have a frame for them
if ( output_streams [ i ] - > filter )
continue ;
ret = init_output_stream ( output_streams [ i ] , error , sizeof ( error ) ) ;
if ( ret < 0 )
goto dump_format ;