summaryrefslogtreecommitdiffstats
path: root/sub/osd_libass.c
diff options
context:
space:
mode:
Diffstat (limited to 'sub/osd_libass.c')
-rw-r--r--sub/osd_libass.c234
1 files changed, 74 insertions, 160 deletions
diff --git a/sub/osd_libass.c b/sub/osd_libass.c
index 29450535bc..11173dad7a 100644
--- a/sub/osd_libass.c
+++ b/sub/osd_libass.c
@@ -35,9 +35,6 @@ static const char osd_font_pfb[] =
#include "mp_core.h"
-// Map OSD symbols (e.g. OSD_PLAY) to the glyphs in osd_font_pfb[].
-#define OSD_CODEPOINTS 0xE000
-
// NOTE: \fs-5 to reduce the size of the symbols in relation to normal text.
// Done because libass doesn't center characters that are too high.
#define ASS_USE_OSD_FONT "{\\fnOSD\\fs-5}"
@@ -55,133 +52,20 @@ 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);
- }
+ 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 bool ass_bb(ASS_Image *imgs, int *x1, int *y1, int *x2, int *y2)
+static void update_font_style(ASS_Track *track, ASS_Style *style, double factor)
{
- *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);
-}
-
+ // Set to neutral base direction, as opposed to VSFilter LTR default
+ style->Encoding = -1;
-static void update_font_scale(ASS_Track *track, ASS_Style *style, double factor)
-{
// duplicated from ass_mp.c
- double fs = track->PlayResY * factor / 100.;
- /* The font size is always proportional to video height only;
- * real -subfont-autoscale behavior is not implemented.
- * Apply a correction that corresponds to about 4:3 aspect ratio
- * video to get a size somewhat closer to what non-libass rendering
- * would produce with the same text_font_scale_factor
- * and subtitle_autoscale.
- */
- if (subtitle_autoscale == 2)
- fs *= 1.3;
- else if (subtitle_autoscale == 3)
- fs *= 1.7;
- style->FontSize = fs;
+ style->FontSize = track->PlayResY * factor / 100.;
style->Outline = style->FontSize / 16;
}
@@ -193,7 +77,7 @@ static ASS_Track *create_osd_ass_track(struct osd_state *osd)
track->PlayResX = track->PlayResY * 1.33333;
- update_font_scale(track, style, text_font_scale_factor);
+ update_font_style(track, style, text_font_scale_factor);
style->Alignment = 5;
@@ -211,9 +95,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];
@@ -252,25 +143,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;
+ if (osd->progbar_type < 0) {
+ clear_obj(obj);
return;
}
@@ -286,22 +179,22 @@ void vo_update_text_progbar(struct osd_state *osd, mp_osd_obj_t* obj)
// Assume the OSD bar takes 2/3 of the OSD width at PlayResY=288 and
// FontSize=22 with an OSD aspect ratio of 16:9. Rescale as needed.
// xxx can fail when unknown fonts are involved
- double asp = (double)osd->w / osd->h;
+ double asp = (double)obj->vo_res.w / obj->vo_res.h;
double scale = (asp / 1.77777) * (obj->osd_track->PlayResY / 288.0);
style->ScaleX = style->ScaleY = scale;
style->FontSize = 22.0;
style->Outline = style->FontSize / 16 * scale;
- int active = (vo_osd_progbar_value * OSDBAR_ELEMS + 255) / 256;
+ int active = (osd->progbar_value * OSDBAR_ELEMS + 255) / 256;
active = FFMIN(OSDBAR_ELEMS, FFMAX(active, 0));
char *text = talloc_strdup(NULL, "{\\q2}");
- if (vo_osd_progbar_type >= 32) {
- text = append_utf8_buffer(text, vo_osd_progbar_type);
- } else if (vo_osd_progbar_type > 0) {
+ if (osd->progbar_type >= 32) {
+ text = append_utf8_buffer(text, osd->progbar_type);
+ } else if (osd->progbar_type > 0) {
text = talloc_strdup_append_buffer(text, ASS_USE_OSD_FONT);
- text = append_utf8_buffer(text, OSD_CODEPOINTS + vo_osd_progbar_type);
+ text = append_utf8_buffer(text, OSD_CODEPOINTS + osd->progbar_type);
text = talloc_strdup_append_buffer(text, "{\\r}");
}
@@ -317,21 +210,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;
}
@@ -340,7 +228,7 @@ void vo_update_text_sub(struct osd_state *osd, mp_osd_obj_t* obj)
ASS_Style *style = obj->osd_track->styles + obj->osd_track->default_style;
- update_font_scale(obj->osd_track, style, text_font_scale_factor);
+ update_font_style(obj->osd_track, style, text_font_scale_factor);
#if LIBASS_VERSION >= 0x01010000
ass_set_line_position(osd->osd_render, 100 - sub_pos);
#endif
@@ -351,14 +239,40 @@ 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, obj->vo_res.w, obj->vo_res.h);
+ ass_set_aspect_ratio(osd->osd_render, obj->vo_res.display_par, 1.0);
+ mp_ass_render_frame(osd->osd_render, obj->osd_track, 0,
+ &obj->parts_cache, out_imgs);
+ talloc_steal(obj, obj->parts_cache);
+}