summaryrefslogtreecommitdiffstats
path: root/sub
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2016-06-17 21:54:12 +0200
committerwm4 <wm4@nowhere>2016-06-17 23:14:26 +0200
commit56058a95e55c200828525f555baf47f91d81ccdd (patch)
treeeb0687fe7c568bbf7bc6c96878e6c88aba8e72c5 /sub
parentf72eb5b394c5145c1f5ae2546f8c628550e928e4 (diff)
downloadmpv-56058a95e55c200828525f555baf47f91d81ccdd.tar.bz2
mpv-56058a95e55c200828525f555baf47f91d81ccdd.tar.xz
sub: fix --sub-gauss
Implement it directly in sd_lavc.c as well. Blurring requires extending the size of the sub-images by the blur radius. Since we now want sub_bitmaps to be packed into a single image, and we don't want to repack for blurring, we add some extra padding to each sub-bitmap in the initial packing, and then extend their size later. This relies on the previous bitmap_packer commit, which always adds the padding in all cases. Since blurring is now done on parts of a large bitmap, the data pointers can become unaligned, depending on their position. To avoid shitty libswscale printing a dumb warning, allocate an extra image, so that the blurring pass is done on two newly allocated images. (I don't find this feature important enough to waste more time on it.) The previous refactor accidentally broke this feature due to a logic bug in osd.c. It didn't matter before it happened to break, and doesn't matter now since the code paths are different.
Diffstat (limited to 'sub')
-rw-r--r--sub/img_convert.c55
-rw-r--r--sub/img_convert.h4
-rw-r--r--sub/osd.c4
-rw-r--r--sub/sd_lavc.c25
4 files changed, 37 insertions, 51 deletions
diff --git a/sub/img_convert.c b/sub/img_convert.c
index ebf9c209da..2015e49ca6 100644
--- a/sub/img_convert.c
+++ b/sub/img_convert.c
@@ -41,52 +41,25 @@ struct osd_conv_cache *osd_conv_cache_new(void)
return talloc_zero(NULL, struct osd_conv_cache);
}
-bool osd_conv_blur_rgba(struct osd_conv_cache *c, struct sub_bitmaps *imgs,
- double gblur)
+void mp_blur_rgba_sub_bitmap(struct sub_bitmap *d, double gblur)
{
- struct sub_bitmaps src = *imgs;
- if (src.format != SUBBITMAP_RGBA)
- return false;
+ struct mp_image *tmp1 = mp_image_alloc(IMGFMT_BGRA, d->w, d->h);
+ struct mp_image *tmp2 = mp_image_alloc(IMGFMT_BGRA, d->w, d->h);
+ if (tmp1 && tmp2) { // on OOM, skip region
+ struct mp_image s = {0};
+ mp_image_setfmt(&s, IMGFMT_BGRA);
+ mp_image_set_size(&s, d->w, d->h);
+ s.stride[0] = d->stride;
+ s.planes[0] = d->bitmap;
- talloc_free(c->parts);
- imgs->parts = c->parts = talloc_array(c, struct sub_bitmap, src.num_parts);
+ mp_image_copy(tmp1, &s);
- for (int n = 0; n < src.num_parts; n++) {
- struct sub_bitmap *d = &imgs->parts[n];
- struct sub_bitmap *s = &src.parts[n];
+ mp_image_sw_blur_scale(tmp2, tmp1, gblur);
- // add a transparent padding border to reduce artifacts
- int pad = 5;
- struct mp_image *temp = mp_image_alloc(IMGFMT_BGRA, s->w + pad * 2,
- s->h + pad * 2);
- if (!temp)
- continue; // on OOM, skip region
- 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 = mp_image_alloc(IMGFMT_BGRA, d->w, d->h);
- talloc_steal(c->parts, image);
- if (image) {
- d->stride = image->stride[0];
- d->bitmap = image->planes[0];
-
- mp_image_sw_blur_scale(image, temp, gblur);
- } else {
- // on OOM, skip region
- *d = *s;
- }
-
- talloc_free(temp);
+ mp_image_copy(&s, tmp2);
}
- return true;
+ talloc_free(tmp1);
+ talloc_free(tmp2);
}
// If RGBA parts need scaling, scale them.
diff --git a/sub/img_convert.h b/sub/img_convert.h
index d5baadced2..a0020df497 100644
--- a/sub/img_convert.h
+++ b/sub/img_convert.h
@@ -5,6 +5,7 @@
struct osd_conv_cache;
struct sub_bitmaps;
+struct sub_bitmap;
struct mp_rect;
struct osd_conv_cache *osd_conv_cache_new(void);
@@ -13,8 +14,7 @@ struct osd_conv_cache *osd_conv_cache_new(void);
// the converted image data into c, and change imgs to point to the data.
bool osd_conv_ass_to_rgba(struct osd_conv_cache *c, struct sub_bitmaps *imgs);
// Sub postprocessing
-bool osd_conv_blur_rgba(struct osd_conv_cache *c, struct sub_bitmaps *imgs,
- double gblur);
+void mp_blur_rgba_sub_bitmap(struct sub_bitmap *d, double gblur);
bool osd_scale_rgba(struct osd_conv_cache *c, struct sub_bitmaps *imgs);
bool mp_sub_bitmaps_bb(struct sub_bitmaps *imgs, struct mp_rect *out_bb);
diff --git a/sub/osd.c b/sub/osd.c
index ea33961c9f..a0618aafd9 100644
--- a/sub/osd.c
+++ b/sub/osd.c
@@ -295,10 +295,6 @@ static void render_object(struct osd_state *osd, struct osd_object *obj,
bool cached = false; // do we have a copy of all the image data?
- if (out_imgs->format == SUBBITMAP_RGBA && opts->sub_gauss != 0.0f)
- cached |= osd_conv_blur_rgba(obj->cache[2], out_imgs, opts->sub_gauss);
-
- // Do this conversion last to not trigger gauss blurring for ASS
if (formats[SUBBITMAP_RGBA] && out_imgs->format == SUBBITMAP_LIBASS)
cached |= osd_conv_ass_to_rgba(obj->cache[3], out_imgs);
diff --git a/sub/sd_lavc.c b/sub/sd_lavc.c
index a5f093bb54..fca4b611bf 100644
--- a/sub/sd_lavc.c
+++ b/sub/sd_lavc.c
@@ -32,6 +32,7 @@
#include "options/options.h"
#include "video/mp_image.h"
#include "video/out/bitmap_packer.h"
+#include "img_convert.h"
#include "sd.h"
#include "dec_sub.h"
@@ -209,8 +210,14 @@ static void read_sub_bitmaps(struct sd *sd, struct sub *sub)
packer_set_size(priv->packer, avsub->num_rects);
+ // If we blur, we want a transparent region around the bitmap data to
+ // avoid "cut off" artifacts on the borders.
+ bool apply_blur = opts->sub_gauss != 0.0f;
+ int extend = apply_blur ? 5 : 0;
// Assume consumers may use bilinear scaling on it (2x2 filter)
- priv->packer->padding = 1;
+ int padding = 1 + extend;
+
+ priv->packer->padding = padding;
for (int i = 0; i < avsub->num_rects; i++) {
struct AVSubtitleRect *r = avsub->rects[i];
@@ -278,11 +285,12 @@ static void read_sub_bitmaps(struct sd *sd, struct sub *sub)
memcpy(pal, data[1], r->nb_colors * 4);
convert_pal(pal, 256, opts->sub_gray);
- int padding = priv->packer->padding;
- for (int y = 0; y < b->h + padding; y++) {
+ for (int y = -padding; y < b->h + padding; y++) {
uint32_t *out = (uint32_t*)((char*)b->bitmap + y * b->stride);
int start = 0;
- if (y < b->h) {
+ for (int x = -padding; x < 0; x++)
+ out[x] = 0;
+ if (y >= 0 && y < b->h) {
uint8_t *in = data[0] + y * linesize[0];
for (int x = 0; x < b->w; x++)
*out++ = pal[*in++];
@@ -291,6 +299,15 @@ static void read_sub_bitmaps(struct sd *sd, struct sub *sub)
for (int x = start; x < b->w + padding; x++)
*out++ = 0;
}
+
+ b->bitmap = (char*)b->bitmap - extend * b->stride - extend * 4;
+ b->x -= extend;
+ b->y -= extend;
+ b->w += extend * 2;
+ b->h += extend * 2;
+
+ if (apply_blur)
+ mp_blur_rgba_sub_bitmap(b, opts->sub_gauss);
}
}