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

Reimar Döffinger Reimar.Doeffinger at stud.uni-karlsruhe.de
Thu Feb 12 11:49:59 CET 2009


On Wed, Feb 11, 2009 at 08:47:45PM +0100, Reimar Döffinger wrote:
> 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

This one uses a struct...

Greetings,
Reimar Döffinger
-------------- next part --------------
Index: libvo/video_out.c
===================================================================
--- libvo/video_out.c	(revision 28529)
+++ libvo/video_out.c	(working copy)
@@ -355,6 +371,66 @@
   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_start, int *src_end, int *dst_start, int *dst_end) {
+  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_start = border;
+    *src_end   = src_size - border;
+    *dst_start = 0;
+    *dst_end   = dst_size;
+  } else {
+    *src_start = 0;
+    *src_end   = src_size;
+    *dst_start = (dst_size - scaled_src_size) / 2;
+    *dst_end   = *dst_start + 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.
+ *
+ * \param crop specifies the cropping border size in the left, right, top and bottom members, may be NULL
+ */
+void calc_src_dst_rects(int src_width, int src_height, struct vo_rect *src, struct vo_rect *dst, struct vo_rect *crop) {
+  static const struct vo_rect no_crop = {0, 0, 0, 0, 0, 0};
+  int scaled_width  = 0;
+  int scaled_height = 0;
+  if (!crop) crop = &no_crop;
+  src_width  -= crop->left + crop->right;
+  src_height -= crop->top  + crop->bottom;
+  if (src_width  < 2) src_width  = 2;
+  if (src_height < 2) src_height = 2;
+  dst->left = 0; dst->right  = vo_dwidth;
+  dst->top  = 0; dst->bottom = vo_dheight;
+  src->left = 0; src->right  = src_width;
+  src->top  = 0; src->bottom = 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->left, &src->right, &dst->left, &dst->right);
+    src_dst_split_scaling(src_height, vo_dheight, scaled_height,
+                          &src->top, &src->bottom, &dst->top, &dst->bottom);
+  }
+  src->left += crop->left; src->right  += crop->left;
+  src->top  += crop->top;  src->bottom += crop->top;
+  src->width  = src->right  - src->left;
+  src->height = src->bottom - src->top;
+  dst->width  = dst->right  - dst->left;
+  dst->height = dst->bottom - dst->top;
+}
+
 #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,9 @@
   int to;
 };
 int lookup_keymap_table(const struct keymap *map, int key);
+struct vo_rect {
+  int left, right, top, bottom, width, height;
+};
+void calc_src_dst_rects(int src_width, int src_height, struct vo_rect *src, struct vo_rect *dst, struct vo_rect *crop);
 
 #endif /* MPLAYER_VIDEO_OUT_H */
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,16 @@
 static void put_xvmc_image(struct xvmc_render_state * p_render_surface,
 			   int draw_ck){
 int rez;
-int clipX,clipY,clipW,clipH;
+struct vo_rect src_rect, dst_rect;
 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);
    
    if(draw_ck)
-      vo_xv_draw_colorkey(clipX,clipY,clipW,clipH);
+      vo_xv_draw_colorkey(dst_rect.left, dst_rect.top, dst_rect.width, dst_rect.height);
 
    if(benchmark)
       return;
@@ -971,8 +962,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.left, src_rect.top, src_rect.width, src_rect.height,
+                        dst_rect.left, dst_rect.top, dst_rect.width, dst_rect.height,
                         bob_deinterlace ? field : 3);
                         //p_render_surface_to_show->display_flags);
    if(rez != Success){
@@ -1036,8 +1027,6 @@
    if(e&VO_EVENT_RESIZE)
    {
       e |= VO_EVENT_EXPOSE;
-
-      vo_calc_drwXY(&drwX, &drwY);
    }
    if ( e & VO_EVENT_EXPOSE )
    {
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 struct vo_rect src_rect;
+static struct vo_rect dst_rect;
 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,13 @@
 
 static void deallocate_xvimage(int foo);
 
+static void resize(void)
+{
+    calc_src_dst_rects(image_width, image_height, &src_rect, &dst_rect, NULL);
+    vo_x11_clearwindow_part(mDisplay, vo_window, dst_rect.width, dst_rect.height, 1);
+    vo_xv_draw_colorkey(dst_rect.left, dst_rect.top, dst_rect.width, dst_rect.height);
+}
+
 /*
  * connect to server, create and map window,
  * allocate colors and (shared) memory
@@ -288,18 +296,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 +370,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.left, src_rect.top, src_rect.width, src_rect.height,
+                      dst_rect.left, dst_rect.top, dst_rect.width, dst_rect.height,
                       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.left, src_rect.top, src_rect.width, src_rect.height,
+                   dst_rect.left, dst_rect.top, dst_rect.width, dst_rect.height);
     }
 }
 
@@ -391,17 +388,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 +767,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_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;
+    struct vo_rect src_rect;
+    struct vo_rect dst_rect;
+    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.left;
+    priv->fs_movie_rect.right    = dst_rect.right;
+    priv->fs_movie_rect.top      = dst_rect.top;
+    priv->fs_movie_rect.bottom   = dst_rect.bottom;
+    priv->fs_panscan_rect.left   = src_rect.left;
+    priv->fs_panscan_rect.right  = src_rect.right;
+    priv->fs_panscan_rect.top    = src_rect.top;
+    priv->fs_panscan_rect.bottom = src_rect.bottom;
 
-    // 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,


More information about the MPlayer-dev-eng mailing list