|
|
|
@ -46,6 +46,8 @@ enum { |
|
|
|
|
STATE_EOF, |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
static int consume_from_fifos(FFFrameSync *fs); |
|
|
|
|
|
|
|
|
|
int ff_framesync2_init(FFFrameSync *fs, AVFilterContext *parent, unsigned nb_in) |
|
|
|
|
{ |
|
|
|
|
/* For filters with several outputs, we will not be able to assume which
|
|
|
|
@ -127,30 +129,20 @@ int ff_framesync2_configure(FFFrameSync *fs) |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void framesync_advance(FFFrameSync *fs) |
|
|
|
|
static int framesync_advance(FFFrameSync *fs) |
|
|
|
|
{ |
|
|
|
|
int latest; |
|
|
|
|
unsigned i; |
|
|
|
|
int64_t pts; |
|
|
|
|
int ret; |
|
|
|
|
|
|
|
|
|
if (fs->eof) |
|
|
|
|
return; |
|
|
|
|
while (!fs->frame_ready) { |
|
|
|
|
latest = -1; |
|
|
|
|
for (i = 0; i < fs->nb_in; i++) { |
|
|
|
|
if (!fs->in[i].have_next) { |
|
|
|
|
if (latest < 0 || fs->in[i].pts < fs->in[latest].pts) |
|
|
|
|
latest = i; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (latest >= 0) { |
|
|
|
|
fs->in_request = latest; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
while (!(fs->frame_ready || fs->eof)) { |
|
|
|
|
ret = consume_from_fifos(fs); |
|
|
|
|
if (ret <= 0) |
|
|
|
|
return ret; |
|
|
|
|
|
|
|
|
|
pts = fs->in[0].pts_next; |
|
|
|
|
for (i = 1; i < fs->nb_in; i++) |
|
|
|
|
if (fs->in[i].pts_next < pts) |
|
|
|
|
pts = INT64_MAX; |
|
|
|
|
for (i = 0; i < fs->nb_in; i++) |
|
|
|
|
if (fs->in[i].have_next && fs->in[i].pts_next < pts) |
|
|
|
|
pts = fs->in[i].pts_next; |
|
|
|
|
if (pts == INT64_MAX) { |
|
|
|
|
framesync_eof(fs); |
|
|
|
@ -181,6 +173,7 @@ static void framesync_advance(FFFrameSync *fs) |
|
|
|
|
fs->frame_ready = 0; |
|
|
|
|
fs->pts = pts; |
|
|
|
|
} |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int64_t framesync_pts_extrapolate(FFFrameSync *fs, unsigned in, |
|
|
|
@ -264,7 +257,7 @@ void ff_framesync2_uninit(FFFrameSync *fs) |
|
|
|
|
av_freep(&fs->in); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int ff_framesync2_activate(FFFrameSync *fs) |
|
|
|
|
static int consume_from_fifos(FFFrameSync *fs) |
|
|
|
|
{ |
|
|
|
|
AVFilterContext *ctx = fs->parent; |
|
|
|
|
AVFrame *frame = NULL; |
|
|
|
@ -300,8 +293,16 @@ int ff_framesync2_activate(FFFrameSync *fs) |
|
|
|
|
ff_inlink_request_frame(ctx->inputs[i]); |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
return 1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
framesync_advance(fs); |
|
|
|
|
int ff_framesync2_activate(FFFrameSync *fs) |
|
|
|
|
{ |
|
|
|
|
int ret; |
|
|
|
|
|
|
|
|
|
ret = framesync_advance(fs); |
|
|
|
|
if (ret < 0) |
|
|
|
|
return ret; |
|
|
|
|
if (fs->eof || !fs->frame_ready) |
|
|
|
|
return 0; |
|
|
|
|
ret = fs->on_event(fs); |
|
|
|
@ -311,3 +312,59 @@ int ff_framesync2_activate(FFFrameSync *fs) |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int ff_framesync2_init_dualinput(FFFrameSync *fs, AVFilterContext *parent) |
|
|
|
|
{ |
|
|
|
|
int ret; |
|
|
|
|
|
|
|
|
|
ret = ff_framesync2_init(fs, parent, 2); |
|
|
|
|
if (ret < 0) |
|
|
|
|
return ret; |
|
|
|
|
fs->in[0].time_base = parent->inputs[0]->time_base; |
|
|
|
|
fs->in[1].time_base = parent->inputs[1]->time_base; |
|
|
|
|
fs->in[0].sync = 2; |
|
|
|
|
fs->in[0].before = EXT_STOP; |
|
|
|
|
fs->in[0].after = EXT_INFINITY; |
|
|
|
|
fs->in[1].sync = 1; |
|
|
|
|
fs->in[1].before = EXT_NULL; |
|
|
|
|
fs->in[1].after = EXT_INFINITY; |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int ff_framesync2_dualinput_get(FFFrameSync *fs, AVFrame **f0, AVFrame **f1) |
|
|
|
|
{ |
|
|
|
|
AVFilterContext *ctx = fs->parent; |
|
|
|
|
AVFrame *mainpic = NULL, *secondpic = NULL; |
|
|
|
|
int ret = 0; |
|
|
|
|
|
|
|
|
|
if ((ret = ff_framesync2_get_frame(fs, 0, &mainpic, 1)) < 0 || |
|
|
|
|
(ret = ff_framesync2_get_frame(fs, 1, &secondpic, 0)) < 0) { |
|
|
|
|
av_frame_free(&mainpic); |
|
|
|
|
return ret; |
|
|
|
|
} |
|
|
|
|
if (ret < 0) |
|
|
|
|
return ret; |
|
|
|
|
av_assert0(mainpic); |
|
|
|
|
mainpic->pts = av_rescale_q(fs->pts, fs->time_base, ctx->outputs[0]->time_base); |
|
|
|
|
if (ctx->is_disabled) |
|
|
|
|
secondpic = NULL; |
|
|
|
|
*f0 = mainpic; |
|
|
|
|
*f1 = secondpic; |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int ff_framesync2_dualinput_get_writable(FFFrameSync *fs, AVFrame **f0, AVFrame **f1) |
|
|
|
|
{ |
|
|
|
|
int ret; |
|
|
|
|
|
|
|
|
|
ret = ff_framesync2_dualinput_get(fs, f0, f1); |
|
|
|
|
if (ret < 0) |
|
|
|
|
return ret; |
|
|
|
|
ret = ff_inlink_make_frame_writable(fs->parent->inputs[0], f0); |
|
|
|
|
if (ret < 0) { |
|
|
|
|
av_frame_free(f0); |
|
|
|
|
av_frame_free(f1); |
|
|
|
|
return ret; |
|
|
|
|
} |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|