summaryrefslogtreecommitdiffstats
path: root/video
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2013-12-03 22:19:27 +0100
committerwm4 <wm4@nowhere>2013-12-04 00:07:38 +0100
commit25635a62c346f307f5d319a38c444f91b7928d43 (patch)
treebc50ccdcf00dda7cd7ea8a8f8ffb3f8e13196cb8 /video
parent733c2369d3d4a70da934899dce06c61871fd26d4 (diff)
downloadmpv-25635a62c346f307f5d319a38c444f91b7928d43.tar.bz2
mpv-25635a62c346f307f5d319a38c444f91b7928d43.tar.xz
vf_lavfi: export a wrapper function
This will allow old filter to run libavfilter instead by calling vf_lw_set_graph(), which turns the filter into a wrapper, using a given libavfilter graph. Later commits use that to automatically "reroute" a bunch of filters to libavfilter. We want to get rid of the old MPlayer filter code, because it's bad an unmaintained, but we still don't want to force everyone to use vf_lavfi, so this solution will do for a while.
Diffstat (limited to 'video')
-rw-r--r--video/filter/vf_lavfi.c118
-rw-r--r--video/filter/vf_lavfi.h44
2 files changed, 156 insertions, 6 deletions
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