[MPlayer-dev-eng] [Patch] sub_pos addition for VOB subtitles

salvador salvador at inti.gov.ar
Fri Apr 26 16:15:59 CEST 2002


Hi All!

Purpose of this patch: This patch adds sub_pos control for subtitles to
spudec.c (subimage subtitles).

Long description:
This patch adds a new parameter to vobsub_draw and spudec_draw_scaled
funtions. This parameter is just sub_pos variable (already existing to
render subtitles from text files). The meaning of this parameter is a little
bit different.
As subimage subtitles have a defined position (and sometime this position is
important) and as sub_pos default value is 100 then a value of 100 means
"let subtitles alone, don't move them". Any other value tries to position
the subtitles to "frame_height*sub_pos/100". The algorithm avoids drawing
the subtitles outside the frame_height. It works OK for the streams I tested
and helps me to move the subtitles to a lower position where they are less
annoying.
This is a simple change but needed an extra work: some streams have a big
subtitle area, most of the time filled with nothing. One I tested left
aprox. 26 lines at the top and 26 at the bottom for moving. For this reason
I added code to compute the real height of the subtitles and adjust it.
While doing it I saw a small bug when stride!=width. At least in my system
clearing the alpha channel wasn't enough and hence I added code to also
clean the image plane, it can be optimized.

Warning!!! This patch is independent to the other I'm sending to the list
(to compute a magic palette) *but* should be applied after the other patch,
I guess it will apply anyways but with offsets.

SET

P.S. What about an option to select the antialiasing from command line?
P.S.2. I commented out spudec_draw because it isn't used at all and I didn't
implement the movement for it, should I patch it too?

--
Salvador Eduardo Tropea (SET). (Electronics Engineer)
Visit my home page: http://welcome.to/SetSoft or
http://www.geocities.com/SiliconValley/Vista/6552/
Alternative e-mail: set at computer.org set at ieee.org
Address: Curapaligue 2124, Caseros, 3 de Febrero
Buenos Aires, (1678), ARGENTINA Phone: +(5411) 4759 0013


-------------- next part --------------
--- spudec.c~1	Fri Apr 26 10:47:19 2002
+++ spudec.c	Fri Apr 26 10:56:52 2002
@@ -46,6 +46,7 @@
   unsigned int cuspal[4];
   unsigned int custom;
   unsigned int now_pts;
+  unsigned int first_y, last_y;
   unsigned int start_pts, end_pts;
   unsigned int start_col, end_col;
   unsigned int start_row, end_row;
@@ -121,7 +122,7 @@
 static void spudec_process_data(spudec_handle_t *this)
 {
   unsigned int cmap[4], alpha[4];
-  unsigned int i, x, y;
+  unsigned int i, x, y, fy, ly;
 
   this->scaled_frame_width = 0;
   this->scaled_frame_height = 0;
@@ -156,9 +157,15 @@
     return;
 
   /* Kludge: draw_alpha needs width multiple of 8. */
-  if (this->width < this->stride)
-    for (y = 0; y < this->height; ++y)
-      memset(this->aimage + y * this->stride + this->width, 0, this->stride - this->width);
+  if (this->width < this->stride) {
+    unsigned int wclear = this->stride - this->width;
+    unsigned char *ai = this->aimage + this->width;
+    unsigned char *i  = this->image  + this->width;
+    for (y = 0; y < this->height; ai+=this->stride, i+=this->stride, ++y) {
+      memset(ai, 0, wclear);
+      memset( i, 0, wclear);
+    }
+  }
 
   i = this->current_nibble[1];
   x = 0;
@@ -194,6 +201,18 @@
       ++y;
     }
   }
+  /* Compute the visible area, some streams have a huge one */
+  /* SET: should I use mp_msg or just remove these printfs? */
+  /*printf("x: %d y %d w %d h %d ",this->start_col,this->start_row,this->width,this->height);*/
+  for (fy=0; fy<this->image_size && !this->aimage[fy]; fy++);
+  for (ly=this->stride*this->height-1; ly && !this->aimage[ly]; ly--);
+  this->first_y = fy / this->stride;
+  this->last_y = ly / this->stride;
+  /*printf("fy %d ly %d ",this->first_y,this->last_y);*/
+  /* Move the start row and reduce the height */
+  this->start_row += this->first_y;
+  this->height = this->last_y - this->first_y + 1;
+  /*printf("new h %d new start %d (sz %d st %d)---\n\n\n",this->height,this->start_row,this->image_size,this->stride);*/
 }
 
 
@@ -425,6 +444,8 @@
     return ret;
 }
 
+#if 0
+/* SET: is that really needed? */
 void spudec_draw(void *this, void (*draw_alpha)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride))
 {
     spudec_handle_t *spu = (spudec_handle_t *)this;
@@ -432,6 +453,7 @@
 	draw_alpha(spu->start_col, spu->start_row, spu->width, spu->height,
 		   spu->image, spu->aimage, spu->stride);
 }
+#endif
 
 /* transform mplayer's alpha value into an opacity value that is linear */
 static inline int canon_alpha(int alpha)
@@ -439,15 +461,38 @@
   return alpha ? 256 - alpha : 0;
 }
 
-void spudec_draw_scaled(void *me, unsigned int dxs, unsigned int dys, void (*draw_alpha)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride))
+void spudec_draw_scaled(void *me, int sub_pos, unsigned int dxs, unsigned int dys, void (*draw_alpha)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride))
 {
   spudec_handle_t *spu = (spudec_handle_t *)me;
+  unsigned char *image, *aimage;
+
   if (spu->start_pts <= spu->now_pts && spu->now_pts < spu->end_pts) {
+  
+    /* Reduce the image to only the used part */
+    image = NULL;
+    if (spu->image) {
+       image = spu->image + spu->stride*spu->first_y;
+       aimage = spu->aimage + spu->stride*spu->first_y;
+    }
+  
     if (spu->orig_frame_width == 0 || spu->orig_frame_height == 0
 	|| (spu->orig_frame_width == dxs && spu->orig_frame_height == dys)) {
-      if (spu->image)
+      if (image) {
+
+        /* Subtitles position */
+        /* sub_pos==100 => normal, any other value => dys*sub_pos/100 */
+        if (sub_pos != 100) {
+           int npos = dys * sub_pos / 100;
+           /* Avoid excess */
+           if (npos + spu->height > dys)
+              spu->start_row = dys - spu->height;
+           else
+              spu->start_row = npos;
+        }
+      
 	draw_alpha(spu->start_col, spu->start_row, spu->width, spu->height,
-		   spu->image, spu->aimage, spu->stride);
+		   image, aimage, spu->stride);
+      }
     }
     else {
       if (spu->scaled_frame_width != dxs || spu->scaled_frame_height != dys) {	/* Resizing is needed */
@@ -492,8 +537,8 @@
 	    int scaled_strides = spu->scaled_stride * y;
 	    for (x = 0; x < spu->scaled_width; ++x) {
 	      int unscaled_x = x * 0x100 / scalex;
-	      spu->scaled_image[scaled_strides + x] = spu->image[strides + unscaled_x];
-	      spu->scaled_aimage[scaled_strides + x] = spu->aimage[strides + unscaled_x];
+	      spu->scaled_image[scaled_strides + x] = image[strides + unscaled_x];
+	      spu->scaled_aimage[scaled_strides + x] = aimage[strides + unscaled_x];
 	    }
 	  }
 #elif ANTIALIASING_ALGORITHM == 1
@@ -516,9 +561,9 @@
 		for (walky = unscaled_top; walky <= unscaled_bottom; ++walky)
 		  for (walkx = unscaled_left; walkx <= unscaled_right; ++walkx) {
 		    base = walky * spu->stride + walkx;
-		    tmp = canon_alpha(spu->aimage[base]);
+		    tmp = canon_alpha(aimage[base]);
 		    alpha += tmp;
-		    color += tmp * spu->image[base];
+		    color += tmp * image[base];
 		  }
 		base = y * spu->scaled_stride + x;
 		spu->scaled_image[base] = alpha ? color / alpha : 0;
@@ -612,34 +657,34 @@
 		*/
 		/* 1: top left part */
 		base = spu->stride * (unsigned int) unscaled_y;
-		tmp = left * top * canon_alpha(spu->aimage[base + (unsigned int) unscaled_x]);
+		tmp = left * top * canon_alpha(aimage[base + (unsigned int) unscaled_x]);
 		alpha += tmp;
-		color += tmp * spu->image[base + (unsigned int) unscaled_x];
+		color += tmp * image[base + (unsigned int) unscaled_x];
 		/* 2: top center part */
 		if (width > 0) {
 		  unsigned int walkx;
 		  for (walkx = left_right_column; walkx < (unsigned int) unscaled_x_right; ++walkx) {
 		    base = spu->stride * (unsigned int) unscaled_y + walkx;
-		    tmp = /* 1.0 * */ top * canon_alpha(spu->aimage[base]);
+		    tmp = /* 1.0 * */ top * canon_alpha(aimage[base]);
 		    alpha += tmp;
-		    color += tmp * spu->image[base];
+		    color += tmp * image[base];
 		  }
 		}
 		/* 3: top right part */
 		if (right > 0.0) {
 		  base = spu->stride * (unsigned int) unscaled_y + (unsigned int) unscaled_x_right;
-		  tmp = right * top * canon_alpha(spu->aimage[base]);
+		  tmp = right * top * canon_alpha(aimage[base]);
 		  alpha += tmp;
-		  color += tmp * spu->image[base];
+		  color += tmp * image[base];
 		}
 		/* 4: center left part */
 		if (height > 0) {
 		  unsigned int walky;
 		  for (walky = top_low_row; walky < (unsigned int) unscaled_y_bottom; ++walky) {
 		    base = spu->stride * walky + (unsigned int) unscaled_x;
-		    tmp = left /* * 1.0 */ * canon_alpha(spu->aimage[base]);
+		    tmp = left /* * 1.0 */ * canon_alpha(aimage[base]);
 		    alpha += tmp;
-		    color += tmp * spu->image[base];
+		    color += tmp * image[base];
 		  }
 		}
 		/* 5: center part */
@@ -649,9 +694,9 @@
 		    unsigned int walkx;
 		    base = spu->stride * walky;
 		    for (walkx = left_right_column; walkx < (unsigned int) unscaled_x_right; ++walkx) {
-		      tmp = /* 1.0 * 1.0 * */ canon_alpha(spu->aimage[base + walkx]);
+		      tmp = /* 1.0 * 1.0 * */ canon_alpha(aimage[base + walkx]);
 		      alpha += tmp;
-		      color += tmp * spu->image[base + walkx];
+		      color += tmp * image[base + walkx];
 		    }
 		  }		    
 		}
@@ -660,34 +705,34 @@
 		  unsigned int walky;
 		  for (walky = top_low_row; walky < (unsigned int) unscaled_y_bottom; ++walky) {
 		    base = spu->stride * walky + (unsigned int) unscaled_x_right;
-		    tmp = right /* * 1.0 */ * canon_alpha(spu->aimage[base]);
+		    tmp = right /* * 1.0 */ * canon_alpha(aimage[base]);
 		    alpha += tmp;
-		    color += tmp * spu->image[base];
+		    color += tmp * image[base];
 		  }
 		}
 		/* 7: bottom left part */
 		if (bottom > 0.0) {
 		  base = spu->stride * (unsigned int) unscaled_y_bottom + (unsigned int) unscaled_x;
-		  tmp = left * bottom * canon_alpha(spu->aimage[base]);
+		  tmp = left * bottom * canon_alpha(aimage[base]);
 		  alpha += tmp;
-		  color += tmp * spu->image[base];
+		  color += tmp * image[base];
 		}
 		/* 8: bottom center part */
 		if (width > 0 && bottom > 0.0) {
 		  unsigned int walkx;
 		  base = spu->stride * (unsigned int) unscaled_y_bottom;
 		  for (walkx = left_right_column; walkx < (unsigned int) unscaled_x_right; ++walkx) {
-		    tmp = /* 1.0 * */ bottom * canon_alpha(spu->aimage[base + walkx]);
+		    tmp = /* 1.0 * */ bottom * canon_alpha(aimage[base + walkx]);
 		    alpha += tmp;
-		    color += tmp * spu->image[base + walkx];
+		    color += tmp * image[base + walkx];
 		  }
 		}
 		/* 9: bottom right part */
 		if (right > 0.0 && bottom > 0.0) {
 		  base = spu->stride * (unsigned int) unscaled_y_bottom + (unsigned int) unscaled_x_right;
-		  tmp = right * bottom * canon_alpha(spu->aimage[base]);
+		  tmp = right * bottom * canon_alpha(aimage[base]);
 		  alpha += tmp;
-		  color += tmp * spu->image[base];
+		  color += tmp * image[base];
 		}
 		/* Finally mix these transparency and brightness information suitably */
 		base = spu->scaled_stride * y + x;
@@ -706,9 +751,22 @@
 	  spu->scaled_frame_height = dys;
 	}
       }
-      if (spu->scaled_image)
+      if (spu->scaled_image) {
+      
+        /* Subtitles position */
+        /* sub_pos==100 => normal, any other value => dys*sub_pos/100 */
+        if (sub_pos != 100) {
+           int npos = dys * sub_pos / 100;
+           /* Avoid excess */
+           if (npos + spu->scaled_height > dys)
+              spu->scaled_start_row = dys - spu->scaled_height;
+           else
+              spu->scaled_start_row = npos;
+        }
+      
 	draw_alpha(spu->scaled_start_col, spu->scaled_start_row, spu->scaled_width, spu->scaled_height,
 		   spu->scaled_image, spu->scaled_aimage, spu->scaled_stride);
+      }
     }
   }
   else
--- spudec.h~1	Fri Apr 26 10:54:53 2002
+++ spudec.h	Fri Apr 26 10:55:09 2002
@@ -4,7 +4,7 @@
 void spudec_heartbeat(void *this, unsigned int pts100);
 void spudec_assemble(void *this, unsigned char *packet, unsigned int len, unsigned int pts100);
 void spudec_draw(void *this, void (*draw_alpha)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride));
-void spudec_draw_scaled(void *this, unsigned int dxs, unsigned int dys, void (*draw_alpha)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride));
+void spudec_draw_scaled(void *this, int sub_pos, unsigned int dxs, unsigned int dys, void (*draw_alpha)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride));
 void spudec_update_palette(void *this, unsigned int *palette);
 void *spudec_new_scaled(unsigned int *palette, unsigned int frame_width, unsigned int frame_height);
 void *spudec_new(unsigned int *palette);
--- vobsub.h~1	Fri Apr 26 10:56:01 2002
+++ vobsub.h	Fri Apr 26 10:57:10 2002
@@ -4,7 +4,7 @@
 extern void *vobsub_open(const char *subname, const int force);
 extern void vobsub_process(void *vob, float pts);
 extern void vobsub_reset(void *vob);
-extern void vobsub_draw(void *vob, int dxs, int dys, void (*draw_alpha)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride));
+extern void vobsub_draw(void *vob, int sub_pos, int dxs, int dys, void (*draw_alpha)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride));
 extern int vobsub_parse_ifo(const char *const name, unsigned int *palette, unsigned int *width, unsigned int *height, int force);
 
 #endif /* MPLAYER_VOBSUB_H */
--- vobsub.c~1	Fri Apr 26 10:55:57 2002
+++ vobsub.c	Fri Apr 26 10:58:39 2002
@@ -940,11 +940,11 @@
     free(vob);
 }
 
-void vobsub_draw(void *this, int dxs, int dys, void (*draw_alpha)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride))
+void vobsub_draw(void *this, int sub_pos, int dxs, int dys, void (*draw_alpha)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride))
 {
     vobsub_t *vob = (vobsub_t *)this;
     if (vob->spudec) {
-	spudec_draw_scaled(vob->spudec, dxs, dys, draw_alpha);
+	spudec_draw_scaled(vob->spudec, sub_pos, dxs, dys, draw_alpha);
     }	
 }
 
--- libvo/sub.c~1	Fri Apr 26 10:59:21 2002
+++ libvo/sub.c	Fri Apr 26 11:00:08 2002
@@ -480,10 +480,10 @@
 	vo_osd_changed_flag=obj->flags&OSDFLAG_CHANGED;	// temp hack
 	switch(obj->type){
 	case OSDTYPE_SPU:
-	    spudec_draw_scaled(vo_spudec, dxs, dys, draw_alpha); // FIXME
+	    spudec_draw_scaled(vo_spudec, sub_pos, dxs, dys, draw_alpha); // FIXME
 	    break;
 	case OSDTYPE_VOBSUB:
-	    vobsub_draw(vo_vobsub, dxs, dys, draw_alpha);  // FIXME
+	    vobsub_draw(vo_vobsub, sub_pos, dxs, dys, draw_alpha);  // FIXME
 	    break;
 	case OSDTYPE_OSD:
 	    vo_draw_text_osd(obj,draw_alpha);


More information about the MPlayer-dev-eng mailing list