summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2012-09-28 21:38:52 +0200
committerwm4 <wm4@nowhere>2012-10-16 07:26:30 +0200
commit3365514951e9c07ec3a21bb3898e5796c214f8b7 (patch)
tree168eec4a47cbd32fa6e6485a884203e350ba8474
parent3099498154a06c6df0c365de2cc0af09686cd6e1 (diff)
downloadmpv-3365514951e9c07ec3a21bb3898e5796c214f8b7.tar.bz2
mpv-3365514951e9c07ec3a21bb3898e5796c214f8b7.tar.xz
sub: allow rendering OSD in ASS image format directly, simplify
Before this commit, the OSD was drawn using libass, but the resulting bitmaps were converted to the internal mplayer OSD format. We want to get rid of the old OSD format, because it's monochrome, and can't even be rendered directly using modern video output methods (like with OpenGL/Direct3D/VDPAU). Change it so that VOs can get the ASS images directly, without additional conversions. (This also has the consequence that the OSD can render colors now.) Currently, this is vo_gl3 only. The other VOs still use the old method. Also, the old OSD format is still used for all VOs with DVD subtitles (spudec). Rewrite sub.c. Remove all the awkward flags and bounding boxes and change detection things. It turns out that much of that isn't needed. Move code related to converting subtitle images to img_convert.c. (It has to be noted that all of these conversions were already done before in some places, and that the new code actually makes less use of them.)
-rw-r--r--Makefile1
-rw-r--r--libvo/video_out.h1
-rw-r--r--libvo/vo_gl3.c6
-rw-r--r--sub/ass_mp.c35
-rw-r--r--sub/ass_mp.h5
-rw-r--r--sub/dec_sub.h13
-rw-r--r--sub/img_convert.c214
-rw-r--r--sub/img_convert.h16
-rw-r--r--sub/osd_dummy.c22
-rw-r--r--sub/osd_libass.c195
-rw-r--r--sub/sd_ass.c36
-rw-r--r--sub/spudec.c40
-rw-r--r--sub/spudec.h3
-rw-r--r--sub/sub.c453
-rw-r--r--sub/sub.h83
15 files changed, 600 insertions, 523 deletions
diff --git a/Makefile b/Makefile
index c93fa6b31c..27aa1997dd 100644
--- a/Makefile
+++ b/Makefile
@@ -266,6 +266,7 @@ SRCS_COMMON = asxparser.c \
sub/sd_lavc.c \
sub/spudec.c \
sub/sub.c \
+ sub/img_convert.c \
sub/subassconvert.c \
sub/subreader.c \
sub/vobsub.c \
diff --git a/libvo/video_out.h b/libvo/video_out.h
index 2cd314f281..cdda6ec79f 100644
--- a/libvo/video_out.h
+++ b/libvo/video_out.h
@@ -66,6 +66,7 @@ enum mp_voctrl {
VOCTRL_BORDER,
VOCTRL_DRAW_EOSD,
VOCTRL_GET_EOSD_RES, // struct mp_eosd_res
+ VOCTRL_QUERY_EOSD_FORMAT, // int
VOCTRL_SET_DEINTERLACE,
VOCTRL_GET_DEINTERLACE,
diff --git a/libvo/vo_gl3.c b/libvo/vo_gl3.c
index 08f1514094..2af63700b4 100644
--- a/libvo/vo_gl3.c
+++ b/libvo/vo_gl3.c
@@ -1851,6 +1851,10 @@ static int control(struct vo *vo, uint32_t request, void *data)
r->mt = r->mb = p->border_y;
return VO_TRUE;
}
+ case VOCTRL_QUERY_EOSD_FORMAT: {
+ int *p = data;
+ return osd_to_gl_formats[*p].shader ? VO_TRUE : VO_NOTIMPL;
+ }
case VOCTRL_ONTOP:
if (!p->glctx->ontop)
break;
@@ -2366,7 +2370,7 @@ const struct vo_driver video_out_gl3 = {
.config = config,
.control = control,
.draw_slice = draw_slice,
- .draw_osd = emulate_draw_osd,
+ .draw_osd = draw_osd_with_eosd,
.flip_page = flip_page,
.check_events = check_events,
.uninit = uninit,
diff --git a/sub/ass_mp.c b/sub/ass_mp.c
index 202664578b..5766a847f8 100644
--- a/sub/ass_mp.c
+++ b/sub/ass_mp.c
@@ -264,6 +264,41 @@ void mp_ass_configure_fonts(ASS_Renderer *priv)
free(family);
}
+void mp_ass_render_frame(ASS_Renderer *renderer, ASS_Track *track, double time,
+ struct sub_bitmap **parts, struct sub_bitmaps *res)
+{
+ int changed;
+ res->imgs = ass_render_frame(renderer, track, time, &changed);
+ if (changed == 2)
+ res->bitmap_id = ++res->bitmap_pos_id;
+ else if (changed)
+ res->bitmap_pos_id++;
+ res->format = SUBBITMAP_LIBASS;
+
+ res->parts = *parts;
+ res->num_parts = 0;
+ int num_parts_alloc = MP_TALLOC_ELEMS(res->parts);
+ for (struct ass_image *img = res->imgs; img; img = img->next) {
+ if (img->w == 0 || img->h == 0)
+ continue;
+ if (res->num_parts >= num_parts_alloc) {
+ num_parts_alloc = FFMAX(num_parts_alloc * 2, 32);
+ res->parts = talloc_realloc(NULL, res->parts, struct sub_bitmap,
+ num_parts_alloc);
+ }
+ struct sub_bitmap *p = &res->parts[res->num_parts];
+ p->bitmap = img->bitmap;
+ p->stride = img->stride;
+ p->libass.color = img->color;
+ p->dw = p->w = img->w;
+ p->dh = p->h = img->h;
+ p->x = img->dst_x;
+ p->y = img->dst_y;
+ res->num_parts++;
+ }
+ *parts = res->parts;
+}
+
static int map_ass_level[] = {
MSGL_ERR, // 0 "FATAL errors"
MSGL_WARN,
diff --git a/sub/ass_mp.h b/sub/ass_mp.h
index 3cfbe147b7..805e9d7310 100644
--- a/sub/ass_mp.h
+++ b/sub/ass_mp.h
@@ -46,6 +46,11 @@ void mp_ass_configure(ASS_Renderer *priv, struct MPOpts *opts,
void mp_ass_configure_fonts(ASS_Renderer *priv);
ASS_Library *mp_ass_init(struct MPOpts *opts);
+struct sub_bitmap;
+struct sub_bitmaps;
+void mp_ass_render_frame(ASS_Renderer *renderer, ASS_Track *track, double time,
+ struct sub_bitmap **parts, struct sub_bitmaps *res);
+
#else /* CONFIG_ASS */
/* Needed for EOSD code using this type to compile */
diff --git a/sub/dec_sub.h b/sub/dec_sub.h
index df6aaf9b91..9c75506c4c 100644
--- a/sub/dec_sub.h
+++ b/sub/dec_sub.h
@@ -4,21 +4,26 @@
#include <stdbool.h>
#include <stdint.h>
-#define MAX_OSD_PARTS 8
-
struct sh_sub;
struct osd_state;
struct ass_track;
enum sub_bitmap_format {
- SUBBITMAP_EMPTY,
+ SUBBITMAP_EMPTY = 0,// no bitmaps; always has num_parts==0
SUBBITMAP_LIBASS, // A8, with a per-surface blend color (libass.color)
- SUBBITMAP_RGBA, // B8G8R8A8
+ SUBBITMAP_RGBA, // B8G8R8A8, can be scaled
SUBBITMAP_OLD, // I8A8 (monochrome), premultiplied alpha
+ SUBBITMAP_OLD_PLANAR, // like previous, but bitmap points to old_osd_planar
SUBBITMAP_COUNT
};
+// For SUBBITMAP_OLD_PANAR
+struct old_osd_planar {
+ unsigned char *bitmap;
+ unsigned char *alpha;
+};
+
typedef struct mp_eosd_res {
int w, h; // screen dimensions, including black borders
int mt, mb, ml, mr; // borders (top, bottom, left, right)
diff --git a/sub/img_convert.c b/sub/img_convert.c
new file mode 100644
index 0000000000..38a367253c
--- /dev/null
+++ b/sub/img_convert.c
@@ -0,0 +1,214 @@
+/*
+ * This file is part of mplayer.
+ *
+ * mplayer is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * mplayer is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with mplayer. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <string.h>
+#include <assert.h>
+
+#include <libavutil/mem.h>
+#include <libavutil/common.h>
+
+#include "talloc.h"
+
+#include "img_convert.h"
+#include "sub.h"
+
+struct osd_conv_cache {
+ struct sub_bitmap part;
+ // 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)
+ unsigned char *packed;
+};
+
+static int osd_conv_cache_destroy(void *p)
+{
+ struct osd_conv_cache *c = p;
+ av_free(c->bmp.bitmap);
+ av_free(c->bmp.alpha);
+ return 0;
+}
+
+struct osd_conv_cache *osd_conv_cache_new(void)
+{
+ struct osd_conv_cache *c = talloc_zero(NULL, struct osd_conv_cache);
+ talloc_set_destructor(c, &osd_conv_cache_destroy);
+ return c;
+}
+
+// allocates/enlarges the alpha/bitmap buffer
+static void osd_conv_cache_alloc_old_p(struct osd_conv_cache *c, int w, int h)
+{
+ assert(w > 0 && h > 0);
+ c->stride = (w + 7) & (~7);
+ int len = c->stride * h;
+ if (c->allocated < len) {
+ av_free(c->bmp.bitmap);
+ av_free(c->bmp.alpha);
+ c->allocated = len;
+ c->bmp.bitmap = av_malloc(len);
+ c->bmp.alpha = av_malloc(len);
+ }
+ memset(c->bmp.bitmap, sub_bg_color, len);
+ memset(c->bmp.alpha, sub_bg_alpha, len);
+ c->part = (struct sub_bitmap) {
+ .bitmap = &c->bmp,
+ .stride = c->stride,
+ .w = w, .h = h,
+ .dw = w, .dh = h,
+ };
+}
+
+static void osd_conv_cache_alloc_old(struct osd_conv_cache *c, int w, int h)
+{
+ size_t size = talloc_get_size(c->packed);
+ size_t new_size = w * 2 * 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,
+ .w = w, .h = h,
+ .dw = w, .dh = h,
+ };
+}
+
+static void draw_alpha_ass_to_old(unsigned char *src, int src_w, int src_h,
+ int src_stride, unsigned char *dst_a,
+ unsigned char *dst_i, size_t dst_stride,
+ int dst_x, int dst_y, uint32_t color)
+{
+ const unsigned int r = (color >> 24) & 0xff;
+ const unsigned int g = (color >> 16) & 0xff;
+ const unsigned int b = (color >> 8) & 0xff;
+ const unsigned int a = 0xff - (color & 0xff);
+
+ int gray = (r + g + b) / 3; // not correct
+
+ dst_a += dst_y * dst_stride + dst_x;
+ dst_i += dst_y * dst_stride + dst_x;
+
+ int src_skip = src_stride - src_w;
+ int dst_skip = dst_stride - src_w;
+
+ for (int y = 0; y < src_h; y++) {
+ for (int x = 0; x < src_w; x++) {
+ unsigned char as = (*src * a) >> 8;
+ unsigned char bs = (gray * as) >> 8;
+ // to mplayer scale
+ as = -as;
+
+ unsigned char *a = dst_a;
+ unsigned char *b = dst_i;
+
+ // NOTE: many special cases, because alpha=0 means transparency,
+ // while alpha=1..255 is opaque..transparent
+ if (as) {
+ *b = ((*b * as) >> 8) + bs;
+ if (*a) {
+ *a = (*a * as) >> 8;
+ if (*a < 1)
+ *a = 1;
+ } else {
+ *a = as;
+ }
+ }
+
+ dst_a++;
+ dst_i++;
+ src++;
+ }
+ dst_a += dst_skip;
+ dst_i += dst_skip;
+ src += src_skip;
+ }
+}
+
+static void render_ass_to_old(unsigned char *a, unsigned char *i,
+ size_t stride, int x, int y,
+ struct sub_bitmaps *imgs)
+{
+ for (int n = 0; n < imgs->num_parts; n++) {
+ struct sub_bitmap *p = &imgs->parts[n];
+ draw_alpha_ass_to_old(p->bitmap, p->w, p->h, p->stride, a, i, stride,
+ x + p->x, y + p->y, p->libass.color);
+ }
+}
+
+// SUBBITMAP_LIBASS -> SUBBITMAP_OLD_PLANAR
+bool osd_conv_ass_to_old_p(struct osd_conv_cache *c, struct sub_bitmaps *imgs)
+{
+ struct sub_bitmaps src = *imgs;
+ if (src.format != SUBBITMAP_LIBASS || src.scaled)
+ return false;
+
+ imgs->format = SUBBITMAP_OLD_PLANAR;
+ imgs->num_parts = 0;
+ imgs->parts = NULL;
+
+ int x1, y1, x2, y2;
+ if (!sub_bitmaps_bb(&src, &x1, &y1, &x2, &y2))
+ return true;
+
+ osd_conv_cache_alloc_old_p(c, x2 - x1, y2 - y1);
+
+ render_ass_to_old(c->bmp.alpha, c->bmp.bitmap, c->stride, -x1, -y1, &src);
+
+ c->part.x = x1;
+ c->part.y = y1;
+
+ 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)
+{
+ struct sub_bitmaps src = *imgs;
+ if (src.format != SUBBITMAP_OLD_PLANAR || src.num_parts > 1)
+ return false;
+
+ imgs->format = SUBBITMAP_OLD;
+ 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_old(c, s->w, s->h);
+
+ 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 * 2;
+ for (int x = 0; x < s->w; x++) {
+ cur[x*2+0] = y_src[x];
+ cur[x*2+1] = -y_srca[x];
+ }
+ }
+
+ c->part.x = s->x;
+ c->part.y = s->y;
+
+ imgs->parts = &c->part;
+ imgs->num_parts = 1;
+ return true;
+}
diff --git a/sub/img_convert.h b/sub/img_convert.h
new file mode 100644
index 0000000000..c40a8de2e4
--- /dev/null
+++ b/sub/img_convert.h
@@ -0,0 +1,16 @@
+#ifndef MPLAYER_SUB_IMG_CONVERT_H
+#define MPLAYER_SUB_IMG_CONVERT_H
+
+#include <stdbool.h>
+
+struct osd_conv_cache;
+struct sub_bitmaps;
+
+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_ass_to_old_p(struct osd_conv_cache *c, struct sub_bitmaps *imgs);
+
+#endif
diff --git a/sub/osd_dummy.c b/sub/osd_dummy.c
index d869fe16c8..782ce21942 100644
--- a/sub/osd_dummy.c
+++ b/sub/osd_dummy.c
@@ -6,18 +6,6 @@
#include "talloc.h"
#include "sub.h"
-void vo_update_text_osd(struct osd_state *osd, mp_osd_obj_t *obj)
-{
-}
-
-void vo_update_text_progbar(struct osd_state *osd, mp_osd_obj_t *obj)
-{
-}
-
-void vo_update_text_sub(struct osd_state *osd, mp_osd_obj_t *obj)
-{
-}
-
void osd_init_backend(struct osd_state *osd)
{
}
@@ -26,14 +14,12 @@ void osd_destroy_backend(struct osd_state *osd)
{
}
-void osd_font_invalidate(void)
-{
-}
-
-void osd_font_load(struct osd_state *osd)
+void osd_get_function_sym(char *buffer, size_t buffer_size, int osd_function)
{
}
-void osd_get_function_sym(char *buffer, size_t buffer_size, int osd_function)
+void osd_object_get_bitmaps(struct osd_state *osd, struct osd_object *obj,
+ struct sub_bitmaps *out_imgs)
{
+ *out_imgs = (struct sub_bitmaps) {0};
}
diff --git a/sub/osd_libass.c b/sub/osd_libass.c
index e770215ce6..2d596a6516 100644
--- a/sub/osd_libass.c
+++ b/sub/osd_libass.c
@@ -55,117 +55,13 @@ void osd_init_backend(struct osd_state *osd)
void osd_destroy_backend(struct osd_state *osd)
{
- if (osd) {
- if (osd->osd_render)
- ass_renderer_done(osd->osd_render);
- osd->osd_render = NULL;
- ass_library_done(osd->osd_ass_library);
- osd->osd_ass_library = NULL;
- }
-}
-
-static void eosd_draw_alpha_a8i8(unsigned char *src,
- int src_w, int src_h,
- int src_stride,
- unsigned char *dst_a,
- unsigned char *dst_i,
- size_t dst_stride,
- int dst_x, int dst_y,
- uint32_t color)
-{
- const unsigned int r = (color >> 24) & 0xff;
- const unsigned int g = (color >> 16) & 0xff;
- const unsigned int b = (color >> 8) & 0xff;
- const unsigned int a = 0xff - (color & 0xff);
-
- int gray = (r + g + b) / 3; // not correct
-
- dst_a += dst_y * dst_stride + dst_x;
- dst_i += dst_y * dst_stride + dst_x;
-
- int src_skip = src_stride - src_w;
- int dst_skip = dst_stride - src_w;
-
- for (int y = 0; y < src_h; y++) {
- for (int x = 0; x < src_w; x++) {
- unsigned char as = (*src * a) >> 8;
- unsigned char bs = (gray * as) >> 8;
- // to mplayer scale
- as = -as;
-
- unsigned char *a = dst_a;
- unsigned char *b = dst_i;
-
- // NOTE: many special cases, because alpha=0 means transparency,
- // while alpha=1..255 is opaque..transparent
- if (as) {
- *b = ((*b * as) >> 8) + bs;
- if (*a) {
- *a = (*a * as) >> 8;
- if (*a < 1)
- *a = 1;
- } else {
- *a = as;
- }
- }
-
- dst_a++;
- dst_i++;
- src++;
- }
- dst_a += dst_skip;
- dst_i += dst_skip;
- src += src_skip;
- }
-}
-
-static void eosd_render_a8i8(unsigned char *a, unsigned char *i, size_t stride,
- int x, int y, ASS_Image *imgs)
-{
- for (ASS_Image *p = imgs; p; p = p->next) {
- eosd_draw_alpha_a8i8(p->bitmap, p->w, p->h, p->stride, a, i, stride,
- x + p->dst_x, y + p->dst_y, p->color);
- }
-}
-
-static bool ass_bb(ASS_Image *imgs, int *x1, int *y1, int *x2, int *y2)
-{
- *x1 = *y1 = INT_MAX;
- *x2 = *y2 = INT_MIN;
- for (ASS_Image *p = imgs; p; p = p->next) {
- *x1 = FFMIN(*x1, p->dst_x);
- *y1 = FFMIN(*y1, p->dst_y);
- *x2 = FFMAX(*x2, p->dst_x + p->w);
- *y2 = FFMAX(*y2, p->dst_y + p->h);
- }
- return *x1 < *x2 && *y1 < *y2;
-}
-
-static void draw_ass_osd(struct osd_state *osd, mp_osd_obj_t *obj)
-{
- ass_set_frame_size(osd->osd_render, osd->w, osd->h);
-
- ASS_Image *imgs = ass_render_frame(osd->osd_render, obj->osd_track, 0,
- NULL);
-
- int x1, y1, x2, y2;
- if (!ass_bb(imgs, &x1, &y1, &x2, &y2)) {
- obj->flags &= ~OSDFLAG_VISIBLE;
- return;
- }
-
- obj->bbox.x1 = x1;
- obj->bbox.y1 = y1;
- obj->bbox.x2 = x2;
- obj->bbox.y2 = y2;
- obj->flags |= OSDFLAG_BBOX;
- osd_alloc_buf(obj);
-
- eosd_render_a8i8(obj->alpha_buffer, obj->bitmap_buffer, obj->stride,
- -x1, -y1, imgs);
+ if (osd->osd_render)
+ ass_renderer_done(osd->osd_render);
+ osd->osd_render = NULL;
+ ass_library_done(osd->osd_ass_library);
+ osd->osd_ass_library = NULL;
}
-
static void update_font_scale(ASS_Track *track, ASS_Style *style, double factor)
{
// duplicated from ass_mp.c
@@ -211,9 +107,16 @@ static ASS_Event *get_osd_ass_event(ASS_Track *track)
event->Start = 0;
event->Duration = 100;
event->Style = track->default_style;
+ assert(event->Text == NULL);
return event;
}
+static void clear_obj(struct osd_object *obj)
+{
+ if (obj->osd_track)
+ ass_flush_events(obj->osd_track);
+}
+
static char *append_utf8_buffer(char *buffer, uint32_t codepoint)
{
char data[8];
@@ -257,25 +160,27 @@ static char *mangle_ass(const char *in)
return res;
}
-void vo_update_text_osd(struct osd_state *osd, mp_osd_obj_t* obj)
+static void update_osd(struct osd_state *osd, struct osd_object *obj)
{
+ if (!osd->osd_text[0]) {
+ clear_obj(obj);
+ return;
+ }
+
if (!obj->osd_track)
obj->osd_track = create_osd_ass_track(osd);
ASS_Event *event = get_osd_ass_event(obj->osd_track);
- event->Text = mangle_ass(osd->osd_text);
- draw_ass_osd(osd, obj);
- talloc_free(event->Text);
- event->Text = NULL;
+ char *text = mangle_ass(osd->osd_text);
+ event->Text = strdup(text);
+ talloc_free(text);
}
#define OSDBAR_ELEMS 46
-void vo_update_text_progbar(struct osd_state *osd, mp_osd_obj_t* obj)
+static void update_progbar(struct osd_state *osd, struct osd_object *obj)
{
- obj->flags |= OSDFLAG_CHANGED | OSDFLAG_VISIBLE;
-
if (vo_osd_progbar_type < 0) {
- obj->flags &= ~OSDFLAG_VISIBLE;
+ clear_obj(obj);
return;
}
@@ -322,21 +227,16 @@ void vo_update_text_progbar(struct osd_state *osd, mp_osd_obj_t* obj)
text = append_utf8_buffer(text, OSD_CODEPOINTS + OSD_PB_END);
ASS_Event *event = get_osd_ass_event(obj->osd_track);
- event->Text = text;
- draw_ass_osd(osd, obj);
- event->Text = NULL;
-
+ event->Text = strdup(text);
talloc_free(text);
}
-void vo_update_text_sub(struct osd_state *osd, mp_osd_obj_t* obj)
+static void update_sub(struct osd_state *osd, struct osd_object *obj)
{
struct MPOpts *opts = osd->opts;
- obj->flags |= OSDFLAG_CHANGED | OSDFLAG_VISIBLE;
-
- if (!vo_sub || !opts->sub_visibility) {
- obj->flags &= ~OSDFLAG_VISIBLE;
+ if (!(vo_sub && opts->sub_visibility)) {
+ clear_obj(obj);
return;
}
@@ -354,14 +254,39 @@ void vo_update_text_sub(struct osd_state *osd, mp_osd_obj_t* obj)
text = talloc_asprintf_append_buffer(text, "%s\n", vo_sub->text[n]);
ASS_Event *event = get_osd_ass_event(obj->osd_track);
- event->Text = mangle_ass(text);
- draw_ass_osd(osd, obj);
- talloc_free(event->Text);
- event->Text = NULL;
-
+ char *escaped_text = mangle_ass(text);
+ event->Text = strdup(escaped_text);
+ talloc_free(escaped_text);
talloc_free(text);
}
-// unneeded
-void osd_font_invalidate(void) {}
-void osd_font_load(struct osd_state *osd) {}
+static void update_object(struct osd_state *osd, struct osd_object *obj)
+{
+ switch (obj->type) {
+ case OSDTYPE_OSD:
+ update_osd(osd, obj);
+ break;
+ case OSDTYPE_SUBTITLE:
+ update_sub(osd, obj);
+ break;
+ case OSDTYPE_PROGBAR:
+ update_progbar(osd, obj);
+ break;
+ }
+}
+
+void osd_object_get_bitmaps(struct osd_state *osd, struct osd_object *obj,
+ struct sub_bitmaps *out_imgs)
+{
+ if (obj->force_redraw)
+ update_object(osd, obj);
+
+ *out_imgs = (struct sub_bitmaps) {0};
+ if (!obj->osd_track)
+ return;
+
+ ass_set_frame_size(osd->osd_render, osd->w, osd->h);
+ mp_ass_render_frame(osd->osd_render, obj->osd_track, 0,
+ &obj->parts_cache, out_imgs);
+ talloc_steal(obj, obj->parts_cache);
+}
diff --git a/sub/sd_ass.c b/sub/sd_ass.c
index aa190ee4ac..478b1c96a9 100644
--- a/sub/sd_ass.c
+++ b/sub/sd_ass.c
@@ -141,39 +141,9 @@ static void get_bitmaps(struct sh_sub *sh, struct osd_state *osd,
ASS_Renderer *renderer = osd->ass_renderer;
mp_ass_configure(renderer, opts, &osd->dim, osd->unscaled);
ass_set_aspect_ratio(renderer, scale, 1);
- int changed;
- res->imgs = ass_render_frame(renderer, ctx->ass_track,
- osd->sub_pts * 1000 + .5, &changed);
- if (changed == 2)
- res->bitmap_id = ++res->bitmap_pos_id;
- else if (changed)
- res->bitmap_pos_id++;
- res->format = SUBBITMAP_LIBASS;
-
- int num_parts = 0;
- int num_parts_alloc = MP_TALLOC_ELEMS(ctx->parts);
- struct ass_image *img = res->imgs;
- while (img) {
- if (img->w == 0 || img->h == 0)
- continue;
- if (num_parts >= num_parts_alloc) {
- num_parts_alloc = FFMAX(num_parts_alloc * 2, 32);
- ctx->parts = talloc_realloc(ctx, ctx->parts, struct sub_bitmap,
- num_parts_alloc);
- }
- struct sub_bitmap *p = &ctx->parts[num_parts];
- p->bitmap = img->bitmap;
- p->stride = img->stride;
- p->libass.color = img->color;
- p->dw = p->w = img->w;
- p->dh = p->h = img->h;
- p->x = img->dst_x;
- p->y = img->dst_y;
- img = img->next;
- num_parts++;
- }
- res->parts = ctx->parts;
- res->num_parts = num_parts;
+ mp_ass_render_frame(renderer, ctx->ass_track, osd->sub_pts * 1000 + .5,
+ &ctx->parts, res);
+ talloc_steal(ctx, ctx->parts);
}
static void reset(struct sh_sub *sh, struct osd_state *osd)
diff --git a/sub/spudec.c b/sub/spudec.c
index 47e1676e2e..a58df60b17 100644
--- a/sub/spudec.c
+++ b/sub/spudec.c
@@ -34,6 +34,7 @@
#include <unistd.h>
#include <string.h>
#include <math.h>
+#include <assert.h>
#include <libavutil/common.h>
#include <libavutil/intreadwrite.h>
@@ -44,6 +45,7 @@
#include "spudec.h"
#include "vobsub.h"
+#include "sub.h"
#include "mpcommon.h"
/* Valid values for spu_aamode:
@@ -57,7 +59,6 @@
int spu_aamode = 3;
int spu_alignment = -1;
float spu_gaussvar = 1.0;
-extern int sub_pos;
typedef struct spu_packet_t packet_t;
struct spu_packet_t {
@@ -123,6 +124,9 @@ typedef struct {
unsigned int is_forced_sub; /* true if current subtitle is a forced subtitle */
struct palette_crop_cache palette_crop_cache;
+
+ struct sub_bitmap borrowed_sub_part;
+ struct old_osd_planar borrowed_sub_image;
} spudec_handle_t;
static void spudec_queue_packet(spudec_handle_t *this, packet_t *packet)
@@ -722,6 +726,40 @@ void spudec_set_forced_subs_only(void * const this, const unsigned int flag)
}
}
+static void get_data(void *ctx, int x0,int y0, int w,int h, unsigned char* src,
+ unsigned char *srca, int stride)
+{
+ struct sub_bitmaps *bmp = ctx;
+ assert(bmp->num_parts == 0);
+ bmp->num_parts = 1;
+ struct sub_bitmap *s = &bmp->parts[0];
+ struct old_osd_planar *p = s->bitmap;
+ // We know that the data stays valid until the next SPU related call
+ p->bitmap = src;
+ p->alpha = srca;
+ *s = (struct sub_bitmap) {
+ .bitmap = p, .stride = stride,
+ .x = x0, .y = y0,
+ .w = w, .h = h,
+ .dw = w, .dh = h,
+ };
+}
+
+void spudec_get_bitmap(void *this, int w, int h, struct sub_bitmaps *res)
+{
+ spudec_handle_t *spu = this;
+ *res = (struct sub_bitmaps) {
+ .format = SUBBITMAP_OLD_PLANAR,
+ .parts = &spu->borrowed_sub_part,
+ };
+ res->parts[0].bitmap = &spu->borrowed_sub_image;
+ if (w == -1 && h == -1) {
+ spudec_draw(this, get_data, res);
+ } else {
+ spudec_draw_scaled(this, w, h, get_data, res);
+ }
+}
+
void spudec_draw(void *this, void (*draw_alpha)(void *ctx, int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride), void *ctx)
{
spudec_handle_t *spu = this;
diff --git a/sub/spudec.h b/sub/spudec.h
index 6104ad7228..2e2542128a 100644
--- a/sub/spudec.h
+++ b/sub/spudec.h
@@ -21,10 +21,13 @@
#include <stdint.h>
+struct sub_bitmaps;
+
void spudec_heartbeat(void *this, unsigned int pts100);
void spudec_assemble(void *this, unsigned char *packet, unsigned int len, int pts100);
void spudec_draw(void *this, void (*draw_alpha)(void *ctx, int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride), void *ctx);
void spudec_draw_scaled(void *this, unsigned int dxs, unsigned int dys, void (*draw_alpha)(void *ctx, int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride), void *ctx);
+void spudec_get_bitmap(void *this, int w, int h, struct sub_bitmaps *res);
int spudec_apply_palette_crop(void *this, uint32_t palette, int sx, int ex, int sy, int ey);
void *spudec_new_scaled(unsigned int *palette, unsigned int frame_width, unsigned int frame_height, uint8_t *extradata, int extradata_len);
void *spudec_new(unsigned int *palette);
diff --git a/sub/sub.c b/sub/sub.c
index 8b89ca497c..3f1b08c185 100644
--- a/sub/sub.c
+++ b/sub/sub.c
@@ -21,7 +21,6 @@
#include <string.h>
#include <assert.h>
-#include <libavutil/mem.h>
#include <libavutil/common.h>
#include "config.h"
@@ -37,6 +36,7 @@
#include "libvo/video_out.h"
#include "sub.h"
#include "sub/ass_mp.h"
+#include "img_convert.h"
#include "spudec.h"
@@ -86,185 +86,57 @@ float font_factor = 0.75;
float sub_delay = 0;
float sub_fps = 0;
-// allocates/enlarges the alpha/bitmap buffer
-void osd_alloc_buf(mp_osd_obj_t* obj)
-{
- int len;
- if (obj->bbox.x2 < obj->bbox.x1) obj->bbox.x2 = obj->bbox.x1;
- if (obj->bbox.y2 < obj->bbox.y1) obj->bbox.y2 = obj->bbox.y1;
- obj->stride = ((obj->bbox.x2-obj->bbox.x1)+7)&(~7);
- len = obj->stride*(obj->bbox.y2-obj->bbox.y1);
- if (obj->allocated<len) {
- obj->allocated = len;
- av_free(obj->bitmap_buffer);
- av_free(obj->alpha_buffer);
- obj->bitmap_buffer = av_malloc(len);
- obj->alpha_buffer = av_malloc(len);
- }
- memset(obj->bitmap_buffer, sub_bg_color, len);
- memset(obj->alpha_buffer, sub_bg_alpha, len);
-}
-
-// renders the buffer
-void vo_draw_text_from_buffer(mp_osd_obj_t* obj,void (*draw_alpha)(void *ctx, int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride), void *ctx)
-{
- if (obj->allocated > 0) {
- draw_alpha(ctx,
- obj->bbox.x1,obj->bbox.y1,
- obj->bbox.x2-obj->bbox.x1,
- obj->bbox.y2-obj->bbox.y1,
- obj->bitmap_buffer,
- obj->alpha_buffer,
- obj->stride);
- }
-}
-
-inline static void vo_update_spudec_sub(struct osd_state *osd, mp_osd_obj_t* obj)
-{
- unsigned int bbox[4];
- spudec_calc_bbox(vo_spudec, osd->w, osd->h, bbox);
- obj->bbox.x1 = bbox[0];
- obj->bbox.x2 = bbox[1];
- obj->bbox.y1 = bbox[2];
- obj->bbox.y2 = bbox[3];
- obj->flags |= OSDFLAG_BBOX;
-}
-
-inline static void vo_draw_spudec_sub(mp_osd_obj_t* obj, void (*draw_alpha)(void *ctx, int x0, int y0, int w, int h, unsigned char* src, unsigned char* srca, int stride), void *ctx)
-{
- spudec_draw_scaled(vo_spudec, obj->dxs, obj->dys, draw_alpha, ctx);
-}
-
void *vo_spudec=NULL;
void *vo_vobsub=NULL;
-mp_osd_obj_t* vo_osd_list=NULL;
-
-static mp_osd_obj_t* new_osd_obj(int type){
- mp_osd_obj_t* osd=malloc(sizeof(mp_osd_obj_t));
- memset(osd,0,sizeof(mp_osd_obj_t));
- osd->next=vo_osd_list;
- vo_osd_list=osd;
- osd->type=type;
- osd->alpha_buffer = NULL;
- osd->bitmap_buffer = NULL;
- osd->allocated = -1;
- return osd;
-}
+static struct osd_state *global_osd;
-void osd_free(struct osd_state *osd)
-{
- osd_destroy_backend(osd);
- mp_osd_obj_t* obj=vo_osd_list;
- while(obj){
- mp_osd_obj_t* next=obj->next;
- av_free(obj->alpha_buffer);