Skip to content

Commit 3b17ea0

Browse files
committed
vo_gpu_next: use shader deinterlacer instead of software bwdif
1 parent 8dd72bf commit 3b17ea0

4 files changed

Lines changed: 50 additions & 4 deletions

File tree

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
add `--deinterlace-algorithm` option

DOCS/man/options.rst

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1780,9 +1780,11 @@ Video
17801780
``--deinterlace=<yes|no|auto>``
17811781
Enable or disable deinterlacing (default: no).
17821782
Interlaced video shows ugly comb-like artifacts, which are visible on
1783-
fast movement. Enabling this typically inserts the bwdif video filter in
1784-
order to deinterlace the video, or lets the video output apply deinterlacing
1785-
if supported.
1783+
fast movement. Enabling this inserts the hardware deinterlacing filter if
1784+
``--hwdec`` is used, otherwise the video output applies deinterlacing. If
1785+
neither is possible, a software bwdif filter is used instead. The
1786+
``--deinterlace-algorithm`` option can be used to select the deinterlacing
1787+
algorithm used by the video output (``gpu-next`` only).
17861788

17871789
When using ``auto``, mpv will insert a deinterlacing filter if ffmpeg
17881790
detects that the video frame is interlaced. Be aware that there can be false
@@ -6212,6 +6214,12 @@ them.
62126214
Among these kernels, ``burkes`` achieves a good balance between performance
62136215
and quality, and probably is the one you want to try first.
62146216

6217+
``--deinterlace-algorithm=<weave|bob|yadif|bwdif>``
6218+
Sets the deinterlacing algorithm to use when the VO is doing deinterlacing.
6219+
Currently only ``gpu-next`` supports this.
6220+
6221+
Default: ``bwdif``.
6222+
62156223
``--gpu-debug``
62166224
Enables GPU debugging. What this means depends on the API type. For OpenGL,
62176225
it calls ``glGetError()``, and requests a debug context. For Vulkan, it

filters/f_auto_filters.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ static void deint_process(struct mp_filter *f)
9595
field_parity = "auto";
9696
}
9797

98+
struct mp_stream_info *info = mp_filter_find_stream_info(f);
9899
bool has_filter = true;
99100
if (img->imgfmt == IMGFMT_VDPAU) {
100101
char *args[] = {"deint", "yes",
@@ -126,6 +127,11 @@ static void deint_process(struct mp_filter *f)
126127
"parity", field_parity, NULL};
127128
p->sub.filter =
128129
mp_create_user_filter(f, MP_OUTPUT_CHAIN_VIDEO, "vavpp", args);
130+
} else if (info && info->deinterlace && !IMGFMT_IS_HWACCEL(img->imgfmt)) {
131+
char *args[] = {"interlaced-only", opts->deinterlace == 1 ? "no" : "yes",
132+
"parity", field_parity, NULL};
133+
p->sub.filter = mp_create_user_filter(f, MP_OUTPUT_CHAIN_VIDEO,
134+
"fieldrate", args);
129135
} else {
130136
has_filter = false;
131137
}

video/out/vo_gpu_next.c

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ struct priv {
147147
pl_options pars;
148148
struct m_config_cache *opts_cache;
149149
struct m_config_cache *next_opts_cache;
150+
struct m_config_cache *filter_opts_cache;
150151
struct gl_next_opts *next_opts;
151152
struct cache shader_cache, icc_cache;
152153
struct mp_csp_equalizer_state *video_eq;
@@ -180,6 +181,7 @@ struct gl_next_opts {
180181
float background_blur_radius;
181182
float corner_rounding;
182183
bool inter_preserve;
184+
int deint_algo;
183185
struct user_lut lut;
184186
struct user_lut image_lut;
185187
struct user_lut target_lut;
@@ -213,6 +215,11 @@ const struct m_sub_options gl_next_conf = {
213215
{"background-blur-radius", OPT_FLOAT(background_blur_radius)},
214216
{"corner-rounding", OPT_FLOAT(corner_rounding), M_RANGE(0, 1)},
215217
{"interpolation-preserve", OPT_BOOL(inter_preserve)},
218+
{"deinterlace-algorithm", OPT_CHOICE(deint_algo,
219+
{"weave", PL_DEINTERLACE_WEAVE},
220+
{"bob", PL_DEINTERLACE_BOB},
221+
{"yadif", PL_DEINTERLACE_YADIF},
222+
{"bwdif", PL_DEINTERLACE_BWDIF})},
216223
{"lut", OPT_STRING(lut.opt), .flags = M_OPT_FILE},
217224
{"lut-type", OPT_CHOICE_C(lut.type, lut_types)},
218225
{"image-lut", OPT_STRING(image_lut.opt), .flags = M_OPT_FILE},
@@ -228,6 +235,7 @@ const struct m_sub_options gl_next_conf = {
228235
.defaults = &(struct gl_next_opts) {
229236
.border_background = BACKGROUND_COLOR,
230237
.background_blur_radius = 16.0f,
238+
.deint_algo = PL_DEINTERLACE_BWDIF,
231239
.inter_preserve = true,
232240
.sub_hdr_peak = PL_COLOR_SDR_WHITE,
233241
.image_subs_hdr_peak = 1000,
@@ -890,6 +898,7 @@ static void update_options(struct vo *vo)
890898
pl_options pars = p->pars;
891899
bool changed = m_config_cache_update(p->opts_cache);
892900
changed = m_config_cache_update(p->next_opts_cache) || changed;
901+
changed = m_config_cache_update(p->filter_opts_cache) || changed;
893902
if (changed)
894903
update_render_options(vo);
895904

@@ -1143,13 +1152,29 @@ static bool draw_frame(struct vo *vo, struct vo_frame *frame)
11431152
mpi->priv = fp;
11441153
fp->vo = vo;
11451154

1155+
bool use_fields = params.deinterlace_params &&
1156+
mpi->fields & MP_IMGFIELD_INTERLACED;
1157+
1158+
// vf_fieldrate emits a frame for each field only to make mpv render
1159+
// at the second field PTS. But don't actually push it to pl_queue,
1160+
// because it already derives it internally from first_field.
1161+
if (use_fields && (mpi->fields & MP_IMGFIELD_TICK_SECOND)) {
1162+
talloc_free(mpi);
1163+
p->last_id = id;
1164+
continue;
1165+
}
1166+
int first_field = !use_fields ? PL_FIELD_NONE :
1167+
(mpi->fields & MP_IMGFIELD_TOP_FIRST) ? PL_FIELD_TOP : PL_FIELD_BOTTOM;
1168+
11461169
pl_queue_push(p->queue, &(struct pl_source_frame) {
11471170
.pts = mpi->pts,
1148-
.duration = can_interpolate ? frame->approx_duration : 0,
1171+
.duration = can_interpolate ? frame->approx_duration :
1172+
use_fields ? mpi->pkt_duration : 0,
11491173
.frame_data = mpi,
11501174
.map = map_frame,
11511175
.unmap = unmap_frame,
11521176
.discard = discard_frame,
1177+
.first_field = first_field,
11531178
});
11541179

11551180
p->last_id = id;
@@ -2229,6 +2254,7 @@ static int preinit(struct vo *vo)
22292254
{
22302255
struct priv *p = vo->priv;
22312256
p->opts_cache = m_config_cache_alloc(p, vo->global, &gl_video_conf);
2257+
p->filter_opts_cache = m_config_cache_alloc(p, vo->global, &filter_conf);
22322258
p->next_opts_cache = m_config_cache_alloc(p, vo->global, &gl_next_conf);
22332259
p->next_opts = p->next_opts_cache->opts;
22342260
p->video_eq = mp_csp_equalizer_create(p, vo->global);
@@ -2556,6 +2582,7 @@ static void update_render_options(struct vo *vo)
25562582
struct priv *p = vo->priv;
25572583
pl_options pars = p->pars;
25582584
const struct gl_video_opts *opts = p->opts_cache->opts;
2585+
const struct filter_opts *fopts = p->filter_opts_cache->opts;
25592586
pars->params.background_color[0] = opts->background_color.r / 255.0;
25602587
pars->params.background_color[1] = opts->background_color.g / 255.0;
25612588
pars->params.background_color[2] = opts->background_color.b / 255.0;
@@ -2589,6 +2616,9 @@ static void update_render_options(struct vo *vo)
25892616
pars->params.plane_upscaler = map_scaler(p, SCALER_CSCALE);
25902617
pars->params.frame_mixer = opts->interpolation ? map_scaler(p, SCALER_TSCALE) : NULL;
25912618

2619+
pars->params.deinterlace_params = fopts->deinterlace != 0 ? &pars->deinterlace_params : NULL;
2620+
pars->deinterlace_params.algo = p->next_opts->deint_algo;
2621+
25922622
// Request as many frames as required from the decoder, depending on the
25932623
// speed VPS/FPS ratio libplacebo may need more frames. Request frames up to
25942624
// ratio of 1/2, but only if anti aliasing is enabled.
@@ -2706,6 +2736,7 @@ const struct vo_driver video_out_gpu_next = {
27062736
.caps = VO_CAP_ROTATE90 |
27072737
VO_CAP_FILM_GRAIN |
27082738
VO_CAP_VFLIP |
2739+
VO_CAP_DEINTERLACE |
27092740
0x0,
27102741
.preinit = preinit,
27112742
.query_format = query_format,

0 commit comments

Comments
 (0)