changeset 28933:b0badbd680c6

Initial support for advanced VDPAU deinterlacers (software-decoded video only). With a lot of help from Reimar
author cehoyos
date Sun, 15 Mar 2009 21:20:06 +0000
parents 41aa8200c7c9
children e8c117f5758a
files DOCS/man/en/mplayer.1 libvo/vo_vdpau.c
diffstat 2 files changed, 39 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/DOCS/man/en/mplayer.1	Sun Mar 15 20:40:48 2009 +0000
+++ b/DOCS/man/en/mplayer.1	Sun Mar 15 21:20:06 2009 +0000
@@ -3464,13 +3464,15 @@
 .IPs 1
 Show only first field, similar to \-vf field.
 .IPs 2
-Bob deinterlacing (current fallback for advanced deinterlacers).
+Bob deinterlacing
+(current fallback for advanced deinterlacers and hardware decoding).
 .IPs 3
-Motion adaptive temporal deinterlacing (not yet working).
+Motion adaptive temporal deinterlacing
+(currently only working with software-decoded video).
 This is the default if "D" is used to enable deinterlacing.
 .IPs 4
 Motion adaptive temporal deinterlacing with edge-guided spatial interpolation
-(not yet working).
+(currently only working with software-decoded video).
 .RE
 .IPs pullup
 Try to apply inverse telecine, needs temporal deinterlacing.
--- a/libvo/vo_vdpau.c	Sun Mar 15 20:40:48 2009 +0000
+++ b/libvo/vo_vdpau.c	Sun Mar 15 21:20:06 2009 +0000
@@ -147,11 +147,13 @@
 /* output_surfaces[NUM_OUTPUT_SURFACES] is misused for OSD. */
 #define osd_surface output_surfaces[NUM_OUTPUT_SURFACES]
 static VdpOutputSurface                   output_surfaces[NUM_OUTPUT_SURFACES + 1];
+static VdpVideoSurface                    deint_surfaces[3];
 static int                                output_surface_width, output_surface_height;
 
 static VdpVideoMixer                      video_mixer;
 static int                                deint;
 static int                                deint_type;
+static int                                deint_counter;
 static int                                pullup;
 static float                              denoise;
 static float                              sharpen;
@@ -212,11 +214,9 @@
     VdpTime dummy;
     VdpStatus vdp_st;
     int i;
-    if (vid_surface_num < 0)
+    if (vid_surface_num < 0 || deint_surfaces[0] == VDP_INVALID_HANDLE)
         return;
 
-    // we would need to provide 2 past and 1 future frames to allow advanced
-    // deinterlacing, which is not really possible currently.
     for (i = 0; i <= !!(deint > 1); i++) {
         int field = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME;
         VdpOutputSurface output_surface;
@@ -236,9 +236,10 @@
         CHECK_ST_WARNING("Error when calling vdp_presentation_queue_block_until_surface_idle")
 
         vdp_st = vdp_video_mixer_render(video_mixer, VDP_INVALID_HANDLE, 0,
-                                        field, 0, NULL,
-                                        surface_render[vid_surface_num].surface,
-                                        0, NULL, &src_rect_vid,
+                                        field, 2, deint_surfaces + 1,
+                                        deint_surfaces[0],
+                                        1, &surface_render[vid_surface_num].surface,
+                                        &src_rect_vid,
                                         output_surface,
                                         NULL, &out_rect_vid, 0, NULL);
         CHECK_ST_WARNING("Error when calling vdp_video_mixer_render")
@@ -407,7 +408,6 @@
         &vid_height,
         &vdp_chroma_type
     };
-    if (deint == 3)
         features[feature_count++] = VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL;
     if (deint == 4)
         features[feature_count++] = VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL;
@@ -425,6 +425,8 @@
     CHECK_ST_ERROR("Error when calling vdp_video_mixer_create")
 
     for (i = 0; i < feature_count; i++) feature_enables[i] = VDP_TRUE;
+    if (deint < 3)
+        feature_enables[0] = VDP_FALSE;
     if (feature_count)
         vdp_video_mixer_set_feature_enables(video_mixer, feature_count, features, feature_enables);
     if (denoise)
@@ -472,7 +474,7 @@
     XSetWindowAttributes xswa;
     XWindowAttributes attribs;
     unsigned long xswamask;
-    int depth;
+    int depth, i;
 
 #ifdef CONFIG_XF86VM
     int vm = flags & VOFLAG_MODESWITCHING;
@@ -541,6 +543,9 @@
     vid_surface_num = -1;
     resize();
 
+    for (i = 0; i < 3; i++)
+        deint_surfaces[i] = VDP_INVALID_HANDLE;
+
     return 0;
 }
 
@@ -837,10 +842,12 @@
     if (IMGFMT_IS_VDPAU(image_format)) {
         struct vdpau_render_state *rndr = mpi->priv;
         vid_surface_num = rndr - surface_render;
+        deint = FFMIN(deint, 2);
     } else if (!(mpi->flags & MP_IMGFLAG_DRAW_CALLBACK)) {
         VdpStatus vdp_st;
         void *destdata[3] = {mpi->planes[0], mpi->planes[2], mpi->planes[1]};
-        struct vdpau_render_state *rndr = get_surface(0);
+        struct vdpau_render_state *rndr = get_surface(deint_counter);
+        deint_counter = (deint_counter + 1) & 3;
         vid_surface_num = rndr - surface_render;
         vdp_st = vdp_video_surface_put_bits_y_cb_cr(rndr->surface,
                                                     VDP_YCBCR_FORMAT_YV12,
@@ -850,7 +857,12 @@
     }
     top_field_first = !!(mpi->fields & MP_IMGFIELD_TOP_FIRST);
 
+    if (deint < 3)
+        deint_surfaces[0] = surface_render[vid_surface_num].surface;
     video_to_output_surface();
+    deint_surfaces[2] = deint_surfaces[1];
+    deint_surfaces[1] = deint_surfaces[0];
+    deint_surfaces[0] = surface_render[vid_surface_num].surface;
     return VO_TRUE;
 }
 
@@ -984,6 +996,7 @@
 
     deint = 0;
     deint_type = 3;
+    deint_counter = 0;
     pullup = 0;
     denoise = 0;
     sharpen = 0;
@@ -1087,6 +1100,18 @@
             deint = *(int*)data;
             if (deint)
                 deint = deint_type;
+            if (deint_type > 2) {
+                VdpStatus vdp_st;
+                VdpVideoMixerFeature features[1] =
+                    {deint_type == 3 ?
+                     VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL :
+                     VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL};
+                VdpBool feature_enables[1] = {deint ? VDP_TRUE : VDP_FALSE};
+                vdp_st = vdp_video_mixer_set_feature_enables(video_mixer, 1,
+                                                             features,
+                                                             feature_enables);
+                CHECK_ST_WARNING("Error changing deinterlacing settings")
+            }
             return VO_TRUE;
         case VOCTRL_PAUSE:
             return (int_pause = 1);