[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