[vlc-devel] [PATCH] vdpau: reorient video

Felix Abecassis felix.abecassis at gmail.com
Fri Jun 6 19:21:54 CEST 2014


---
 modules/hw/vdpau/display.c | 55 ++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 53 insertions(+), 2 deletions(-)

diff --git a/modules/hw/vdpau/display.c b/modules/hw/vdpau/display.c
index 1206cdc..0bed9af 100644
--- a/modules/hw/vdpau/display.c
+++ b/modules/hw/vdpau/display.c
@@ -65,6 +65,7 @@ struct vout_display_sys_t
     VdpPresentationQueueTarget target; /**< VDPAU presentation queue target */
     VdpPresentationQueue queue; /**< VDPAU presentation queue */
     VdpRGBAFormat rgb_fmt; /**< Output surface format */
+    VdpOutputSurface render_surface; /**< displayed surface */
 
     picture_pool_t *pool; /**< pictures pool */
 };
@@ -241,6 +242,17 @@ out:/* Destroy GPU surface */
     vdp_bitmap_surface_destroy(sys->vdp, surface);
 }
 
+static uint32_t GetVDPAURotation(const video_format_t *fmt)
+{
+    switch (fmt->orientation)
+    {
+    case ORIENT_ROTATED_90: return VDP_OUTPUT_SURFACE_RENDER_ROTATE_90;
+    case ORIENT_ROTATED_180: return VDP_OUTPUT_SURFACE_RENDER_ROTATE_180;
+    case ORIENT_ROTATED_270: return VDP_OUTPUT_SURFACE_RENDER_ROTATE_270;
+    default: return VDP_OUTPUT_SURFACE_RENDER_ROTATE_0;
+    }
+}
+
 static void Queue(vout_display_t *vd, picture_t *pic, subpicture_t *subpic)
 {
     vout_display_sys_t *sys = vd->sys;
@@ -254,10 +266,22 @@ static void Queue(vout_display_t *vd, picture_t *pic, subpicture_t *subpic)
     if (err == VDP_STATUS_OK && status != VDP_PRESENTATION_QUEUE_STATUS_IDLE)
         msg_Dbg(vd, "surface status: %u", status);
 
+    /* Composite the picture into the entire rendering surface and
+     * apply the rotation if needed. */
+    int rotation_flag = GetVDPAURotation(&vd->fmt);
+    err = vdp_output_surface_render_output_surface(sys->vdp, sys->render_surface, NULL,
+                                                   surface, NULL, NULL, NULL, rotation_flag);
+    if (err != VDP_STATUS_OK)
+    {
+        msg_Err(vd, "composition to render surface failure: %s",
+                vdp_get_error_string(sys->vdp, err));
+        return;
+    }
+
     if (subpic != NULL)
         for (subpicture_region_t *r = subpic->p_region; r != NULL;
              r = r->p_next)
-            RenderRegion(vd, surface, subpic, r);
+            RenderRegion(vd, sys->render_surface, subpic, r);
 
     /* Compute picture presentation time */
     mtime_t now = mdate();
@@ -284,7 +308,7 @@ static void Queue(vout_display_t *vd, picture_t *pic, subpicture_t *subpic)
     pts += delay * 1000;
 
     /* Queue picture */
-    err = vdp_presentation_queue_display(sys->vdp, sys->queue, surface, 0, 0,
+    err = vdp_presentation_queue_display(sys->vdp, sys->queue, sys->render_surface, 0, 0,
                                          pts);
     if (err != VDP_STATUS_OK)
         msg_Err(vd, "presentation queue display failure: %s",
@@ -356,6 +380,23 @@ static int Control(vout_display_t *vd, int query, va_list ap)
                              XCB_CONFIG_WINDOW_X|XCB_CONFIG_WINDOW_Y|
                              XCB_CONFIG_WINDOW_WIDTH|XCB_CONFIG_WINDOW_HEIGHT,
                              values);
+
+        VdpOutputSurface new_surface;
+        VdpStatus err = vdp_output_surface_create(sys->vdp, sys->device, sys->rgb_fmt,
+                                                  fmt->i_visible_width, fmt->i_visible_height,
+                                                  &new_surface);
+        if (err != VDP_STATUS_OK)
+        {
+            /* If allocation of the new surface failed, keep the old one. */
+            msg_Err(vd, "%s creation failure: %s", "render surface",
+                    vdp_get_error_string(sys->vdp, err));
+        }
+        else
+        {
+            vdp_output_surface_destroy(sys->vdp, sys->render_surface);
+            sys->render_surface = new_surface;
+        }
+
         break;
     }
     case VOUT_DISPLAY_CHANGE_FULLSCREEN:
@@ -636,6 +677,16 @@ static int Open(vlc_object_t *obj)
             spu_chromas = subpicture_chromas;
     }
 
+    err = vdp_output_surface_create(sys->vdp, sys->device, sys->rgb_fmt,
+                                    vd->fmt.i_visible_width, vd->fmt.i_visible_height,
+                                    &sys->render_surface);
+    if (err != VDP_STATUS_OK)
+    {
+        msg_Err(vd, "%s creation failure: %s", "render surface",
+                vdp_get_error_string(sys->vdp, err));
+        goto error;
+    }
+
     /* Initialize VDPAU queue */
     err = vdp_presentation_queue_target_create_x11(sys->vdp, sys->device,
                                                    sys->window, &sys->target);
-- 
1.9.1




More information about the vlc-devel mailing list