From d752f743fffa2440361f7b7ebb0930c173286644 Mon Sep 17 00:00:00 2001 From: wm4 Date: Wed, 29 Nov 2017 18:04:26 +0100 Subject: vf: add vf_convert as interim replacement for vf_scale We want to drop vf_scale, but we still need a way to auto convert between imgfmts. In particular, vf.c will auto insert the "scale" filter if the VO doesn't support a pixfmt. To avoid chaos, create a new vf_convert.c filter, based on vf_scale.c, but without the unrelicensed code parts. In particular, this filter does not do scaling and has no options. It merely converts from one imgfmt to another, if needed. --- video/filter/vf.c | 6 ++- video/filter/vf_convert.c | 128 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 132 insertions(+), 2 deletions(-) create mode 100644 video/filter/vf_convert.c (limited to 'video') diff --git a/video/filter/vf.c b/video/filter/vf.c index c2fc4f716a..6e2cb251e0 100644 --- a/video/filter/vf.c +++ b/video/filter/vf.c @@ -53,6 +53,7 @@ extern const vf_info_t vf_info_pullup; extern const vf_info_t vf_info_sub; extern const vf_info_t vf_info_yadif; extern const vf_info_t vf_info_stereo3d; +extern const vf_info_t vf_info_convert; extern const vf_info_t vf_info_lavfi; extern const vf_info_t vf_info_lavfi_bridge; extern const vf_info_t vf_info_vaapi; @@ -81,6 +82,7 @@ static const vf_info_t *const filter_list[] = { &vf_info_sub, #endif + &vf_info_convert, &vf_info_lavfi, &vf_info_lavfi_bridge, &vf_info_buffer, @@ -553,7 +555,7 @@ static void query_formats(uint8_t *fmts, struct vf_instance *vf) static bool is_conv_filter(struct vf_instance *vf) { - return vf && (strcmp(vf->info->name, "scale") == 0 || vf->autoinserted); + return vf && (strcmp(vf->info->name, "convert") == 0 || vf->autoinserted); } static const char *find_conv_filter(uint8_t *fmts_in, uint8_t *fmts_out) @@ -569,7 +571,7 @@ static const char *find_conv_filter(uint8_t *fmts_in, uint8_t *fmts_out) } } } - return "scale"; + return "convert"; } static void update_formats(struct vf_chain *c, struct vf_instance *vf, diff --git a/video/filter/vf_convert.c b/video/filter/vf_convert.c new file mode 100644 index 0000000000..d7b4c21e56 --- /dev/null +++ b/video/filter/vf_convert.c @@ -0,0 +1,128 @@ +/* + * This file is part of mpv. + * + * mpv is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * mpv is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with mpv. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "common/av_common.h" +#include "common/msg.h" + +#include "options/options.h" + +#include "video/img_format.h" +#include "video/mp_image.h" +#include "video/sws_utils.h" +#include "video/fmt-conversion.h" +#include "vf.h" + +struct vf_priv_s { + struct mp_sws_context *sws; +}; + +static int find_best_out(vf_instance_t *vf, int in_format) +{ + int best = 0; + for (int out_format = IMGFMT_START; out_format < IMGFMT_END; out_format++) { + if (!vf_next_query_format(vf, out_format)) + continue; + if (sws_isSupportedOutput(imgfmt2pixfmt(out_format)) < 1) + continue; + if (best) { + int candidate = mp_imgfmt_select_best(best, out_format, in_format); + if (candidate) + best = candidate; + } else { + best = out_format; + } + } + return best; +} + +static int reconfig(struct vf_instance *vf, struct mp_image_params *in, + struct mp_image_params *out) +{ + unsigned int best = find_best_out(vf, in->imgfmt); + if (!best) { + MP_WARN(vf, "no supported output format found\n"); + return -1; + } + + *out = *in; + out->imgfmt = best; + + mp_image_params_guess_csp(out); + + mp_sws_set_from_cmdline(vf->priv->sws, vf->chain->opts->vo->sws_opts); + vf->priv->sws->src = *in; + vf->priv->sws->dst = *out; + + if (mp_sws_reinit(vf->priv->sws) < 0) { + // error... + MP_WARN(vf, "Couldn't init libswscale for this setup\n"); + return -1; + } + return 0; +} + +static struct mp_image *filter(struct vf_instance *vf, struct mp_image *mpi) +{ + struct mp_image *dmpi = vf_alloc_out_image(vf); + if (!dmpi) + return NULL; + mp_image_copy_attributes(dmpi, mpi); + + mp_sws_scale(vf->priv->sws, dmpi, mpi); + + talloc_free(mpi); + return dmpi; +} + +static int query_format(struct vf_instance *vf, unsigned int fmt) +{ + if (IMGFMT_IS_HWACCEL(fmt) || sws_isSupportedInput(imgfmt2pixfmt(fmt)) < 1) + return 0; + return !!find_best_out(vf, fmt); +} + +static void uninit(struct vf_instance *vf) +{ +} + +static int vf_open(vf_instance_t *vf) +{ + vf->reconfig = reconfig; + vf->filter = filter; + vf->query_format = query_format; + vf->uninit = uninit; + vf->priv->sws = mp_sws_alloc(vf); + vf->priv->sws->log = vf->log; + return 1; +} + +const vf_info_t vf_info_convert = { + .description = "image format conversion with libswscale", + .name = "convert", + .open = vf_open, + .priv_size = sizeof(struct vf_priv_s), +}; -- cgit v1.2.3