@ -18,12 +18,9 @@
* 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA
*/
# define FF_INTERNAL_FIELDS 1
# include "framequeue.h"
# include "libavutil/avassert.h"
# include "avfilter.h"
# include "bufferqueue .h"
# include "filters.h"
# include "framesync2.h"
# include "internal.h"
@ -49,8 +46,13 @@ enum {
STATE_EOF ,
} ;
int ff_framesync2_init ( FFFrameSync * fs , void * parent , unsigned nb_in )
int ff_framesync2_init ( FFFrameSync * fs , AVFilterContext * parent , unsigned nb_in )
{
/* For filters with several outputs, we will not be able to assume which
output is relevant for ff_outlink_frame_wanted ( ) and
ff_outlink_set_status ( ) . To be designed when needed . */
av_assert0 ( parent - > nb_outputs = = 1 ) ;
fs - > class = & framesync_class ;
fs - > parent = parent ;
fs - > nb_in = nb_in ;
@ -61,6 +63,13 @@ int ff_framesync2_init(FFFrameSync *fs, void *parent, unsigned nb_in)
return 0 ;
}
static void framesync_eof ( FFFrameSync * fs )
{
fs - > eof = 1 ;
fs - > frame_ready = 0 ;
ff_outlink_set_status ( fs - > parent - > outputs [ 0 ] , AVERROR_EOF , AV_NOPTS_VALUE ) ;
}
static void framesync_sync_level_update ( FFFrameSync * fs )
{
unsigned i , level = 0 ;
@ -74,7 +83,7 @@ static void framesync_sync_level_update(FFFrameSync *fs)
if ( level )
fs - > sync_level = level ;
else
fs - > eof = 1 ;
framesync_eof ( fs ) ;
}
int ff_framesync2_configure ( FFFrameSync * fs )
@ -144,7 +153,7 @@ static void framesync_advance(FFFrameSync *fs)
if ( fs - > in [ i ] . pts_next < pts )
pts = fs - > in [ i ] . pts_next ;
if ( pts = = INT64_MAX ) {
fs - > eof = 1 ;
framesync_eof ( fs ) ;
break ;
}
for ( i = 0 ; i < fs - > nb_in ; i + + ) {
@ -162,11 +171,9 @@ static void framesync_advance(FFFrameSync *fs)
fs - > frame_ready = 1 ;
if ( fs - > in [ i ] . state = = STATE_EOF & &
fs - > in [ i ] . after = = EXT_STOP )
fs - > eof = 1 ;
framesync_eof ( fs ) ;
}
}
if ( fs - > eof )
fs - > frame_ready = 0 ;
if ( fs - > frame_ready )
for ( i = 0 ; i < fs - > nb_in ; i + + )
if ( ( fs - > in [ i ] . state = = STATE_BOF & &
@ -188,45 +195,24 @@ static void framesync_inject_frame(FFFrameSync *fs, unsigned in, AVFrame *frame)
int64_t pts ;
av_assert0 ( ! fs - > in [ in ] . have_next ) ;
if ( frame ) {
av_assert0 ( frame ) ;
pts = av_rescale_q ( frame - > pts , fs - > in [ in ] . time_base , fs - > time_base ) ;
frame - > pts = pts ;
} else {
pts = fs - > in [ in ] . state ! = STATE_RUN | | fs - > in [ in ] . after = = EXT_INFINITY
? INT64_MAX : framesync_pts_extrapolate ( fs , in , fs - > in [ in ] . pts ) ;
fs - > in [ in ] . sync = 0 ;
framesync_sync_level_update ( fs ) ;
}
fs - > in [ in ] . frame_next = frame ;
fs - > in [ in ] . pts_next = pts ;
fs - > in [ in ] . have_next = 1 ;
}
int ff_framesync2_add_frame ( FFFrameSync * fs , unsigned in , AVFrame * frame )
static void framesync_inject_status ( FFFrameSync * fs , unsigned in , int status , int64_t pts )
{
av_assert1 ( in < fs - > nb_in ) ;
if ( ! fs - > in [ in ] . have_next )
framesync_inject_frame ( fs , in , frame ) ;
else
ff_bufqueue_add ( fs , & fs - > in [ in ] . queue , frame ) ;
return 0 ;
}
void ff_framesync2_next ( FFFrameSync * fs )
{
unsigned i ;
av_assert0 ( ! fs - > frame_ready ) ;
for ( i = 0 ; i < fs - > nb_in ; i + + )
if ( ! fs - > in [ i ] . have_next & & fs - > in [ i ] . queue . available )
framesync_inject_frame ( fs , i , ff_bufqueue_get ( & fs - > in [ i ] . queue ) ) ;
fs - > frame_ready = 0 ;
framesync_advance ( fs ) ;
}
void ff_framesync2_drop ( FFFrameSync * fs )
{
fs - > frame_ready = 0 ;
av_assert0 ( ! fs - > in [ in ] . have_next ) ;
pts = fs - > in [ in ] . state ! = STATE_RUN | | fs - > in [ in ] . after = = EXT_INFINITY
? INT64_MAX : framesync_pts_extrapolate ( fs , in , fs - > in [ in ] . pts ) ;
fs - > in [ in ] . sync = 0 ;
framesync_sync_level_update ( fs ) ;
fs - > in [ in ] . frame_next = NULL ;
fs - > in [ in ] . pts_next = pts ;
fs - > in [ in ] . have_next = 1 ;
}
int ff_framesync2_get_frame ( FFFrameSync * fs , unsigned in , AVFrame * * rframe ,
@ -273,71 +259,55 @@ void ff_framesync2_uninit(FFFrameSync *fs)
for ( i = 0 ; i < fs - > nb_in ; i + + ) {
av_frame_free ( & fs - > in [ i ] . frame ) ;
av_frame_free ( & fs - > in [ i ] . frame_next ) ;
ff_bufqueue_discard_all ( & fs - > in [ i ] . queue ) ;
}
av_freep ( & fs - > in ) ;
}
int ff_framesync2_process_fram e ( FFFrameSync * fs , unsigned all )
int ff_framesync2_activat e ( FFFrameSync * fs )
{
int ret , count = 0 ;
AVFilterContext * ctx = fs - > parent ;
AVFrame * frame = NULL ;
int64_t pts ;
unsigned i , nb_active , nb_miss ;
int ret , status ;
av_assert0 ( fs - > on_event ) ;
while ( 1 ) {
ff_framesync2_next ( fs ) ;
if ( fs - > eof | | ! fs - > frame_ready )
break ;
if ( ( ret = fs - > on_event ( fs ) ) < 0 )
nb_active = nb_miss = 0 ;
for ( i = 0 ; i < fs - > nb_in ; i + + ) {
if ( fs - > in [ i ] . have_next | | fs - > in [ i ] . state = = STATE_EOF )
continue ;
nb_active + + ;
ret = ff_inlink_consume_frame ( ctx - > inputs [ i ] , & frame ) ;
if ( ret < 0 )
return ret ;
ff_framesync2_drop ( fs ) ;
count + + ;
if ( ! all )
break ;
if ( ret ) {
av_assert0 ( frame ) ;
framesync_inject_frame ( fs , i , frame ) ;
} else {
ret = ff_inlink_acknowledge_status ( ctx - > inputs [ i ] , & status , & pts ) ;
if ( ret > 0 ) {
framesync_inject_status ( fs , i , status , pts ) ;
} else if ( ! ret ) {
nb_miss + + ;
}
if ( ! count & & fs - > eof )
return AVERROR_EOF ;
return count ;
}
int ff_framesync2_filter_frame ( FFFrameSync * fs , AVFilterLink * inlink ,
AVFrame * in )
{
int ret ;
if ( ( ret = ff_framesync2_process_frame ( fs , 1 ) ) < 0 )
return ret ;
if ( ( ret = ff_framesync2_add_frame ( fs , FF_INLINK_IDX ( inlink ) , in ) ) < 0 )
return ret ;
if ( ( ret = ff_framesync2_process_frame ( fs , 0 ) ) < 0 )
return ret ;
}
if ( nb_miss ) {
if ( nb_miss = = nb_active & & ! ff_outlink_frame_wanted ( ctx - > outputs [ 0 ] ) )
return FFERROR_NOT_READY ;
for ( i = 0 ; i < fs - > nb_in ; i + + )
if ( ! fs - > in [ i ] . have_next & & fs - > in [ i ] . state ! = STATE_EOF )
ff_inlink_request_frame ( ctx - > inputs [ i ] ) ;
return 0 ;
}
int ff_framesync2_request_frame ( FFFrameSync * fs , AVFilterLink * outlink )
{
AVFilterContext * ctx = outlink - > src ;
int input , ret , i ;
if ( ( ret = ff_framesync2_process_frame ( fs , 0 ) ) < 0 )
return ret ;
if ( ret > 0 )
framesync_advance ( fs ) ;
if ( fs - > eof | | ! fs - > frame_ready )
return 0 ;
if ( fs - > eof )
return AVERROR_EOF ;
input = fs - > in_request ;
/* Detect status change early */
for ( i = 0 ; i < fs - > nb_in ; i + + )
if ( ! ff_framequeue_queued_frames ( & ctx - > inputs [ i ] - > fifo ) & &
ctx - > inputs [ i ] - > status_in & & ! ctx - > inputs [ i ] - > status_out )
input = i ;
ret = ff_request_frame ( ctx - > inputs [ input ] ) ;
if ( ret = = AVERROR_EOF ) {
if ( ( ret = ff_framesync2_add_frame ( fs , input , NULL ) ) < 0 )
return ret ;
if ( ( ret = ff_framesync2_process_frame ( fs , 0 ) ) < 0 )
return ret ;
ret = 0 ;
}
ret = fs - > on_event ( fs ) ;
if ( ret < 0 )
return ret ;
fs - > frame_ready = 0 ;
return 0 ;
}