[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