@@ -149,6 +149,7 @@ struct priv {
149149 pl_options pars ;
150150 struct m_config_cache * opts_cache ;
151151 struct m_config_cache * next_opts_cache ;
152+ struct m_config_cache * filter_opts_cache ;
152153 struct gl_next_opts * next_opts ;
153154 struct cache shader_cache , icc_cache ;
154155 struct mp_csp_equalizer_state * video_eq ;
@@ -182,6 +183,7 @@ struct gl_next_opts {
182183 float background_blur_radius ;
183184 float corner_rounding ;
184185 bool inter_preserve ;
186+ int deint_algo ;
185187 struct user_lut lut ;
186188 struct user_lut image_lut ;
187189 struct user_lut target_lut ;
@@ -215,6 +217,11 @@ const struct m_sub_options gl_next_conf = {
215217 {"background-blur-radius" , OPT_FLOAT (background_blur_radius )},
216218 {"corner-rounding" , OPT_FLOAT (corner_rounding ), M_RANGE (0 , 1 )},
217219 {"interpolation-preserve" , OPT_BOOL (inter_preserve )},
220+ {"deinterlace-algorithm" , OPT_CHOICE (deint_algo ,
221+ {"weave" , PL_DEINTERLACE_WEAVE },
222+ {"bob" , PL_DEINTERLACE_BOB },
223+ {"yadif" , PL_DEINTERLACE_YADIF },
224+ {"bwdif" , PL_DEINTERLACE_BWDIF })},
218225 {"lut" , OPT_STRING (lut .opt ), .flags = M_OPT_FILE },
219226 {"lut-type" , OPT_CHOICE_C (lut .type , lut_types )},
220227 {"image-lut" , OPT_STRING (image_lut .opt ), .flags = M_OPT_FILE },
@@ -230,6 +237,7 @@ const struct m_sub_options gl_next_conf = {
230237 .defaults = & (struct gl_next_opts ) {
231238 .border_background = BACKGROUND_COLOR ,
232239 .background_blur_radius = 16.0f ,
240+ .deint_algo = PL_DEINTERLACE_BWDIF ,
233241 .inter_preserve = true,
234242 .image_subs_hdr_peak = 1000 ,
235243 .target_hint = -1 ,
@@ -1036,6 +1044,7 @@ static void update_options(struct vo *vo)
10361044 pl_options pars = p -> pars ;
10371045 bool changed = m_config_cache_update (p -> opts_cache );
10381046 changed = m_config_cache_update (p -> next_opts_cache ) || changed ;
1047+ changed = m_config_cache_update (p -> filter_opts_cache ) || changed ;
10391048 if (changed )
10401049 update_render_options (vo );
10411050
@@ -1290,13 +1299,50 @@ static bool draw_frame(struct vo *vo, struct vo_frame *frame)
12901299 mpi -> priv = fp ;
12911300 fp -> vo = vo ;
12921301
1302+ bool is_deinterlacing = params .deinterlace_params &&
1303+ mpi -> fields & MP_IMGFIELD_INTERLACED ;
1304+
1305+ // vf_fieldrate emits a frame for each field only to make mpv render
1306+ // at the second field PTS. But don't actually push it to pl_queue,
1307+ // because it already derives it internally from first_field.
1308+ bool second_tick = is_deinterlacing && (mpi -> fields & MP_IMGFIELD_TICK_SECOND );
1309+ if (second_tick && p -> last_id ) {
1310+ talloc_free (mpi );
1311+ p -> last_id = id ;
1312+ continue ;
1313+ }
1314+ int first_field = !is_deinterlacing ? PL_FIELD_NONE :
1315+ (mpi -> fields & MP_IMGFIELD_TOP_FIRST ) ? PL_FIELD_TOP : PL_FIELD_BOTTOM ;
1316+
1317+ if (!p -> last_id && !second_tick && mpi -> deint_prev ) {
1318+ struct mp_image * prev = mp_image_new_ref (mpi -> deint_prev );
1319+ mp_image_unrefp (& prev -> deint_prev );
1320+ struct frame_priv * prev_fp = talloc_zero (prev , struct frame_priv );
1321+ prev -> priv = prev_fp ;
1322+ prev_fp -> vo = vo ;
1323+ mp_assert (prev -> fields & MP_IMGFIELD_TICK_SECOND );
1324+ pl_queue_push (p -> queue , & (struct pl_source_frame ) {
1325+ .pts = prev -> pts - prev -> pkt_duration / 2 ,
1326+ .duration = prev -> pkt_duration ,
1327+ .frame_data = prev ,
1328+ .map = map_frame ,
1329+ .unmap = unmap_frame ,
1330+ .discard = discard_frame ,
1331+ .first_field = (prev -> fields & MP_IMGFIELD_TOP_FIRST ) ?
1332+ PL_FIELD_TOP : PL_FIELD_BOTTOM ,
1333+ });
1334+ }
1335+ mp_image_unrefp (& mpi -> deint_prev );
1336+
12931337 pl_queue_push (p -> queue , & (struct pl_source_frame ) {
1294- .pts = mpi -> pts ,
1295- .duration = can_interpolate ? frame -> approx_duration : 0 ,
1338+ .pts = second_tick ? mpi -> pts - mpi -> pkt_duration / 2 : mpi -> pts ,
1339+ .duration = can_interpolate ? frame -> approx_duration :
1340+ is_deinterlacing ? mpi -> pkt_duration : 0 ,
12961341 .frame_data = mpi ,
12971342 .map = map_frame ,
12981343 .unmap = unmap_frame ,
12991344 .discard = discard_frame ,
1345+ .first_field = first_field ,
13001346 });
13011347
13021348 p -> last_id = id ;
@@ -2388,6 +2434,7 @@ static int preinit(struct vo *vo)
23882434{
23892435 struct priv * p = vo -> priv ;
23902436 p -> opts_cache = m_config_cache_alloc (p , vo -> global , & gl_video_conf );
2437+ p -> filter_opts_cache = m_config_cache_alloc (p , vo -> global , & filter_conf );
23912438 p -> next_opts_cache = m_config_cache_alloc (p , vo -> global , & gl_next_conf );
23922439 p -> next_opts = p -> next_opts_cache -> opts ;
23932440 p -> video_eq = mp_csp_equalizer_create (p , vo -> global );
@@ -2715,6 +2762,7 @@ static void update_render_options(struct vo *vo)
27152762 struct priv * p = vo -> priv ;
27162763 pl_options pars = p -> pars ;
27172764 const struct gl_video_opts * opts = p -> opts_cache -> opts ;
2765+ const struct filter_opts * fopts = p -> filter_opts_cache -> opts ;
27182766 pars -> params .background_color [0 ] = opts -> background_color .r / 255.0 ;
27192767 pars -> params .background_color [1 ] = opts -> background_color .g / 255.0 ;
27202768 pars -> params .background_color [2 ] = opts -> background_color .b / 255.0 ;
@@ -2748,6 +2796,9 @@ static void update_render_options(struct vo *vo)
27482796 pars -> params .plane_upscaler = map_scaler (p , SCALER_CSCALE );
27492797 pars -> params .frame_mixer = opts -> interpolation ? map_scaler (p , SCALER_TSCALE ) : NULL ;
27502798
2799+ pars -> params .deinterlace_params = fopts -> deinterlace != 0 ? & pars -> deinterlace_params : NULL ;
2800+ pars -> deinterlace_params .algo = p -> next_opts -> deint_algo ;
2801+
27512802 // Request as many frames as required from the decoder, depending on the
27522803 // speed VPS/FPS ratio libplacebo may need more frames. Request frames up to
27532804 // ratio of 1/2, but only if anti aliasing is enabled.
@@ -2756,6 +2807,9 @@ static void update_render_options(struct vo *vo)
27562807 req_frames += ceilf (pars -> params .frame_mixer -> kernel -> radius ) *
27572808 (pars -> params .skip_anti_aliasing ? 1 : 2 );
27582809 }
2810+
2811+ if (pars -> params .deinterlace_params )
2812+ req_frames ++ ;
27592813 vo_set_queue_params (vo , 0 , MPMIN (VO_MAX_REQ_FRAMES , req_frames ));
27602814
27612815 pars -> params .deband_params = opts -> deband ? & pars -> deband_params : NULL ;
@@ -2865,6 +2919,7 @@ const struct vo_driver video_out_gpu_next = {
28652919 .caps = VO_CAP_ROTATE90 |
28662920 VO_CAP_FILM_GRAIN |
28672921 VO_CAP_VFLIP |
2922+ VO_CAP_DEINTERLACE |
28682923 0x0 ,
28692924 .preinit = preinit ,
28702925 .query_format = query_format ,
0 commit comments