summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2014-09-18 19:25:46 +0200
committerwm4 <wm4@nowhere>2014-09-18 19:36:27 +0200
commit580cf433bd3713f1c00a612be2d57d5b959e8496 (patch)
tree327fedd77fc0c095009201f6a527b70cdf459e70
parent5c8549ac68c1a8a4921e5f0ea842969aa8072a18 (diff)
downloadmpv-580cf433bd3713f1c00a612be2d57d5b959e8496.tar.bz2
mpv-580cf433bd3713f1c00a612be2d57d5b959e8496.tar.xz
video/filter: allow better dataflow
Consider a filter which turns 1 frame into 2 frames (such as an deinterlacer). Until now, we forced filters to produce all output frames at once. This was done for simplicity. Change the filter API such that a filter can produce frames incrementally.
-rw-r--r--video/filter/vf.c13
-rw-r--r--video/filter/vf.h9
2 files changed, 20 insertions, 2 deletions
diff --git a/video/filter/vf.c b/video/filter/vf.c
index e76d30ea23..f00e9689c6 100644
--- a/video/filter/vf.c
+++ b/video/filter/vf.c
@@ -379,10 +379,19 @@ void vf_add_output_frame(struct vf_instance *vf, struct mp_image *img)
}
}
+static bool vf_has_output_frame(struct vf_instance *vf)
+{
+ if (!vf->num_out_queued && vf->filter_out) {
+ if (vf->filter_out(vf) < 0)
+ MP_ERR(vf, "Error filtering frame.\n");
+ }
+ return vf->num_out_queued > 0;
+}
+
static struct mp_image *vf_dequeue_output_frame(struct vf_instance *vf)
{
struct mp_image *res = NULL;
- if (vf->num_out_queued) {
+ if (vf_has_output_frame(vf)) {
res = vf->out_queued[0];
MP_TARRAY_REMOVE_AT(vf->out_queued, vf->num_out_queued, 0);
}
@@ -445,7 +454,7 @@ int vf_output_frame(struct vf_chain *c, bool eof)
if (r < 0)
return r;
}
- if (cur->num_out_queued)
+ if (vf_has_output_frame(cur))
last = cur;
}
if (!last)
diff --git a/video/filter/vf.h b/video/filter/vf.h
index 71dcb699c2..6f0985293e 100644
--- a/video/filter/vf.h
+++ b/video/filter/vf.h
@@ -75,6 +75,15 @@ typedef struct vf_instance {
// can be used to output delayed or otherwise remaining images.
int (*filter_ext)(struct vf_instance *vf, struct mp_image *mpi);
+ // Produce an output frame. This is called after filter or filter_ext.
+ // You can add 0 or more frames with vf_add_output_frame(). (This allows
+ // distributing the filter load over time -> typically add at most 1 frame.)
+ // If this adds no frame (or is NULL), then the caller assumes that the
+ // filter needs new input.
+ // Return a negative value on error. (No more frames is not an error.)
+ // May be called multiple times, even if the filter gives no output.
+ int (*filter_out)(struct vf_instance *vf);
+
void (*uninit)(struct vf_instance *vf);
char *label;