summaryrefslogtreecommitdiffstats
path: root/sub
diff options
context:
space:
mode:
Diffstat (limited to 'sub')
-rw-r--r--sub/ass_mp.c25
-rw-r--r--sub/ass_mp.h2
-rw-r--r--sub/osd.h3
-rw-r--r--sub/osd_libass.c57
-rw-r--r--sub/osd_state.h2
5 files changed, 82 insertions, 7 deletions
diff --git a/sub/ass_mp.c b/sub/ass_mp.c
index d5d9e3e7d6..d214375b61 100644
--- a/sub/ass_mp.c
+++ b/sub/ass_mp.c
@@ -23,6 +23,7 @@
#include <stdarg.h>
#include <stdbool.h>
#include <assert.h>
+#include <math.h>
#include <ass/ass.h>
#include <ass/ass_types.h>
@@ -385,3 +386,27 @@ void mp_ass_packer_pack(struct mp_ass_packer *p, ASS_Image **image_lists,
p->cached_subs.change_id = 0;
p->cached_subs_valid = true;
}
+
+// Set *out_rc to [x0, y0, x1, y1] of the graphical bounding box in script
+// coordinates.
+// Set it to [inf, inf, -inf, -inf] if empty.
+void mp_ass_get_bb(ASS_Image *image_list, ASS_Track *track,
+ struct mp_osd_res *res, double *out_rc)
+{
+ double rc[4] = {INFINITY, INFINITY, -INFINITY, -INFINITY};
+
+ for (ASS_Image *img = image_list; img; img = img->next) {
+ if (img->w == 0 || img->h == 0)
+ continue;
+ rc[0] = MPMIN(rc[0], img->dst_x);
+ rc[1] = MPMIN(rc[1], img->dst_y);
+ rc[2] = MPMAX(rc[2], img->dst_x + img->w);
+ rc[3] = MPMAX(rc[3], img->dst_y + img->h);
+ }
+
+ double scale = track->PlayResY / (double)MPMAX(res->h, 1);
+ if (scale > 0) {
+ for (int i = 0; i < 4; i++)
+ out_rc[i] = rc[i] * scale;
+ }
+}
diff --git a/sub/ass_mp.h b/sub/ass_mp.h
index 4ebb7f39a6..f4488bf8c7 100644
--- a/sub/ass_mp.h
+++ b/sub/ass_mp.h
@@ -55,5 +55,7 @@ struct mp_ass_packer *mp_ass_packer_alloc(void *ta_parent);
void mp_ass_packer_pack(struct mp_ass_packer *p, ASS_Image **image_lists,
int num_image_lists, bool changed,
int preferred_osd_format, struct sub_bitmaps *out);
+void mp_ass_get_bb(ASS_Image *image_list, ASS_Track *track,
+ struct mp_osd_res *res, double *out_rc);
#endif /* MPLAYER_ASS_MP_H */
diff --git a/sub/osd.h b/sub/osd.h
index 31b3dd532b..5a6809817f 100644
--- a/sub/osd.h
+++ b/sub/osd.h
@@ -209,6 +209,9 @@ struct osd_external_ass {
char *data;
int res_x, res_y;
int z;
+ bool hidden;
+
+ double *out_rc; // hack to pass boundary rect, [x0, y0, x1, y1]
};
// defined in osd_libass.c and osd_dummy.c
diff --git a/sub/osd_libass.c b/sub/osd_libass.c
index 01c0337eb4..bf527e17f3 100644
--- a/sub/osd_libass.c
+++ b/sub/osd_libass.c
@@ -40,6 +40,9 @@ static const char osd_font_pfb[] =
#define ASS_USE_OSD_FONT "{\\fnmpv-osd-symbols}"
+static void append_ass(struct ass_state *ass, struct mp_osd_res *res,
+ ASS_Image **img_list, bool *changed);
+
void osd_init_backend(struct osd_state *osd)
{
}
@@ -101,6 +104,8 @@ static void update_playres(struct ass_state *ass, struct mp_osd_res *vo_res)
int old_res_x = track->PlayResX;
int old_res_y = track->PlayResY;
+ ass->vo_res = *vo_res;
+
double aspect = 1.0 * vo_res->w / MPMAX(vo_res->h, 1);
if (vo_res->display_par > 0)
aspect = aspect / vo_res->display_par;
@@ -531,10 +536,12 @@ void osd_set_external(struct osd_state *osd, struct osd_external_ass *ov)
struct osd_external *entry = obj->externals[index];
if (!ov->format) {
+ if (!entry->ov.hidden) {
+ obj->changed = true;
+ osd->want_redraw_notification = true;
+ }
destroy_external(entry);
MP_TARRAY_REMOVE_AT(obj->externals, obj->num_externals, index);
- obj->changed = true;
- osd->want_redraw_notification = true;
goto done;
}
@@ -547,17 +554,42 @@ void osd_set_external(struct osd_state *osd, struct osd_external_ass *ov)
entry->ov.res_y = ov->res_y;
zorder_changed |= entry->ov.z != ov->z;
entry->ov.z = ov->z;
+ entry->ov.hidden = ov->hidden;
update_external(osd, obj, entry);
- obj->changed = true;
- osd->want_redraw_notification = true;
+ if (!entry->ov.hidden) {
+ obj->changed = true;
+ osd->want_redraw_notification = true;
+ }
if (zorder_changed) {
qsort(obj->externals, obj->num_externals, sizeof(obj->externals[0]),
cmp_zorder);
}
+ if (ov->out_rc) {
+ struct mp_osd_res vo_res = entry->ass.vo_res;
+ // Defined fallback if VO has not drawn this yet
+ if (vo_res.w < 1 || vo_res.h < 1) {
+ vo_res = (struct mp_osd_res){
+ .w = entry->ov.res_x,
+ .h = entry->ov.res_y,
+ .display_par = 1,
+ };
+ // According to osd-overlay command description.
+ if (vo_res.w < 1)
+ vo_res.w = 1280;
+ if (vo_res.h < 1)
+ vo_res.h = 720;
+ }
+
+ ASS_Image *img_list = NULL;
+ append_ass(&entry->ass, &vo_res, &img_list, NULL);
+
+ mp_ass_get_bb(img_list, entry->ass.track, &vo_res, ov->out_rc);
+ }
+
done:
pthread_mutex_unlock(&osd->lock);
}
@@ -593,7 +625,13 @@ static void append_ass(struct ass_state *ass, struct mp_osd_res *res,
int ass_changed;
*img_list = ass_render_frame(ass->render, ass->track, 0, &ass_changed);
- *changed |= ass_changed;
+
+ ass->changed |= ass_changed;
+
+ if (changed) {
+ *changed |= ass->changed;
+ ass->changed = false;
+ }
}
void osd_object_get_bitmaps(struct osd_state *osd, struct osd_object *obj,
@@ -609,8 +647,13 @@ void osd_object_get_bitmaps(struct osd_state *osd, struct osd_object *obj,
append_ass(&obj->ass, &obj->vo_res, &obj->ass_imgs[0], &obj->changed);
for (int n = 0; n < obj->num_externals; n++) {
- append_ass(&obj->externals[n]->ass, &obj->vo_res,
- &obj->ass_imgs[n + 1], &obj->changed);
+ if (obj->externals[n]->ov.hidden) {
+ update_playres(&obj->externals[n]->ass, &obj->vo_res);
+ obj->ass_imgs[n + 1] = NULL;
+ } else {
+ append_ass(&obj->externals[n]->ass, &obj->vo_res,
+ &obj->ass_imgs[n + 1], &obj->changed);
+ }
}
mp_ass_packer_pack(obj->ass_packer, obj->ass_imgs, obj->num_externals + 1,
diff --git a/sub/osd_state.h b/sub/osd_state.h
index 8207cf0dda..b563502fd6 100644
--- a/sub/osd_state.h
+++ b/sub/osd_state.h
@@ -23,6 +23,8 @@ struct ass_state {
struct ass_renderer *render;
struct ass_library *library;
int res_x, res_y;
+ bool changed;
+ struct mp_osd_res vo_res; // last known value
};
struct osd_object {