[FFmpeg-devel] [PATCH 2/2] lavfi/dualinput: reimplement on top of framesync.
Nicolas George
nicolas.george at normalesup.org
Sun Sep 8 17:42:30 CEST 2013
Signed-off-by: Nicolas George <nicolas.george at normalesup.org>
---
libavfilter/Makefile | 8 +--
libavfilter/dualinput.c | 149 +++++++++++++----------------------------------
libavfilter/dualinput.h | 8 ++-
libavfilter/vf_blend.c | 4 ++
libavfilter/vf_lut3d.c | 4 ++
libavfilter/vf_overlay.c | 5 ++
libavfilter/vf_psnr.c | 4 ++
7 files changed, 66 insertions(+), 116 deletions(-)
diff --git a/libavfilter/Makefile b/libavfilter/Makefile
index b57d4c9..c9d8027 100644
--- a/libavfilter/Makefile
+++ b/libavfilter/Makefile
@@ -111,7 +111,7 @@ OBJS-$(CONFIG_ALPHAMERGE_FILTER) += vf_alphamerge.o
OBJS-$(CONFIG_BBOX_FILTER) += bbox.o vf_bbox.o
OBJS-$(CONFIG_BLACKDETECT_FILTER) += vf_blackdetect.o
OBJS-$(CONFIG_BLACKFRAME_FILTER) += vf_blackframe.o
-OBJS-$(CONFIG_BLEND_FILTER) += vf_blend.o dualinput.o
+OBJS-$(CONFIG_BLEND_FILTER) += vf_blend.o dualinput.o framesync.o
OBJS-$(CONFIG_BOXBLUR_FILTER) += vf_boxblur.o
OBJS-$(CONFIG_COLORBALANCE_FILTER) += vf_colorbalance.o
OBJS-$(CONFIG_COLORCHANNELMIXER_FILTER) += vf_colorchannelmixer.o
@@ -139,7 +139,7 @@ OBJS-$(CONFIG_FPS_FILTER) += vf_fps.o
OBJS-$(CONFIG_FREI0R_FILTER) += vf_frei0r.o
OBJS-$(CONFIG_GEQ_FILTER) += vf_geq.o
OBJS-$(CONFIG_GRADFUN_FILTER) += vf_gradfun.o
-OBJS-$(CONFIG_HALDCLUT_FILTER) += vf_lut3d.o dualinput.o
+OBJS-$(CONFIG_HALDCLUT_FILTER) += vf_lut3d.o dualinput.o framesync.o
OBJS-$(CONFIG_HFLIP_FILTER) += vf_hflip.o
OBJS-$(CONFIG_HISTEQ_FILTER) += vf_histeq.o
OBJS-$(CONFIG_HISTOGRAM_FILTER) += vf_histogram.o
@@ -163,7 +163,7 @@ OBJS-$(CONFIG_NOISE_FILTER) += vf_noise.o
OBJS-$(CONFIG_NULL_FILTER) += vf_null.o
OBJS-$(CONFIG_OCV_FILTER) += vf_libopencv.o
OBJS-$(CONFIG_OPENCL) += deshake_opencl.o unsharp_opencl.o
-OBJS-$(CONFIG_OVERLAY_FILTER) += vf_overlay.o dualinput.o
+OBJS-$(CONFIG_OVERLAY_FILTER) += vf_overlay.o dualinput.o framesync.o
OBJS-$(CONFIG_OWDENOISE_FILTER) += vf_owdenoise.o
OBJS-$(CONFIG_PAD_FILTER) += vf_pad.o
OBJS-$(CONFIG_PERMS_FILTER) += f_perms.o
@@ -171,7 +171,7 @@ OBJS-$(CONFIG_PERSPECTIVE_FILTER) += vf_perspective.o
OBJS-$(CONFIG_PHASE_FILTER) += vf_phase.o
OBJS-$(CONFIG_PIXDESCTEST_FILTER) += vf_pixdesctest.o
OBJS-$(CONFIG_PP_FILTER) += vf_pp.o
-OBJS-$(CONFIG_PSNR_FILTER) += vf_psnr.o dualinput.o
+OBJS-$(CONFIG_PSNR_FILTER) += vf_psnr.o dualinput.o framesync.o
OBJS-$(CONFIG_REMOVELOGO_FILTER) += bbox.o lswsutils.o lavfutils.o vf_removelogo.o
OBJS-$(CONFIG_ROTATE_FILTER) += vf_rotate.o
OBJS-$(CONFIG_SEPARATEFIELDS_FILTER) += vf_separatefields.o
diff --git a/libavfilter/dualinput.c b/libavfilter/dualinput.c
index 10e3652..179c3ef 100644
--- a/libavfilter/dualinput.c
+++ b/libavfilter/dualinput.c
@@ -16,144 +16,75 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#define MAIN 0
-#define SECOND 1
-
#include "dualinput.h"
#include "libavutil/timestamp.h"
-static int try_filter_frame(FFDualInputContext *s,
- AVFilterContext *ctx, AVFrame *mainpic)
+static int process_frame(FFFrameSync *fs)
{
- int ret;
-
- /* Discard obsolete second frames: if there is a next second frame with pts
- * before the main frame, we can drop the current second. */
- while (1) {
- AVFrame *next_overpic = ff_bufqueue_peek(&s->queue[SECOND], 0);
- if (!next_overpic && s->second_eof && !s->repeatlast) {
- av_frame_free(&s->second_frame);
- break;
- }
- if (!next_overpic || av_compare_ts(next_overpic->pts, ctx->inputs[SECOND]->time_base,
- mainpic->pts, ctx->inputs[MAIN]->time_base) > 0)
- break;
- ff_bufqueue_get(&s->queue[SECOND]);
- av_frame_free(&s->second_frame);
- s->second_frame = next_overpic;
+ AVFilterContext *ctx = fs->parent;
+ FFDualInputContext *s = fs->opaque;
+ AVFrame *mainpic = NULL, *secondpic = NULL;
+ int ret = 0;
+
+ if ((ret = ff_framesync_get_frame(&s->fs, 0, &mainpic, 1)) < 0 ||
+ (ret = ff_framesync_get_frame(&s->fs, 1, &secondpic, 0)) < 0) {
+ av_frame_free(&mainpic);
+ return ret;
}
-
- /* If there is no next frame and no EOF and the second frame is before
- * the main frame, we can not know yet if it will be superseded. */
- if (!s->queue[SECOND].available && !s->second_eof &&
- (!s->second_frame || av_compare_ts(s->second_frame->pts, ctx->inputs[SECOND]->time_base,
- mainpic->pts, ctx->inputs[MAIN]->time_base) < 0))
- return AVERROR(EAGAIN);
-
- /* At this point, we know that the current second frame extends to the
- * time of the main frame. */
- av_dlog(ctx, "main_pts:%s main_pts_time:%s",
- av_ts2str(mainpic->pts), av_ts2timestr(mainpic->pts, &ctx->inputs[MAIN]->time_base));
- if (s->second_frame)
- av_dlog(ctx, " second_pts:%s second_pts_time:%s",
- av_ts2str(s->second_frame->pts), av_ts2timestr(s->second_frame->pts, &ctx->inputs[SECOND]->time_base));
- av_dlog(ctx, "\n");
-
- if (s->second_frame && !ctx->is_disabled)
- mainpic = s->process(ctx, mainpic, s->second_frame);
+ av_assert0(mainpic);
+ mainpic->pts = av_rescale_q(mainpic->pts, s->fs.time_base, ctx->outputs[0]->time_base);
+ if (secondpic && !ctx->is_disabled)
+ mainpic = s->process(ctx, mainpic, secondpic);
ret = ff_filter_frame(ctx->outputs[0], mainpic);
av_assert1(ret != AVERROR(EAGAIN));
s->frame_requested = 0;
return ret;
}
-static int try_filter_next_frame(FFDualInputContext *s, AVFilterContext *ctx)
-{
- AVFrame *next_mainpic = ff_bufqueue_peek(&s->queue[MAIN], 0);
- int ret;
-
- if (!next_mainpic)
- return AVERROR(EAGAIN);
- if ((ret = try_filter_frame(s, ctx, next_mainpic)) == AVERROR(EAGAIN))
- return ret;
- ff_bufqueue_get(&s->queue[MAIN]);
- return ret;
-}
-
-static int flush_frames(FFDualInputContext *s, AVFilterContext *ctx)
+int ff_dualinput_init(AVFilterContext *ctx, FFDualInputContext *s)
{
- int ret;
+ FFFrameSyncIn *in = s->fs.in;
+
+ ff_framesync_init(&s->fs, ctx, 2);
+ s->fs.opaque = s;
+ s->fs.on_event = process_frame;
+ in[0].time_base = ctx->inputs[0]->time_base;
+ in[1].time_base = ctx->inputs[1]->time_base;
+ in[0].sync = 2;
+ in[0].before = EXT_STOP;
+ in[0].after = EXT_INFINITY;
+ in[1].sync = 1;
+ in[1].before = EXT_NULL;
+ in[1].after = EXT_INFINITY;
+
+ if (s->shortest)
+ in[1].after = EXT_STOP;
+ if (!s->repeatlast) {
+ in[0].after = EXT_STOP;
+ in[1].sync = 0;
+ }
- while (!(ret = try_filter_next_frame(s, ctx)));
- return ret == AVERROR(EAGAIN) ? 0 : ret;
+ return ff_framesync_configure(&s->fs);
}
int ff_dualinput_filter_frame_main(FFDualInputContext *s,
AVFilterLink *inlink, AVFrame *in)
{
- AVFilterContext *ctx = inlink->dst;
- int ret;
-
- if ((ret = flush_frames(s, ctx)) < 0)
- return ret;
- if ((ret = try_filter_frame(s, ctx, in)) < 0) {
- if (ret != AVERROR(EAGAIN))
- return ret;
- ff_bufqueue_add(ctx, &s->queue[MAIN], in);
- }
-
- if (!s->second_frame)
- return 0;
- flush_frames(s, ctx);
-
- return 0;
+ return ff_framesync_filter_frame(&s->fs, inlink, in);
}
int ff_dualinput_filter_frame_second(FFDualInputContext *s,
AVFilterLink *inlink, AVFrame *in)
{
- AVFilterContext *ctx = inlink->dst;
- int ret;
-
- if ((ret = flush_frames(s, ctx)) < 0)
- return ret;
- ff_bufqueue_add(ctx, &s->queue[SECOND], in);
- ret = try_filter_next_frame(s, ctx);
- return ret == AVERROR(EAGAIN) ? 0 : ret;
+ return ff_framesync_filter_frame(&s->fs, inlink, in);
}
int ff_dualinput_request_frame(FFDualInputContext *s, AVFilterLink *outlink)
{
- AVFilterContext *ctx = outlink->src;
- int input, ret;
-
- if (!try_filter_next_frame(s, ctx))
- return 0;
- s->frame_requested = 1;
- while (s->frame_requested) {
- /* TODO if we had a frame duration, we could guess more accurately */
- input = !s->second_eof && (s->queue[MAIN].available ||
- s->queue[SECOND].available < 2) ?
- SECOND : MAIN;
- ret = ff_request_frame(ctx->inputs[input]);
- /* EOF on main is reported immediately */
- if (ret == AVERROR_EOF && input == SECOND) {
- s->second_eof = 1;
- if (s->shortest)
- return ret;
- if ((ret = try_filter_next_frame(s, ctx)) != AVERROR(EAGAIN))
- return ret;
- ret = 0; /* continue requesting frames on main */
- }
- if (ret < 0)
- return ret;
- }
- return 0;
+ return ff_framesync_request_frame(&s->fs, outlink);
}
void ff_dualinput_uninit(FFDualInputContext *s)
{
- av_frame_free(&s->second_frame);
- ff_bufqueue_discard_all(&s->queue[MAIN]);
- ff_bufqueue_discard_all(&s->queue[SECOND]);
+ ff_framesync_uninit(&s->fs);
}
diff --git a/libavfilter/dualinput.h b/libavfilter/dualinput.h
index 98d0544..aaefd78 100644
--- a/libavfilter/dualinput.h
+++ b/libavfilter/dualinput.h
@@ -26,18 +26,20 @@
#include <stdint.h>
#include "bufferqueue.h"
+#include "framesync.h"
#include "internal.h"
typedef struct {
+ FFFrameSync fs;
+ FFFrameSyncIn second_input; /* must be immediately after fs */
+
uint8_t frame_requested;
- uint8_t second_eof;
- AVFrame *second_frame;
- struct FFBufQueue queue[2];
AVFrame *(*process)(AVFilterContext *ctx, AVFrame *main, const AVFrame *second);
int shortest; ///< terminate stream when the second input terminates
int repeatlast; ///< repeat last second frame
} FFDualInputContext;
+int ff_dualinput_init(AVFilterContext *ctx, FFDualInputContext *s);
int ff_dualinput_filter_frame_main(FFDualInputContext *s, AVFilterLink *inlink, AVFrame *in);
int ff_dualinput_filter_frame_second(FFDualInputContext *s, AVFilterLink *inlink, AVFrame *in);
int ff_dualinput_request_frame(FFDualInputContext *s, AVFilterLink *outlink);
diff --git a/libavfilter/vf_blend.c b/libavfilter/vf_blend.c
index 959fcad..f0552c8 100644
--- a/libavfilter/vf_blend.c
+++ b/libavfilter/vf_blend.c
@@ -368,6 +368,7 @@ static int config_output(AVFilterLink *outlink)
AVFilterLink *bottomlink = ctx->inputs[BOTTOM];
BlendContext *b = ctx->priv;
const AVPixFmtDescriptor *pix_desc = av_pix_fmt_desc_get(toplink->format);
+ int ret;
if (toplink->format != bottomlink->format) {
av_log(ctx, AV_LOG_ERROR, "inputs must be of same pixel format\n");
@@ -399,6 +400,9 @@ static int config_output(AVFilterLink *outlink)
b->vsub = pix_desc->log2_chroma_h;
b->nb_planes = av_pix_fmt_count_planes(toplink->format);
+ if ((ret = ff_dualinput_init(ctx, &b->dinput)) < 0)
+ return ret;
+
return 0;
}
diff --git a/libavfilter/vf_lut3d.c b/libavfilter/vf_lut3d.c
index 48002b8..dd7f381 100644
--- a/libavfilter/vf_lut3d.c
+++ b/libavfilter/vf_lut3d.c
@@ -656,10 +656,14 @@ static void update_clut(LUT3DContext *lut3d, const AVFrame *frame)
static int config_output(AVFilterLink *outlink)
{
AVFilterContext *ctx = outlink->src;
+ LUT3DContext *lut3d = ctx->priv;
+ int ret;
outlink->w = ctx->inputs[0]->w;
outlink->h = ctx->inputs[0]->h;
outlink->time_base = ctx->inputs[0]->time_base;
+ if ((ret = ff_dualinput_init(ctx, &lut3d->dinput)) < 0)
+ return ret;
return 0;
}
diff --git a/libavfilter/vf_overlay.c b/libavfilter/vf_overlay.c
index f3e7891..e4aaa5f 100644
--- a/libavfilter/vf_overlay.c
+++ b/libavfilter/vf_overlay.c
@@ -310,6 +310,11 @@ static int config_input_overlay(AVFilterLink *inlink)
static int config_output(AVFilterLink *outlink)
{
AVFilterContext *ctx = outlink->src;
+ OverlayContext *s = ctx->priv;
+ int ret;
+
+ if ((ret = ff_dualinput_init(ctx, &s->dinput)) < 0)
+ return ret;
outlink->w = ctx->inputs[MAIN]->w;
outlink->h = ctx->inputs[MAIN]->h;
diff --git a/libavfilter/vf_psnr.c b/libavfilter/vf_psnr.c
index ef638ff..8f33141 100644
--- a/libavfilter/vf_psnr.c
+++ b/libavfilter/vf_psnr.c
@@ -255,13 +255,17 @@ static int config_input_ref(AVFilterLink *inlink)
static int config_output(AVFilterLink *outlink)
{
AVFilterContext *ctx = outlink->src;
+ PSNRContext *s = ctx->priv;
AVFilterLink *mainlink = ctx->inputs[0];
+ int ret;
outlink->w = mainlink->w;
outlink->h = mainlink->h;
outlink->time_base = mainlink->time_base;
outlink->sample_aspect_ratio = mainlink->sample_aspect_ratio;
outlink->frame_rate = mainlink->frame_rate;
+ if ((ret = ff_dualinput_init(ctx, &s->dinput)) < 0)
+ return ret;
return 0;
}
--
1.8.4.rc3
More information about the ffmpeg-devel
mailing list