summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--DOCS/man/en/changes.rst1
-rw-r--r--DOCS/man/en/options.rst7
-rw-r--r--core/cfg-mplayer.h1
-rw-r--r--core/options.h1
-rw-r--r--sub/img_convert.c42
-rw-r--r--sub/img_convert.h2
-rw-r--r--sub/sub.c5
-rw-r--r--video/sws_utils.c42
-rw-r--r--video/sws_utils.h3
9 files changed, 97 insertions, 7 deletions
diff --git a/DOCS/man/en/changes.rst b/DOCS/man/en/changes.rst
index 2f012f7b1b..b46691c888 100644
--- a/DOCS/man/en/changes.rst
+++ b/DOCS/man/en/changes.rst
@@ -110,6 +110,7 @@ Command line switches
--cursor-autohide-delay --cursor-autohide
-sub-fuzziness --autosub-match
-subfont-text-scale --sub-scale
+ -spugauss --sub-gauss
=================================== ===================================
input.conf and slave commands
diff --git a/DOCS/man/en/options.rst b/DOCS/man/en/options.rst
index e533618583..f0d9ddb57b 100644
--- a/DOCS/man/en/options.rst
+++ b/DOCS/man/en/options.rst
@@ -1882,6 +1882,13 @@
*NOTE*: <rate> > movie fps speeds the subtitles up for frame-based
subtitle files and slows them down for time-based ones.
+--sub-gauss=<0.0-3.0>
+ Apply gaussian blur to image subtitles (default: 0). This can help making
+ pixelated DVD/Vobsubs look nicer. A value other than 0 also switches to
+ software subtitle scaling. Might be slow.
+
+ *NOTE*: never applied to text subtitles.
+
--sub-pos=<0-100>
Specify the position of subtitles on the screen. The value is the vertical
position of the subtitle in % of the screen height.
diff --git a/core/cfg-mplayer.h b/core/cfg-mplayer.h
index d9dcb56e6a..ded7245f83 100644
--- a/core/cfg-mplayer.h
+++ b/core/cfg-mplayer.h
@@ -506,6 +506,7 @@ const m_option_t common_opts[] = {
{"autosub-match", &sub_match_fuzziness, CONF_TYPE_CHOICE, 0,
M_CHOICES(({"exact", 0}, {"fuzzy", 1}, {"all", 2}))},
{"sub-pos", &sub_pos, CONF_TYPE_INT, CONF_RANGE, 0, 100, NULL},
+ OPT_FLOATRANGE("sub-gauss", sub_gauss, 0, 0.0, 3.0),
OPT_MAKE_FLAGS("ass", ass_enabled, 0),
OPT_FLOATRANGE("sub-scale", sub_scale, 0, 0, 100),
OPT_FLOATRANGE("ass-line-spacing", ass_line_spacing, 0, -1000, 1000),
diff --git a/core/options.h b/core/options.h
index 28bdd70e3c..58d6a64e70 100644
--- a/core/options.h
+++ b/core/options.h
@@ -113,6 +113,7 @@ typedef struct MPOpts {
int sub_auto;
struct osd_style_opts *osd_style;
float sub_scale;
+ float sub_gauss;
int ass_enabled;
float ass_line_spacing;
int ass_top_margin;
diff --git a/sub/img_convert.c b/sub/img_convert.c
index e2eded24c3..274a83d833 100644
--- a/sub/img_convert.c
+++ b/sub/img_convert.c
@@ -28,6 +28,7 @@
#include "video/img_format.h"
#include "video/mp_image.h"
#include "video/sws_utils.h"
+#include "video/memcpy_pic.h"
struct osd_conv_cache {
struct sub_bitmap part;
@@ -86,3 +87,44 @@ bool osd_conv_idx_to_rgba(struct osd_conv_cache *c, struct sub_bitmaps *imgs)
}
return true;
}
+
+bool osd_conv_blur_rgba(struct osd_conv_cache *c, struct sub_bitmaps *imgs,
+ double gblur)
+{
+ struct sub_bitmaps src = *imgs;
+ if (src.format != SUBBITMAP_RGBA)
+ return false;
+
+ talloc_free(c->parts);
+ imgs->parts = c->parts = talloc_array(c, struct sub_bitmap, src.num_parts);
+
+ for (int n = 0; n < src.num_parts; n++) {
+ struct sub_bitmap *d = &imgs->parts[n];
+ struct sub_bitmap *s = &src.parts[n];
+
+ // add a transparent padding border to reduce artifacts
+ int pad = 5;
+ struct mp_image *temp = alloc_mpi(s->w + pad * 2, s->h + pad * 2,
+ IMGFMT_BGRA);
+ memset_pic(temp->planes[0], 0, temp->w * 4, temp->h, temp->stride[0]);
+ uint8_t *p0 = temp->planes[0] + pad * 4 + pad * temp->stride[0];
+ memcpy_pic(p0, s->bitmap, s->w * 4, s->h, temp->stride[0], s->stride);
+
+ double sx = (double)s->dw / s->w;
+ double sy = (double)s->dh / s->h;
+
+ d->x = s->x - pad * sx;
+ d->y = s->y - pad * sy;
+ d->w = d->dw = s->dw + pad * 2 * sx;
+ d->h = d->dh = s->dh + pad * 2 * sy;
+ struct mp_image *image = alloc_mpi(d->w, d->h, IMGFMT_BGRA);
+ talloc_steal(c->parts, image);
+ d->stride = image->stride[0];
+ d->bitmap = image->planes[0];
+
+ mp_image_sw_blur_scale(image, temp, gblur);
+
+ talloc_free(temp);
+ }
+ return true;
+}
diff --git a/sub/img_convert.h b/sub/img_convert.h
index c947c44f01..eab543051c 100644
--- a/sub/img_convert.h
+++ b/sub/img_convert.h
@@ -11,5 +11,7 @@ struct osd_conv_cache *osd_conv_cache_new(void);
// These functions convert from one OSD format to another. On success, they copy
// the converted image data into c, and change imgs to point to the data.
bool osd_conv_idx_to_rgba(struct osd_conv_cache *c, struct sub_bitmaps *imgs);
+bool osd_conv_blur_rgba(struct osd_conv_cache *c, struct sub_bitmaps *imgs,
+ double gblur);
#endif
diff --git a/sub/sub.c b/sub/sub.c
index dd8c887b4c..66ee6ea42c 100644
--- a/sub/sub.c
+++ b/sub/sub.c
@@ -172,6 +172,8 @@ static void render_object(struct osd_state *osd, struct osd_object *obj,
const bool formats[SUBBITMAP_COUNT],
struct sub_bitmaps *out_imgs)
{
+ struct MPOpts *opts = osd->opts;
+
*out_imgs = (struct sub_bitmaps) {0};
if (!osd_res_equals(res, obj->vo_res))
@@ -222,6 +224,9 @@ static void render_object(struct osd_state *osd, struct osd_object *obj,
if (formats[SUBBITMAP_RGBA] && out_imgs->format == SUBBITMAP_INDEXED)
cached |= osd_conv_idx_to_rgba(obj->cache[0], out_imgs);
+ if (out_imgs->format == SUBBITMAP_RGBA && opts->sub_gauss != 0.0f)
+ cached |= osd_conv_blur_rgba(obj->cache[1], out_imgs, opts->sub_gauss);
+
if (cached)
obj->cached = *out_imgs;
}
diff --git a/video/sws_utils.c b/video/sws_utils.c
index 663a0e282a..7a1385cfac 100644
--- a/video/sws_utils.c
+++ b/video/sws_utils.c
@@ -171,12 +171,10 @@ static void to_gbrp(struct mp_image *dst, struct mp_image *src,
talloc_free(temp);
}
-void mp_image_swscale(struct mp_image *dst, struct mp_image *src,
- int my_sws_flags)
-{
- if (dst->imgfmt == IMGFMT_GBRP)
- return to_gbrp(dst, src, my_sws_flags);
+static void mp_sws_set_conv(struct SwsContext *sws, struct mp_image *dst,
+ struct mp_image *src, int my_sws_flags)
+{
enum PixelFormat s_fmt = imgfmt2pixfmt(src->imgfmt);
if (src->imgfmt == IMGFMT_RGB8 || src->imgfmt == IMGFMT_BGR8)
s_fmt = PIX_FMT_PAL8;
@@ -195,8 +193,6 @@ void mp_image_swscale(struct mp_image *dst, struct mp_image *src,
s_range = s_range && s_yuv;
d_range = d_range && d_yuv;
- struct SwsContext *sws = sws_alloc_context();
-
av_opt_set_int(sws, "sws_flags", my_sws_flags, 0);
av_opt_set_int(sws, "srcw", src->w, 0);
@@ -210,6 +206,16 @@ void mp_image_swscale(struct mp_image *dst, struct mp_image *src,
sws_setColorspaceDetails(sws, sws_getCoefficients(s_csp), s_range,
sws_getCoefficients(d_csp), d_range,
0, 1 << 16, 1 << 16);
+}
+
+void mp_image_swscale(struct mp_image *dst, struct mp_image *src,
+ int my_sws_flags)
+{
+ if (dst->imgfmt == IMGFMT_GBRP)
+ return to_gbrp(dst, src, my_sws_flags);
+
+ struct SwsContext *sws = sws_alloc_context();
+ mp_sws_set_conv(sws, dst, src, my_sws_flags);
int res = sws_init_context(sws, NULL, NULL);
assert(res >= 0);
@@ -219,4 +225,26 @@ void mp_image_swscale(struct mp_image *dst, struct mp_image *src,
sws_freeContext(sws);
}
+void mp_image_sw_blur_scale(struct mp_image *dst, struct mp_image *src,
+ float gblur)
+{
+ struct SwsContext *sws = sws_alloc_context();
+
+ int flags = SWS_LANCZOS | SWS_FULL_CHR_H_INT | SWS_FULL_CHR_H_INP |
+ SWS_ACCURATE_RND | SWS_BITEXACT;
+
+ mp_sws_set_conv(sws, dst, src, flags);
+
+ SwsFilter *src_filter = sws_getDefaultFilter(gblur, gblur, 0, 0, 0, 0, 0);
+
+ int res = sws_init_context(sws, src_filter, NULL);
+ assert(res >= 0);
+
+ sws_scale(sws, (const uint8_t *const *) src->planes, src->stride,
+ 0, src->h, dst->planes, dst->stride);
+ sws_freeContext(sws);
+
+ sws_freeFilter(src_filter);
+}
+
// vim: ts=4 sw=4 et tw=80
diff --git a/video/sws_utils.h b/video/sws_utils.h
index d9e22d763b..22d16edefb 100644
--- a/video/sws_utils.h
+++ b/video/sws_utils.h
@@ -23,6 +23,9 @@ bool mp_sws_supported_format(int imgfmt);
void mp_image_swscale(struct mp_image *dst, struct mp_image *src,
int my_sws_flags);
+void mp_image_sw_blur_scale(struct mp_image *dst, struct mp_image *src,
+ float gblur);
+
#endif /* MP_SWS_UTILS_H */
// vim: ts=4 sw=4 et tw=80