1
0
mirror of https://github.com/FFmpeg/FFmpeg.git synced 2024-11-21 10:55:51 +02:00

lavfi/framesync2: add dualinput helper functions.

This commit is contained in:
Nicolas George 2017-07-17 20:45:52 +02:00
parent 6bde475cf2
commit 0ae8df4109
2 changed files with 103 additions and 21 deletions

View File

@ -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;
}

View File

@ -245,4 +245,29 @@ int ff_framesync2_get_frame(FFFrameSync *fs, unsigned in, AVFrame **rframe,
*/
int ff_framesync2_activate(FFFrameSync *fs);
/**
* Initialize a frame sync structure for dualinput.
*
* Compared to generic framesync, dualinput assumes the first input is the
* main one and the filtering is performed on it. The first input will be
* the only one with sync set and generic timeline support will just pass it
* unchanged when disabled.
*
* Equivalent to ff_framesync2_init(fs, parent, 2) then setting the time
* base, sync and ext modes on the inputs.
*/
int ff_framesync2_init_dualinput(FFFrameSync *fs, AVFilterContext *parent);
/**
* @param f0 used to return the main frame
* @param f1 used to return the second frame, or NULL if disabled
* @return >=0 for success or AVERROR code
*/
int ff_framesync2_dualinput_get(FFFrameSync *fs, AVFrame **f0, AVFrame **f1);
/**
* Same as ff_framesync2_dualinput_get(), but make sure that f0 is writable.
*/
int ff_framesync2_dualinput_get_writable(FFFrameSync *fs, AVFrame **f0, AVFrame **f1);
#endif /* AVFILTER_FRAMESYNC2_H */