summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--DOCS/mplayer.130
-rw-r--r--cfg-common.h3
-rw-r--r--libvo/sub.h3
-rw-r--r--spudec.c139
4 files changed, 139 insertions, 36 deletions
diff --git a/DOCS/mplayer.1 b/DOCS/mplayer.1
index 0fe7f44817..aecfc5e8f4 100644
--- a/DOCS/mplayer.1
+++ b/DOCS/mplayer.1
@@ -1047,6 +1047,36 @@ This is the full pathname without extensions, i.e.\& without the '.idx',
.TP
.B \-vobsubid <0-31>
Specify the VobSub subtitle id.
+.TP
+.B \-spualign <-1\-2>
+Specify how spu (DVD/VobSub) subtitles should be aligned.
+Values are the same as for -subpos, with the extra choice -1 for original
+position.
+.TP
+.B \-spuaa <mode>
+Antialiasing/scaling mode for DVD/VobSub. A value of 16 may be added
+to mode in order to force scaling even when original and scaled frame
+size already match, for example to smooth subtitles with the gaussian
+blur. The available modes are:
+.PD 0
+.RSs
+.IPs 0
+none (fastest, very ugly)
+.IPs 1
+approximate (broken?)
+.IPs 2
+full (slow)
+.IPs 3
+bilinear (default, fast and not too bad)
+.IPs 4
+uses swscaler gaussian blur (looks very good)
+.RE
+.PD 1
+.
+.TP
+.B \-spugauss <0.0\-3.0>
+Variance parameter of gaussian used by -spuaa 4. Higher means more
+blur. The default is 1.0.
.SH "AUDIO OUTPUT OPTIONS (MPLAYER ONLY)"
diff --git a/cfg-common.h b/cfg-common.h
index 1ca35bcb50..47024b6aea 100644
--- a/cfg-common.h
+++ b/cfg-common.h
@@ -192,6 +192,9 @@
{"subpos", &sub_pos, CONF_TYPE_INT, CONF_RANGE, 0, 100, NULL},
{"subalign", &sub_alignment, CONF_TYPE_INT, CONF_RANGE, 0, 2, NULL},
{"subwidth", &sub_width_p, CONF_TYPE_INT, CONF_RANGE, 10, 100, NULL},
+ {"spualign", &spu_alignment, CONF_TYPE_INT, CONF_RANGE, -1, 2, NULL},
+ {"spuaa", &spu_aamode, CONF_TYPE_INT, CONF_RANGE, 0, 31, NULL},
+ {"spugauss", &spu_gaussvar, CONF_TYPE_FLOAT, CONF_RANGE, 0.0, 3.0, NULL},
#ifdef HAVE_FREETYPE
{"subfont-encoding", &subtitle_font_encoding, CONF_TYPE_STRING, 0, 0, 0, NULL},
{"subfont-text-scale", &text_font_scale_factor, CONF_TYPE_FLOAT, CONF_RANGE, 0, 100, NULL},
diff --git a/libvo/sub.h b/libvo/sub.h
index 6868f59723..46af2b6fc5 100644
--- a/libvo/sub.h
+++ b/libvo/sub.h
@@ -103,6 +103,9 @@ extern int sub_visibility;
extern int suboverlap_enabled;
extern int sub_bg_color; /* subtitles background color */
extern int sub_bg_alpha;
+extern int spu_alignment;
+extern int spu_aamode;
+extern float spu_gaussvar;
//extern void vo_draw_text_osd(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 vo_draw_text_progbar(int dxs,int dys,void (*draw_alpha)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride));
diff --git a/spudec.c b/spudec.c
index 5eb7bdeb5f..57275b9250 100644
--- a/spudec.c
+++ b/spudec.c
@@ -1,17 +1,3 @@
-/* Valid values for ANTIALIASING_ALGORITHM:
- -1: bilinear (similiar to vobsub, fast and good quality)
- 0: none (fastest, most ugly)
- 1: approximate
- 2: full (slowest, best looking)
- */
-#define ANTIALIASING_ALGORITHM -1
-
-/* Valid values for SUBPOS:
- 0: leave the sub on it's original place
- 1: put the sub at the bottom of the picture
- */
-#define SUBPOS 0
-
/* SPUdec.c
Skeleton of function spudec_process_controll() is from xine sources.
Further works:
@@ -34,14 +20,26 @@
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
-#if ANTIALIASING_ALGORITHM == 2
#include <math.h>
-#endif
#include "libvo/video_out.h"
#include "spudec.h"
+#include "postproc/swscale.h"
#define MIN(a, b) ((a)<(b)?(a):(b))
+/* Valid values for spu_aamode:
+ 0: none (fastest, most ugly)
+ 1: approximate
+ 2: full (slowest)
+ 3: bilinear (similiar to vobsub, fast and not too bad)
+ 4: uses swscaler gaussian (this is the only one that looks good)
+ */
+
+int spu_aamode = 3;
+int spu_alignment = -1;
+float spu_gaussvar = 1.0;
+extern int sub_pos;
+
typedef struct packet_t packet_t;
struct packet_t {
unsigned char *data;
@@ -605,13 +603,33 @@ void spudec_calc_bbox(void *me, unsigned int dxs, unsigned int dys, unsigned int
unsigned int scaley = 0x100 * dys / spu->orig_frame_height;
bbox[0] = spu->start_col * scalex / 0x100;
bbox[1] = spu->start_col * scalex / 0x100 + spu->width * scalex / 0x100;
-#if SUBPOS == 0
- bbox[2] = spu->start_row * scaley / 0x100;
- bbox[3] = spu->start_row * scaley / 0x100 + spu->height * scaley / 0x100;
-#elif SUBPOS == 1
- bbox[3] = dys -1;
- bbox[2] = bbox[3] -spu->height * scaley / 0x100;
-#endif
+ switch (spu_alignment) {
+ case 0:
+ bbox[3] = dys*sub_pos/100 + spu->height * scaley / 0x100;
+ if (bbox[3] > dys) bbox[3] = dys;
+ bbox[2] = bbox[3] - spu->height * scaley / 0x100;
+ break;
+ case 1:
+ if (sub_pos < 50) {
+ bbox[2] = dys*sub_pos/100 - spu->height * scaley / 0x200;
+ if (bbox[2] < 0) bbox[2] = 0;
+ bbox[3] = bbox[2] + spu->height;
+ } else {
+ bbox[3] = dys*sub_pos/100 + spu->height * scaley / 0x200;
+ if (bbox[3] > dys) bbox[3] = dys;
+ bbox[2] = bbox[3] - spu->height * scaley / 0x100;
+ }
+ break;
+ case 2:
+ bbox[2] = dys*sub_pos/100 - spu->height * scaley / 0x100;
+ if (bbox[2] < 0) bbox[2] = 0;
+ bbox[3] = bbox[2] + spu->height;
+ break;
+ default: /* -1 */
+ bbox[2] = spu->start_row * scaley / 0x100;
+ bbox[3] = spu->start_row * scaley / 0x100 + spu->height * scaley / 0x100;
+ break;
+ }
}
}
/* transform mplayer's alpha value into an opacity value that is linear */
@@ -627,7 +645,6 @@ typedef struct {
}scale_pixel;
-#if ANTIALIASING_ALGORITHM == -1
static void scale_table(unsigned int start_src, unsigned int start_tar, unsigned int end_src, unsigned int end_tar, scale_pixel * table)
{
unsigned int t;
@@ -674,7 +691,32 @@ static void scale_image(int x, int y, scale_pixel* table_x, scale_pixel* table_y
spu->scaled_image[scaled] = 256 - spu->scaled_aimage[scaled];
}
}
-#endif
+
+void sws_spu_image(unsigned char *d1, unsigned char *d2, int dw, int dh, int ds,
+ unsigned char *s1, unsigned char *s2, int sw, int sh, int ss)
+{
+ SwsContext *ctx;
+ static SwsFilter filter;
+ static int firsttime = 1;
+ static float oldvar;
+ int i;
+
+ if (!firsttime && oldvar != spu_gaussvar) freeVec(filter.lumH);
+ if (firsttime) {
+ filter.lumH = filter.lumV =
+ filter.chrH = filter.chrV = getGaussianVec(spu_gaussvar, 3.0);
+ normalizeVec(filter.lumH, 1.0);
+ firsttime = 0;
+ oldvar = spu_gaussvar;
+ }
+
+ ctx=getSwsContext(sw, sh, IMGFMT_Y800, dw, dh, IMGFMT_Y800, SWS_GAUSS, &filter, NULL);
+ ctx->swScale(ctx,&s1,&ss,0,sh,&d1,&ds);
+ for (i=ss*sh-1; i>=0; i--) if (!s2[i]) s2[i] = 255; //else s2[i] = 1;
+ ctx->swScale(ctx,&s2,&ss,0,sh,&d2,&ds);
+ for (i=ds*dh-1; i>=0; i--) if (d2[i]==0) d2[i] = 1; else if (d2[i]==255) d2[i] = 0;
+ freeSwsContext(ctx);
+}
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))
{
@@ -682,8 +724,8 @@ void spudec_draw_scaled(void *me, unsigned int dxs, unsigned int dys, void (*dra
scale_pixel *table_x;
scale_pixel *table_y;
if (spu->start_pts <= spu->now_pts && spu->now_pts < spu->end_pts) {
- if (spu->orig_frame_width == 0 || spu->orig_frame_height == 0
- || (spu->orig_frame_width == dxs && spu->orig_frame_height == dys)) {
+ if (!(spu_aamode&16) && (spu->orig_frame_width == 0 || spu->orig_frame_height == 0
+ || (spu->orig_frame_width == dxs && spu->orig_frame_height == dys))) {
if (spu->image)
{
draw_alpha(spu->start_col, spu->start_row, spu->width, spu->height,
@@ -729,7 +771,13 @@ void spudec_draw_scaled(void *me, unsigned int dxs, unsigned int dys, void (*dra
if (spu->scaled_width <= 1 || spu->scaled_height <= 1) {
goto nothing_to_do;
}
-#if ANTIALIASING_ALGORITHM == -1
+ switch(spu_aamode&15) {
+ case 4:
+ sws_spu_image(spu->scaled_image, spu->scaled_aimage,
+ spu->scaled_width, spu->scaled_height, spu->scaled_stride,
+ spu->image, spu->aimage, spu->width, spu->height, spu->stride);
+ break;
+ case 3:
table_x = calloc(spu->scaled_width, sizeof(scale_pixel));
table_y = calloc(spu->scaled_height, sizeof(scale_pixel));
if (!table_x || !table_y) {
@@ -742,7 +790,8 @@ void spudec_draw_scaled(void *me, unsigned int dxs, unsigned int dys, void (*dra
scale_image(x, y, table_x, table_y, spu);
free(table_x);
free(table_y);
-#elif ANTIALIASING_ALGORITHM == 0
+ break;
+ case 0:
/* no antialiasing */
for (y = 0; y < spu->scaled_height; ++y) {
int unscaled_y = y * 0x100 / scaley;
@@ -754,7 +803,8 @@ void spudec_draw_scaled(void *me, unsigned int dxs, unsigned int dys, void (*dra
spu->scaled_aimage[scaled_strides + x] = spu->aimage[strides + unscaled_x];
}
}
-#elif ANTIALIASING_ALGORITHM == 1
+ break;
+ case 1:
{
/* Intermediate antialiasing. */
for (y = 0; y < spu->scaled_height; ++y) {
@@ -792,7 +842,8 @@ void spudec_draw_scaled(void *me, unsigned int dxs, unsigned int dys, void (*dra
}
}
}
-#else
+ break;
+ case 2:
{
/* Best antialiasing. Very slow. */
/* Any pixel (x, y) represents pixels from the original
@@ -959,17 +1010,33 @@ void spudec_draw_scaled(void *me, unsigned int dxs, unsigned int dys, void (*dra
}
}
}
-#endif
+ }
nothing_to_do:
spu->scaled_frame_width = dxs;
spu->scaled_frame_height = dys;
}
}
if (spu->scaled_image){
-#if SUBPOS == 1
- /*set subs at the bottom, i don't like to put it at the very bottom, so -1 :)*/
- spu->scaled_start_row = dys - spu->scaled_height - 1;
-#endif
+ switch (spu_alignment) {
+ case 0:
+ spu->scaled_start_row = dys*sub_pos/100;
+ if (spu->scaled_start_row + spu->scaled_height > dys)
+ spu->scaled_start_row = dys - spu->scaled_height;
+ break;
+ case 1:
+ spu->scaled_start_row = dys*sub_pos/100 - spu->scaled_height/2;
+ if (sub_pos < 50) {
+ if (spu->scaled_start_row < 0) spu->scaled_start_row = 0;
+ } else {
+ if (spu->scaled_start_row + spu->scaled_height > dys)
+ spu->scaled_start_row = dys - spu->scaled_height;
+ }
+ break;
+ case 2:
+ spu->scaled_start_row = dys*sub_pos/100 - spu->scaled_height;
+ if (spu->scaled_start_row < 0) spu->scaled_start_row = 0;
+ break;
+ }
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);
spu->spu_changed = 0;