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:
parent
6bde475cf2
commit
0ae8df4109
@ -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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user