[MPlayer-dev-eng] [PATCH] factor out panscan etc. calculation from xv, xvmc and direct3d

Reimar Döffinger Reimar.Doeffinger at stud.uni-karlsruhe.de
Wed Feb 11 20:47:45 CET 2009


Hello,
this is mostly due to vo_direct3d and because vo_vdpau needs the same
code.
It adds a function calc_src_dst_rects that returns two rectangles that
specify which part of the video (source) must be scaled onto which part of
the window (destination).
The reason for doing this for xvmc is that it is trivial to add
support for cropping (and xv is changed to keep them at least somewhat
consistent).
After this patch, the only thing that is missing to support cropping is:
a way for the vo to get cropping values (I'd be in favour of a VOCTRL),
fixing up aspect due to the cropping,
fixing the OSD so it does not get cropped as well and
passing the cropping values to calc_src_dst_rects

Greetings,
Reimar Döffinger
-------------- next part --------------
Index: libvo/vo_xv.c
===================================================================
--- libvo/vo_xv.c	(revision 28529)
+++ libvo/vo_xv.c	(working copy)
@@ -106,7 +106,8 @@
 
 static int int_pause;
 
-static uint32_t drwX, drwY;
+static int src_rect[2][2];
+static int dst_rect[2][2];
 static uint32_t max_width = 0, max_height = 0; // zero means: not set
 
 static void (*draw_alpha_fnc) (int x0, int y0, int w, int h,
@@ -158,6 +159,18 @@
 
 static void deallocate_xvimage(int foo);
 
+static void resize(void)
+{
+    calc_src_dst_rects(image_width, image_height, src_rect, dst_rect, NULL);
+    // calculate width and height from start/end
+    src_rect[0][1] -= src_rect[0][0];
+    src_rect[1][1] -= src_rect[1][0];
+    dst_rect[0][1] -= dst_rect[0][0];
+    dst_rect[1][1] -= dst_rect[1][0];
+    vo_x11_clearwindow_part(mDisplay, vo_window, dst_rect[0][1], dst_rect[1][1], 1);
+    vo_xv_draw_colorkey(dst_rect[0][0], dst_rect[1][0], dst_rect[0][1], dst_rect[1][1]);
+}
+
 /*
  * connect to server, create and map window,
  * allocate colors and (shared) memory
@@ -288,18 +301,9 @@
     current_ip_buf = 0;
 
     if ((flags & VOFLAG_FULLSCREEN) && WinID <= 0) vo_fs = 1;
-    vo_calc_drwXY(&drwX, &drwY);
-
-    panscan_calc();
     
-    vo_xv_draw_colorkey(drwX - (vo_panscan_x >> 1),
-                        drwY - (vo_panscan_y >> 1),
-                        vo_dwidth + vo_panscan_x - 1,
-                        vo_dheight + vo_panscan_y - 1);
+    resize();
 
-    mp_msg(MSGT_VO, MSGL_V, "[xv] dx: %d dy: %d dw: %d dh: %d\n", drwX,
-           drwY, vo_dwidth, vo_dheight);
-
     return 0;
 }
 
@@ -371,19 +375,17 @@
     if (Shmem_Flag)
     {
         XvShmPutImage(mDisplay, xv_port, vo_window, vo_gc,
-                      xvi, 0, 0, image_width,
-                      image_height, drwX - (vo_panscan_x >> 1),
-                      drwY - (vo_panscan_y >> 1), vo_dwidth + vo_panscan_x,
-                      vo_dheight + vo_panscan_y,
+                      xvi,
+                      src_rect[0][0], src_rect[1][0], src_rect[0][1], src_rect[1][1],
+                      dst_rect[0][0], dst_rect[1][0], dst_rect[0][1], dst_rect[1][1],
                       False);
     } else
 #endif
     {
         XvPutImage(mDisplay, xv_port, vo_window, vo_gc,
-                   xvi, 0, 0, image_width, image_height,
-                   drwX - (vo_panscan_x >> 1), drwY - (vo_panscan_y >> 1),
-                   vo_dwidth + vo_panscan_x,
-                   vo_dheight + vo_panscan_y);
+                   xvi,
+                   src_rect[0][0], src_rect[1][0], src_rect[0][1], src_rect[1][1],
+                   dst_rect[0][0], dst_rect[1][0], dst_rect[0][1], dst_rect[1][1]);
     }
 }
 
@@ -391,17 +393,9 @@
 {
     int e = vo_x11_check_events(mDisplay);
 
-    if (e & VO_EVENT_RESIZE)
-    {
-        vo_calc_drwXY(&drwX, &drwY);
-    }
-
     if (e & VO_EVENT_EXPOSE || e & VO_EVENT_RESIZE)
     {
-	vo_xv_draw_colorkey(drwX - (vo_panscan_x >> 1),
-			    drwY - (vo_panscan_y >> 1),
-			    vo_dwidth + vo_panscan_x - 1,
-			    vo_dheight + vo_panscan_y - 1);
+        resize();
     }
 
     if ((e & VO_EVENT_EXPOSE || e & VO_EVENT_RESIZE) && int_pause)
@@ -777,14 +772,7 @@
 
                 if (old_y != vo_panscan_y)
                 {
-                    vo_x11_clearwindow_part(mDisplay, vo_window,
-                                            vo_dwidth + vo_panscan_x - 1,
-                                            vo_dheight + vo_panscan_y - 1,
-                                            1);
-		    vo_xv_draw_colorkey(drwX - (vo_panscan_x >> 1),
-					drwY - (vo_panscan_y >> 1),
-					vo_dwidth + vo_panscan_x - 1,
-					vo_dheight + vo_panscan_y - 1);
+                    resize();
                     flip_page();
                 }
             }
Index: libvo/vo_xvmc.c
===================================================================
--- libvo/vo_xvmc.c	(revision 28529)
+++ libvo/vo_xvmc.c	(working copy)
@@ -81,7 +81,6 @@
 
 static int image_width,image_height;
 static int image_format;
-static uint32_t  drwX,drwY;
 
 #define NO_SUBPICTURE      0
 #define OVERLAY_SUBPICTURE 1
@@ -676,12 +675,7 @@
    }
 
    if ((flags & VOFLAG_FULLSCREEN) && WinID <= 0) vo_fs = 1;
-   vo_calc_drwXY(&drwX, &drwY);
 
-   panscan_calc();
-
-   mp_msg(MSGT_VO,MSGL_V, "[xvmc] dx: %d dy: %d dw: %d dh: %d\n",drwX,drwY,vo_dwidth,vo_dheight );
-
 //end vo_xv
 
    /* store image dimesions for displaying */
@@ -950,19 +944,21 @@
 static void put_xvmc_image(struct xvmc_render_state * p_render_surface,
 			   int draw_ck){
 int rez;
-int clipX,clipY,clipW,clipH;
+int src_rect[2][2], dst_rect[2][2];
 int i;
 
    if(p_render_surface == NULL)
       return;
 
-   clipX = drwX-(vo_panscan_x>>1);
-   clipY = drwY-(vo_panscan_y>>1); 
-   clipW = vo_dwidth+vo_panscan_x;
-   clipH = vo_dheight+vo_panscan_y;
+   calc_src_dst_rects(image_width, image_height, src_rect, dst_rect, NULL);
+   // calculate width and height from start/end
+   src_rect[0][1] -= src_rect[0][0];
+   src_rect[1][1] -= src_rect[1][0];
+   dst_rect[0][1] -= dst_rect[0][0];
+   dst_rect[1][1] -= dst_rect[1][0];
    
    if(draw_ck)
-      vo_xv_draw_colorkey(clipX,clipY,clipW,clipH);
+      vo_xv_draw_colorkey(dst_rect[0][0], dst_rect[1][0], dst_rect[0][1], dst_rect[1][1]);
 
    if(benchmark)
       return;
@@ -971,8 +967,8 @@
    int field = top_field_first ? i : i ^ 3;
    rez = XvMCPutSurface(mDisplay, p_render_surface->p_surface, 
                         vo_window,
-                        0, 0, image_width, image_height,
-                        clipX, clipY, clipW, clipH,
+                        src_rect[0][0], src_rect[1][0], src_rect[0][1], src_rect[1][1],
+                        dst_rect[0][0], dst_rect[1][0], dst_rect[0][1], dst_rect[1][1],
                         bob_deinterlace ? field : 3);
                         //p_render_surface_to_show->display_flags);
    if(rez != Success){
@@ -1036,8 +1032,6 @@
    if(e&VO_EVENT_RESIZE)
    {
       e |= VO_EVENT_EXPOSE;
-
-      vo_calc_drwXY(&drwX, &drwY);
    }
    if ( e & VO_EVENT_EXPOSE )
    {
Index: libvo/vo_direct3d.c
===================================================================
--- libvo/vo_direct3d.c	(revision 28529)
+++ libvo/vo_direct3d.c	(working copy)
@@ -147,48 +147,19 @@
  */
 static void calc_fs_rect(void)
 {
-    int scaled_height = 0;
-    int scaled_width  = 0;
+    int src_rect[2][2];
+    int dst_rect[2][2];
+    calc_src_dst_rects(priv->src_width, priv->src_height, src_rect, dst_rect, NULL);
 
-    // set default values
-    priv->fs_movie_rect.left     = 0;
-    priv->fs_movie_rect.right    = vo_dwidth;
-    priv->fs_movie_rect.top      = 0;
-    priv->fs_movie_rect.bottom   = vo_dheight;
-    priv->fs_panscan_rect.left   = 0;
-    priv->fs_panscan_rect.right  = priv->src_width;
-    priv->fs_panscan_rect.top    = 0;
-    priv->fs_panscan_rect.bottom = priv->src_height;
-    if (!vo_fs)
-        return;
+    priv->fs_movie_rect.left     = dst_rect[0][0];
+    priv->fs_movie_rect.right    = dst_rect[0][1];
+    priv->fs_movie_rect.top      = dst_rect[1][0];
+    priv->fs_movie_rect.bottom   = dst_rect[1][1];
+    priv->fs_panscan_rect.left   = src_rect[0][0];
+    priv->fs_panscan_rect.right  = src_rect[0][1];
+    priv->fs_panscan_rect.top    = src_rect[1][0];
+    priv->fs_panscan_rect.bottom = src_rect[1][1];
 
-    // adjust for fullscreen aspect and panscan
-    aspect(&scaled_width, &scaled_height, A_ZOOM);
-    panscan_calc();
-    scaled_width  += vo_panscan_x;
-    scaled_height += vo_panscan_y;
-
-    // note: border is rounded to a multiple of two since at least
-    // ATI drivers can not handle odd values with YV12 input
-    if (scaled_width > vo_dwidth) {
-        int border = priv->src_width * (scaled_width - vo_dwidth) / scaled_width;
-        border = (border / 2 + 1) & ~1;
-        priv->fs_panscan_rect.left   = border;
-        priv->fs_panscan_rect.right  = priv->src_width - border;
-    } else {
-        priv->fs_movie_rect.left     = (vo_dwidth - scaled_width) / 2;
-        priv->fs_movie_rect.right    = priv->fs_movie_rect.left + scaled_width;
-    }
-    if (scaled_height > vo_dheight) {
-        int border = priv->src_height * (scaled_height - vo_dheight) / scaled_height;
-        border = (border / 2 + 1) & ~1;
-        priv->fs_panscan_rect.top    = border;
-        priv->fs_panscan_rect.bottom = priv->src_height - border;
-    } else {
-        priv->fs_movie_rect.top      = (vo_dheight - scaled_height) / 2;
-        priv->fs_movie_rect.bottom   = priv->fs_movie_rect.top + scaled_height;
-    }
-
     mp_msg(MSGT_VO, MSGL_V,
            "<vo_direct3d>Fullscreen movie rectangle: t: %ld, l: %ld, r: %ld, b:%ld\n",
            priv->fs_movie_rect.top,   priv->fs_movie_rect.left,
Index: libvo/video_out.c
===================================================================
--- libvo/video_out.c	(revision 28529)
+++ libvo/video_out.c	(working copy)
@@ -355,6 +371,58 @@
   return map->to;
 }
 
+/**
+ * \brief helper function for the kind of panscan-scaling that needs a source
+ *        and destination rectangle like Direct3D and VDPAU
+ */
+static void src_dst_split_scaling(int src_size, int dst_size, int scaled_src_size,
+                                  int src[2], int dst[2]) {
+  if (scaled_src_size > dst_size) {
+    int border = src_size * (scaled_src_size - dst_size) / scaled_src_size;
+    // round to a multiple of 2, this is at least needed for vo_direct3d and ATI cards
+    border = (border / 2 + 1) & ~1;
+    src[0] = border;
+    src[1] = src_size - border;
+    dst[0] = 0;
+    dst[1] = dst_size;
+  } else {
+    src[0] = 0;
+    src[1] = src_size;
+    dst[0] = (dst_size - scaled_src_size) / 2;
+    dst[1] = dst[0] + scaled_src_size;
+  }
+}
+
+/**
+ * Calculate the appropriate source and destination rectangle to
+ * get a correctly scaled picture, including pan-scan.
+ * Can be extended to take future cropping support into account.
+ */
+void calc_src_dst_rects(int src_width, int src_height, int src[2][2], int dst[2][2], int crop[2][2]) {
+  static const int no_crop[2][2] = {{0, 0}, {0, 0}};
+  int scaled_width  = 0;
+  int scaled_height = 0;
+  if (!crop) crop = no_crop;
+  src_width  -= crop[0][0] + crop[0][1];
+  src_height -= crop[1][0] + crop[1][1];
+  if (src_width  < 2) src_width  = 2;
+  if (src_height < 2) src_height = 2;
+  dst[0][0] = 0; dst[0][1] = vo_dwidth;
+  dst[1][0] = 0; dst[1][1] = vo_dheight;
+  src[0][0] = 0; src[0][1] = src_width;
+  src[1][0] = 0; src[1][1] = src_height;
+  if (vo_fs) {
+    aspect(&scaled_width, &scaled_height, A_ZOOM);
+    panscan_calc();
+    scaled_width  += vo_panscan_x;
+    scaled_height += vo_panscan_y;
+    src_dst_split_scaling(src_width, vo_dwidth, scaled_width, src[0], dst[0]);
+    src_dst_split_scaling(src_height, vo_dheight, scaled_height, src[1], dst[1]);
+  }
+  src[0][0] += crop[0][0]; src[0][1] += crop[0][0];
+  src[1][0] += crop[1][0]; src[1][1] += crop[1][0];
+}
+
 #if defined(CONFIG_FBDEV) || defined(CONFIG_VESA)
 /* Borrowed from vo_fbdev.c
 Monitor ranges related functions*/
Index: libvo/video_out.h
===================================================================
--- libvo/video_out.h	(revision 28529)
+++ libvo/video_out.h	(working copy)
@@ -269,5 +276,6 @@
   int to;
 };
 int lookup_keymap_table(const struct keymap *map, int key);
+void calc_src_dst_rects(int src_width, int src_height, int src[2][2], int dst[2][2], int crop[2][2]);
 
 #endif /* MPLAYER_VIDEO_OUT_H */


More information about the MPlayer-dev-eng mailing list