[MPlayer-dev-eng] [PATCH] Add support for rotating the video via OpenGL.

Reimar Döffinger Reimar.Doeffinger at gmx.de
Thu May 9 08:59:09 CEST 2013


---
 Changelog             |    2 ++
 DOCS/man/en/mplayer.1 |    7 +++++++
 cfg-mplayer.h         |    1 +
 libvo/aspect.c        |   30 ++++++++++++++++++++++++++----
 libvo/video_out.c     |    1 +
 libvo/video_out.h     |    8 ++++++++
 libvo/vo_gl.c         |   48 +++++++++++++++++++++++++++++++-----------------
 7 files changed, 76 insertions(+), 21 deletions(-)

diff --git a/Changelog b/Changelog
index 1110ace..953edd8 100644
--- a/Changelog
+++ b/Changelog
@@ -9,6 +9,8 @@ MPlayer
     * support for XYZ color space in -vo gl
     * -vo gl now supports OSD (not EOSD though) with GLES backend.
     * GLES backend now uses GLES v2 with YUV support via shaders
+    * -vo gl supports rotated display without needing video filters via
+      -rotate command-line option.
     * -vo gl now has an OSX/Cocoa backend, so it should be a better
       alternative to -vo corevideo now.
     * -vo gl2 renamed to -vo gl_tiled to stop people from assuming it is
diff --git a/DOCS/man/en/mplayer.1 b/DOCS/man/en/mplayer.1
index 461be5f..4da08a0 100644
--- a/DOCS/man/en/mplayer.1
+++ b/DOCS/man/en/mplayer.1
@@ -3628,6 +3628,13 @@ E.g.\& \-panscanrange \-3 allows a zoom factor of up to 4.
 This feature is experimental.
 .
 .TP
+.B \-rotate <0-3> (experimental)
+Rotate display by 90, 180 or 270 degrees.
+Rotates also the OSD, not just the video image itself.
+Currently only supported by the gl video output driver.
+For all other video outputs -vf ass,expand=osd=1,rotate=n can be used, in the future this might even happen automatically.
+.
+.TP
 .B \-refreshrate <Hz>
 Set the monitor refreshrate in Hz.
 Currently only supported by \-vo directx combined with the \-vm option.
diff --git a/cfg-mplayer.h b/cfg-mplayer.h
index bd97d7d..8af12e4 100644
--- a/cfg-mplayer.h
+++ b/cfg-mplayer.h
@@ -173,6 +173,7 @@ const m_option_t mplayer_opts[]={
     {"novsync", &vo_vsync, CONF_TYPE_FLAG, 0, 1, 0, NULL},
     {"panscan", &vo_panscan, CONF_TYPE_FLOAT, CONF_RANGE, -1.0, 1.0, NULL},
     {"panscanrange", &vo_panscanrange, CONF_TYPE_FLOAT, CONF_RANGE, -19.0, 99.0, NULL},
+    {"rotate", &vo_rotate, CONF_TYPE_INT, CONF_RANGE, 0, 3, NULL},
 
     {"grabpointer", &vo_grabpointer, CONF_TYPE_FLAG, 0, 0, 1, NULL},
     {"nograbpointer", &vo_grabpointer, CONF_TYPE_FLAG, 0, 1, 0, NULL},
diff --git a/libvo/aspect.c b/libvo/aspect.c
index bd568b9..5b2a2ea 100644
--- a/libvo/aspect.c
+++ b/libvo/aspect.c
@@ -46,25 +46,44 @@ static struct {
   int orgh; // real height
   int prew; // prescaled width
   int preh; // prescaled height
+  int orgw_norot;
+  int orgh_norot;
+  int prew_norot;
+  int preh_norot;
   int scrw; // horizontal resolution
   int scrh; // vertical resolution
   float asp;
 } aspdat;
 
+static void aspect_rotate(void) {
+  int i;
+  if (vo_rotate & 1) {
+    aspdat.orgw = aspdat.orgh_norot;
+    aspdat.orgh = aspdat.orgw_norot;
+    aspdat.prew = aspdat.preh_norot;
+    aspdat.preh = aspdat.prew_norot;
+  } else {
+    aspdat.orgw = aspdat.orgw_norot;
+    aspdat.orgh = aspdat.orgh_norot;
+    aspdat.prew = aspdat.prew_norot;
+    aspdat.preh = aspdat.preh_norot;
+  }
+}
+
 void aspect_save_orig(int orgw, int orgh){
 #ifdef ASPECT_DEBUG
   printf("aspect_save_orig %dx%d \n",orgw,orgh);
 #endif
-  aspdat.orgw = orgw;
-  aspdat.orgh = orgh;
+  aspdat.orgw_norot = orgw;
+  aspdat.orgh_norot = orgh;
 }
 
 void aspect_save_prescale(int prew, int preh){
 #ifdef ASPECT_DEBUG
   printf("aspect_save_prescale %dx%d \n",prew,preh);
 #endif
-  aspdat.prew = prew;
-  aspdat.preh = preh;
+  aspdat.prew_norot = prew;
+  aspdat.preh_norot = preh;
 }
 
 void aspect_save_screenres(int scrw, int scrh){
@@ -92,6 +111,7 @@ void aspect_save_screenres(int scrw, int scrh){
 void aspect_fit(int *srcw, int *srch, int fitw, int fith){
   int tmpw;
 
+  aspect_rotate();
 #ifdef ASPECT_DEBUG
   printf("aspect(0) fitin: %dx%d screenaspect: %.2f\n",aspdat.scrw,aspdat.scrh,
       monitor_aspect);
@@ -139,6 +159,7 @@ static void get_max_dims(int *w, int *h, int zoom)
 void aspect(int *srcw, int *srch, int zoom){
   int fitw;
   int fith;
+  aspect_rotate();
   get_max_dims(&fitw, &fith, zoom);
   if( !zoom && geometry_wh_changed ) {
 #ifdef ASPECT_DEBUG
@@ -161,6 +182,7 @@ static void panscan_calc_internal(int zoom)
  int fwidth,fheight;
  int vo_panscan_area;
  int max_w, max_h;
+ aspect_rotate();
  get_max_dims(&max_w, &max_h, zoom);
 
  if (vo_panscanrange > 0) {
diff --git a/libvo/video_out.c b/libvo/video_out.c
index d361669..6470f2a 100644
--- a/libvo/video_out.c
+++ b/libvo/video_out.c
@@ -65,6 +65,7 @@ int vo_vsync = 0;
 int vo_fs = 0;
 int vo_fsmode = 0;
 float vo_panscan = 0.0f;
+int vo_rotate;
 int vo_ontop = 0;
 int vo_adapter_num=0;
 int vo_refresh_rate=0;
diff --git a/libvo/video_out.h b/libvo/video_out.h
index eb9a030..a9e5ce1 100644
--- a/libvo/video_out.h
+++ b/libvo/video_out.h
@@ -30,6 +30,13 @@
 #include "libmpcodecs/img_format.h"
 //#include "vidix/vidix.h"
 
+
+#define ROTATE(t, x, y) do { \
+  t rot_tmp = x; \
+  x = y; \
+  y = -rot_tmp; \
+} while(0)
+
 #define VO_EVENT_EXPOSE 1
 #define VO_EVENT_RESIZE 2
 #define VO_EVENT_KEYPRESS 4
@@ -224,6 +231,7 @@ extern int vo_vsync;
 extern int vo_fs;
 extern int vo_fsmode;
 extern float vo_panscan;
+extern int vo_rotate;
 extern int vo_adapter_num;
 extern int vo_refresh_rate;
 extern int vo_keepaspect;
diff --git a/libvo/vo_gl.c b/libvo/vo_gl.c
index 3294168..ab397a2 100644
--- a/libvo/vo_gl.c
+++ b/libvo/vo_gl.c
@@ -120,6 +120,7 @@ static int yuvconvtype;
 static int use_rectangle;
 static int using_tex_rect;
 static int err_shown;
+static int draw_width, draw_height;
 static uint32_t image_width;
 static uint32_t image_height;
 static uint32_t image_format;
@@ -176,8 +177,12 @@ static int did_render;
 static void redraw(void);
 
 static float video_matrix[16];
+static float osd_matrix[16];
 
 static void resize(void) {
+  int i;
+  draw_width  = (vo_rotate & 1) ? vo_dheight : vo_dwidth;
+  draw_height = (vo_rotate & 1) ? vo_dwidth  : vo_dheight;
   // simple orthogonal projection for 0-image_width;0-image_height
   memset(video_matrix, 0, sizeof(video_matrix));
   video_matrix[0]  = 2.0/image_width;
@@ -185,6 +190,12 @@ static void resize(void) {
   video_matrix[12] = -1;
   video_matrix[13] = 1;
   video_matrix[15] = 1;
+  memcpy(osd_matrix, video_matrix, sizeof(osd_matrix));
+  if (!scaled_osd) {
+    // simple orthogonal projection for 0-vo_dwidth;0-vo_dheight
+    osd_matrix[0] =  2.0/draw_width;
+    osd_matrix[5] = -2.0/draw_height;
+  }
   mp_msg(MSGT_VO, MSGL_V, "[gl] Resize: %dx%d\n", vo_dwidth, vo_dheight);
   if (WinID >= 0) {
     int left = 0, top = 0, w = vo_dwidth, h = vo_dheight;
@@ -194,6 +205,14 @@ static void resize(void) {
   } else
     mpglViewport(0, 0, vo_dwidth, vo_dheight);
 
+  for (i = 0; i < (vo_rotate & 3); i++) {
+    int j;
+    for (j = 0; j < 16; j += 4) {
+      ROTATE(float, video_matrix[j], video_matrix[j+1]);
+      ROTATE(float, osd_matrix[j], osd_matrix[j+1]);
+    }
+  }
+
   ass_border_x = ass_border_y = 0;
   if (aspect_scaling() && use_aspect) {
     int new_w, new_h;
@@ -205,11 +224,16 @@ static void resize(void) {
     scale_x = (double)new_w / (double)vo_dwidth;
     scale_y = (double)new_h / (double)vo_dheight;
     video_matrix[0]  *= scale_x;
+    video_matrix[4]  *= scale_x;
     video_matrix[12] *= scale_x;
+    video_matrix[1]  *= scale_y;
     video_matrix[5]  *= scale_y;
     video_matrix[13] *= scale_y;
-    ass_border_x = (vo_dwidth - new_w) / 2;
-    ass_border_y = (vo_dheight - new_h) / 2;
+    if (vo_rotate & 1) {
+      int tmp = new_w; new_w = new_h; new_h = tmp;
+    }
+    ass_border_x = (draw_width  - new_w) / 2;
+    ass_border_y = (draw_height - new_h) / 2;
   }
   mpglLoadMatrixf(video_matrix);
 
@@ -831,16 +855,7 @@ static void do_render_osd(int type) {
   if (!draw_osd && !draw_eosd)
     return;
   // set special rendering parameters
-  if (!scaled_osd) {
-    // simple orthogonal projection for 0-vo_dwidth;0-vo_dheight
-    float matrix[16] = {
-      2.0/vo_dwidth,   0, 0, 0,
-      0, -2.0/vo_dheight, 0, 0,
-      0,  0, 0, 0,
-      -1, 1, 0, 1
-    };
-    mpglLoadMatrixf(matrix);
-  }
+  mpglLoadMatrixf(osd_matrix);
   mpglEnable(GL_BLEND);
   if (draw_eosd) {
     mpglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
@@ -874,8 +889,7 @@ static void do_render_osd(int type) {
   }
   // set rendering parameters back to defaults
   mpglDisable(GL_BLEND);
-  if (!scaled_osd)
-    mpglLoadMatrixf(video_matrix);
+  mpglLoadMatrixf(video_matrix);
   mpglBindTexture(gl_target, 0);
 }
 
@@ -885,8 +899,8 @@ static void draw_osd(void)
   if (vo_osd_changed(0)) {
     int osd_h, osd_w;
     clearOSD();
-    osd_w = scaled_osd ? image_width : vo_dwidth;
-    osd_h = scaled_osd ? image_height : vo_dheight;
+    osd_w = scaled_osd ? image_width  : draw_width;
+    osd_h = scaled_osd ? image_height : draw_height;
     vo_draw_text_ext(osd_w, osd_h, ass_border_x, ass_border_y, ass_border_x, ass_border_y,
                      image_width, image_height, create_osd_texture);
   }
@@ -1463,7 +1477,7 @@ static int control(uint32_t request, void *data)
   case VOCTRL_GET_EOSD_RES:
     {
       struct mp_eosd_settings *r = data;
-      r->w = vo_dwidth; r->h = vo_dheight;
+      r->w = draw_width; r->h = draw_height;
       r->srcw = image_width; r->srch = image_height;
       r->mt = r->mb = r->ml = r->mr = 0;
       if (scaled_osd) {r->w = image_width; r->h = image_height;}
-- 
1.7.10.4



More information about the MPlayer-dev-eng mailing list