@@ -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