summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2019-10-02 21:27:07 +0200
committerwm4 <wm4@nowhere>2019-10-02 21:27:07 +0200
commit3e02f39087029380d666cfda963084d3952582f8 (patch)
tree4cbc8395fa56cfa278c6086f954aa0ef29d1019f
parent49f9146fe4dfa6fb2e76e59b7e75a99707782dd9 (diff)
downloadmpv-3e02f39087029380d666cfda963084d3952582f8.tar.bz2
mpv-3e02f39087029380d666cfda963084d3952582f8.tar.xz
f_auto_filters: use software conversion if hw deint is not possible
Before this commit, enabling hardware deinterlacing via the "deinterlace" option/property just failed if no hardware deinterlacing was available. An error message was logged, and playback continued without deinterlacing. Change this, and try to copy the hardware surface to memory, and then use yadif. This will have approximately the same effect as --hwdec=auto-copy. Technically it's implemented differently, because changing the hwdec mode is much more convoluted than just inserting a filter for performing the "download". But the low level code for actually performing the download is the same again. Although performance won't be as good as with a hardware deinterlacer (probably), it's more convenient than forcing the user to switch hwdec modes separately. The "deinterlace" property is supposed to be a convenience thing after all. As far as the code architecture goes, it would make sense to auto-insert such a download filter for all software-only filters that need it. However, libavfilter does not tell us what formats a filter supports (isn't that fucking crazy?), so all attempts to work towards this are kind of hopeless. In this case, we merely have hardcoded knowledge that vf_yadif definitely does not support hardware formats. But yes, this sucks ass.
-rw-r--r--filters/f_auto_filters.c35
1 files changed, 28 insertions, 7 deletions
diff --git a/filters/f_auto_filters.c b/filters/f_auto_filters.c
index 55ce7d8523..b94cfabf29 100644
--- a/filters/f_auto_filters.c
+++ b/filters/f_auto_filters.c
@@ -5,8 +5,10 @@
#include "options/m_config.h"
#include "options/options.h"
#include "video/mp_image.h"
+#include "video/mp_image_pool.h"
#include "f_auto_filters.h"
+#include "f_hwtransfer.h"
#include "f_swscale.h"
#include "f_utils.h"
#include "filter.h"
@@ -76,14 +78,33 @@ static void deint_process(struct mp_filter *f)
char *args[] = {"mode", "send_field", NULL};
p->sub.filter =
mp_create_user_filter(f, MP_OUTPUT_CHAIN_VIDEO, "yadif_cuda", args);
- } else if (mp_sws_supports_input(img->imgfmt)) {
- char *args[] = {"mode", "send_field", NULL};
- p->sub.filter =
- mp_create_user_filter(f, MP_OUTPUT_CHAIN_VIDEO, "yadif", args);
} else {
- MP_ERR(f, "no deinterlace filter available for this format\n");
- mp_subfilter_continue(&p->sub);
- return;
+ int sw_format = img->imgfmt;
+
+ if (img->hwctx)
+ sw_format = mp_image_hw_download_get_sw_format(img);
+
+ if (mp_sws_supports_input(sw_format)) {
+ struct mp_filter *subf = mp_bidir_dummy_filter_create(f);
+ struct mp_filter *filters[2] = {0};
+
+ if (sw_format != img->imgfmt) {
+ struct mp_hwdownload *hwd = mp_hwdownload_create(subf);
+ filters[0] = hwd->f;
+ }
+
+ char *args[] = {"mode", "send_field", NULL};
+ filters[1] =
+ mp_create_user_filter(subf, MP_OUTPUT_CHAIN_VIDEO, "yadif", args);
+
+ mp_chain_filters(subf->ppins[0], subf->ppins[1], filters, 2);
+ p->sub.filter = subf;
+ } else {
+ MP_ERR(f, "no deinterlace filter available for format %s\n",
+ mp_imgfmt_to_name(img->imgfmt));
+ mp_subfilter_continue(&p->sub);
+ return;
+ }
}
if (!p->sub.filter)