[Mplayer-dev-eng] Patch to make mplayer smarter about aspect ratios

Stephen Davies steve at daviesfam.org
Mon Jun 18 00:05:46 CEST 2001


Hi,

Not sure of the protocol for code submission, but attached is a little
patch to improve mplayer's handling of aspect ratio.

Headline improvements are that:
  - 16:9 (aspect 3) mpeg movies now get the right sized window
    automatically, or are letterboxed for -fs
  - non-square pixel video formats are adjusted for.
  - non-square pixel X display modes are adjusted for
  - -x/-y are still honoured when used with -fs
  - -x/-y/-xy can now have <1 "scale down factors".
  - float parameters can be expressed as rational numbers, ie
    numerator:denominator or numerator/denominator.  Especially
    nice for aspect ratios, eg 4:3, 16:9.

Feature can be turned off in config.h.  Docs included in new DOCS file.

Hope that this is useful/welcome - if it is can it be put into the CVS
source?

Thanks,
Steve

-------------- next part --------------
diff -U3 -N -r main.orig/DOCS/AboutAspectRatio main/DOCS/AboutAspectRatio
--- main.orig/DOCS/AboutAspectRatio	Thu Jan  1 01:00:00 1970
+++ main/DOCS/AboutAspectRatio	Sun Jun 17 22:28:46 2001
@@ -0,0 +1,107 @@
+
+From:		Steve Davies <steve at daviesfam.org>
+Subject:	Aspect Ratio processing in mplayer
+Date:		17th June 2001
+
+
+Hi,
+
+I've added some new functionality to mplayer to get it to handle
+aspect ratios better.  Here's some background, and details on
+my changes.
+
+
+BACKGROUND
+----------
+
+Computer displays - in theory at least - usually have "square pixels".
+That is, each pixel has the same height and width.
+
+For example: computer monitors have an x to y ratio of 4:3.  Standard
+video modes (640x480, 1024x768) have the same ratio of x to y pixels.
+
+Of course you may be using an X mode which doesn't have square pixels.
+If you are, you are probably used to seeing distorted images - X
+programs generally don't take this into account - but mplayer now does.
+
+It's common (usual, even) for digitized video to have non-square
+pixels too.
+
+The most obvious example is anamorphic widescreen DVD - where a 16:9
+ratio picture is encoded at 720x576 pixels.  In this case the pixels
+are 42% wider than they are high.  So, for it to display correctly on
+a screen with square pixels, it needs to be scaled to 1024x576.
+
+But even non-widescreen video files have slightly non-square pixels.
+Standard TV displays have 4:3 aspect.  But non-widescreen DVD is
+encoded at 720x576 - the pixels are 6.67% wider than they are high.
+So this needs to be scaled to 768x576 to avoid putting everyone on a
+diet!
+
+Material encoded for 'SuperVCD' is another example: 4:3 source
+material is encoded at 480x576 - needs to be scaled to 768x576 for
+correct viewing.
+
+Mplayer attempts to make scaling adjustments to correct for all this -
+rescaling to account for non-square pixels both in the input video
+and on the output display.
+
+
+IMPLEMENTATION
+--------------
+
+Here's how I've implemented aspect ratio processing.
+
+First off - if you use the -x and -y options to mplayer then the sizes
+that you give are used with no further adjustment.  This ensures that
+you can always get exactly the size that you want.
+
+The -x and -y options are now honoured with -fs too.  The image will
+set to the size you request and centred on the screen.
+
+Some examples:
+
+  mplayer -x 640 -y 480 filename.mpg	 - 640x480 pixel window used
+  mplayer -x 640 -y 480 -fs filename.mpg - 640x480 image centred fullscreen
+  mplayer -x 1 -y 1 filename.mpg	 - shown pixel-for-pixel same size
+
+If you do not specify the -x or -y options, then aspect ratio
+processing is done to determine the correct size.
+
+To do this, the code needs to know the physical aspect ratio of the
+source video, together with the physical aspect ratio of your output
+display.  That is: the width:height ratio represented by the x and y
+pixels in the input file or on the output display.
+
+By default both are set to 4:3, except for MPEG input files in "aspect
+3" - where 16:9 is used.
+
+The -aspect and -displayaspect parameters can be used to explictly
+pass the aspect ratio of the source video and output display.  You
+might use these if you have a non-MPEG widescreen file, or an unusual
+display mode in X.
+
+In full-screen mode, the code will maximize the image size whilst
+maintaining the physical aspect ratio.  In non-full-screen mode, the x
+size will be scaled to correct the aspect ratio.
+
+The -xy option may be used to scale the overall picture size.
+Fractional scaling can be used to reduce the picture size.
+
+Some examples:
+
+ mplayer file.mpg			- assumes source and destination aspect is 4:3,
+ mplayer -aspect 16:9 file.mpg		- assumes source is 16:9, destination 4:3.
+ mplayer -aspect 16:9 -fs file.mpg	- scales x to be full display width, y is worked
+					  out to provide the right 16:9 image size
+ mplayer -displayaspect 16:9 file.mpg   - you've got a widescreen monitor... <jealous>
+
+
+FINAL NOTES
+-----------
+
+All this only applies for -vo drivers that support scaling.
+
+Questions/bugs to steve at daviesfam.org
+
+					  
\ No newline at end of file
diff -U3 -N -r main.orig/cfg-mplayer.h main/cfg-mplayer.h
--- main.orig/cfg-mplayer.h	Wed Jun 13 22:55:24 2001
+++ main/cfg-mplayer.h	Sun Jun 17 20:47:27 2001
@@ -137,9 +137,17 @@
 	{"forcexv", &sdl_forcexv, CONF_TYPE_FLAG, 0, 0, 1},
 	{"sdla", &sdl_adriver, CONF_TYPE_STRING, 0, 0, 0},
 #endif	
-	{"x", &screen_size_x, CONF_TYPE_INT, CONF_RANGE, 1, 4096},
-	{"y", &screen_size_y, CONF_TYPE_INT, CONF_RANGE, 1, 4096},
-	{"xy", &screen_size_xy, CONF_TYPE_INT, CONF_RANGE, 1, 4096},
+#ifdef DO_ASPECT
+	{"x", &parm_screen_size_x, CONF_TYPE_FLOAT, CONF_RANGE, 0.0, 4096.0},
+	{"y", &parm_screen_size_y, CONF_TYPE_FLOAT, CONF_RANGE, 0.0, 4096.0},
+	{"xy", &parm_screen_size_xy, CONF_TYPE_FLOAT, CONF_RANGE, 0.0, 4096.0},
+	{"aspect", &videoaspect, CONF_TYPE_FLOAT, CONF_RANGE, 0.2, 3.0},
+	{"displayaspect", &displayaspect, CONF_TYPE_FLOAT, CONF_RANGE, 0.2, 3.0},
+#else
+	{"x", &screen_size_x, CONF_TYPE_INT, CONF_RANGE, 0, 4096},
+	{"y", &screen_size_y, CONF_TYPE_INT, CONF_RANGE, 0, 4096},
+	{"xy", &screen_size_xy, CONF_TYPE_INT, CONF_RANGE, 0, 4096},
+#endif
         {"vm", &vidmode, CONF_TYPE_FLAG, 0, 0, 1},
         {"novm", &vidmode, CONF_TYPE_FLAG, 0, 1, 0},
 	{"fs", &fullscreen, CONF_TYPE_FLAG, 0, 0, 1},
diff -U3 -N -r main.orig/cfgparser.c main/cfgparser.c
--- main.orig/cfgparser.c	Mon Jun 11 01:12:09 2001
+++ main/cfgparser.c	Sun Jun 17 21:07:34 2001
@@ -14,6 +14,9 @@
 #include <string.h>
 #include <errno.h>
 
+#include "version.h"
+#include "config.h"
+
 #define ERR_NOT_AN_OPTION	-1
 #define ERR_MISSING_PARAM	-2
 #define ERR_OUT_OF_RANGE	-3
@@ -147,8 +150,16 @@
 				goto err_missing_param;
 
 			tmp_float = strtod(param, &endptr);
+#ifdef RATIOS_FOR_FLOAT_PARAMS
+			if ((*endptr == ':') || (*endptr == '/'))
+			  tmp_float /= strtod(endptr+1, &endptr);
+#endif
 			if (*endptr) {
-				printf("parameter must be a floating point number:\n");
+				printf("parameter must be a floating point number"
+#ifdef RATIOS_FOR_FLOAT_PARAMS
+				       " or a ratio (numerator[:/]denominator)"
+#endif
+				       ":\n");
 				ret = ERR_MISSING_PARAM;
 				goto out;
 			}
diff -U3 -N -r main.orig/configure main/configure
--- main.orig/configure	Fri Jun 15 17:32:21 2001
+++ main/configure	Sun Jun 17 21:08:36 2001
@@ -6,6 +6,10 @@
 #
 # Changes in reversed order:
 #
+# 2001/06/17 by Steve Davies
+# - added RATIOS_FOR_FLOAT_PARAMS and DO_ASPECT to generated config.h,
+#   enabled by default
+#
 # 2001/06/05 by Pontscho
 # - added alsa and esd detection
 #
@@ -1407,6 +1411,21 @@
 cat > $CCONF << EOF
 
 /* -------- Generated by ./configure ----------- */
+
+/* This define enables the parsing of numerator/denominator or
+   numerator:denominator where float parameters are expected.
+   This allows you to say things like "-aspect 4:3" instead of
+   "-aspect 1.3333".  Undefine if you don't want this for some
+   reason */
+#define RATIOS_FOR_FLOAT_PARAMS
+
+
+/* Aspect ratio processing attempts to ensure that your video is
+   displayed with the right x to y ratio.  Read more about that in
+   DOCS/AboutAspectRatio.  Undefine this for the "old behaviour"
+   which just assumed source video and destination display had the
+   same aspect ratio. */
+#define DO_ASPECT
 
 /* Define this to enable avg. byte/sec-based AVI sync method by default:
    (use -bps or -nobps commandline option for run-time method selection)    */
diff -U3 -N -r main.orig/help_mp.h main/help_mp.h
--- main.orig/help_mp.h	Sun Jun  3 06:12:53 2001
+++ main/help_mp.h	Sun Jun 17 20:46:14 2001
@@ -35,7 +35,12 @@
 "    -mc <s/5f>      maximum sync correction per 5 frames (in seconds)\n"
 //"    -afm <1-5>      force audio format  1:MPEG 2:PCM 3:AC3 4:Win32 5:aLaw\n"
 "    -fs -vm -zoom   fullscreen playing options (fullsc,vidmode chg,softscale)\n"
-"    -x <x> -y <y>   scale image to <x> * <y> resolution [if scalable!]\n"
+"    -x <x> -y <y>   scale image to <x> * <y> resolution, <=8 is a scale factor\n"
+"                          [not all vo drivers support scaling!]\n"
+#ifdef DO_ASPECT
+"    -aspect <r>     aspect ratio of video file (default is 4:3)\n"
+"    -displayaspect <r> aspect ratio of display (default is 4:3)\n"
+#endif
 "\n"
 "  Keys:\n"
 "    <-  or  ->      seek backward/forward  10 seconds\n"
diff -U3 -N -r main.orig/mplayer.c main/mplayer.c
--- main.orig/mplayer.c	Wed Jun 13 22:57:36 2001
+++ main/mplayer.c	Sun Jun 17 22:31:01 2001
@@ -432,6 +432,15 @@
 int vidmode=0;
 int softzoom=0;
 int flip=-1;
+
+#ifdef DO_ASPECT
+float parm_screen_size_x=0.0;
+float parm_screen_size_y=0.0;
+float parm_screen_size_xy=0.0;
+float videoaspect = 0.0; //(4.0/3.0);
+float displayaspect = 0.0; //(4.0/3.0);
+float aspectscale; // nett x scaling factor needed to correct aspect ratio
+#endif
 int screen_size_x=0;//SCREEN_SIZE_X;
 int screen_size_y=0;//SCREEN_SIZE_Y;
 int screen_size_xy=0;
@@ -477,6 +486,21 @@
 }
 }
 
+#ifdef DO_ASPECT
+int scale_size(int video_size, float scaling) {
+  //  printf("scale_size %d, %f\n", video_size, scaling);
+  if (scaling == 0.0) {
+    return video_size;
+  }
+  else if (scaling <= 8.0) {
+    return (video_size * scaling);
+  }
+  else {
+    return scaling;
+  }
+}
+#endif
+
 #ifndef HAVE_GUI
  int main(int argc,char* argv[], char *envp[]){
 #else
@@ -1282,10 +1306,83 @@
 
 // ========== Init keyboard FIFO (connection to libvo) ============
 
-make_pipe(&keyb_fifo_get,&keyb_fifo_put);
+   make_pipe(&keyb_fifo_get,&keyb_fifo_put);
 
 // ========== Init display (sh_video->disp_w*sh_video->disp_h/out_fmt) ============
 
+#ifdef DO_ASPECT
+
+// Improved version of scaling calcs that:
+//   1) Supports fractional scaling ratios (including <1)
+//   2) Takes scaling into account for full-screen too
+//   3) Allows for different aspect ratios of source video and destination display,
+//      eg - non-square pixels in input (CCIR601 video), or on output display
+//               Questions to <steve at daviesfam.org>
+
+   if (parm_screen_size_x != 0.0 || parm_screen_size_y != 0.0) {
+     /* If -x and/or -y are specified then they are used as given and that is that */
+     /* this is irrespective of whether -fs or not (a change from previous version) */
+     /* This means that you can always set whatever absolute size you want */
+     /* We do honour -xy too, so -x 2 -xy 2 results in x*4, y*2 */
+     if (parm_screen_size_xy == 0.0) parm_screen_size_xy = 1.0;
+     screen_size_x = scale_size( scale_size(sh_video->disp_w, parm_screen_size_x),
+				 parm_screen_size_xy);
+     screen_size_y = scale_size( scale_size(sh_video->disp_h, parm_screen_size_y),
+				 parm_screen_size_xy);
+     //printf("-x-y: screen_size_x=%d, screen_size_y=%d\n", screen_size_x, screen_size_y);
+   }
+   else {
+     /* No specific -x -y sizes given.  Screen size will be video size scaled by -xy and */
+     /* adjusted to account for aspect ratio differences */
+     /* Aspect ratio given on command line?  Otherwise get from mpeg2, otherwise default */
+     if (videoaspect == 0.0) {
+       // FIXME: Are there other input types that record an aspect ratio?
+       if ((file_format == DEMUXER_TYPE_MPEG_ES || file_format == DEMUXER_TYPE_MPEG_PS)) {
+	 // FIXME: What ARE the other aspect_ratio_information values for MPEG?
+	 videoaspect = (picture->aspect_ratio_information == 3) ? 16.0/9.0 : 4.0/3.0;
+       }
+       else
+	 videoaspect = 4.0/3.0;
+     }
+     // FIXME: Consider getting this from X; though could be issues with this data being wrong...
+     // FIXME: OTOH, it can be set in XF86Config-4, and may help other programs?
+     if (displayaspect == 0.0) displayaspect = 4.0/3.0;
+     /* Remaining factors - -xy, the aspect ratios, and -fs... */
+     printf("videoaspect=%f, displayaspect=%f\n", videoaspect, displayaspect);
+     vo_init(); /* Otherwise vo_screenwidth/height aren't known */
+     /* Calculate "adjustment factor" for x  */
+     aspectscale = videoaspect / ((float)sh_video->disp_w / (float)sh_video->disp_h);
+     aspectscale *= ((float)vo_screenwidth / (float)vo_screenheight) / displayaspect;
+     printf("aspectscale comes out at %f\n", aspectscale);
+     /* Do the sums */
+     if (parm_screen_size_xy != 0.0) {
+       screen_size_x = 0.5 + parm_screen_size_xy * aspectscale * sh_video->disp_w;
+       screen_size_y = 0.5 + parm_screen_size_xy * sh_video->disp_h;
+       /* And that's that - even for -fs: -xy was specified so that's what they get */
+     }
+     else if (fullscreen) {
+       /* Peg x or y to screen size, whichever is the limiting one */
+       if (videoaspect >= displayaspect) {
+	 screen_size_x = vo_screenwidth;
+	 screen_size_y = 0.5 + sh_video->disp_h *
+	   vo_screenwidth / (aspectscale * sh_video->disp_w);
+       }
+       else {
+	 screen_size_y = vo_screenheight;
+	 screen_size_x = 0.5 + aspectscale * sh_video->disp_w *
+	   (float)vo_screenheight / (float)sh_video->disp_h;
+       }
+     }
+     else {
+       screen_size_x = 0.5 + aspectscale * sh_video->disp_w;
+       screen_size_y = sh_video->disp_h;
+     }
+   }
+
+#else
+
+   // Original version follows:
+
 #ifdef X11_FULLSCREEN
    if(fullscreen){
      if(vo_init()){
@@ -1309,6 +1406,8 @@
      if(screen_size_x<=8) screen_size_x*=sh_video->disp_w;
      if(screen_size_y<=8) screen_size_y*=sh_video->disp_h;
    }
+
+#endif /* DO_ASPECT */
 
    { const vo_info_t *info = video_out->get_info();
      printf("VO: [%s] %dx%d => %dx%d %s%s%s%s ",info->short_name,
diff -U3 -N -r main.orig/mplayer.h main/mplayer.h
--- main.orig/mplayer.h	Mon Jun  4 19:41:34 2001
+++ main/mplayer.h	Sat Jun 16 23:26:08 2001
@@ -46,6 +46,13 @@
 extern int fullscreen;
 extern int vidmode;
 extern int softzoom;
+#ifdef DO_ASPECT
+extern float screen_size_x;//SCREEN_SIZE_X;
+extern float screen_size_y;//SCREEN_SIZE_Y;
+extern float screen_size_xy;
+extern float videoaspect; // Aspect ratio of source video
+extern float displayaspect; // Aspect ratio of display
+#endif
 extern int screen_size_x;//SCREEN_SIZE_X;
 extern int screen_size_y;//SCREEN_SIZE_Y;
 extern int screen_size_xy;
@@ -82,4 +89,4 @@
 extern void parse_cfgfiles( void );
 extern void exit_player(char* how);
 
-#endif
\ No newline at end of file
+#endif


More information about the MPlayer-dev-eng mailing list