summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--DOCS/man/en/vf.rst4
-rw-r--r--video/filter/vf_lavfi.c118
-rw-r--r--video/filter/vf_lavfi.h44
3 files changed, 158 insertions, 8 deletions
diff --git a/DOCS/man/en/vf.rst b/DOCS/man/en/vf.rst
index 4c1423f9d2..ab32cd6907 100644
--- a/DOCS/man/en/vf.rst
+++ b/DOCS/man/en/vf.rst
@@ -377,7 +377,7 @@ Available filters are:
Horizontal deblocking on luminance only, and switch vertical
deblocking on or off automatically depending on available CPU time.
-``lavfi=graph[:sws_flags[:o=opts]]``
+``lavfi=graph[:sws-flags[:o=opts]]``
Filter video using FFmpeg's libavfilter.
``<graph>``
@@ -411,7 +411,7 @@ Available filters are:
``'--vf=lavfi=graph="gradfun=radius=30:strength=20,vflip"'``
Same as before, but uses named parameters for everything.
- ``<sws_flags>``
+ ``<sws-flags>``
If libavfilter inserts filters for pixel format conversion, this
option gives the flags which should be passed to libswscale. This
option is numeric and takes a bit-wise combination of ``SWS_`` flags.
diff --git a/video/filter/vf_lavfi.c b/video/filter/vf_lavfi.c
index 74f32a9519..9e064f49d9 100644
--- a/video/filter/vf_lavfi.c
+++ b/video/filter/vf_lavfi.c
@@ -21,6 +21,7 @@
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
+#include <stdarg.h>
#include <assert.h>
#include <libavutil/avstring.h>
@@ -44,6 +45,7 @@
#include "video/sws_utils.h"
#include "video/fmt-conversion.h"
#include "vf.h"
+#include "vf_lavfi.h"
#define IS_LIBAV_FORK (LIBAVFILTER_VERSION_MICRO < 100)
@@ -74,6 +76,10 @@ struct vf_priv_s {
AVRational timebase_out;
AVRational par_in;
+ // for the lw wrapper
+ void *old_priv;
+ void (*lw_recreate_cb)(struct vf_instance *vf);
+
// options
char *cfg_graph;
int64_t cfg_sws_flags;
@@ -120,6 +126,9 @@ static bool recreate_graph(struct vf_instance *vf, int width, int height,
struct vf_priv_s *p = vf->priv;
AVFilterContext *in = NULL, *out = NULL, *f_format = NULL;
+ if (vf->priv->lw_recreate_cb)
+ vf->priv->lw_recreate_cb(vf);
+
if (bstr0(p->cfg_graph).len == 0) {
mp_msg(MSGT_VFILTER, MSGL_FATAL, "lavfi: no filter graph set\n");
return false;
@@ -294,15 +303,20 @@ static int filter_ext(struct vf_instance *vf, struct mp_image *mpi)
return 0;
}
-static int control(vf_instance_t *vf, int request, void *data)
+static void reset(vf_instance_t *vf)
{
struct vf_priv_s *p = vf->priv;
+ if (p->graph) {
+ struct mp_image_params *f = &vf->fmt_in.params;
+ recreate_graph(vf, f->w, f->h, f->d_w, f->d_h, f->imgfmt);
+ }
+}
+
+static int control(vf_instance_t *vf, int request, void *data)
+{
switch (request) {
case VFCTRL_SEEK_RESET:
- if (p->graph) {
- struct mp_image_params *f = &vf->fmt_in.params;
- recreate_graph(vf, f->w, f->h, f->d_w, f->d_h, f->imgfmt);
- }
+ reset(vf);
break;
}
return vf_next_control(vf, request, data);
@@ -317,8 +331,10 @@ static void uninit(struct vf_instance *vf)
static int vf_open(vf_instance_t *vf, char *args)
{
+ vf->reconfig = NULL;
vf->config = config;
vf->filter_ext = filter_ext;
+ vf->filter = NULL;
vf->query_format = query_format;
vf->control = control;
vf->uninit = uninit;
@@ -367,7 +383,7 @@ static void print_help(void)
#define OPT_BASE_STRUCT struct vf_priv_s
static const m_option_t vf_opts_fields[] = {
OPT_STRING("graph", cfg_graph, M_OPT_MIN, .min = 1),
- OPT_INT64("sws_flags", cfg_sws_flags, 0),
+ OPT_INT64("sws-flags", cfg_sws_flags, 0),
OPT_STRING("o", cfg_avopts, 0),
{0}
};
@@ -381,3 +397,93 @@ const vf_info_t vf_info_lavfi = {
.options = vf_opts_fields,
.print_help = print_help,
};
+
+// The following code is for the old filters wrapper code.
+
+struct vf_lw_opts {
+ int enable;
+ int64_t sws_flags;
+ char *avopts;
+};
+
+#undef OPT_BASE_STRUCT
+#define OPT_BASE_STRUCT struct vf_lw_opts
+const struct m_sub_options vf_lw_conf = {
+ .opts = (const m_option_t[]) {
+ OPT_FLAG("lavfi", enable, 0),
+ OPT_INT64("lavfi-sws-flags", sws_flags, 0),
+ OPT_STRING("lavfi-o", avopts, 0),
+ {0}
+ },
+ .defaults = &(const struct vf_lw_opts){
+ .enable = 1,
+ .sws_flags = SWS_BICUBIC,
+ },
+ .size = sizeof(struct vf_lw_opts),
+};
+
+static bool have_filter(const char *name)
+{
+ for (const AVFilter *filter = avfilter_next(NULL); filter;
+ filter = avfilter_next(filter))
+ {
+ if (strcmp(filter->name, name) == 0)
+ return true;
+ }
+ return false;
+}
+
+// This is used by "old" filters for wrapping lavfi if possible.
+// On success, this overwrites all vf callbacks and literally takes over the
+// old filter and replaces it with vf_lavfi.
+// On error (<0), nothing is changed.
+int vf_lw_set_graph(struct vf_instance *vf, struct vf_lw_opts *lavfi_opts,
+ char *filter, char *opts, ...)
+{
+ if (!lavfi_opts)
+ lavfi_opts = (struct vf_lw_opts *)vf_lw_conf.defaults;
+ if (!lavfi_opts->enable || !have_filter(filter))
+ return -1;
+ mp_msg(MSGT_VFILTER, MSGL_V, "Using libavfilter for '%s'\n", vf->info->name);
+ void *old_priv = vf->priv;
+ struct vf_priv_s *p = talloc(vf, struct vf_priv_s);
+ vf->priv = p;
+ *p = vf_priv_dflt;
+ p->cfg_sws_flags = lavfi_opts->sws_flags;
+ p->cfg_avopts = lavfi_opts->avopts;
+ va_list ap;
+ va_start(ap, opts);
+ char *s = talloc_vasprintf(vf, opts, ap);
+ p->cfg_graph = talloc_asprintf(vf, "%s=%s", filter, s);
+ talloc_free(s);
+ va_end(ap);
+ p->old_priv = old_priv;
+ // Note: we should be sure vf_open really overwrites _all_ vf callbacks.
+ if (vf_open(vf, NULL) < 1)
+ abort();
+ return 1;
+}
+
+void *vf_lw_old_priv(struct vf_instance *vf)
+{
+ struct vf_priv_s *p = vf->priv;
+ return p->old_priv;
+}
+
+void vf_lw_update_graph(struct vf_instance *vf, char *filter, char *opts, ...)
+{
+ struct vf_priv_s *p = vf->priv;
+ va_list ap;
+ va_start(ap, opts);
+ char *s = talloc_vasprintf(vf, opts, ap);
+ talloc_free(p->cfg_graph);
+ p->cfg_graph = talloc_asprintf(vf, "%s=%s", filter, s);
+ talloc_free(s);
+ va_end(ap);
+}
+
+void vf_lw_set_recreate_cb(struct vf_instance *vf,
+ void (*recreate)(struct vf_instance *vf))
+{
+ vf->priv->lw_recreate_cb = recreate;
+}
diff --git a/video/filter/vf_lavfi.h b/video/filter/vf_lavfi.h
new file mode 100644
index 0000000000..45765d9dea
--- /dev/null
+++ b/video/filter/vf_lavfi.h
@@ -0,0 +1,44 @@
+#ifndef MP_VF_LAVFI_H_
+#define MP_VF_LAVFI_H_
+
+#include "config.h"
+
+#include "mpvcore/mp_common.h"
+#include "vf.h"
+
+struct vf_lw_opts;
+
+#if HAVE_VF_LAVFI
+
+extern const struct m_sub_options vf_lw_conf;
+
+int vf_lw_set_graph(struct vf_instance *vf, struct vf_lw_opts *lavfi_opts,
+ char *filter, char *opts, ...) PRINTF_ATTRIBUTE(4,5);
+void *vf_lw_old_priv(struct vf_instance *vf);
+void vf_lw_update_graph(struct vf_instance *vf, char *filter, char *opts, ...)
+ PRINTF_ATTRIBUTE(3,4);
+void vf_lw_set_recreate_cb(struct vf_instance *vf,
+ void (*recreate)(struct vf_instance *vf));
+#else
+static inline
+int vf_lw_set_graph(struct vf_instance *vf, struct vf_lw_opts *lavfi_opts,
+ char *filter, char *opts, ...)
+{
+ return -1;
+}
+static void *vf_lw_old_priv(struct vf_instance *vf)
+{
+ return 0;
+}
+static void vf_lw_update_graph(struct vf_instance *vf, char *filter, char *opts, ...)
+{
+}
+static void vf_lw_set_recreate_cb(struct vf_instance *vf,
+ void (*recreate)(struct vf_instance *vf))
+{
+}
+#include "mpvcore/m_option.h"
+static const struct m_sub_options vf_lw_conf = {0};
+#endif
+
+#endif