@ -34,15 +34,14 @@
# include "libavutil/rational.h"
# include "libavutil/samplefmt.h"
# define FF_INTERNAL_FIELDS 1
# include "framequeue.h"
# include "audio.h"
# include "avfilter.h"
# include "filters.h"
# include "formats.h"
# include "framequeue.h"
# include "framepool.h"
# include "internal.h"
# include "link_internal.h"
# include "video.h"
static void tlog_ref ( void * ctx , AVFrame * ref , int end )
@ -149,6 +148,7 @@ int ff_append_outpad_free_name(AVFilterContext *f, AVFilterPad *p)
int avfilter_link ( AVFilterContext * src , unsigned srcpad ,
AVFilterContext * dst , unsigned dstpad )
{
FilterLinkInternal * li ;
AVFilterLink * link ;
av_assert0 ( src - > graph ) ;
@ -172,9 +172,10 @@ int avfilter_link(AVFilterContext *src, unsigned srcpad,
return AVERROR ( EINVAL ) ;
}
link = av_mallocz ( sizeof ( * link ) ) ;
if ( ! link )
li = av_mallocz ( sizeof ( * li ) ) ;
if ( ! li )
return AVERROR ( ENOMEM ) ;
link = & li - > l ;
src - > outputs [ srcpad ] = dst - > inputs [ dstpad ] = link ;
@ -186,17 +187,20 @@ int avfilter_link(AVFilterContext *src, unsigned srcpad,
av_assert0 ( AV_PIX_FMT_NONE = = - 1 & & AV_SAMPLE_FMT_NONE = = - 1 ) ;
link - > format = - 1 ;
link - > colorspace = AVCOL_SPC_UNSPECIFIED ;
ff_framequeue_init ( & link - > fifo , & src - > graph - > internal - > frame_queues ) ;
ff_framequeue_init ( & li - > fifo , & src - > graph - > internal - > frame_queues ) ;
return 0 ;
}
void avfilter_link_free ( AVFilterLink * * link )
{
FilterLinkInternal * li ;
if ( ! * link )
return ;
li = ff_link_internal ( * link ) ;
ff_framequeue_free ( & ( * link ) - > fifo ) ;
ff_framequeue_free ( & li - > fifo ) ;
ff_frame_pool_uninit ( ( FFFramePool * * ) & ( * link ) - > frame_pool ) ;
av_channel_layout_uninit ( & ( * link ) - > ch_layout ) ;
@ -227,20 +231,24 @@ static void filter_unblock(AVFilterContext *filter)
{
unsigned i ;
for ( i = 0 ; i < filter - > nb_outputs ; i + + )
filter - > outputs [ i ] - > frame_blocked_in = 0 ;
for ( i = 0 ; i < filter - > nb_outputs ; i + + ) {
FilterLinkInternal * const li = ff_link_internal ( filter - > outputs [ i ] ) ;
li - > frame_blocked_in = 0 ;
}
}
void ff_avfilter_link_set_in_status ( AVFilterLink * link , int status , int64_t pts )
{
if ( link - > status_in = = status )
FilterLinkInternal * const li = ff_link_internal ( link ) ;
if ( li - > status_in = = status )
return ;
av_assert0 ( ! link - > status_in ) ;
link - > status_in = status ;
link - > status_in_pts = pts ;
av_assert0 ( ! li - > status_in ) ;
li - > status_in = status ;
li - > status_in_pts = pts ;
link - > frame_wanted_out = 0 ;
link - > frame_blocked_in = 0 ;
li - > frame_blocked_in = 0 ;
filter_unblock ( link - > dst ) ;
ff_filter_set_ready ( link - > dst , 200 ) ;
}
@ -251,9 +259,11 @@ void ff_avfilter_link_set_in_status(AVFilterLink *link, int status, int64_t pts)
*/
static void link_set_out_status ( AVFilterLink * link , int status , int64_t pts )
{
FilterLinkInternal * const li = ff_link_internal ( link ) ;
av_assert0 ( ! link - > frame_wanted_out ) ;
av_assert0 ( ! link - > status_out ) ;
link - > status_out = status ;
av_assert0 ( ! li - > status_out ) ;
li - > status_out = status ;
if ( pts ! = AV_NOPTS_VALUE )
update_link_current_pts ( link , pts ) ;
filter_unblock ( link - > dst ) ;
@ -437,13 +447,15 @@ void ff_tlog_link(void *ctx, AVFilterLink *link, int end)
int ff_request_frame ( AVFilterLink * link )
{
FilterLinkInternal * const li = ff_link_internal ( link ) ;
FF_TPRINTF_START ( NULL , request_frame ) ; ff_tlog_link ( NULL , link , 1 ) ;
av_assert1 ( ! link - > dst - > filter - > activate ) ;
if ( link - > status_out )
return link - > status_out ;
if ( link - > status_in ) {
if ( ff_framequeue_queued_frames ( & link - > fifo ) ) {
if ( li - > status_out )
return li - > status_out ;
if ( li - > status_in ) {
if ( ff_framequeue_queued_frames ( & li - > fifo ) ) {
av_assert1 ( ! link - > frame_wanted_out ) ;
av_assert1 ( link - > dst - > ready > = 300 ) ;
return 0 ;
@ -451,8 +463,8 @@ int ff_request_frame(AVFilterLink *link)
/* Acknowledge status change. Filters using ff_request_frame() will
handle the change automatically . Filters can also check the
status directly but none do yet . */
link_set_out_status ( link , link - > status_in , link - > status_in_pts ) ;
return link - > status_out ;
link_set_out_status ( link , li - > status_in , li - > status_in_pts ) ;
return li - > status_out ;
}
}
link - > frame_wanted_out = 1 ;
@ -465,14 +477,18 @@ static int64_t guess_status_pts(AVFilterContext *ctx, int status, AVRational lin
unsigned i ;
int64_t r = INT64_MAX ;
for ( i = 0 ; i < ctx - > nb_inputs ; i + + )
if ( ctx - > inputs [ i ] - > status_out = = status )
for ( i = 0 ; i < ctx - > nb_inputs ; i + + ) {
FilterLinkInternal * const li = ff_link_internal ( ctx - > inputs [ i ] ) ;
if ( li - > status_out = = status )
r = FFMIN ( r , av_rescale_q ( ctx - > inputs [ i ] - > current_pts , ctx - > inputs [ i ] - > time_base , link_time_base ) ) ;
}
if ( r < INT64_MAX )
return r ;
av_log ( ctx , AV_LOG_WARNING , " EOF timestamp not reliable \n " ) ;
for ( i = 0 ; i < ctx - > nb_inputs ; i + + )
r = FFMIN ( r , av_rescale_q ( ctx - > inputs [ i ] - > status_in_pts , ctx - > inputs [ i ] - > time_base , link_time_base ) ) ;
for ( i = 0 ; i < ctx - > nb_inputs ; i + + ) {
FilterLinkInternal * const li = ff_link_internal ( ctx - > inputs [ i ] ) ;
r = FFMIN ( r , av_rescale_q ( li - > status_in_pts , ctx - > inputs [ i ] - > time_base , link_time_base ) ) ;
}
if ( r < INT64_MAX )
return r ;
return AV_NOPTS_VALUE ;
@ -480,17 +496,18 @@ static int64_t guess_status_pts(AVFilterContext *ctx, int status, AVRational lin
static int ff_request_frame_to_filter ( AVFilterLink * link )
{
FilterLinkInternal * const li = ff_link_internal ( link ) ;
int ret = - 1 ;
FF_TPRINTF_START ( NULL , request_frame_to_filter ) ; ff_tlog_link ( NULL , link , 1 ) ;
/* Assume the filter is blocked, let the method clear it if not */
link - > frame_blocked_in = 1 ;
li - > frame_blocked_in = 1 ;
if ( link - > srcpad - > request_frame )
ret = link - > srcpad - > request_frame ( link ) ;
else if ( link - > src - > inputs [ 0 ] )
ret = ff_request_frame ( link - > src - > inputs [ 0 ] ) ;
if ( ret < 0 ) {
if ( ret ! = AVERROR ( EAGAIN ) & & ret ! = link - > status_in )
if ( ret ! = AVERROR ( EAGAIN ) & & ret ! = li - > status_in )
ff_avfilter_link_set_in_status ( link , ret , guess_status_pts ( link - > src , ret , link - > time_base ) ) ;
if ( ret = = AVERROR_EOF )
ret = 0 ;
@ -988,6 +1005,7 @@ fail:
int ff_filter_frame ( AVFilterLink * link , AVFrame * frame )
{
FilterLinkInternal * const li = ff_link_internal ( link ) ;
int ret ;
FF_TPRINTF_START ( NULL , filter_frame ) ; ff_tlog_link ( NULL , link , 1 ) ; ff_tlog ( NULL , " " ) ; tlog_ref ( NULL , frame , 1 ) ;
@ -1027,11 +1045,11 @@ FF_ENABLE_DEPRECATION_WARNINGS
# endif
}
link - > frame_blocked_in = link - > frame_wanted_out = 0 ;
li - > frame_blocked_in = link - > frame_wanted_out = 0 ;
link - > frame_count_in + + ;
link - > sample_count_in + = frame - > nb_samples ;
filter_unblock ( link - > dst ) ;
ret = ff_framequeue_add ( & link - > fifo , frame ) ;
ret = ff_framequeue_add ( & li - > fifo , frame ) ;
if ( ret < 0 ) {
av_frame_free ( & frame ) ;
return ret ;
@ -1044,16 +1062,17 @@ error:
return AVERROR_PATCHWELCOME ;
}
static int samples_ready ( AV FilterLink * link , unsigned min )
static int samples_ready ( FilterLinkInternal * link , unsigned min )
{
return ff_framequeue_queued_frames ( & link - > fifo ) & &
( ff_framequeue_queued_samples ( & link - > fifo ) > = min | |
link - > status_in ) ;
}
static int take_samples ( AV FilterLink * link , unsigned min , unsigned max ,
static int take_samples ( FilterLinkInternal * li , unsigned min , unsigned max ,
AVFrame * * rframe )
{
AVFilterLink * link = & li - > l ;
AVFrame * frame0 , * frame , * buf ;
unsigned nb_samples , nb_frames , i , p ;
int ret ;
@ -1061,9 +1080,9 @@ static int take_samples(AVFilterLink *link, unsigned min, unsigned max,
/* Note: this function relies on no format changes and must only be
called with enough samples . */
av_assert1 ( samples_ready ( link , link - > min_samples ) ) ;
frame0 = frame = ff_framequeue_peek ( & link - > fifo , 0 ) ;
if ( ! link - > fifo . samples_skipped & & frame - > nb_samples > = min & & frame - > nb_samples < = max ) {
* rframe = ff_framequeue_take ( & link - > fifo ) ;
frame0 = frame = ff_framequeue_peek ( & li - > fifo , 0 ) ;
if ( ! li - > fifo . samples_skipped & & frame - > nb_samples > = min & & frame - > nb_samples < = max ) {
* rframe = ff_framequeue_take ( & li - > fifo ) ;
return 0 ;
}
nb_frames = 0 ;
@ -1076,9 +1095,9 @@ static int take_samples(AVFilterLink *link, unsigned min, unsigned max,
}
nb_samples + = frame - > nb_samples ;
nb_frames + + ;
if ( nb_frames = = ff_framequeue_queued_frames ( & link - > fifo ) )
if ( nb_frames = = ff_framequeue_queued_frames ( & li - > fifo ) )
break ;
frame = ff_framequeue_peek ( & link - > fifo , nb_frames ) ;
frame = ff_framequeue_peek ( & li - > fifo , nb_frames ) ;
}
buf = ff_get_audio_buffer ( link , nb_samples ) ;
@ -1092,7 +1111,7 @@ static int take_samples(AVFilterLink *link, unsigned min, unsigned max,
p = 0 ;
for ( i = 0 ; i < nb_frames ; i + + ) {
frame = ff_framequeue_take ( & link - > fifo ) ;
frame = ff_framequeue_take ( & li - > fifo ) ;
av_samples_copy ( buf - > extended_data , frame - > extended_data , p , 0 ,
frame - > nb_samples , link - > ch_layout . nb_channels , link - > format ) ;
p + = frame - > nb_samples ;
@ -1100,10 +1119,10 @@ static int take_samples(AVFilterLink *link, unsigned min, unsigned max,
}
if ( p < nb_samples ) {
unsigned n = nb_samples - p ;
frame = ff_framequeue_peek ( & link - > fifo , 0 ) ;
frame = ff_framequeue_peek ( & li - > fifo , 0 ) ;
av_samples_copy ( buf - > extended_data , frame - > extended_data , p , 0 , n ,
link - > ch_layout . nb_channels , link - > format ) ;
ff_framequeue_skip_samples ( & link - > fifo , n , link - > time_base ) ;
ff_framequeue_skip_samples ( & li - > fifo , n , link - > time_base ) ;
}
* rframe = buf ;
@ -1112,6 +1131,7 @@ static int take_samples(AVFilterLink *link, unsigned min, unsigned max,
static int ff_filter_frame_to_filter ( AVFilterLink * link )
{
FilterLinkInternal * const li = ff_link_internal ( link ) ;
AVFrame * frame = NULL ;
AVFilterContext * dst = link - > dst ;
int ret ;
@ -1132,7 +1152,7 @@ static int ff_filter_frame_to_filter(AVFilterLink *link)
before the frame ; ff_filter_frame_framed ( ) will re - increment it . */
link - > frame_count_out - - ;
ret = ff_filter_frame_framed ( link , frame ) ;
if ( ret < 0 & & ret ! = link - > status_out ) {
if ( ret < 0 & & ret ! = li - > status_out ) {
link_set_out_status ( link , ret , AV_NOPTS_VALUE ) ;
} else {
/* Run once again, to see if several frames were available, or if
@ -1142,18 +1162,21 @@ static int ff_filter_frame_to_filter(AVFilterLink *link)
return ret ;
}
static int forward_status_change ( AVFilterContext * filter , AV FilterLink * in )
static int forward_status_change ( AVFilterContext * filter , FilterLinkInternal * li_ in)
{
AVFilterLink * in = & li_in - > l ;
unsigned out = 0 , progress = 0 ;
int ret ;
av_assert0 ( ! in - > status_out ) ;
av_assert0 ( ! li_ in- > status_out ) ;
if ( ! filter - > nb_outputs ) {
/* not necessary with the current API and sinks */
return 0 ;
}
while ( ! in - > status_out ) {
if ( ! filter - > outputs [ out ] - > status_in ) {
while ( ! li_in - > status_out ) {
FilterLinkInternal * li_out = ff_link_internal ( filter - > outputs [ out ] ) ;
if ( ! li_out - > status_in ) {
progress + + ;
ret = ff_request_frame_to_filter ( filter - > outputs [ out ] ) ;
if ( ret < 0 )
@ -1163,7 +1186,7 @@ static int forward_status_change(AVFilterContext *filter, AVFilterLink *in)
if ( ! progress ) {
/* Every output already closed: input no longer interesting
( example : overlay in shortest mode , other input closed ) . */
link_set_out_status ( in , in - > status_in , in - > status_in_pts ) ;
link_set_out_status ( in , li_ in- > status_in , li_ in- > status_in_pts ) ;
return 0 ;
}
progress = 0 ;
@ -1179,7 +1202,8 @@ static int ff_filter_activate_default(AVFilterContext *filter)
unsigned i ;
for ( i = 0 ; i < filter - > nb_outputs ; i + + ) {
int ret = filter - > outputs [ i ] - > status_in ;
FilterLinkInternal * li = ff_link_internal ( filter - > outputs [ i ] ) ;
int ret = li - > status_in ;
if ( ret ) {
for ( int j = 0 ; j < filter - > nb_inputs ; j + + )
@ -1189,19 +1213,22 @@ static int ff_filter_activate_default(AVFilterContext *filter)
}
for ( i = 0 ; i < filter - > nb_inputs ; i + + ) {
if ( samples_ready ( filter - > inputs [ i ] , filter - > inputs [ i ] - > min_samples ) ) {
if ( samples_ready ( ff_link_internal ( filter - > inputs [ i ] ) ,
filter - > inputs [ i ] - > min_samples ) ) {
return ff_filter_frame_to_filter ( filter - > inputs [ i ] ) ;
}
}
for ( i = 0 ; i < filter - > nb_inputs ; i + + ) {
if ( filter - > inputs [ i ] - > status_in & & ! filter - > inputs [ i ] - > status_out ) {
av_assert1 ( ! ff_framequeue_queued_frames ( & filter - > inputs [ i ] - > fifo ) ) ;
return forward_status_change ( filter , filter - > inputs [ i ] ) ;
FilterLinkInternal * const li = ff_link_internal ( filter - > inputs [ i ] ) ;
if ( li - > status_in & & ! li - > status_out ) {
av_assert1 ( ! ff_framequeue_queued_frames ( & li - > fifo ) ) ;
return forward_status_change ( filter , li ) ;
}
}
for ( i = 0 ; i < filter - > nb_outputs ; i + + ) {
FilterLinkInternal * const li = ff_link_internal ( filter - > outputs [ i ] ) ;
if ( filter - > outputs [ i ] - > frame_wanted_out & &
! fi lter - > outputs [ i ] - > frame_blocked_in ) {
! li - > frame_blocked_in ) {
return ff_request_frame_to_filter ( filter - > outputs [ i ] ) ;
}
}
@ -1357,39 +1384,44 @@ int ff_filter_activate(AVFilterContext *filter)
int ff_inlink_acknowledge_status ( AVFilterLink * link , int * rstatus , int64_t * rpts )
{
FilterLinkInternal * const li = ff_link_internal ( link ) ;
* rpts = link - > current_pts ;
if ( ff_framequeue_queued_frames ( & link - > fifo ) )
if ( ff_framequeue_queued_frames ( & li - > fifo ) )
return * rstatus = 0 ;
if ( link - > status_out )
return * rstatus = link - > status_out ;
if ( ! link - > status_in )
if ( li - > status_out )
return * rstatus = li - > status_out ;
if ( ! li - > status_in )
return * rstatus = 0 ;
* rstatus = link - > status_out = link - > status_in ;
update_link_current_pts ( link , link - > status_in_pts ) ;
* rstatus = li - > status_out = li - > status_in ;
update_link_current_pts ( link , li - > status_in_pts ) ;
* rpts = link - > current_pts ;
return 1 ;
}
size_t ff_inlink_queued_frames ( AVFilterLink * link )
{
return ff_framequeue_queued_frames ( & link - > fifo ) ;
FilterLinkInternal * const li = ff_link_internal ( link ) ;
return ff_framequeue_queued_frames ( & li - > fifo ) ;
}
int ff_inlink_check_available_frame ( AVFilterLink * link )
{
return ff_framequeue_queued_frames ( & link - > fifo ) > 0 ;
FilterLinkInternal * const li = ff_link_internal ( link ) ;
return ff_framequeue_queued_frames ( & li - > fifo ) > 0 ;
}
int ff_inlink_queued_samples ( AVFilterLink * link )
{
return ff_framequeue_queued_samples ( & link - > fifo ) ;
FilterLinkInternal * const li = ff_link_internal ( link ) ;
return ff_framequeue_queued_samples ( & li - > fifo ) ;
}
int ff_inlink_check_available_samples ( AVFilterLink * link , unsigned min )
{
uint64_t samples = ff_framequeue_queued_samples ( & link - > fifo ) ;
FilterLinkInternal * const li = ff_link_internal ( link ) ;
uint64_t samples = ff_framequeue_queued_samples ( & li - > fifo ) ;
av_assert1 ( min ) ;
return samples > = min | | ( link - > status_in & & samples ) ;
return samples > = min | | ( li - > status_in & & samples ) ;
}
static void consume_update ( AVFilterLink * link , const AVFrame * frame )
@ -1403,18 +1435,19 @@ static void consume_update(AVFilterLink *link, const AVFrame *frame)
int ff_inlink_consume_frame ( AVFilterLink * link , AVFrame * * rframe )
{
FilterLinkInternal * const li = ff_link_internal ( link ) ;
AVFrame * frame ;
* rframe = NULL ;
if ( ! ff_inlink_check_available_frame ( link ) )
return 0 ;
if ( link - > fifo . samples_skipped ) {
frame = ff_framequeue_peek ( & link - > fifo , 0 ) ;
if ( li - > fifo . samples_skipped ) {
frame = ff_framequeue_peek ( & li - > fifo , 0 ) ;
return ff_inlink_consume_samples ( link , frame - > nb_samples , frame - > nb_samples , rframe ) ;
}
frame = ff_framequeue_take ( & link - > fifo ) ;
frame = ff_framequeue_take ( & li - > fifo ) ;
consume_update ( link , frame ) ;
* rframe = frame ;
return 1 ;
@ -1423,6 +1456,7 @@ int ff_inlink_consume_frame(AVFilterLink *link, AVFrame **rframe)
int ff_inlink_consume_samples ( AVFilterLink * link , unsigned min , unsigned max ,
AVFrame * * rframe )
{
FilterLinkInternal * const li = ff_link_internal ( link ) ;
AVFrame * frame ;
int ret ;
@ -1430,9 +1464,9 @@ int ff_inlink_consume_samples(AVFilterLink *link, unsigned min, unsigned max,
* rframe = NULL ;
if ( ! ff_inlink_check_available_samples ( link , min ) )
return 0 ;
if ( link - > status_in )
min = FFMIN ( min , ff_framequeue_queued_samples ( & link - > fifo ) ) ;
ret = take_samples ( link , min , max , & frame ) ;
if ( li - > status_in )
min = FFMIN ( min , ff_framequeue_queued_samples ( & li - > fifo ) ) ;
ret = take_samples ( li , min , max , & frame ) ;
if ( ret < 0 )
return ret ;
consume_update ( link , frame ) ;
@ -1442,7 +1476,8 @@ int ff_inlink_consume_samples(AVFilterLink *link, unsigned min, unsigned max,
AVFrame * ff_inlink_peek_frame ( AVFilterLink * link , size_t idx )
{
return ff_framequeue_peek ( & link - > fifo , idx ) ;
FilterLinkInternal * const li = ff_link_internal ( link ) ;
return ff_framequeue_peek ( & li - > fifo , idx ) ;
}
int ff_inlink_make_frame_writable ( AVFilterLink * link , AVFrame * * rframe )
@ -1534,29 +1569,32 @@ void ff_inlink_request_frame(AVFilterLink *link)
void ff_inlink_set_status ( AVFilterLink * link , int status )
{
if ( link - > status_out )
FilterLinkInternal * const li = ff_link_internal ( link ) ;
if ( li - > status_out )
return ;
link - > frame_wanted_out = 0 ;
link - > frame_blocked_in = 0 ;
li - > frame_blocked_in = 0 ;
link_set_out_status ( link , status , AV_NOPTS_VALUE ) ;
while ( ff_framequeue_queued_frames ( & link - > fifo ) ) {
AVFrame * frame = ff_framequeue_take ( & link - > fifo ) ;
while ( ff_framequeue_queued_frames ( & li - > fifo ) ) {
AVFrame * frame = ff_framequeue_take ( & li - > fifo ) ;
av_frame_free ( & frame ) ;
}
if ( ! link - > status_in )
link - > status_in = status ;
if ( ! li - > status_in )
li - > status_in = status ;
}
int ff_outlink_get_status ( AVFilterLink * link )
{
return link - > status_in ;
FilterLinkInternal * const li = ff_link_internal ( link ) ;
return li - > status_in ;
}
int ff_inoutlink_check_flow ( AVFilterLink * inlink , AVFilterLink * outlink )
{
FilterLinkInternal * const li_in = ff_link_internal ( inlink ) ;
return ff_outlink_frame_wanted ( outlink ) | |
ff_inlink_check_available_frame ( inlink ) | |
inlink - > status_out ;
li_in - > status_out ;
}