summaryrefslogtreecommitdiffstats
path: root/sub
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2012-09-28 21:48:30 +0200
committerwm4 <wm4@nowhere>2012-10-16 07:26:30 +0200
commit5fc5ae752bfaa6bddf76aa1912b4b9724578f5dd (patch)
tree109fe6a200877e1388f7d8b69c85d4ae84e96fc5 /sub
parent3365514951e9c07ec3a21bb3898e5796c214f8b7 (diff)
downloadmpv-5fc5ae752bfaa6bddf76aa1912b4b9724578f5dd.tar.bz2
mpv-5fc5ae752bfaa6bddf76aa1912b4b9724578f5dd.tar.xz
sub: allow converting DVD subs to RGBA
The mplayer DVD sub decoder is the only remaining OSD image producer that still requires the old mplayer OSD format (SUBBITMAP_OLD_PLANAR). To make supporting this format optional in VOs, add a step that allows converting these images to RGBA in case the VO doesn't have direct support for it. Note: the mplayer DVD sub decoder uses the old mplayer OSD format (SUBBITMAP_OLD_PLANAR), which is assumed to use premultiplied alpha. However, it seems DVDs allow only binary transparency, so the rendered result will be the same.
Diffstat (limited to 'sub')
-rw-r--r--sub/img_convert.c52
-rw-r--r--sub/img_convert.h1
-rw-r--r--sub/sub.c4
-rw-r--r--sub/sub.h2
4 files changed, 53 insertions, 6 deletions
diff --git a/sub/img_convert.c b/sub/img_convert.c
index 38a367253c..6eef4a01a3 100644
--- a/sub/img_convert.c
+++ b/sub/img_convert.c
@@ -31,7 +31,7 @@ struct osd_conv_cache {
// for osd_conv_cache_alloc_old_p() (SUBBITMAP_PLANAR)
int allocated, stride;
struct old_osd_planar bmp;
- // for osd_conv_cache_alloc_old() (SUBBITMAP_OLD_PLANAR)
+ // for osd_conv_cache_alloc_bmp() (various other formats)
unsigned char *packed;
};
@@ -73,15 +73,16 @@ static void osd_conv_cache_alloc_old_p(struct osd_conv_cache *c, int w, int h)
};
}
-static void osd_conv_cache_alloc_old(struct osd_conv_cache *c, int w, int h)
+static void osd_conv_cache_alloc_bmp(struct osd_conv_cache *c, int w, int h,
+ int bpp)
{
size_t size = talloc_get_size(c->packed);
- size_t new_size = w * 2 * h;
+ size_t new_size = w * bpp * h;
if (new_size > size)
c->packed = talloc_realloc(c, c->packed, unsigned char, new_size);
c->part = (struct sub_bitmap) {
.bitmap = c->packed,
- .stride = w * 2,
+ .stride = w * bpp,
.w = w, .h = h,
.dw = w, .dh = h,
};
@@ -176,6 +177,47 @@ bool osd_conv_ass_to_old_p(struct osd_conv_cache *c, struct sub_bitmaps *imgs)
return true;
}
+// SUBBITMAP_OLD_PLANAR -> SUBBITMAP_RGBA
+bool osd_conv_old_p_to_rgba(struct osd_conv_cache *c, struct sub_bitmaps *imgs)
+{
+ struct sub_bitmaps src = *imgs;
+ if (src.format != SUBBITMAP_OLD_PLANAR || src.num_parts > 1)
+ return false;
+
+ imgs->format = SUBBITMAP_RGBA;
+ imgs->num_parts = 0;
+ imgs->parts = NULL;
+
+ if (src.num_parts == 0)
+ return true;
+
+ struct sub_bitmap *s = &src.parts[0];
+ struct old_osd_planar *p = s->bitmap;
+
+ osd_conv_cache_alloc_bmp(c, s->w, s->h, 4);
+
+ for (int y = 0; y < s->h; y++) {
+ unsigned char *y_src = p->bitmap + s->stride * y;
+ unsigned char *y_srca = p->alpha + s->stride * y;
+ unsigned char *cur = c->packed + y * s->w * 4;
+ for (int x = 0; x < s->w; x++) {
+ // This is incorrect, as input is premultiplied alpha, but output
+ // has to be non-premultiplied. However, this code is for
+ // compatibility with spudec.c only, and DVD subtitles have
+ // binary transparency only - the rendered result will be the same.
+ cur[x*4+0] = cur[x*4+1] = cur[x*4+2] = y_src[x];
+ cur[x*4+3] = -y_srca[x];
+ }
+ }
+
+ c->part.x = s->x;
+ c->part.y = s->y;
+
+ imgs->parts = &c->part;
+ imgs->num_parts = 1;
+ return true;
+}
+
// SUBBITMAP_OLD_PLANAR -> SUBBITMAP_OLD
bool osd_conv_old_p_to_old(struct osd_conv_cache *c, struct sub_bitmaps *imgs)
{
@@ -193,7 +235,7 @@ bool osd_conv_old_p_to_old(struct osd_conv_cache *c, struct sub_bitmaps *imgs)
struct sub_bitmap *s = &src.parts[0];
struct old_osd_planar *p = s->bitmap;
- osd_conv_cache_alloc_old(c, s->w, s->h);
+ osd_conv_cache_alloc_bmp(c, s->w, s->h, 2);
for (int y = 0; y < s->h; y++) {
unsigned char *y_src = p->bitmap + s->stride * y;
diff --git a/sub/img_convert.h b/sub/img_convert.h
index c40a8de2e4..b4201f606c 100644
--- a/sub/img_convert.h
+++ b/sub/img_convert.h
@@ -11,6 +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_old_p_to_old(struct osd_conv_cache *c, struct sub_bitmaps *imgs);
+bool osd_conv_old_p_to_rgba(struct osd_conv_cache *c, struct sub_bitmaps *imgs);
bool osd_conv_ass_to_old_p(struct osd_conv_cache *c, struct sub_bitmaps *imgs);
#endif
diff --git a/sub/sub.c b/sub/sub.c
index 3f1b08c185..182215310f 100644
--- a/sub/sub.c
+++ b/sub/sub.c
@@ -210,6 +210,10 @@ static bool render_object(struct osd_state *osd, struct osd_object *obj,
cached |= osd_conv_old_p_to_old(obj->cache[1], out_imgs);
}
+ if (formats[SUBBITMAP_RGBA] && out_imgs->format == SUBBITMAP_OLD_PLANAR) {
+ cached |= osd_conv_old_p_to_rgba(obj->cache[2], out_imgs);
+ }
+
if (cached)
obj->cached = *out_imgs;
diff --git a/sub/sub.h b/sub/sub.h
index 1dee0c8a8f..7deaf73b8e 100644
--- a/sub/sub.h
+++ b/sub/sub.h
@@ -34,7 +34,7 @@ struct vo;
#define MAX_OSD_PARTS 5
-#define OSD_CONV_CACHE_MAX 2
+#define OSD_CONV_CACHE_MAX 3
struct osd_object {
int type; // OSDTYPE_*