[MPlayer-dev-eng] [PATCH] libass support in vf_vo

Reimar Döffinger Reimar.Doeffinger at stud.uni-karlsruhe.de
Sat Aug 26 12:24:30 CEST 2006


Hello,
On Sat, Aug 26, 2006 at 02:30:28AM +0400, Evgeniy Stepanov wrote:
> I'm getting "Too many OSD parts, contact the developers!" message.
> MAX_OSD_PARTS is too low. In libass, every glyph produces at least 2 images: 
> the glyph and its outline (border), so the total number of images can easily 
> reach 300 and more.

I know, that was just a quick first hack :-).
I have updated the patch, and it will show the problem with not calling
VOCTRL_GET_EOSD_RES for every frame quite clearly: with -vo
gl:scaled-osd it will work but look bad for lowres videos, without it
will look good but break as soon as the initial size is changed.
I used something like -vf scale=32:32,dsize=64:64 (optionally also with
-fs) to test.
Also, VOCTRL_GET_EOSD_RES currently will return the scaled size
_including_ the black borders in fullscreen. Not sure if this is
desired, or if maybe the borders should be specified separately or so.
And one final thing: my implementation will leave the last OSD on screen
until config is called or VOCTRL_DRAW_EOSD is called with NULL. The
advantage is that it leaves space for optimization when the same content
should be displayed for multiple frames, since setting up all those textures
etc. is quite slow, but I don't have many samples to test if the current
implementation in vf_vo can cope with that.

Greetings,
Reimar Döffinger
-------------- next part --------------
Index: libvo/vo_gl.c
===================================================================
--- libvo/vo_gl.c	(revision 19534)
+++ libvo/vo_gl.c	(working copy)
@@ -16,6 +16,7 @@
 #ifdef HAVE_NEW_GUI
 #include "Gui/interface.h"
 #endif
+#include "libass/ass.h"
 
 static vo_info_t info = 
 {
@@ -51,13 +52,16 @@
 //! Alpha textures for OSD
 static GLuint osdatex[MAX_OSD_PARTS];
 #endif
+static GLuint *eosdtex;
 //! Display lists that draw the OSD parts
 static GLuint osdDispList[MAX_OSD_PARTS];
 #ifndef FAST_OSD
 static GLuint osdaDispList[MAX_OSD_PARTS];
 #endif
+static GLuint eosdDispList;
 //! How many parts the OSD currently consists of
 static int osdtexCnt;
+static int eosdtexCnt;
 static int osd_color;
 
 static int use_aspect;
@@ -222,6 +226,53 @@
   osdtexCnt = 0;
 }
 
+static void clearEOSD(void) {
+  if (!eosdtexCnt)
+    return;
+  glDeleteTextures(eosdtexCnt, eosdtex);
+  free(eosdtex);
+  eosdtex = NULL;
+  glDeleteLists(eosdDispList, 1);
+  eosdtexCnt = 0;
+}
+
+static void genEOSD(ass_image_t *img) {
+  int sx = 8, sy = 8;
+  GLuint *curtex;
+  GLint scale_type = (scaled_osd) ? GL_LINEAR : GL_NEAREST;
+  ass_image_t *i;
+  clearEOSD();
+  for (i = img; i; i = i->next)
+    eosdtexCnt++;
+  if (!eosdtexCnt)
+    return;
+  eosdtex = calloc(eosdtexCnt, sizeof(GLuint));
+  glGenTextures(eosdtexCnt, eosdtex);
+  for (i = img, curtex = eosdtex; i; i = i->next, curtex++) {
+    if (i->w <= 0 || i->h <= 0 || i->stride < i->w) {
+      mp_msg(MSGT_VO, MSGL_V, "Invalid dimensions OSD for part!\n");
+      continue;
+    }
+    texSize(i->w, i->h, &sx, &sy);
+    BindTexture(gl_target, *curtex);
+    glCreateClearTex(gl_target, GL_ALPHA, scale_type, sx, sy, 0);
+    glUploadTex(gl_target, GL_ALPHA, GL_UNSIGNED_BYTE, i->bitmap, i->stride,
+                0, 0, i->w, i->h, 0);
+  }
+  eosdDispList = glGenLists(1);
+  glNewList(eosdDispList, GL_COMPILE);
+  for (i = img, curtex = eosdtex; i; i = i->next, curtex++) {
+    if (i->w <= 0 || i->h <= 0 || i->stride < i->w)
+      continue;
+    glColor4ub(i->color >> 24, (i->color >> 16) & 0xff, (i->color >> 8) & 0xff, 255 - i->color & 0xff);
+    texSize(i->w, i->h, &sx, &sy);
+    BindTexture(gl_target, *curtex);
+    glDrawTex(i->dst_x, i->dst_y, i->w, i->h, 0, 0, i->w, i->h, sx, sy, use_rectangle == 1, 0, 0);
+  }
+  glEndList();
+  BindTexture(gl_target, 0);
+}
+
 /**
  * \brief uninitialize OpenGL context, freeing textures, buffers etc.
  */
@@ -236,6 +287,7 @@
     glDeleteTextures(i, default_texs);
   default_texs[0] = 0;
   clearOSD();
+  clearEOSD();
   if (DeleteBuffers && gl_buffer)
     DeleteBuffers(1, &gl_buffer);
   gl_buffer = 0; gl_buffersize = 0;
@@ -248,6 +300,7 @@
  */
 static int initGl(uint32_t d_width, uint32_t d_height) {
   osdtexCnt = 0; gl_buffer = 0; gl_buffersize = 0; err_shown = 0;
+  eosdtexCnt = 0;
   fragprog = 0;
   texSize(image_width, image_height, &texture_width, &texture_height);
 
@@ -532,7 +585,7 @@
   if (image_format == IMGFMT_YV12)
     glDisableYUVConversion(gl_target, yuvconvtype);
 
-  if (osdtexCnt > 0) {
+  if (osdtexCnt > 0 || eosdtexCnt > 0) {
     // set special rendering parameters
     if (!scaled_osd) {
     glMatrixMode(GL_PROJECTION);
@@ -541,6 +594,11 @@
     glOrtho(0, vo_dwidth, vo_dheight, 0, -1, 1);
     }
     glEnable(GL_BLEND);
+    if (eosdtexCnt > 0) {
+      glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+      glCallList(eosdDispList);
+    }
+  if (osdtexCnt > 0) {
     glColor4ub((osd_color >> 16) & 0xff, (osd_color >> 8) & 0xff, osd_color & 0xff, 0xff);
     // draw OSD
 #ifndef FAST_OSD
@@ -549,6 +607,7 @@
 #endif
     glBlendFunc(GL_ONE, GL_ONE);
     glCallLists(osdtexCnt, GL_UNSIGNED_INT, osdDispList);
+  }
     // set rendering parameters back to defaults
     glDisable (GL_BLEND);
     if (!scaled_osd)
@@ -674,7 +733,7 @@
                VFCAP_FLIP |
                VFCAP_HWSCALE_UP | VFCAP_HWSCALE_DOWN | VFCAP_ACCEPT_STRIDE;
     if (use_osd)
-      caps |= VFCAP_OSD;
+      caps |= VFCAP_OSD | VFCAP_EOSD;
     if ((format == IMGFMT_RGB24) || (format == IMGFMT_RGBA))
         return caps;
     if (use_yuv && format == IMGFMT_YV12)
@@ -818,6 +877,16 @@
     return get_image(data);
   case VOCTRL_DRAW_IMAGE:
     return draw_image(data);
+  case VOCTRL_DRAW_EOSD:
+    genEOSD(data);
+    return VO_TRUE;
+  case VOCTRL_GET_EOSD_RES:
+    {
+      mp_eosd_res_t *r = data;
+      if (scaled_osd) {r->w = image_width; r->h = image_height;}
+      else {r->w = vo_dwidth; r->h = vo_dheight;}
+    }
+    return VO_TRUE;
   case VOCTRL_GUISUPPORT:
     return VO_TRUE;
   case VOCTRL_ONTOP:


More information about the MPlayer-dev-eng mailing list